aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c10
-rw-r--r--lib/asn1/doc/src/Makefile1
-rw-r--r--lib/asn1/doc/src/asn1ct.xml14
-rw-r--r--lib/asn1/doc/src/notes.xml77
-rw-r--r--lib/asn1/test/asn1_SUITE.erl59
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/doc/src/Makefile3
-rw-r--r--lib/common_test/doc/src/common_test_app.xml43
-rw-r--r--lib/common_test/doc/src/ct.xml144
-rw-r--r--lib/common_test/doc/src/ct_cover.xml8
-rw-r--r--lib/common_test/doc/src/ct_ftp.xml26
-rw-r--r--lib/common_test/doc/src/ct_hooks.xml161
-rw-r--r--lib/common_test/doc/src/ct_master.xml24
-rw-r--r--lib/common_test/doc/src/ct_netconfc.xml110
-rw-r--r--lib/common_test/doc/src/ct_property_test.xml6
-rw-r--r--lib/common_test/doc/src/ct_rpc.xml18
-rw-r--r--lib/common_test/doc/src/ct_slave.xml12
-rw-r--r--lib/common_test/doc/src/ct_snmp.xml38
-rw-r--r--lib/common_test/doc/src/ct_ssh.xml152
-rw-r--r--lib/common_test/doc/src/ct_telnet.xml63
-rw-r--r--lib/common_test/doc/src/ct_testspec.xml4
-rw-r--r--lib/common_test/doc/src/notes.xml198
-rw-r--r--lib/common_test/doc/src/unix_telnet.xml6
-rw-r--r--lib/common_test/doc/src/write_test_chapter.xml18
-rw-r--r--lib/common_test/src/ct_config.erl8
-rw-r--r--lib/common_test/src/ct_framework.erl314
-rw-r--r--lib/common_test/src/ct_groups.erl83
-rw-r--r--lib/common_test/src/ct_hooks.erl77
-rw-r--r--lib/common_test/src/ct_logs.erl14
-rw-r--r--lib/common_test/src/ct_netconfc.erl10
-rw-r--r--lib/common_test/src/ct_telnet.erl144
-rw-r--r--lib/common_test/src/ct_telnet_client.erl6
-rw-r--r--lib/common_test/src/cth_log_redirect.erl13
-rw-r--r--lib/common_test/src/test_server.erl263
-rw-r--r--lib/common_test/src/test_server_ctrl.erl137
-rw-r--r--lib/common_test/src/test_server_node.erl103
-rw-r--r--lib/common_test/src/test_server_sup.erl2
-rw-r--r--lib/common_test/test/Makefile4
-rw-r--r--lib/common_test/test/ct_auto_compile_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl49
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl451
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_SUITE.erl47
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_cth.erl100
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_update_result_post_end_tc_SUITE.erl101
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_match_state_cth.erl58
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_group_only_cth_SUITE.erl54
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl28
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_result_post_end_tc_cth.erl98
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_tc_repeat_SUITE.erl438
-rw-r--r--lib/common_test/test/ct_tc_repeat_SUITE_data/tc_repeat_SUITE.erl85
-rw-r--r--lib/common_test/test/ct_telnet_SUITE.erl39
-rw-r--r--lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_faulty_regexp_SUITE.erl79
-rw-r--r--lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl11
-rw-r--r--lib/common_test/test/ct_util_SUITE.erl490
-rw-r--r--lib/common_test/test/ct_util_SUITE_data/ct_util_cth.erl105
-rw-r--r--lib/common_test/test/ct_util_SUITE_data/curr_tc_SUITE.erl59
-rw-r--r--lib/common_test/test_server/configure.in6
-rw-r--r--lib/common_test/test_server/ts_erl_config.erl6
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/Makefile3
-rw-r--r--lib/compiler/doc/src/compile.xml29
-rw-r--r--lib/compiler/doc/src/notes.xml302
-rw-r--r--lib/compiler/src/beam_jump.erl15
-rw-r--r--lib/compiler/src/beam_type.erl5
-rw-r--r--lib/compiler/src/beam_utils.erl22
-rw-r--r--lib/compiler/src/beam_validator.erl38
-rw-r--r--lib/compiler/src/compile.erl42
-rw-r--r--lib/compiler/src/sys_core_bsm.erl62
-rw-r--r--lib/compiler/src/sys_core_fold.erl114
-rw-r--r--lib/compiler/src/v3_codegen.erl141
-rw-r--r--lib/compiler/src/v3_core.erl64
-rw-r--r--lib/compiler/test/andor_SUITE.erl4
-rw-r--r--lib/compiler/test/apply_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_block_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_except_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_jump_SUITE.erl23
-rw-r--r--lib/compiler/test/beam_reorder_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl38
-rw-r--r--lib/compiler/test/beam_utils_SUITE.erl69
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl2
-rw-r--r--lib/compiler/test/bif_SUITE.erl4
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl15
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl6
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl6
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl82
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl4
-rw-r--r--lib/compiler/test/compilation_SUITE.erl4
-rw-r--r--lib/compiler/test/compile_SUITE.erl47
-rw-r--r--lib/compiler/test/core_SUITE.erl7
-rw-r--r--lib/compiler/test/core_SUITE_data/fun_letrec_effect.core25
-rw-r--r--lib/compiler/test/core_alias_SUITE.erl4
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl26
-rw-r--r--lib/compiler/test/error_SUITE.erl4
-rw-r--r--lib/compiler/test/float_SUITE.erl4
-rw-r--r--lib/compiler/test/fun_SUITE.erl2
-rw-r--r--lib/compiler/test/guard_SUITE.erl4
-rw-r--r--lib/compiler/test/inline_SUITE.erl4
-rw-r--r--lib/compiler/test/lc_SUITE.erl2
-rw-r--r--lib/compiler/test/map_SUITE.erl135
-rw-r--r--lib/compiler/test/match_SUITE.erl24
-rw-r--r--lib/compiler/test/misc_SUITE.erl2
-rw-r--r--lib/compiler/test/overridden_bif_SUITE.erl4
-rw-r--r--lib/compiler/test/receive_SUITE.erl79
-rw-r--r--lib/compiler/test/record_SUITE.erl4
-rw-r--r--lib/compiler/test/regressions_SUITE.erl21
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl28
-rw-r--r--lib/compiler/test/warnings_SUITE.erl23
-rw-r--r--lib/compiler/test/z_SUITE.erl2
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/crypto/c_src/crypto.c1116
-rw-r--r--lib/crypto/c_src/crypto_callback.c6
-rw-r--r--lib/crypto/c_src/otp_test_engine.c181
-rw-r--r--lib/crypto/doc/specs/.gitignore1
-rw-r--r--lib/crypto/doc/src/Makefile10
-rw-r--r--lib/crypto/doc/src/algorithm_details.xml355
-rw-r--r--lib/crypto/doc/src/crypto.xml1424
-rw-r--r--lib/crypto/doc/src/engine_keys.xml6
-rw-r--r--lib/crypto/doc/src/engine_load.xml33
-rw-r--r--lib/crypto/doc/src/notes.xml259
-rw-r--r--lib/crypto/doc/src/specs.xml4
-rw-r--r--lib/crypto/doc/src/usersguide.xml1
-rw-r--r--lib/crypto/src/crypto.erl1265
-rw-r--r--lib/crypto/src/crypto_ec_curves.erl36
-rw-r--r--lib/crypto/test/Makefile4
-rw-r--r--lib/crypto/test/blowfish_SUITE.erl300
-rw-r--r--lib/crypto/test/crypto.spec5
-rw-r--r--lib/crypto/test/crypto_SUITE.erl1362
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT128.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT192.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT256.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT128.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT192.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT256.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT128.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT192.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT256.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt9
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zipbin0 -> 319267 bytes
-rw-r--r--lib/crypto/test/crypto_bench.spec3
-rw-r--r--lib/crypto/test/crypto_bench_SUITE.erl400
-rw-r--r--lib/crypto/test/engine_SUITE.erl417
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/Makefile4
-rw-r--r--lib/debugger/doc/src/debugger.xml12
-rw-r--r--lib/debugger/doc/src/i.xml64
-rw-r--r--lib/debugger/doc/src/int.xml64
-rw-r--r--lib/debugger/doc/src/notes.xml15
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--lib/dialyzer/doc/src/Makefile1
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml12
-rw-r--r--lib/dialyzer/doc/src/notes.xml45
-rw-r--r--lib/dialyzer/src/dialyzer_codeserver.erl8
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl130
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl37
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/para1
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/para/para4.erl11
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/para/para4_adt.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/left_assoc2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/spec_other_module2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl96
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/lists_key_bug.erl75
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/spec_other_module.erl7
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/doc/src/Makefile3
-rw-r--r--lib/diameter/doc/src/diameter.xml52
-rw-r--r--lib/diameter/doc/src/diameter_app.xml18
-rw-r--r--lib/diameter/doc/src/diameter_codec.xml6
-rw-r--r--lib/diameter/doc/src/diameter_make.xml10
-rw-r--r--lib/diameter/doc/src/diameter_sctp.xml4
-rw-r--r--lib/diameter/doc/src/diameter_tcp.xml4
-rw-r--r--lib/diameter/doc/src/diameter_transport.xml35
-rw-r--r--lib/diameter/doc/src/notes.xml90
-rw-r--r--lib/diameter/src/base/diameter.erl4
-rw-r--r--lib/diameter/src/base/diameter_callback.erl4
-rw-r--r--lib/diameter/src/base/diameter_dist.erl535
-rw-r--r--lib/diameter/src/base/diameter_gen.erl2
-rw-r--r--lib/diameter/src/base/diameter_misc_sup.erl3
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl4
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl99
-rw-r--r--lib/diameter/src/diameter.appup.src14
-rw-r--r--lib/diameter/src/modules.mk3
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl8
-rw-r--r--lib/diameter/test/diameter_dist_SUITE.erl332
-rw-r--r--lib/diameter/test/diameter_distribution_SUITE.erl7
-rw-r--r--lib/diameter/test/diameter_pool_SUITE.erl3
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl5
-rw-r--r--lib/diameter/test/modules.mk3
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/edoc/doc/src/Makefile1
-rw-r--r--lib/edoc/doc/src/notes.xml31
-rw-r--r--lib/edoc/src/edoc.erl17
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/eldap/doc/src/Makefile1
-rw-r--r--lib/eldap/doc/src/eldap.xml68
-rw-r--r--lib/eldap/doc/src/notes.xml84
-rw-r--r--lib/eldap/src/eldap.erl21
-rw-r--r--lib/eldap/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/Makefile1
-rw-r--r--lib/erl_docgen/doc/src/docgen_xml_check.xml4
-rw-r--r--lib/erl_docgen/doc/src/notes.xml42
-rw-r--r--lib/erl_docgen/priv/css/otp_doc.css39
-rw-r--r--lib/erl_docgen/priv/dtd/cref.dtd2
-rw-r--r--lib/erl_docgen/priv/dtd/erlref.dtd2
-rw-r--r--lib/erl_docgen/priv/xsl/db_eix.xsl81
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl185
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/configure.in20
-rw-r--r--lib/erl_interface/doc/src/Makefile3
-rw-r--r--lib/erl_interface/doc/src/ei.xml191
-rw-r--r--lib/erl_interface/doc/src/ei_connect.xml414
-rw-r--r--lib/erl_interface/doc/src/ei_users_guide.xml18
-rw-r--r--lib/erl_interface/doc/src/erl_connect.xml50
-rw-r--r--lib/erl_interface/doc/src/erl_error.xml10
-rw-r--r--lib/erl_interface/doc/src/erl_eterm.xml58
-rw-r--r--lib/erl_interface/doc/src/erl_format.xml4
-rw-r--r--lib/erl_interface/doc/src/erl_global.xml8
-rw-r--r--lib/erl_interface/doc/src/erl_malloc.xml16
-rw-r--r--lib/erl_interface/doc/src/erl_marshal.xml18
-rw-r--r--lib/erl_interface/doc/src/notes.xml151
-rw-r--r--lib/erl_interface/doc/src/registry.xml40
-rw-r--r--lib/erl_interface/include/ei.h53
-rw-r--r--lib/erl_interface/src/Makefile.in40
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c1188
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c22
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.h2
-rw-r--r--lib/erl_interface/src/connect/eirecv.c62
-rw-r--r--lib/erl_interface/src/connect/send.c74
-rw-r--r--lib/erl_interface/src/connect/send_exit.c25
-rw-r--r--lib/erl_interface/src/connect/send_reg.c64
-rw-r--r--lib/erl_interface/src/depend.mk1133
-rw-r--r--lib/erl_interface/src/epmd/epmd_port.c85
-rw-r--r--lib/erl_interface/src/epmd/epmd_publish.c36
-rw-r--r--lib/erl_interface/src/epmd/epmd_unpublish.c33
-rw-r--r--lib/erl_interface/src/legacy/erl_connect.c9
-rw-r--r--lib/erl_interface/src/legacy/erl_eterm.c2
-rw-r--r--lib/erl_interface/src/legacy/erl_marshal.c2
-rw-r--r--lib/erl_interface/src/misc/ei_init.c32
-rw-r--r--lib/erl_interface/src/misc/ei_internal.h20
-rw-r--r--lib/erl_interface/src/misc/ei_portio.c865
-rw-r--r--lib/erl_interface/src/misc/ei_portio.h95
-rw-r--r--lib/erl_interface/src/misc/ei_pthreads.c3
-rw-r--r--lib/erl_interface/src/not_used/send_link.c3
-rw-r--r--lib/erl_interface/src/prog/ei_fake_prog.c11
-rw-r--r--lib/erl_interface/src/prog/erl_call.c54
-rw-r--r--lib/erl_interface/src/prog/erl_start.c2
-rw-r--r--lib/erl_interface/test/Makefile1
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE.erl20
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c52
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c88
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl18
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c16
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl22
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c22
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl8
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c5
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE.erl24
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c14
-rw-r--r--lib/erl_interface/test/ei_format_SUITE.erl14
-rw-r--r--lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c8
-rw-r--r--lib/erl_interface/test/ei_print_SUITE.erl14
-rw-r--r--lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c8
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE.erl30
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c8
-rw-r--r--lib/erl_interface/test/erl_call_SUITE.erl96
-rw-r--r--lib/erl_interface/test/erl_connect_SUITE.erl12
-rw-r--r--lib/erl_interface/test/erl_eterm_SUITE.erl80
-rw-r--r--lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c42
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE.erl15
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c14
-rw-r--r--lib/erl_interface/test/erl_format_SUITE.erl12
-rw-r--r--lib/erl_interface/test/erl_global_SUITE.erl11
-rw-r--r--lib/erl_interface/test/erl_match_SUITE.erl9
-rw-r--r--lib/erl_interface/test/port_call_SUITE.erl8
-rw-r--r--lib/erl_interface/test/runner.erl56
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/Makefile1
-rw-r--r--lib/et/doc/src/et.xml14
-rw-r--r--lib/et/doc/src/et_collector.xml56
-rw-r--r--lib/et/doc/src/et_selector.xml14
-rw-r--r--lib/et/doc/src/et_viewer.xml14
-rw-r--r--lib/et/doc/src/notes.xml32
-rw-r--r--lib/et/src/et_collector.erl4
-rw-r--r--lib/et/src/et_wx_viewer.erl37
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/eunit/doc/src/Makefile1
-rw-r--r--lib/eunit/doc/src/notes.xml15
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/ftp/doc/src/Makefile1
-rw-r--r--lib/ftp/doc/src/ftp.xml96
-rw-r--r--lib/ftp/doc/src/notes.xml33
-rw-r--r--lib/ftp/src/ftp.app.src2
-rw-r--r--lib/ftp/src/ftp.erl407
-rw-r--r--lib/ftp/test/ftp_SUITE.erl73
-rw-r--r--lib/ftp/vsn.mk2
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl5
-rw-r--r--lib/hipe/cerl/erl_types.erl94
-rw-r--r--lib/hipe/doc/src/Makefile3
-rw-r--r--lib/hipe/doc/src/notes.xml46
-rw-r--r--lib/hipe/main/hipe.erl2
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/inets/doc/src/Makefile1
-rw-r--r--lib/inets/doc/src/http_uri.xml12
-rw-r--r--lib/inets/doc/src/httpc.xml50
-rw-r--r--lib/inets/doc/src/httpd.xml26
-rw-r--r--lib/inets/doc/src/httpd_custom_api.xml8
-rw-r--r--lib/inets/doc/src/httpd_socket.xml8
-rw-r--r--lib/inets/doc/src/httpd_util.xml55
-rw-r--r--lib/inets/doc/src/inets.xml20
-rw-r--r--lib/inets/doc/src/mod_alias.xml10
-rw-r--r--lib/inets/doc/src/mod_auth.xml58
-rw-r--r--lib/inets/doc/src/mod_esi.xml8
-rw-r--r--lib/inets/doc/src/mod_security.xml39
-rw-r--r--lib/inets/doc/src/notes.xml254
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl26
-rw-r--r--lib/inets/src/http_client/httpc_request.erl23
-rw-r--r--lib/inets/src/http_client/httpc_response.erl31
-rw-r--r--lib/inets/src/http_server/httpd_example.erl29
-rw-r--r--lib/inets/src/http_server/httpd_file.erl5
-rw-r--r--lib/inets/src/http_server/httpd_response.erl8
-rw-r--r--lib/inets/src/http_server/mod_esi.erl23
-rw-r--r--lib/inets/src/inets_app/inets.appup.src2
-rw-r--r--lib/inets/test/httpc_SUITE.erl215
-rw-r--r--lib/inets/test/httpd_SUITE.erl273
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/jinterface/doc/src/Makefile13
-rw-r--r--lib/jinterface/doc/src/notes.xml15
-rw-r--r--lib/jinterface/vsn.mk2
-rw-r--r--lib/kernel/doc/src/.gitignore1
-rw-r--r--lib/kernel/doc/src/Makefile15
-rw-r--r--lib/kernel/doc/src/application.xml109
-rw-r--r--lib/kernel/doc/src/auth.xml12
-rw-r--r--lib/kernel/doc/src/code.xml84
-rw-r--r--lib/kernel/doc/src/disk_log.xml74
-rw-r--r--lib/kernel/doc/src/erl_boot_server.xml12
-rw-r--r--lib/kernel/doc/src/erl_ddll.xml32
-rw-r--r--lib/kernel/doc/src/erl_epmd.xml16
-rw-r--r--lib/kernel/doc/src/error_handler.xml8
-rw-r--r--lib/kernel/doc/src/error_logger.xml46
-rw-r--r--lib/kernel/doc/src/file.xml122
-rw-r--r--lib/kernel/doc/src/gen_sctp.xml111
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml52
-rw-r--r--lib/kernel/doc/src/gen_udp.xml51
-rw-r--r--lib/kernel/doc/src/global.xml42
-rw-r--r--lib/kernel/doc/src/global_group.xml22
-rw-r--r--lib/kernel/doc/src/heart.xml18
-rw-r--r--lib/kernel/doc/src/inet.xml405
-rw-r--r--lib/kernel/doc/src/inet_res.xml38
-rw-r--r--lib/kernel/doc/src/kernel_app.xml49
-rw-r--r--lib/kernel/doc/src/logger.xml497
-rw-r--r--lib/kernel/doc/src/logger_arch.diabin0 -> 2527 bytes
-rw-r--r--lib/kernel/doc/src/logger_arch.pngbin32187 -> 117205 bytes
-rw-r--r--lib/kernel/doc/src/logger_chapter.xml130
-rw-r--r--lib/kernel/doc/src/logger_disk_log_h.xml14
-rw-r--r--lib/kernel/doc/src/logger_filters.xml10
-rw-r--r--lib/kernel/doc/src/logger_formatter.xml30
-rw-r--r--lib/kernel/doc/src/logger_std_h.xml123
-rw-r--r--lib/kernel/doc/src/net_adm.xml22
-rw-r--r--lib/kernel/doc/src/net_kernel.xml36
-rw-r--r--lib/kernel/doc/src/notes.xml488
-rw-r--r--lib/kernel/doc/src/os.xml38
-rw-r--r--lib/kernel/doc/src/pg2.xml22
-rw-r--r--lib/kernel/doc/src/rpc.xml56
-rw-r--r--lib/kernel/doc/src/seq_trace.xml20
-rw-r--r--lib/kernel/doc/src/wrap_log_reader.xml12
-rw-r--r--lib/kernel/include/logger.hrl4
-rw-r--r--lib/kernel/src/Makefile9
-rw-r--r--lib/kernel/src/application.erl22
-rw-r--r--lib/kernel/src/application_controller.erl104
-rw-r--r--lib/kernel/src/code_server.erl10
-rw-r--r--lib/kernel/src/erl_epmd.erl8
-rw-r--r--lib/kernel/src/error_logger.erl44
-rw-r--r--lib/kernel/src/gen_sctp.erl18
-rw-r--r--lib/kernel/src/gen_tcp.erl16
-rw-r--r--lib/kernel/src/gen_udp.erl19
-rw-r--r--lib/kernel/src/inet.erl99
-rw-r--r--lib/kernel/src/inet6_tcp.erl8
-rw-r--r--lib/kernel/src/inet_db.erl7
-rw-r--r--lib/kernel/src/inet_int.hrl8
-rw-r--r--lib/kernel/src/inet_tcp.erl8
-rw-r--r--lib/kernel/src/inet_tcp_dist.erl2
-rw-r--r--lib/kernel/src/kernel.app.src6
-rw-r--r--lib/kernel/src/kernel.appup.src57
-rw-r--r--lib/kernel/src/logger.erl489
-rw-r--r--lib/kernel/src/logger_backend.erl2
-rw-r--r--lib/kernel/src/logger_config.erl35
-rw-r--r--lib/kernel/src/logger_disk_log_h.erl731
-rw-r--r--lib/kernel/src/logger_formatter.erl251
-rw-r--r--lib/kernel/src/logger_h_common.erl649
-rw-r--r--lib/kernel/src/logger_h_common.hrl188
-rw-r--r--lib/kernel/src/logger_handler_watcher.erl113
-rw-r--r--lib/kernel/src/logger_internal.hrl9
-rw-r--r--lib/kernel/src/logger_olp.erl627
-rw-r--r--lib/kernel/src/logger_olp.hrl185
-rw-r--r--lib/kernel/src/logger_proxy.erl165
-rw-r--r--lib/kernel/src/logger_server.erl231
-rw-r--r--lib/kernel/src/logger_simple_h.erl11
-rw-r--r--lib/kernel/src/logger_std_h.erl1123
-rw-r--r--lib/kernel/src/logger_sup.erl8
-rw-r--r--lib/kernel/src/net_kernel.erl137
-rw-r--r--lib/kernel/src/raw_file_io_inflate.erl2
-rw-r--r--lib/kernel/src/seq_trace.erl2
-rw-r--r--lib/kernel/src/standard_error.erl3
-rw-r--r--lib/kernel/src/user.erl3
-rw-r--r--lib/kernel/src/user_drv.erl7
-rw-r--r--lib/kernel/test/Makefile3
-rw-r--r--lib/kernel/test/application_SUITE.erl97
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl99
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl9
-rw-r--r--lib/kernel/test/file_SUITE.erl35
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl408
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl176
-rw-r--r--lib/kernel/test/global_SUITE.erl30
-rw-r--r--lib/kernel/test/inet_SUITE.erl203
-rw-r--r--lib/kernel/test/inet_sockopt_SUITE.erl9
-rw-r--r--lib/kernel/test/init_SUITE.erl23
-rw-r--r--lib/kernel/test/kernel.spec1
-rw-r--r--lib/kernel/test/kernel_bench.spec1
-rw-r--r--lib/kernel/test/logger.cover5
-rw-r--r--lib/kernel/test/logger.spec2
-rw-r--r--lib/kernel/test/logger_SUITE.erl392
-rw-r--r--lib/kernel/test/logger_disk_log_h_SUITE.erl465
-rw-r--r--lib/kernel/test/logger_env_var_SUITE.erl35
-rw-r--r--lib/kernel/test/logger_formatter_SUITE.erl103
-rw-r--r--lib/kernel/test/logger_olp_SUITE.erl90
-rw-r--r--lib/kernel/test/logger_proxy_SUITE.erl274
-rw-r--r--lib/kernel/test/logger_simple_h_SUITE.erl3
-rw-r--r--lib/kernel/test/logger_std_h_SUITE.erl819
-rw-r--r--lib/kernel/test/logger_stress_SUITE.erl550
-rw-r--r--lib/kernel/test/logger_test_lib.erl10
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl3
-rw-r--r--lib/kernel/test/sendfile_SUITE.erl26
-rw-r--r--lib/kernel/test/seq_trace_SUITE.erl57
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/doc/src/Makefile3
-rw-r--r--lib/megaco/doc/src/book.xml2
-rw-r--r--lib/megaco/doc/src/megaco.xml102
-rw-r--r--lib/megaco/doc/src/megaco_codec_meas.xml6
-rw-r--r--lib/megaco/doc/src/megaco_codec_mstone1.xml26
-rw-r--r--lib/megaco/doc/src/megaco_codec_mstone2.xml6
-rw-r--r--lib/megaco/doc/src/megaco_codec_transform.xml6
-rw-r--r--lib/megaco/doc/src/megaco_edist_compress.xml6
-rw-r--r--lib/megaco/doc/src/megaco_encoder.xml14
-rw-r--r--lib/megaco/doc/src/megaco_flex_scanner.xml12
-rw-r--r--lib/megaco/doc/src/megaco_tcp.xml30
-rw-r--r--lib/megaco/doc/src/megaco_transport.xml8
-rw-r--r--lib/megaco/doc/src/megaco_udp.xml30
-rw-r--r--lib/megaco/doc/src/megaco_user.xml48
-rw-r--r--lib/megaco/doc/src/notes.xml17
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/Makefile1
-rw-r--r--lib/mnesia/doc/src/mnesia.xml243
-rw-r--r--lib/mnesia/doc/src/mnesia_frag_hash.xml16
-rw-r--r--lib/mnesia/doc/src/mnesia_registry.xml6
-rw-r--r--lib/mnesia/doc/src/notes.xml91
-rw-r--r--lib/mnesia/src/mnesia.erl22
-rw-r--r--lib/mnesia/src/mnesia_controller.erl30
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl6
-rw-r--r--lib/mnesia/src/mnesia_index.erl2
-rw-r--r--lib/mnesia/src/mnesia_loader.erl8
-rw-r--r--lib/mnesia/test/mnesia_durability_test.erl107
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl105
-rw-r--r--lib/mnesia/test/mnesia_isolation_test.erl11
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/Makefile1
-rw-r--r--lib/observer/doc/src/crashdump.xml8
-rw-r--r--lib/observer/doc/src/etop.xml14
-rw-r--r--lib/observer/doc/src/notes.xml91
-rw-r--r--lib/observer/doc/src/observer.xml4
-rw-r--r--lib/observer/doc/src/ttb.xml47
-rw-r--r--lib/observer/src/Makefile1
-rw-r--r--lib/observer/src/cdv_detail_wx.erl3
-rw-r--r--lib/observer/src/cdv_html_wx.erl33
-rw-r--r--lib/observer/src/cdv_persistent_cb.erl32
-rw-r--r--lib/observer/src/cdv_table_wx.erl3
-rw-r--r--lib/observer/src/cdv_virtual_list_wx.erl3
-rw-r--r--lib/observer/src/cdv_wx.erl19
-rw-r--r--lib/observer/src/crashdump_viewer.erl313
-rw-r--r--lib/observer/src/observer.app.src1
-rw-r--r--lib/observer/src/observer_alloc_wx.erl3
-rw-r--r--lib/observer/src/observer_app_wx.erl11
-rw-r--r--lib/observer/src/observer_html_lib.erl3
-rw-r--r--lib/observer/src/observer_perf_wx.erl15
-rw-r--r--lib/observer/src/observer_port_wx.erl14
-rw-r--r--lib/observer/src/observer_pro_wx.erl15
-rw-r--r--lib/observer/src/observer_procinfo.erl8
-rw-r--r--lib/observer/src/observer_trace_wx.erl17
-rw-r--r--lib/observer/src/observer_traceoptions_wx.erl9
-rw-r--r--lib/observer/src/observer_tv_table.erl3
-rw-r--r--lib/observer/src/observer_tv_wx.erl13
-rw-r--r--lib/observer/src/observer_wx.erl20
-rw-r--r--lib/observer/test/crashdump_helper.erl66
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE.erl38
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/c_src/odbcserver.c5
-rw-r--r--lib/odbc/doc/src/Makefile3
-rw-r--r--lib/odbc/doc/src/notes.xml34
-rw-r--r--lib/odbc/doc/src/odbc.xml52
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/os_mon/c_src/cpu_sup.c50
-rw-r--r--lib/os_mon/doc/src/Makefile1
-rw-r--r--lib/os_mon/doc/src/cpu_sup.xml14
-rw-r--r--lib/os_mon/doc/src/disksup.xml12
-rw-r--r--lib/os_mon/doc/src/memsup.xml24
-rw-r--r--lib/os_mon/doc/src/notes.xml33
-rw-r--r--lib/os_mon/doc/src/nteventlog.xml8
-rw-r--r--lib/os_mon/doc/src/os_mon_mib.xml6
-rw-r--r--lib/os_mon/doc/src/os_sup.xml10
-rw-r--r--lib/os_mon/src/cpu_sup.erl26
-rw-r--r--lib/os_mon/test/cpu_sup_SUITE.erl11
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/otp_mibs/doc/src/Makefile3
-rw-r--r--lib/otp_mibs/doc/src/notes.xml15
-rw-r--r--lib/otp_mibs/doc/src/otp_mib.xml6
-rw-r--r--lib/otp_mibs/vsn.mk2
-rw-r--r--lib/parsetools/doc/src/Makefile3
-rw-r--r--lib/parsetools/doc/src/leex.xml19
-rw-r--r--lib/parsetools/doc/src/notes.xml15
-rw-r--r--lib/parsetools/doc/src/yecc.xml6
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/public_key/asn1/OTP-PKIX.asn124
-rw-r--r--lib/public_key/doc/specs/.gitignore1
-rw-r--r--lib/public_key/doc/src/Makefile10
-rw-r--r--lib/public_key/doc/src/notes.xml124
-rw-r--r--lib/public_key/doc/src/public_key.xml723
-rw-r--r--lib/public_key/doc/src/specs.xml4
-rw-r--r--lib/public_key/priv/moduli66
-rw-r--r--lib/public_key/src/pubkey_cert.erl4
-rw-r--r--lib/public_key/src/pubkey_moduli.hrl134
-rw-r--r--lib/public_key/src/pubkey_pem.erl11
-rw-r--r--lib/public_key/src/pubkey_ssh.erl99
-rw-r--r--lib/public_key/src/public_key.erl465
-rw-r--r--lib/public_key/test/public_key_SUITE.erl15
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/Makefile3
-rw-r--r--lib/reltool/doc/src/notes.xml35
-rw-r--r--lib/reltool/doc/src/reltool.xml36
-rw-r--r--lib/reltool/src/reltool_utils.erl13
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl16
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/doc/src/Makefile1
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml114
-rw-r--r--lib/runtime_tools/doc/src/dyntrace.xml32
-rw-r--r--lib/runtime_tools/doc/src/erts_alloc_config.xml10
-rw-r--r--lib/runtime_tools/doc/src/msacc.xml32
-rw-r--r--lib/runtime_tools/doc/src/notes.xml32
-rw-r--r--lib/runtime_tools/doc/src/scheduler.xml12
-rw-r--r--lib/runtime_tools/doc/src/system_information.xml6
-rw-r--r--lib/runtime_tools/examples/dist.systemtap26
-rw-r--r--lib/runtime_tools/examples/driver1.systemtap44
-rw-r--r--lib/runtime_tools/examples/function-calls.systemtap22
-rw-r--r--lib/runtime_tools/examples/garbage-collection.systemtap16
-rw-r--r--lib/runtime_tools/examples/memory1.systemtap16
-rw-r--r--lib/runtime_tools/examples/messages.systemtap16
-rw-r--r--lib/runtime_tools/examples/port1.systemtap28
-rw-r--r--lib/runtime_tools/examples/process-scheduling.systemtap14
-rw-r--r--lib/runtime_tools/examples/spawn-exit.systemtap16
-rw-r--r--lib/runtime_tools/examples/user-probe-n.systemtap13
-rw-r--r--lib/runtime_tools/examples/user-probe.systemtap12
-rw-r--r--lib/runtime_tools/src/observer_backend.erl2
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/doc/src/Makefile1
-rw-r--r--lib/sasl/doc/src/alarm_handler.xml8
-rw-r--r--lib/sasl/doc/src/notes.xml32
-rw-r--r--lib/sasl/doc/src/rb.xml38
-rw-r--r--lib/sasl/doc/src/release_handler.xml42
-rw-r--r--lib/sasl/doc/src/systools.xml16
-rw-r--r--lib/sasl/src/sasl.app.src2
-rw-r--r--lib/sasl/src/sasl.appup.src35
-rw-r--r--lib/sasl/src/systools_make.erl4
-rw-r--r--lib/sasl/test/sasl_report_SUITE.erl84
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/doc/src/Makefile3
-rw-r--r--lib/snmp/doc/src/notes.xml45
-rw-r--r--lib/snmp/doc/src/snmp.xml99
-rw-r--r--lib/snmp/doc/src/snmp_community_mib.xml12
-rw-r--r--lib/snmp/doc/src/snmp_framework_mib.xml10
-rw-r--r--lib/snmp/doc/src/snmp_generic.xml30
-rw-r--r--lib/snmp/doc/src/snmp_impl_example_agent.xml2
-rw-r--r--lib/snmp/doc/src/snmp_index.xml18
-rw-r--r--lib/snmp/doc/src/snmp_notification_mib.xml10
-rw-r--r--lib/snmp/doc/src/snmp_pdus.xml26
-rw-r--r--lib/snmp/doc/src/snmp_standard_mib.xml14
-rw-r--r--lib/snmp/doc/src/snmp_target_mib.xml16
-rw-r--r--lib/snmp/doc/src/snmp_user_based_sm_mib.xml10
-rw-r--r--lib/snmp/doc/src/snmp_view_based_acm_mib.xml18
-rw-r--r--lib/snmp/doc/src/snmpa.xml260
-rw-r--r--lib/snmp/doc/src/snmpa_conf.xml112
-rw-r--r--lib/snmp/doc/src/snmpa_discovery_handler.xml4
-rw-r--r--lib/snmp/doc/src/snmpa_error.xml6
-rw-r--r--lib/snmp/doc/src/snmpa_error_io.xml6
-rw-r--r--lib/snmp/doc/src/snmpa_error_logger.xml6
-rw-r--r--lib/snmp/doc/src/snmpa_error_report.xml6
-rw-r--r--lib/snmp/doc/src/snmpa_local_db.xml24
-rw-r--r--lib/snmp/doc/src/snmpa_mib_data.xml34
-rw-r--r--lib/snmp/doc/src/snmpa_mib_storage.xml26
-rw-r--r--lib/snmp/doc/src/snmpa_mpd.xml20
-rw-r--r--lib/snmp/doc/src/snmpa_network_interface.xml12
-rw-r--r--lib/snmp/doc/src/snmpa_network_interface_filter.xml10
-rw-r--r--lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml6
-rw-r--r--lib/snmp/doc/src/snmpa_notification_filter.xml4
-rw-r--r--lib/snmp/doc/src/snmpa_supervisor.xml10
-rw-r--r--lib/snmp/doc/src/snmpc.xml10
-rw-r--r--lib/snmp/doc/src/snmpm.xml232
-rw-r--r--lib/snmp/doc/src/snmpm_conf.xml48
-rw-r--r--lib/snmp/doc/src/snmpm_mpd.xml10
-rw-r--r--lib/snmp/doc/src/snmpm_network_interface.xml20
-rw-r--r--lib/snmp/doc/src/snmpm_network_interface_filter.xml10
-rw-r--r--lib/snmp/doc/src/snmpm_user.xml16
-rw-r--r--lib/snmp/src/agent/snmpa_net_if.erl111
-rw-r--r--lib/snmp/src/compile/snmpc.erl6
-rw-r--r--lib/snmp/src/misc/snmp_log.erl334
-rw-r--r--lib/snmp/test/snmp_agent_test.erl2
-rw-r--r--lib/snmp/test/snmp_to_snmpnet_SUITE.erl2
-rw-r--r--lib/snmp/vsn.mk4
-rw-r--r--lib/ssh/doc/src/Makefile4
-rw-r--r--lib/ssh/doc/src/notes.xml241
-rw-r--r--lib/ssh/doc/src/ref_man.xml1
-rw-r--r--lib/ssh/doc/src/specs.xml1
-rw-r--r--lib/ssh/doc/src/ssh.xml161
-rw-r--r--lib/ssh/doc/src/ssh_app.xml23
-rw-r--r--lib/ssh/doc/src/ssh_client_channel.xml32
-rw-r--r--lib/ssh/doc/src/ssh_client_key_api.xml8
-rw-r--r--lib/ssh/doc/src/ssh_connection.xml36
-rw-r--r--lib/ssh/doc/src/ssh_file.xml285
-rw-r--r--lib/ssh/doc/src/ssh_server_channel.xml10
-rw-r--r--lib/ssh/doc/src/ssh_server_key_api.xml6
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml117
-rw-r--r--lib/ssh/doc/src/ssh_sftpd.xml4
-rw-r--r--lib/ssh/doc/src/terminology.xml185
-rw-r--r--lib/ssh/doc/src/usersguide.xml1
-rw-r--r--lib/ssh/doc/src/using_ssh.xml11
-rw-r--r--lib/ssh/src/ssh.erl62
-rw-r--r--lib/ssh/src/ssh.hrl75
-rw-r--r--lib/ssh/src/ssh_auth.erl112
-rw-r--r--lib/ssh/src/ssh_channel.erl4
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl88
-rw-r--r--lib/ssh/src/ssh_dbg.erl189
-rw-r--r--lib/ssh/src/ssh_file.erl31
-rw-r--r--lib/ssh/src/ssh_message.erl16
-rw-r--r--lib/ssh/src/ssh_options.erl24
-rw-r--r--lib/ssh/src/ssh_sftp.erl13
-rw-r--r--lib/ssh/src/ssh_sftpd.erl13
-rw-r--r--lib/ssh/src/ssh_transport.erl310
-rw-r--r--lib/ssh/src/ssh_xfer.erl4
-rw-r--r--lib/ssh/test/.gitignore5
-rw-r--r--lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl20
-rw-r--r--lib/ssh/test/property_test/ssh_eqc_client_server.erl230
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE.erl7
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ed255197
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ed25519.pub1
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ed44810
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/id_ed448.pub1
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key7
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key.pub1
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key10
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key.pub1
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl48
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_ed255197
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_ed25519.pub1
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_ed44810
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_ed448.pub1
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key7
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key.pub1
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key10
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key.pub1
-rw-r--r--lib/ssh/test/ssh_bench_SUITE.erl83
-rw-r--r--lib/ssh/test/ssh_compat_SUITE.erl39
-rwxr-xr-xlib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all6
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key7
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key10
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed255197
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed25519.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed44810
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed448.pub1
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE.erl68
-rw-r--r--lib/ssh/test/ssh_engine_SUITE.erl11
-rw-r--r--lib/ssh/test/ssh_options_SUITE.erl39
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE.erl7
-rw-r--r--lib/ssh/test/ssh_test_lib.erl25
-rw-r--r--lib/ssh/test/ssh_trpt_test_lib.erl99
-rw-r--r--lib/ssh/vsn.mk3
-rw-r--r--lib/ssl/doc/specs/.gitignore1
-rw-r--r--lib/ssl/doc/src/Makefile11
-rw-r--r--lib/ssl/doc/src/notes.xml557
-rw-r--r--lib/ssl/doc/src/specs.xml9
-rw-r--r--lib/ssl/doc/src/ssl.xml1850
-rw-r--r--lib/ssl/doc/src/ssl_app.xml14
-rw-r--r--lib/ssl/doc/src/ssl_crl_cache.xml33
-rw-r--r--lib/ssl/doc/src/ssl_crl_cache_api.xml71
-rw-r--r--lib/ssl/doc/src/ssl_session_cache_api.xml109
-rw-r--r--lib/ssl/examples/src/client_server.erl14
-rw-r--r--lib/ssl/src/Makefile4
-rw-r--r--lib/ssl/src/dtls.erl113
-rw-r--r--lib/ssl/src/dtls_connection.erl592
-rw-r--r--lib/ssl/src/dtls_handshake.erl25
-rw-r--r--lib/ssl/src/dtls_handshake.hrl1
-rw-r--r--lib/ssl/src/dtls_packet_demux.erl7
-rw-r--r--lib/ssl/src/dtls_record.erl69
-rw-r--r--lib/ssl/src/dtls_socket.erl59
-rw-r--r--lib/ssl/src/dtls_v1.erl8
-rw-r--r--lib/ssl/src/inet_tls_dist.erl42
-rw-r--r--lib/ssl/src/ssl.app.src4
-rw-r--r--lib/ssl/src/ssl.appup.src4
-rw-r--r--lib/ssl/src/ssl.erl852
-rw-r--r--lib/ssl/src/ssl_alert.erl96
-rw-r--r--lib/ssl/src/ssl_api.hrl43
-rw-r--r--lib/ssl/src/ssl_certificate.erl97
-rw-r--r--lib/ssl/src/ssl_cipher.erl1984
-rw-r--r--lib/ssl/src/ssl_cipher.hrl3
-rw-r--r--lib/ssl/src/ssl_cipher_format.erl1763
-rw-r--r--lib/ssl/src/ssl_config.erl6
-rw-r--r--lib/ssl/src/ssl_connection.erl2313
-rw-r--r--lib/ssl/src/ssl_connection.hrl148
-rw-r--r--lib/ssl/src/ssl_crl_cache.erl4
-rw-r--r--lib/ssl/src/ssl_crl_cache_api.erl15
-rw-r--r--lib/ssl/src/ssl_handshake.erl252
-rw-r--r--lib/ssl/src/ssl_internal.hrl63
-rw-r--r--lib/ssl/src/ssl_manager.erl58
-rw-r--r--lib/ssl/src/ssl_pem_cache.erl37
-rw-r--r--lib/ssl/src/ssl_pkix_db.erl19
-rw-r--r--lib/ssl/src/ssl_record.erl113
-rw-r--r--lib/ssl/src/ssl_record.hrl4
-rw-r--r--lib/ssl/src/ssl_session.erl17
-rw-r--r--lib/ssl/src/ssl_session_cache_api.erl24
-rw-r--r--lib/ssl/src/ssl_v3.erl4
-rw-r--r--lib/ssl/src/tls.erl112
-rw-r--r--lib/ssl/src/tls_connection.erl822
-rw-r--r--lib/ssl/src/tls_connection.hrl1
-rw-r--r--lib/ssl/src/tls_handshake.erl26
-rw-r--r--lib/ssl/src/tls_record.erl421
-rw-r--r--lib/ssl/src/tls_sender.erl516
-rw-r--r--lib/ssl/src/tls_socket.erl73
-rw-r--r--lib/ssl/src/tls_v1.erl2
-rw-r--r--lib/ssl/test/Makefile2
-rw-r--r--lib/ssl/test/make_certs.erl12
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl128
-rw-r--r--lib/ssl/test/ssl_ECC_openssl_SUITE.erl17
-rw-r--r--lib/ssl/test/ssl_alpn_handshake_SUITE.erl90
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl1092
-rw-r--r--lib/ssl/test/ssl_bench_SUITE.erl1
-rw-r--r--lib/ssl/test/ssl_bench_test_lib.erl4
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl181
-rw-r--r--lib/ssl/test/ssl_crl_SUITE.erl30
-rw-r--r--lib/ssl/test/ssl_dist_bench_SUITE.erl249
-rw-r--r--lib/ssl/test/ssl_engine_SUITE.erl45
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl55
-rw-r--r--lib/ssl/test/ssl_npn_handshake_SUITE.erl62
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl75
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl771
-rw-r--r--lib/ssl/test/ssl_pem_cache_SUITE.erl58
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl128
-rw-r--r--lib/ssl/test/ssl_sni_SUITE.erl8
-rw-r--r--lib/ssl/test/ssl_test_lib.erl550
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl284
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/Makefile1
-rw-r--r--lib/stdlib/doc/src/array.xml60
-rw-r--r--lib/stdlib/doc/src/assert_hrl.xml2
-rw-r--r--lib/stdlib/doc/src/base64.xml14
-rw-r--r--lib/stdlib/doc/src/beam_lib.xml38
-rw-r--r--lib/stdlib/doc/src/binary.xml56
-rw-r--r--lib/stdlib/doc/src/c.xml70
-rw-r--r--lib/stdlib/doc/src/calendar.xml70
-rw-r--r--lib/stdlib/doc/src/dets.xml90
-rw-r--r--lib/stdlib/doc/src/dict.xml44
-rw-r--r--lib/stdlib/doc/src/digraph.xml66
-rw-r--r--lib/stdlib/doc/src/digraph_utils.xml38
-rw-r--r--lib/stdlib/doc/src/epp.xml42
-rw-r--r--lib/stdlib/doc/src/erl_anno.xml36
-rw-r--r--lib/stdlib/doc/src/erl_eval.xml32
-rw-r--r--lib/stdlib/doc/src/erl_expand_records.xml4
-rw-r--r--lib/stdlib/doc/src/erl_id_trans.xml4
-rw-r--r--lib/stdlib/doc/src/erl_internal.xml22
-rw-r--r--lib/stdlib/doc/src/erl_lint.xml12
-rw-r--r--lib/stdlib/doc/src/erl_parse.xml32
-rw-r--r--lib/stdlib/doc/src/erl_pp.xml32
-rw-r--r--lib/stdlib/doc/src/erl_scan.xml30
-rw-r--r--lib/stdlib/doc/src/erl_tar.xml30
-rw-r--r--lib/stdlib/doc/src/ets.xml283
-rw-r--r--lib/stdlib/doc/src/file_sorter.xml30
-rw-r--r--lib/stdlib/doc/src/filelib.xml30
-rw-r--r--lib/stdlib/doc/src/filename.xml72
-rw-r--r--lib/stdlib/doc/src/gb_sets.xml72
-rw-r--r--lib/stdlib/doc/src/gb_trees.xml54
-rw-r--r--lib/stdlib/doc/src/gen_event.xml54
-rw-r--r--lib/stdlib/doc/src/gen_server.xml56
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml48
-rw-r--r--lib/stdlib/doc/src/io.xml96
-rw-r--r--lib/stdlib/doc/src/io_lib.xml64
-rw-r--r--lib/stdlib/doc/src/lists.xml180
-rw-r--r--lib/stdlib/doc/src/log_mf_h.xml6
-rw-r--r--lib/stdlib/doc/src/maps.xml80
-rw-r--r--lib/stdlib/doc/src/math.xml52
-rw-r--r--lib/stdlib/doc/src/ms_transform.xml8
-rw-r--r--lib/stdlib/doc/src/notes.xml261
-rw-r--r--lib/stdlib/doc/src/orddict.xml44
-rw-r--r--lib/stdlib/doc/src/ordsets.xml38
-rw-r--r--lib/stdlib/doc/src/pool.xml18
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml58
-rw-r--r--lib/stdlib/doc/src/proplists.xml45
-rw-r--r--lib/stdlib/doc/src/qlc.xml54
-rw-r--r--lib/stdlib/doc/src/queue.xml62
-rw-r--r--lib/stdlib/doc/src/rand.xml38
-rw-r--r--lib/stdlib/doc/src/random.xml18
-rw-r--r--lib/stdlib/doc/src/re.xml22
-rw-r--r--lib/stdlib/doc/src/sets.xml38
-rw-r--r--lib/stdlib/doc/src/shell.xml16
-rw-r--r--lib/stdlib/doc/src/slave.xml22
-rw-r--r--lib/stdlib/doc/src/sofs.xml168
-rw-r--r--lib/stdlib/doc/src/string.xml142
-rw-r--r--lib/stdlib/doc/src/supervisor.xml38
-rw-r--r--lib/stdlib/doc/src/supervisor_bridge.xml10
-rw-r--r--lib/stdlib/doc/src/sys.xml78
-rw-r--r--lib/stdlib/doc/src/timer.xml44
-rw-r--r--lib/stdlib/doc/src/unicode.xml32
-rw-r--r--lib/stdlib/doc/src/uri_string.xml18
-rw-r--r--lib/stdlib/doc/src/win32reg.xml28
-rw-r--r--lib/stdlib/doc/src/zip.xml44
-rw-r--r--lib/stdlib/src/beam_lib.erl25
-rw-r--r--lib/stdlib/src/calendar.erl103
-rw-r--r--lib/stdlib/src/dets.erl23
-rw-r--r--lib/stdlib/src/epp.erl13
-rw-r--r--lib/stdlib/src/erl_eval.erl15
-rw-r--r--lib/stdlib/src/erl_internal.erl2
-rw-r--r--lib/stdlib/src/erl_lint.erl3
-rw-r--r--lib/stdlib/src/erl_parse.yrl9
-rw-r--r--lib/stdlib/src/erl_pp.erl6
-rw-r--r--lib/stdlib/src/erl_tar.erl4
-rw-r--r--lib/stdlib/src/filename.erl31
-rw-r--r--lib/stdlib/src/gen_statem.erl230
-rw-r--r--lib/stdlib/src/io_lib.erl67
-rw-r--r--lib/stdlib/src/io_lib_format.erl38
-rw-r--r--lib/stdlib/src/io_lib_pretty.erl66
-rw-r--r--lib/stdlib/src/ms_transform.erl11
-rw-r--r--lib/stdlib/src/proc_lib.erl175
-rw-r--r--lib/stdlib/src/stdlib.appup.src53
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl34
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl15
-rw-r--r--lib/stdlib/test/calendar_SUITE.erl84
-rw-r--r--lib/stdlib/test/dets_SUITE.erl15
-rw-r--r--lib/stdlib/test/epp_SUITE.erl16
-rw-r--r--lib/stdlib/test/epp_SUITE_data/source_name.erl27
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl20
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl11
-rw-r--r--lib/stdlib/test/ets_SUITE.erl124
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl2
-rw-r--r--lib/stdlib/test/io_SUITE.erl59
-rw-r--r--lib/stdlib/test/lists_SUITE.erl49
-rw-r--r--lib/stdlib/test/rand_SUITE.erl3
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput216
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput58
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl7
-rw-r--r--lib/stdlib/test/sys_SUITE.erl17
-rw-r--r--lib/stdlib/test/unicode_util_SUITE.erl27
-rwxr-xr-xlib/stdlib/uc_spec/gen_unicode_mod.escript2
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/src/Makefile1
-rw-r--r--lib/syntax_tools/doc/src/notes.xml71
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl5
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl58
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl2
-rw-r--r--lib/syntax_tools/test/merl_SUITE.erl14
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE.erl116
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE_data/specs_and_funs.erl18
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/tftp/doc/src/Makefile1
-rw-r--r--lib/tftp/doc/src/notes.xml17
-rw-r--r--lib/tftp/doc/src/tftp.xml42
-rw-r--r--lib/tftp/src/tftp.app.src2
-rw-r--r--lib/tftp/vsn.mk2
-rw-r--r--lib/tools/c_src/Makefile.in7
-rw-r--r--lib/tools/doc/src/Makefile1
-rw-r--r--lib/tools/doc/src/cover.xml84
-rw-r--r--lib/tools/doc/src/cprof.xml42
-rw-r--r--lib/tools/doc/src/eprof.xml38
-rw-r--r--lib/tools/doc/src/fprof.xml50
-rw-r--r--lib/tools/doc/src/instrument.xml10
-rw-r--r--lib/tools/doc/src/lcnt.xml68
-rw-r--r--lib/tools/doc/src/make.xml10
-rw-r--r--lib/tools/doc/src/notes.xml91
-rw-r--r--lib/tools/doc/src/tags.xml16
-rw-r--r--lib/tools/doc/src/xref.xml64
-rw-r--r--lib/tools/emacs/Makefile1
-rw-r--r--lib/tools/emacs/erlang-edoc.el1
-rw-r--r--lib/tools/emacs/erlang-eunit.el10
-rw-r--r--lib/tools/emacs/erlang-pkg.el3
-rw-r--r--lib/tools/emacs/erlang-skels.el2
-rw-r--r--lib/tools/emacs/erlang-test.el77
-rw-r--r--lib/tools/emacs/erlang.el72
-rw-r--r--lib/tools/emacs/erlang_appwiz.el13
-rw-r--r--lib/tools/priv/styles.css96
-rw-r--r--lib/tools/src/Makefile7
-rw-r--r--lib/tools/src/cover.erl157
-rw-r--r--lib/tools/src/eprof.erl52
-rw-r--r--lib/tools/test/cover_SUITE.erl29
-rw-r--r--lib/tools/test/emacs_SUITE.erl175
-rw-r--r--lib/tools/test/xref_SUITE.erl8
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/wx/api_gen/wx_extra/added_func.h6
-rw-r--r--lib/wx/api_gen/wx_gen.erl9
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl17
-rw-r--r--lib/wx/api_gen/wxapi.conf36
-rw-r--r--lib/wx/c_src/Makefile.in1
-rw-r--r--lib/wx/c_src/gen/wxe_derived_dest.h10
-rw-r--r--lib/wx/c_src/gen/wxe_events.cpp4
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp125
-rw-r--r--lib/wx/c_src/gen/wxe_init.cpp66
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h20
-rw-r--r--lib/wx/c_src/wxe_driver.c165
-rw-r--r--lib/wx/c_src/wxe_driver.h4
-rw-r--r--lib/wx/c_src/wxe_helpers.cpp3
-rw-r--r--lib/wx/c_src/wxe_helpers.h2
-rw-r--r--lib/wx/c_src/wxe_impl.cpp24
-rw-r--r--lib/wx/c_src/wxe_impl.h2
-rw-r--r--lib/wx/c_src/wxe_main.cpp15
-rw-r--r--lib/wx/c_src/wxe_ps_init.c14
-rw-r--r--lib/wx/doc/src/Makefile3
-rw-r--r--lib/wx/doc/src/notes.xml50
-rw-r--r--lib/wx/include/wx.hrl16
-rw-r--r--lib/wx/src/gen/wxDisplay.erl131
-rw-r--r--lib/wx/src/gen/wxGCDC.erl287
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl18
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl18
-rwxr-xr-xlib/wx/test/wxt6
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--lib/xmerl/doc/src/Makefile1
-rw-r--r--lib/xmerl/doc/src/notes.xml85
-rw-r--r--lib/xmerl/doc/src/xmerl_sax_parser.xml10
-rw-r--r--lib/xmerl/src/xmerl_sax_parser.erl144
-rw-r--r--lib/xmerl/src/xmerl_scan.erl19
-rw-r--r--lib/xmerl/vsn.mk2
953 files changed, 80442 insertions, 22252 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 0053238826..cdb3f3f3dc 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,7 +58,7 @@ else
SUB_DIRECTORIES = hipe parsetools asn1/src
else
ifdef TERTIARY_BOOTSTRAP
- SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools wx
+ SUB_DIRECTORIES = snmp sasl jinterface syntax_tools wx
else
ifdef DOC_BOOTSTRAP
SUB_DIRECTORIES = xmerl edoc erl_docgen
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index d5aaadb89b..da43af3405 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -949,6 +949,12 @@ static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *
unsigned char *tmp_out_buff;
ERL_NIF_TERM term = 0, curr_head = 0;
+ /* Recursion depth limitation, borrow a signed int: maybe_ret */
+ maybe_ret = (int) (ErlNifSInt) ((char *)value - (char *)ib_index);
+ maybe_ret = maybe_ret < 0 ? -maybe_ret : maybe_ret;
+ if (maybe_ret >= sizeof(void *) * 8192) /* 8 k pointer words */
+ return ASN1_ERROR;
+
if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
len = in_buf[*ib_index];
} else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH) {
@@ -993,7 +999,7 @@ static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *
while (*ib_index < end_index) {
if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index,
- in_buf_len)) <= ASN1_ERROR
+ end_index )) <= ASN1_ERROR
)
return maybe_ret;
curr_head = enif_make_list_cell(env, term, curr_head);
diff --git a/lib/asn1/doc/src/Makefile b/lib/asn1/doc/src/Makefile
index f200c4aae2..9c0d865884 100644
--- a/lib/asn1/doc/src/Makefile
+++ b/lib/asn1/doc/src/Makefile
@@ -107,6 +107,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(GEN_XML) errs core *~
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index ccf07a9cc1..e86dbd9f5e 100644
--- a/lib/asn1/doc/src/asn1ct.xml
+++ b/lib/asn1/doc/src/asn1ct.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>asn1.sgml</file>
</header>
- <module>asn1ct</module>
+ <module since="">asn1ct</module>
<modulesummary>ASN.1 compiler and compile-time support functions</modulesummary>
<description>
<p>The ASN.1 compiler takes an ASN.1 module as input and generates a
@@ -72,8 +72,8 @@
<funcs>
<func>
- <name>compile(Asn1module) -> ok | {error, Reason}</name>
- <name>compile(Asn1module, Options) -> ok | {error, Reason}</name>
+ <name since="">compile(Asn1module) -> ok | {error, Reason}</name>
+ <name since="">compile(Asn1module, Options) -> ok | {error, Reason}</name>
<fsummary>Compiles an ASN.1 module and generates encode/decode functions according to encoding rules BER or PER.</fsummary>
<type>
<v>Asn1module = atom() | string()</v>
@@ -336,7 +336,7 @@ File3.asn</pre>
</func>
<func>
- <name>value(Module, Type) -> {ok, Value} | {error, Reason}</name>
+ <name since="">value(Module, Type) -> {ok, Value} | {error, Reason}</name>
<fsummary>Creates an ASN.1 value for test purposes.</fsummary>
<type>
<v>Module = Type = atom()</v>
@@ -361,9 +361,9 @@ File3.asn</pre>
</func>
<func>
- <name>test(Module) -> ok | {error, Reason}</name>
- <name>test(Module, Type | Options) -> ok | {error, Reason}</name>
- <name>test(Module, Type, Value | Options) -> ok | {error, Reason}</name>
+ <name since="">test(Module) -> ok | {error, Reason}</name>
+ <name since="">test(Module, Type | Options) -> ok | {error, Reason}</name>
+ <name since="">test(Module, Type, Value | Options) -> ok | {error, Reason}</name>
<fsummary>Performs a test of encode and decode for types in an ASN.1 module.</fsummary>
<type>
<v>Module = Type = atom()</v>
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 860cf4d22d..22ca7840de 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -32,6 +32,44 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 5.0.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Handle erroneous length during decode (BER only) without
+ crashing.</p>
+ <p>
+ Own Id: OTP-15470 Aux Id: ERIERL-278 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>A bug in ASN.1 BER decoding has been fixed. When
+ decoding a recursively enclosed term the length was not
+ propagated to that term decoding, so if the length of the
+ enclosed term was longer than the enclosing that error
+ was not detected.</p> <p>A hard coded C stack limitation
+ for decoding recursive ASN.1 terms has been introduced.
+ This is currently set to 8 kWords giving a nesting depth
+ of about 1000 levels. Deeper terms can not be decoded,
+ which should not be much of a real world limitation.</p>
+ <p>
+ Own Id: OTP-14440 Aux Id: ERIERL-220 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 5.0.6</title>
<section><title>Improvements and New Features</title>
@@ -47,6 +85,44 @@
</section>
+<section><title>Asn1 5.0.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Handle erroneous length during decode (BER only) without
+ crashing.</p>
+ <p>
+ Own Id: OTP-15470 Aux Id: ERIERL-278 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.5.1</title>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>A bug in ASN.1 BER decoding has been fixed. When
+ decoding a recursively enclosed term the length was not
+ propagated to that term decoding, so if the length of the
+ enclosed term was longer than the enclosing that error
+ was not dectected</p> <p>A hard coded C stack limitation
+ for decoding recursive ASN.1 terms has been introduced.
+ This is currently set to 8 kWords giving a nesting depth
+ of about 1000 levels. Deeper terms can not be decoded,
+ which should not be much of a real world limitation.</p>
+ <p>
+ Own Id: OTP-14440 Aux Id: ERIERL-220 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 5.0.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1936,4 +2012,3 @@
<!-- p>There are also release notes for <url href="notes_history.html">older versions</url>.</p -->
</section>
</chapter>
-
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 7b669c1c2c..ab78678110 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -63,7 +63,8 @@ groups() ->
constraint_equivalence]},
{ber, Parallel,
- [ber_choiceinseq,
+ [ber_decode_invalid_length,
+ ber_choiceinseq,
% Uses 'SOpttest'
ber_optional,
tagdefault_automatic]},
@@ -132,7 +133,8 @@ groups() ->
testSeq2738,
% Uses 'Constructed'
{group, [], [constructed,
- ber_decode_error]},
+ ber_decode_error,
+ otp_14440]},
testSeqSetIndefinite,
testChoiceIndefinite,
per_open_type,
@@ -664,6 +666,19 @@ module_test(M0, Config, Rule, Opts) ->
end
end.
+ber_decode_invalid_length(_Config) ->
+ Bin = <<48,129,157,48,0,2,1,2,164,0,48,129,154,49,24,48,22,6,
+ 3,85,4,10,19,15,69,120,97,109,112,108,101,32,67,111,
+ 109,112,97,110,121,49,29,48,27,6,9,42,134,72,134,247,
+ 13,1,9,1,22,14,99,97,64,101,120,97,109,112,108,101,46,
+ 99,111,109,49,13,48,11,6,3,85,4,7,19,4,79,117,108,117,
+ 49,26,48,24,6,3,85,4,8,19,17,80,111,104,106,111,105,
+ 115,45,80,111,104,106,97,110,109,97,97,49,11,48,9,6,3,
+ 85,4,6,19,2,70,73,49,19,48,17,6,3,85,4,3,19,10,69,120,
+ 97,109,112,108,101,32,67,65,49,11,48,16,6,3,85,4,11,
+ 19,9,84,101>>,
+ {'EXIT',{error,{asn1,{invalid_value,12}}}} = (catch asn1rt_nif:decode_ber_tlv(Bin)),
+ ok.
ber_choiceinseq(Config) ->
test(Config, fun ber_choiceinseq/3, [ber]).
@@ -736,6 +751,36 @@ ber_decode_error(Config, Rule, Opts) ->
asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
ber_decode_error:run(Opts).
+otp_14440(_Config) ->
+ Args = " -pa \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
+ {ok,N} = slave:start(hostname(), otp_14440, Args),
+ Result = rpc:call(N, ?MODULE, otp_14440_decode, []),
+ io:format("Decode result = ~p~n", [Result]),
+ case Result of
+ {exit,{error,{asn1,{invalid_value,5}}}} ->
+ ok = slave:stop(N);
+ %% We get this if stack depth limit kicks in:
+ {exit,{error,{asn1,{unknown,_}}}} ->
+ ok = slave:stop(N);
+ _ ->
+ _ = slave:stop(N),
+ ?t:fail(Result)
+ end.
+%%
+otp_14440_decode() ->
+ Data =
+ iolist_to_binary(
+ lists:duplicate(
+ 32, list_to_binary(lists:duplicate(1024, 16#7f)))),
+ try asn1rt_nif:decode_ber_tlv(Data) of
+ Result ->
+ {unexpected_return,Result}
+ catch
+ Class:Reason ->
+ {Class,Reason}
+ end.
+
+
h323test(Config) -> test(Config, fun h323test/3).
h323test(Config, Rule, Opts) ->
Files = ["H235-SECURITY-MESSAGES", "H323-MESSAGES",
@@ -1350,7 +1395,7 @@ xref_export_all(_Config) ->
{ok,_} = xref:q(S, Def),
{ok,Unused} = xref:q(S, "X - Called - range (closure E | Called)"),
xref:stop(S),
- case Unused of
+ case Unused -- [{?MODULE,otp_14440_decode,0}] of
[] ->
ok;
[_|_] ->
@@ -1385,3 +1430,11 @@ all_called_1([F|T]) when is_atom(F) ->
L ++ all_called_1(T);
all_called_1([]) ->
[].
+
+hostname() ->
+ hostname(atom_to_list(node())).
+
+hostname([$@ | Hostname]) ->
+ list_to_atom(Hostname);
+hostname([_C | Cs]) ->
+ hostname(Cs).
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 30cbca3773..69f1af28e8 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1 +1 @@
-ASN1_VSN = 5.0.6
+ASN1_VSN = 5.0.8
diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile
index 293ef591cb..b5acdc6f95 100644
--- a/lib/common_test/doc/src/Makefile
+++ b/lib/common_test/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2017. All Rights Reserved.
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -140,6 +140,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml
index a3b3f927eb..081adeaec7 100644
--- a/lib/common_test/doc/src/common_test_app.xml
+++ b/lib/common_test/doc/src/common_test_app.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>common_test_app.sgml</file>
</header>
- <module>common_test</module>
+ <module since="">common_test</module>
<modulesummary>A framework for automated testing of any target nodes.</modulesummary>
<description>
@@ -68,18 +68,19 @@
<funcs>
<func>
- <name>Module:all() -> Tests | {skip,Reason} </name>
+ <name since="">Module:all() -> Tests | {skip,Reason} </name>
<fsummary>Returns the list of all test case groups and test cases
in the module.</fsummary>
<type>
- <v>Tests = [TestCase | {group,GroupName} | {group,GroupName,Properties} | {group,GroupName,Properties,SubGroups}]</v>
+ <v>Tests = [TestCase | {testcase,TestCase,TCRepeatProps} | {group,GroupName} | {group,GroupName,Properties} | {group,GroupName,Properties,SubGroups}]</v>
<v>TestCase = atom()</v>
+ <v>TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {repeat_until_fail,N}]</v>
<v>GroupName = atom()</v>
- <v>Properties = [parallel | sequence | Shuffle | {RepeatType,N}] | default</v>
+ <v>Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}] | default</v>
<v>SubGroups = [{GroupName,Properties} | {GroupName,Properties,SubGroups}]</v>
<v>Shuffle = shuffle | {shuffle,Seed}</v>
<v>Seed = {integer(),integer(),integer()}</v>
- <v>RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | repeat_until_any_ok | repeat_until_any_fail</v>
+ <v>GroupRepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | repeat_until_any_ok | repeat_until_any_fail</v>
<v>N = integer() | forever</v>
<v>Reason = term()</v>
</type>
@@ -91,7 +92,8 @@
test suite module to be executed. This list also specifies the
order the cases and groups are executed by <c>Common Test</c>.
A test case is represented by an atom,
- the name of the test case function. A test case group is
+ the name of the test case function, or a <c>testcase</c> tuple
+ indicating that the test case shall be repeated. A test case group is
represented by a <c>group</c> tuple, where <c>GroupName</c>,
an atom, is the name of the group (defined in
<seealso marker="#Module:groups-0"><c>groups/0</c></seealso>).
@@ -115,18 +117,19 @@
</func>
<func>
- <name>Module:groups() -> GroupDefs</name>
+ <name since="">Module:groups() -> GroupDefs</name>
<fsummary>Returns a list of test case group definitions.</fsummary>
<type>
<v>GroupDefs = [Group]</v>
<v>Group = {GroupName,Properties,GroupsAndTestCases}</v>
<v>GroupName = atom()</v>
- <v>Properties = [parallel | sequence | Shuffle | {RepeatType,N}]</v>
- <v>GroupsAndTestCases = [Group | {group,GroupName} | TestCase]</v>
+ <v>Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]</v>
+ <v>GroupsAndTestCases = [Group | {group,GroupName} | TestCase | {testcase,TestCase,TCRepeatProps}]</v>
<v>TestCase = atom()</v>
+ <v>TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {repeat_until_fail,N}]</v>
<v>Shuffle = shuffle | {shuffle,Seed}</v>
<v>Seed = {integer(),integer(),integer()}</v>
- <v>RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | repeat_until_any_ok | repeat_until_any_fail</v>
+ <v>GroupRepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | repeat_until_any_ok | repeat_until_any_fail</v>
<v>N = integer() | forever</v>
</type>
@@ -140,7 +143,7 @@
</func>
<func>
- <name>Module:suite() -> [Info] </name>
+ <name since="">Module:suite() -> [Info] </name>
<fsummary>Test suite info function (providing default data
for the suite).</fsummary>
<type>
@@ -213,7 +216,7 @@
</func>
<func>
- <name>Module:init_per_suite(Config) -> NewConfig | {skip,Reason} |
+ <name since="">Module:init_per_suite(Config) -> NewConfig | {skip,Reason} |
{skip_and_save,Reason,SaveConfig}</name>
<fsummary>Test suite initializations.</fsummary>
<type>
@@ -248,7 +251,7 @@
</func>
<func>
- <name>Module:end_per_suite(Config) -> term() |
+ <name since="">Module:end_per_suite(Config) -> term() |
{save_config,SaveConfig}</name>
<fsummary>Test suite finalization.</fsummary>
<type>
@@ -272,7 +275,7 @@
</func>
<func>
- <name>Module:group(GroupName) -> [Info] </name>
+ <name since="OTP R15B">Module:group(GroupName) -> [Info] </name>
<fsummary>Test case group information function (providing default data
for a test case group, that is, its test cases and
subgroups).</fsummary>
@@ -352,7 +355,7 @@
</func>
<func>
- <name>Module:init_per_group(GroupName, Config) -> NewConfig |
+ <name since="">Module:init_per_group(GroupName, Config) -> NewConfig |
{skip,Reason}</name>
<fsummary>Test case group initializations.</fsummary>
<type>
@@ -390,7 +393,7 @@
</func>
<func>
- <name>Module:end_per_group(GroupName, Config) -> term() |
+ <name since="">Module:end_per_group(GroupName, Config) -> term() |
{return_group_result,Status}</name>
<fsummary>Test case group finalization.</fsummary>
<type>
@@ -424,7 +427,7 @@
</func>
<func>
- <name>Module:init_per_testcase(TestCase, Config) -> NewConfig | {fail,Reason} | {skip,Reason}</name>
+ <name since="">Module:init_per_testcase(TestCase, Config) -> NewConfig | {fail,Reason} | {skip,Reason}</name>
<fsummary>Test case initializations.</fsummary>
<type>
<v> TestCase = atom()</v>
@@ -454,7 +457,7 @@
</func>
<func>
- <name>Module:end_per_testcase(TestCase, Config) -> term() | {fail,Reason} | {save_config,SaveConfig}</name>
+ <name since="">Module:end_per_testcase(TestCase, Config) -> term() | {fail,Reason} | {save_config,SaveConfig}</name>
<fsummary>Test case finalization.</fsummary>
<type>
<v>TestCase = atom()</v>
@@ -486,7 +489,7 @@
</func>
<func>
- <name>Module:Testcase() -> [Info] </name>
+ <name since="OTP R14B">Module:Testcase() -> [Info] </name>
<fsummary>Test case information function.</fsummary>
<type>
<v>Info = {timetrap,Time} | {require,Required} | {require,Name,Required} | {userdata,UserData} | {silent_connections,Conns}</v>
@@ -560,7 +563,7 @@
</func>
<func>
- <name>Module:Testcase(Config) -> term() | {skip,Reason} | {comment,Comment} | {save_config,SaveConfig} | {skip_and_save,Reason,SaveConfig} | exit() </name>
+ <name since="OTP R14B">Module:Testcase(Config) -> term() | {skip,Reason} | {comment,Comment} | {save_config,SaveConfig} | {skip_and_save,Reason,SaveConfig} | exit() </name>
<fsummary>A test case.</fsummary>
<type>
<v>Config = SaveConfig = [{Key,Value}]</v>
diff --git a/lib/common_test/doc/src/ct.xml b/lib/common_test/doc/src/ct.xml
index b51dee266b..83c0ecb309 100644
--- a/lib/common_test/doc/src/ct.xml
+++ b/lib/common_test/doc/src/ct.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct.xml</file>
</header>
- <module>ct</module>
+ <module since="">ct</module>
<modulesummary>Main user interface for the Common Test framework.</modulesummary>
<description>
@@ -139,7 +139,7 @@
<funcs>
<func>
- <name>abort_current_testcase(Reason) -&gt; ok | {error, ErrorReason}</name>
+ <name since="">abort_current_testcase(Reason) -&gt; ok | {error, ErrorReason}</name>
<fsummary>Aborts the currently executing test case.</fsummary>
<type>
<v>Reason = term()</v>
@@ -157,7 +157,7 @@
</func>
<func>
- <name>add_config(Callback, Config) -&gt; ok | {error, Reason}</name>
+ <name since="OTP R14B">add_config(Callback, Config) -&gt; ok | {error, Reason}</name>
<fsummary>Loads configuration variables using the specified callback
module and configuration string.</fsummary>
<type>
@@ -176,7 +176,7 @@
</func>
<func>
- <name>break(Comment) -&gt; ok | {error, Reason}</name>
+ <name since="OTP R15B02">break(Comment) -&gt; ok | {error, Reason}</name>
<fsummary>Cancels any active timetrap and pause the execution of the
current test case until the user calls function continue/0.</fsummary>
<type>
@@ -206,7 +206,7 @@
</func>
<func>
- <name>break(TestCase, Comment) -&gt; ok | {error, Reason}</name>
+ <name since="OTP R15B02">break(TestCase, Comment) -&gt; ok | {error, Reason}</name>
<fsummary>Works the same way as break/1, only argument TestCase makes it
possible to pause a test case executing in a parallel group.</fsummary>
<type>
@@ -228,7 +228,7 @@
</func>
<func>
- <name>capture_get() -&gt; ListOfStrings</name>
+ <name since="OTP R15B">capture_get() -&gt; ListOfStrings</name>
<fsummary>Equivalent to capture_get([default]).</fsummary>
<type>
<v>ListOfStrings = [string()]</v>
@@ -240,7 +240,7 @@
</func>
<func>
- <name>capture_get(ExclCategories) -&gt; ListOfStrings</name>
+ <name since="OTP R15B">capture_get(ExclCategories) -&gt; ListOfStrings</name>
<fsummary>Returns and purges the list of text strings buffered during
the latest session of capturing printouts to stdout.</fsummary>
<type>
@@ -262,7 +262,7 @@
</func>
<func>
- <name>capture_start() -&gt; ok</name>
+ <name since="OTP R15B">capture_start() -&gt; ok</name>
<fsummary>Starts capturing all text strings printed to stdout
during execution of the test case.</fsummary>
<desc><marker id="capture_start-0"/>
@@ -276,7 +276,7 @@
</func>
<func>
- <name>capture_stop() -&gt; ok</name>
+ <name since="OTP R15B">capture_stop() -&gt; ok</name>
<fsummary>Stops capturing text strings (a session started with
capture_start/0).</fsummary>
<desc><marker id="capture_stop-0"/>
@@ -290,7 +290,7 @@
</func>
<func>
- <name>comment(Comment) -&gt; ok</name>
+ <name since="">comment(Comment) -&gt; ok</name>
<fsummary>Prints the specified Comment in the comment field in the
table on the test suite result page.</fsummary>
<type>
@@ -307,7 +307,7 @@
</func>
<func>
- <name>comment(Format, Args) -&gt; ok</name>
+ <name since="OTP R15B">comment(Format, Args) -&gt; ok</name>
<fsummary>Prints the formatted string in the comment field in the
table on the test suite result page.</fsummary>
<type>
@@ -326,7 +326,7 @@
</func>
<func>
- <name>continue() -&gt; ok</name>
+ <name since="OTP R15B02">continue() -&gt; ok</name>
<fsummary>This function must be called to continue after a test
case (not executing in a parallel group) has called break/1.</fsummary>
<desc><marker id="continue-0"/>
@@ -337,7 +337,7 @@
</func>
<func>
- <name>continue(TestCase) -&gt; ok</name>
+ <name since="OTP R15B02">continue(TestCase) -&gt; ok</name>
<fsummary>This function must be called to continue after a test case
has called break/2.</fsummary>
<type>
@@ -353,7 +353,7 @@
</func>
<func>
- <name>decrypt_config_file(EncryptFileName, TargetFileName) -&gt; ok | {error, Reason}</name>
+ <name since="">decrypt_config_file(EncryptFileName, TargetFileName) -&gt; ok | {error, Reason}</name>
<fsummary>Decrypts EncryptFileName, previously generated with
encrypt_config_file/2,3.</fsummary>
<type>
@@ -372,7 +372,7 @@
</func>
<func>
- <name>decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile) -&gt; ok | {error, Reason}</name>
+ <name since="">decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile) -&gt; ok | {error, Reason}</name>
<fsummary>Decrypts EncryptFileName, previously generated with
encrypt_config_file/2,3.</fsummary>
<type>
@@ -390,7 +390,7 @@
</func>
<func>
- <name>encrypt_config_file(SrcFileName, EncryptFileName) -&gt; ok | {error, Reason}</name>
+ <name since="">encrypt_config_file(SrcFileName, EncryptFileName) -&gt; ok | {error, Reason}</name>
<fsummary>Encrypts the source configuration file with DES3 and saves the
result in file EncryptFileName.</fsummary>
<type>
@@ -416,7 +416,7 @@
</func>
<func>
- <name>encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile) -&gt; ok | {error, Reason}</name>
+ <name since="">encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile) -&gt; ok | {error, Reason}</name>
<fsummary>Encrypts the source configuration file with DES3 and saves the
result in the target file EncryptFileName.</fsummary>
<type>
@@ -442,7 +442,7 @@
</func>
<func>
- <name>fail(Reason) -&gt; ok</name>
+ <name since="">fail(Reason) -&gt; ok</name>
<fsummary>Terminates a test case with the specified error
Reason.</fsummary>
<type>
@@ -454,7 +454,7 @@
</func>
<func>
- <name>fail(Format, Args) -&gt; ok</name>
+ <name since="OTP R15B">fail(Format, Args) -&gt; ok</name>
<fsummary>Terminates a test case with an error message specified by
a format string and a list of values (used as arguments to
io_lib:format/2).</fsummary>
@@ -470,7 +470,7 @@
</func>
<func>
- <name>get_config(Required) -&gt; Value</name>
+ <name since="">get_config(Required) -&gt; Value</name>
<fsummary>Equivalent to get_config(Required, undefined, []).</fsummary>
<desc><marker id="get_config-1"/>
<p>Equivalent to <seealso marker="#get_config-3"><c>ct:get_config(Required,
@@ -479,7 +479,7 @@
</func>
<func>
- <name>get_config(Required, Default) -&gt; Value</name>
+ <name since="">get_config(Required, Default) -&gt; Value</name>
<fsummary>Equivalent to get_config(Required, Default, []).</fsummary>
<desc><marker id="get_config-2"/>
<p>Equivalent to <seealso marker="#get_config-3"><c>ct:get_config(Required,
@@ -488,7 +488,7 @@
</func>
<func>
- <name>get_config(Required, Default, Opts) -&gt; ValueOrElement</name>
+ <name since="">get_config(Required, Default, Opts) -&gt; ValueOrElement</name>
<fsummary>Reads configuration data values.</fsummary>
<type>
<v>Required = KeyOrName | {KeyOrName, SubKey} | {KeyOrName, SubKey, SubKey}</v>
@@ -554,7 +554,7 @@
</func>
<func>
- <name>get_event_mgr_ref() -&gt; EvMgrRef</name>
+ <name since="OTP 17.5">get_event_mgr_ref() -&gt; EvMgrRef</name>
<fsummary>Gets a reference to the <c>Common Test</c> event manager.</fsummary>
<type>
<v>EvMgrRef = atom()</v>
@@ -572,7 +572,7 @@
</func>
<func>
- <name>get_progname() -&gt; string()</name>
+ <name since="OTP 21.0">get_progname() -&gt; string()</name>
<fsummary>Returns the command used to start this Erlang instance.</fsummary>
<desc><marker id="get_progname-0"/>
<p>Returns the command used to start this Erlang instance.
@@ -582,7 +582,7 @@
</func>
<func>
- <name>get_status() -&gt; TestStatus | {error, Reason} | no_tests_running</name>
+ <name since="">get_status() -&gt; TestStatus | {error, Reason} | no_tests_running</name>
<fsummary>Returns status of ongoing test.</fsummary>
<type>
<v>TestStatus = [StatusElem]</v>
@@ -608,7 +608,7 @@
</func>
<func>
- <name>get_target_name(Handle) -&gt; {ok, TargetName} | {error, Reason}</name>
+ <name since="">get_target_name(Handle) -&gt; {ok, TargetName} | {error, Reason}</name>
<fsummary>Returns the name of the target that the specified connection
belongs to.</fsummary>
<type>
@@ -622,7 +622,7 @@
</func>
<func>
- <name>get_testspec_terms() -&gt; TestSpecTerms | undefined</name>
+ <name since="OTP 18.0">get_testspec_terms() -&gt; TestSpecTerms | undefined</name>
<fsummary>Gets a list of all test specification terms used to
configure and run this test.</fsummary>
<type>
@@ -636,7 +636,7 @@
</func>
<func>
- <name>get_testspec_terms(Tags) -&gt; TestSpecTerms | undefined</name>
+ <name since="OTP 18.0">get_testspec_terms(Tags) -&gt; TestSpecTerms | undefined</name>
<fsummary>Reads one or more terms from the test specification used to
configure and run this test.</fsummary>
<type>
@@ -663,7 +663,7 @@
</func>
<func>
- <name>get_timetrap_info() -&gt; {Time, {Scaling,ScaleVal}}</name>
+ <name since="OTP R15B">get_timetrap_info() -&gt; {Time, {Scaling,ScaleVal}}</name>
<fsummary>Reads information about the timetrap set for the current
test case.</fsummary>
<type>
@@ -682,7 +682,7 @@
</func>
<func>
- <name>get_verbosity(Category) -&gt; Level | undefined</name>
+ <name since="OTP 19.1">get_verbosity(Category) -&gt; Level | undefined</name>
<fsummary>Read the verbosity level for a logging category.</fsummary>
<type>
<v>Category = default | atom()</v>
@@ -697,7 +697,7 @@
</func>
<func>
- <name>install(Opts) -&gt; ok | {error, Reason}</name>
+ <name since="">install(Opts) -&gt; ok | {error, Reason}</name>
<fsummary>Installs configuration files and event handlers.</fsummary>
<type>
<v>Opts = [Opt]</v>
@@ -724,7 +724,7 @@
</func>
<func>
- <name>listenv(Telnet) -&gt; [Env]</name>
+ <name since="">listenv(Telnet) -&gt; [Env]</name>
<fsummary>Performs command listenv on the specified Telnet connection
and returns the result as a list of key-value pairs.</fsummary>
<type>
@@ -740,7 +740,7 @@
</func>
<func>
- <name>log(Format) -&gt; ok</name>
+ <name since="">log(Format) -&gt; ok</name>
<fsummary>Equivalent to log(default, 50, Format, [], []).</fsummary>
<desc><marker id="log-1"/>
<p>Equivalent to
@@ -749,7 +749,7 @@
</func>
<func>
- <name>log(X1, X2) -&gt; ok</name>
+ <name since="">log(X1, X2) -&gt; ok</name>
<fsummary>Equivalent to log(Category, Importance, Format,
FormatArgs, []).</fsummary>
<type>
@@ -763,7 +763,7 @@
</func>
<func>
- <name>log(X1, X2, X3) -&gt; ok</name>
+ <name since="">log(X1, X2, X3) -&gt; ok</name>
<fsummary>Equivalent to log(Category, Importance, Format,
FormatArgs, Opts).</fsummary>
<type>
@@ -778,7 +778,7 @@
</func>
<func>
- <name>log(X1, X2, X3, X4) -&gt; ok</name>
+ <name since="OTP R15B02">log(X1, X2, X3, X4) -&gt; ok</name>
<fsummary>Equivalent to log(Category, Importance, Format,
FormatArgs, Opts).</fsummary>
<type>
@@ -794,7 +794,7 @@
</func>
<func>
- <name>log(Category, Importance, Format, FormatArgs, Opts) -&gt; ok</name>
+ <name since="OTP 18.3">log(Category, Importance, Format, FormatArgs, Opts) -&gt; ok</name>
<fsummary>Prints from a test case to the log file.</fsummary>
<type>
<v>Category = atom()</v>
@@ -825,7 +825,7 @@
</func>
<func>
- <name>make_priv_dir() -&gt; ok | {error, Reason}</name>
+ <name since="OTP R15B01">make_priv_dir() -&gt; ok | {error, Reason}</name>
<fsummary>If the test has been started with option create_priv_dir
set to manual_per_tc, in order for the test case to use the private
directory, it must first create it by calling this function.</fsummary>
@@ -841,7 +841,7 @@
</func>
<func>
- <name>notify(Name, Data) -&gt; ok</name>
+ <name since="OTP R15B02">notify(Name, Data) -&gt; ok</name>
<fsummary>Sends an asynchronous notification of type Name with Data
to the <c>Common Test</c> event manager.</fsummary>
<type>
@@ -859,7 +859,7 @@
</func>
<func>
- <name>pal(Format) -&gt; ok</name>
+ <name since="">pal(Format) -&gt; ok</name>
<fsummary>Equivalent to pal(default, 50, Format, [], []).</fsummary>
<desc><marker id="pal-1"/>
<p>Equivalent to
@@ -869,7 +869,7 @@
</func>
<func>
- <name>pal(X1, X2) -&gt; ok</name>
+ <name since="">pal(X1, X2) -&gt; ok</name>
<fsummary>Equivalent to pal(Category, Importance, Format,
FormatArgs, []).</fsummary>
<type>
@@ -883,7 +883,7 @@
</func>
<func>
- <name>pal(X1, X2, X3) -&gt; ok</name>
+ <name since="">pal(X1, X2, X3) -&gt; ok</name>
<fsummary>Equivalent to pal(Category, Importance, Format,
FormatArgs, Opts).</fsummary>
<type>
@@ -898,7 +898,7 @@
</func>
<func>
- <name>pal(X1, X2, X3, X4) -&gt; ok</name>
+ <name since="OTP R15B02">pal(X1, X2, X3, X4) -&gt; ok</name>
<fsummary>Equivalent to pal(Category, Importance, Format,
FormatArgs, Opts).</fsummary>
<type>
@@ -914,7 +914,7 @@
</func>
<func>
- <name>pal(Category, Importance, Format, FormatArgs, Opts) -&gt; ok</name>
+ <name since="OTP 19.2">pal(Category, Importance, Format, FormatArgs, Opts) -&gt; ok</name>
<fsummary>Prints and logs from a test case.</fsummary>
<type>
<v>Category = atom()</v>
@@ -945,7 +945,7 @@
</func>
<func>
- <name>parse_table(Data) -&gt; {Heading, Table}</name>
+ <name since="">parse_table(Data) -&gt; {Heading, Table}</name>
<fsummary>Parses the printout from an SQL table and returns a list of
tuples.</fsummary>
<type>
@@ -967,7 +967,7 @@
</func>
<func>
- <name>print(Format) -&gt; ok</name>
+ <name since="">print(Format) -&gt; ok</name>
<fsummary>Equivalent to print(default, 50, Format, [], []).</fsummary>
<desc><marker id="print-1"/>
<p>Equivalent to <seealso marker="#print-5"><c>ct:print(default,
@@ -976,7 +976,7 @@
</func>
<func>
- <name>print(X1, X2) -&gt; ok</name>
+ <name since="OTP R15B02">print(X1, X2) -&gt; ok</name>
<fsummary>Equivalent to print(Category, Importance, Format,
FormatArgs, []).</fsummary>
<type>
@@ -990,7 +990,7 @@
</func>
<func>
- <name>print(X1, X2, X3) -&gt; ok</name>
+ <name since="">print(X1, X2, X3) -&gt; ok</name>
<fsummary>Equivalent to print(Category, Importance, Format,
FormatArgs, Opts).</fsummary>
<type>
@@ -1005,7 +1005,7 @@
</func>
<func>
- <name>print(X1, X2, X3, X4) -&gt; ok</name>
+ <name since="OTP R15B02">print(X1, X2, X3, X4) -&gt; ok</name>
<fsummary>Equivalent to print(Category, Importance, Format,
FormatArgs, Opts).</fsummary>
<type>
@@ -1021,7 +1021,7 @@
</func>
<func>
- <name>print(Category, Importance, Format, FormatArgs, Opts) -&gt; ok</name>
+ <name since="OTP 19.2">print(Category, Importance, Format, FormatArgs, Opts) -&gt; ok</name>
<fsummary>Prints from a test case to the console.</fsummary>
<type>
<v>Category = atom()</v>
@@ -1048,7 +1048,7 @@
</func>
<func>
- <name>reload_config(Required) -&gt; ValueOrElement | {error, Reason}</name>
+ <name since="OTP R14B">reload_config(Required) -&gt; ValueOrElement | {error, Reason}</name>
<fsummary>Reloads configuration file containing specified configuration
key.</fsummary>
<type>
@@ -1071,7 +1071,7 @@
</func>
<func>
- <name>remaining_test_procs() -&gt; {TestProcs,SharedGL,OtherGLs}</name>
+ <name since="OTP 20.2">remaining_test_procs() -&gt; {TestProcs,SharedGL,OtherGLs}</name>
<fsummary>>This function will return the identity of test- and group
leader processes that are still running at the time of this call.</fsummary>
<type>
@@ -1107,7 +1107,7 @@
</func>
<func>
- <name>remove_config(Callback, Config) -&gt; ok</name>
+ <name since="OTP R14B">remove_config(Callback, Config) -&gt; ok</name>
<fsummary>Removes configuration variables (together with
their aliases) that were loaded with specified callback module and
configuration string.</fsummary>
@@ -1124,7 +1124,7 @@
</func>
<func>
- <name>require(Required) -&gt; ok | {error, Reason}</name>
+ <name since="">require(Required) -&gt; ok | {error, Reason}</name>
<fsummary>Checks if the required configuration is available.</fsummary>
<type>
<v>Required = Key | {Key, SubKeys} | {Key, SubKey, SubKeys}</v>
@@ -1178,7 +1178,7 @@
</func>
<func>
- <name>require(Name, Required) -&gt; ok | {error, Reason}</name>
+ <name since="">require(Name, Required) -&gt; ok | {error, Reason}</name>
<fsummary>Checks if the required configuration is available and gives
it a name.</fsummary>
<type>
@@ -1237,7 +1237,7 @@
</func>
<func>
- <name>run(TestDirs) -&gt; Result</name>
+ <name since="">run(TestDirs) -&gt; Result</name>
<fsummary>Runs all test cases in all suites in the specified
directories.</fsummary>
<type>
@@ -1251,7 +1251,7 @@
</func>
<func>
- <name>run(TestDir, Suite) -&gt; Result</name>
+ <name since="">run(TestDir, Suite) -&gt; Result</name>
<fsummary>Runs all test cases in the specified suite.</fsummary>
<desc><marker id="run-2"/>
<p>Runs all test cases in the specified suite.</p>
@@ -1261,7 +1261,7 @@
</func>
<func>
- <name>run(TestDir, Suite, Cases) -&gt; Result</name>
+ <name since="">run(TestDir, Suite, Cases) -&gt; Result</name>
<fsummary>Runs the specified test cases.</fsummary>
<type>
<v>TestDir = string()</v>
@@ -1283,7 +1283,7 @@
</func>
<func>
- <name>run_test(Opts) -&gt; Result</name>
+ <name since="">run_test(Opts) -&gt; Result</name>
<fsummary>Runs tests as specified by the combination of options in
Opts.</fsummary>
<type>
@@ -1355,7 +1355,7 @@
</func>
<func>
- <name>run_testspec(TestSpec) -&gt; Result</name>
+ <name since="">run_testspec(TestSpec) -&gt; Result</name>
<fsummary>Runs a test specified by TestSpec.</fsummary>
<type>
<v>TestSpec = [term()]</v>
@@ -1375,7 +1375,7 @@
</func>
<func>
- <name>set_verbosity(Category, Level) -&gt; ok</name>
+ <name since="OTP 19.1">set_verbosity(Category, Level) -&gt; ok</name>
<fsummary>Set the verbosity level for a logging category.</fsummary>
<type>
<v>Category = default | atom()</v>
@@ -1390,7 +1390,7 @@
</func>
<func>
- <name>sleep(Time) -&gt; ok</name>
+ <name since="OTP R14B">sleep(Time) -&gt; ok</name>
<fsummary>This function, similar to timer:sleep/1, suspends the
test case for a specified time.</fsummary>
<type>
@@ -1412,7 +1412,7 @@
</func>
<func>
- <name>start_interactive() -&gt; ok</name>
+ <name since="">start_interactive() -&gt; ok</name>
<fsummary>Starts <c>Common Test</c> in interactive mode.</fsummary>
<desc><marker id="start_interactive-0"/>
<p>Starts <c>Common Test</c> in interactive mode.</p>
@@ -1440,7 +1440,7 @@
</func>
<func>
- <name>step(TestDir, Suite, Case) -&gt; Result</name>
+ <name since="">step(TestDir, Suite, Case) -&gt; Result</name>
<fsummary>Steps through a test case with the debugger.</fsummary>
<type>
<v>Case = atom()</v>
@@ -1453,7 +1453,7 @@
</func>
<func>
- <name>step(TestDir, Suite, Case, Opts) -&gt; Result</name>
+ <name since="">step(TestDir, Suite, Case, Opts) -&gt; Result</name>
<fsummary>Steps through a test case with the debugger.</fsummary>
<type>
<v>Case = atom()</v>
@@ -1470,7 +1470,7 @@
</func>
<func>
- <name>stop_interactive() -&gt; ok</name>
+ <name since="">stop_interactive() -&gt; ok</name>
<fsummary>Exits the interactive mode.</fsummary>
<desc><marker id="stop_interactive-0"/>
<p>Exits the interactive mode.</p>
@@ -1482,7 +1482,7 @@
</func>
<func>
- <name>sync_notify(Name, Data) -&gt; ok</name>
+ <name since="OTP R15B02">sync_notify(Name, Data) -&gt; ok</name>
<fsummary>Sends a synchronous notification of type Name with Data to
the <c>Common Test</c> event manager.</fsummary>
<type>
@@ -1501,7 +1501,7 @@
</func>
<func>
- <name>testcases(TestDir, Suite) -&gt; Testcases | {error, Reason}</name>
+ <name since="">testcases(TestDir, Suite) -&gt; Testcases | {error, Reason}</name>
<fsummary>Returns all test cases in the specified suite.</fsummary>
<type>
<v>TestDir = string()</v>
@@ -1515,14 +1515,14 @@
</func>
<func>
- <name>timetrap(Time) -&gt; ok</name>
+ <name since="OTP R14B">timetrap(Time) -&gt; ok</name>
<fsummary>Sets a new timetrap for the running test case.</fsummary>
<type>
<v>Time = {hours, Hours} | {minutes, Mins} | {seconds, Secs} | Millisecs | infinity | Func</v>
<v>Hours = integer()</v>
<v>Mins = integer()</v>
<v>Secs = integer()</v>
- <v>Millisecs = integer() | float()</v>
+ <v>Millisecs = integer()</v>
<v>Func = {M, F, A} | function()</v>
<v>M = atom()</v>
<v>F = atom()</v>
@@ -1539,7 +1539,7 @@
</func>
<func>
- <name>userdata(TestDir, Suite) -&gt; SuiteUserData | {error, Reason}</name>
+ <name since="">userdata(TestDir, Suite) -&gt; SuiteUserData | {error, Reason}</name>
<fsummary>Returns any data specified with tag userdata in the list of
tuples returned from Suite:suite/0.</fsummary>
<type>
@@ -1556,7 +1556,7 @@
</func>
<func>
- <name>userdata(TestDir, Suite, Case::GroupOrCase) -&gt; TCUserData | {error, Reason}</name>
+ <name since="">userdata(TestDir, Suite, Case::GroupOrCase) -&gt; TCUserData | {error, Reason}</name>
<fsummary>Returns any data specified with tag userdata in the list of
tuples returned from Suite:group(GroupName) or Suite:Case().</fsummary>
<type>
diff --git a/lib/common_test/doc/src/ct_cover.xml b/lib/common_test/doc/src/ct_cover.xml
index 89d944acbe..61365d3522 100644
--- a/lib/common_test/doc/src/ct_cover.xml
+++ b/lib/common_test/doc/src/ct_cover.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_cover.xml</file>
</header>
- <module>ct_cover</module>
+ <module since="">ct_cover</module>
<modulesummary>Common Test framework code coverage support module.
</modulesummary>
@@ -47,7 +47,7 @@
<funcs>
<func>
- <name>add_nodes(Nodes) -&gt; {ok, StartedNodes} | {error, Reason}</name>
+ <name since="">add_nodes(Nodes) -&gt; {ok, StartedNodes} | {error, Reason}</name>
<fsummary>Adds nodes to current cover test (only works if cover support
is active).</fsummary>
<type>
@@ -67,7 +67,7 @@
</func>
<func>
- <name>cross_cover_analyse(Level, Tests) -&gt; ok</name>
+ <name since="OTP R16B">cross_cover_analyse(Level, Tests) -&gt; ok</name>
<fsummary>Accumulates cover results over multiple tests.</fsummary>
<type>
<v>Level = overview | details</v>
@@ -83,7 +83,7 @@
</func>
<func>
- <name>remove_nodes(Nodes) -&gt; ok | {error, Reason}</name>
+ <name since="">remove_nodes(Nodes) -&gt; ok | {error, Reason}</name>
<fsummary>Removes nodes from the current cover test.</fsummary>
<type>
<v>Nodes = [atom()]</v>
diff --git a/lib/common_test/doc/src/ct_ftp.xml b/lib/common_test/doc/src/ct_ftp.xml
index 592c5eb05d..7ee6049486 100644
--- a/lib/common_test/doc/src/ct_ftp.xml
+++ b/lib/common_test/doc/src/ct_ftp.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_ftp.xml</file>
</header>
- <module>ct_ftp</module>
+ <module since="">ct_ftp</module>
<modulesummary>FTP client module (based on the FTP application).</modulesummary>
<description>
@@ -59,7 +59,7 @@
<funcs>
<func>
- <name>cd(Connection, Dir) -&gt; ok | {error, Reason}</name>
+ <name since="">cd(Connection, Dir) -&gt; ok | {error, Reason}</name>
<fsummary>Changes directory on remote host.</fsummary>
<type>
<v>Connection = connection()</v>
@@ -71,7 +71,7 @@
</func>
<func>
- <name>close(Connection) -&gt; ok | {error, Reason}</name>
+ <name since="">close(Connection) -&gt; ok | {error, Reason}</name>
<fsummary>Closes the FTP connection.</fsummary>
<type>
<v>Connection = connection()</v>
@@ -82,7 +82,7 @@
</func>
<func>
- <name>delete(Connection, File) -&gt; ok | {error, Reason}</name>
+ <name since="">delete(Connection, File) -&gt; ok | {error, Reason}</name>
<fsummary>Deletes a file on remote host.</fsummary>
<type>
<v>Connection = connection()</v>
@@ -94,7 +94,7 @@
</func>
<func>
- <name>get(KeyOrName, RemoteFile, LocalFile) -&gt; ok | {error, Reason}</name>
+ <name since="">get(KeyOrName, RemoteFile, LocalFile) -&gt; ok | {error, Reason}</name>
<fsummary>Opens an FTP connection and fetches a file from the remote
host.</fsummary>
<type>
@@ -122,7 +122,7 @@
</func>
<func>
- <name>ls(Connection, Dir) -&gt; {ok, Listing} | {error, Reason}</name>
+ <name since="">ls(Connection, Dir) -&gt; {ok, Listing} | {error, Reason}</name>
<fsummary>Lists directory Dir.</fsummary>
<type>
<v>Connection = connection()</v>
@@ -135,7 +135,7 @@
</func>
<func>
- <name>open(KeyOrName) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">open(KeyOrName) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Opens an FTP connection to the specified node.</fsummary>
<type>
<v>KeyOrName = Key | Name</v>
@@ -164,7 +164,7 @@
</func>
<func>
- <name>put(KeyOrName, LocalFile, RemoteFile) -&gt; ok | {error, Reason}</name>
+ <name since="">put(KeyOrName, LocalFile, RemoteFile) -&gt; ok | {error, Reason}</name>
<fsummary>Opens an FTP connection and sends a file to the remote
host.</fsummary>
<type>
@@ -203,7 +203,7 @@
</func>
<func>
- <name>recv(Connection, RemoteFile) -&gt; ok | {error, Reason}</name>
+ <name since="">recv(Connection, RemoteFile) -&gt; ok | {error, Reason}</name>
<fsummary>Fetches a file over FTP.</fsummary>
<desc><marker id="recv-2"/>
<p>Fetches a file over FTP.</p>
@@ -215,7 +215,7 @@
</func>
<func>
- <name>recv(Connection, RemoteFile, LocalFile) -&gt; ok | {error, Reason}</name>
+ <name since="">recv(Connection, RemoteFile, LocalFile) -&gt; ok | {error, Reason}</name>
<fsummary>Fetches a file over FTP.</fsummary>
<type>
<v>Connection = connection()</v>
@@ -230,7 +230,7 @@
</func>
<func>
- <name>send(Connection, LocalFile) -&gt; ok | {error, Reason}</name>
+ <name since="">send(Connection, LocalFile) -&gt; ok | {error, Reason}</name>
<fsummary>Sends a file over FTP.</fsummary>
<desc><marker id="send-2"/>
<p>Sends a file over FTP.</p>
@@ -243,7 +243,7 @@
</func>
<func>
- <name>send(Connection, LocalFile, RemoteFile) -&gt; ok | {error, Reason}</name>
+ <name since="">send(Connection, LocalFile, RemoteFile) -&gt; ok | {error, Reason}</name>
<fsummary>Sends a file over FTP.</fsummary>
<type>
<v>Connection = connection()</v>
@@ -258,7 +258,7 @@
</func>
<func>
- <name>type(Connection, Type) -&gt; ok | {error, Reason}</name>
+ <name since="">type(Connection, Type) -&gt; ok | {error, Reason}</name>
<fsummary>Changes the file transfer type.</fsummary>
<type>
<v>Connection = connection()</v>
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml
index 954be0ffba..7664dcc9d1 100644
--- a/lib/common_test/doc/src/ct_hooks.xml
+++ b/lib/common_test/doc/src/ct_hooks.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>ct_hooks.sgml</file>
</header>
- <module>ct_hooks</module>
+ <module since="OTP R14B02">ct_hooks</module>
<modulesummary>A callback interface on top of Common Test.</modulesummary>
<description>
@@ -75,7 +75,7 @@
<funcs>
<func>
- <name>Module:init(Id, Opts) -&gt; {ok, State} | {ok, State, Priority}</name>
+ <name since="OTP R14B02">Module:init(Id, Opts) -&gt; {ok, State} | {ok, State, Priority}</name>
<fsummary>Initiates the Common Test Hook.</fsummary>
<type>
<v>Id = reference() | term()</v>
@@ -109,7 +109,132 @@
</func>
<func>
- <name>Module:pre_init_per_suite(SuiteName, InitData, CTHState) -&gt; Result</name>
+ <name since="OTP 21.3.8">Module:post_groups(SuiteName, GroupDefs) -&gt; NewGroupDefs</name>
+ <fsummary>Called after groups/0.</fsummary>
+ <type>
+ <v>SuiteName = atom()</v>
+ <v>GroupDefs = NewGroupDefs = [Group]</v>
+ <v>Group = {GroupName,Properties,GroupsAndTestCases}</v>
+ <v>GroupName = atom()</v>
+ <v>Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]</v>
+ <v>GroupsAndTestCases = [Group | {group,GroupName} | TestCase | {testcase,TestCase,TCRepeatProps}]</v>
+ <v>TestCase = atom()</v>
+ <v>TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {repeat_until_fail,N}]</v>
+ <v>Shuffle = shuffle | {shuffle,Seed}</v>
+ <v>Seed = {integer(),integer(),integer()}</v>
+ <v>GroupRepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | repeat_until_any_ok | repeat_until_any_fail</v>
+ <v>N = integer() | forever</v>
+ </type>
+ <desc>
+ <p>OPTIONAL</p>
+
+ <p>This function is called after
+ <seealso marker="common_test#Module:groups-0"><c>groups/0</c></seealso>.
+ It is used to modify the test group definitions, for
+ instance to add or remove groups or change group properties.</p>
+
+ <p><c>GroupDefs</c> is what
+ <seealso marker="common_test#Module:groups-0"><c>groups/0</c></seealso>
+ returned, that is, a list of group definitions.</p>
+
+ <p><c>NewGroupDefs</c> is the possibly modified version of this list.</p>
+
+ <p>This function is called only if the CTH is added before
+ <c>init_per_suite</c> is run. For details, see section
+ <seealso marker="ct_hooks_chapter#scope">CTH Scope</seealso>
+ in the User's Guide.</p>
+
+ <p>Notice that for CTHs that are installed by means of the
+ <seealso marker="common_test#Module:suite-0"><c>suite/0</c></seealso>
+ function, <c>post_groups/2</c> is called before
+ the <seealso marker="#Module:init-2"><c>init/2</c></seealso>
+ hook function. However, for CTHs that are installed by means
+ of the CT start flag,
+ the <seealso marker="#Module:init-2"><c>init/2</c></seealso>
+ function is called first.</p>
+
+ <note>
+ <p>Prior to each test execution, Common Test does a
+ simulated test run in order to count test suites, groups
+ and cases for logging purposes. This causes
+ the <c>post_groups/2</c> hook function to always be called
+ twice. For this reason, side effects are best avoided in
+ this callback.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.3.8">Module:post_all(SuiteName, Return, GroupDefs) -&gt; NewReturn</name>
+ <fsummary>Called after all/0.</fsummary>
+ <type>
+ <v>SuiteName = atom()</v>
+ <v>Return = NewReturn = Tests | {skip,Reason}</v>
+ <v>Tests = [TestCase | {testcase,TestCase,TCRepeatProps} | {group,GroupName} | {group,GroupName,Properties} | {group,GroupName,Properties,SubGroups}]</v>
+ <v>TestCase = atom()</v>
+ <v>TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {repeat_until_fail,N}]</v>
+ <v>GroupName = atom()</v>
+ <v>Properties = GroupProperties | default</v>
+ <v>SubGroups = [{GroupName,Properties} | {GroupName,Properties,SubGroups}]</v>
+ <v>Shuffle = shuffle | {shuffle,Seed}</v>
+ <v>Seed = {integer(),integer(),integer()}</v>
+ <v>GroupRepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | repeat_until_any_ok | repeat_until_any_fail</v>
+ <v>N = integer() | forever</v>
+ <v>GroupDefs = NewGroupDefs = [Group]</v>
+ <v>Group = {GroupName,GroupProperties,GroupsAndTestCases}</v>
+ <v>GroupProperties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]</v>
+ <v>GroupsAndTestCases = [Group | {group,GroupName} | TestCase]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>OPTIONAL</p>
+
+ <p>This function is called after
+ <seealso marker="common_test#Module:all-0"><c>all/0</c></seealso>.
+ It is used to modify the set of test cases and test group to
+ be executed, for instance to add or remove test cases and
+ groups, change group properties, or even skip all tests in
+ the suite.</p>
+
+ <p><c>Return</c> is what
+ <seealso marker="common_test#Module:all-0"><c>all/0</c></seealso>
+ returned, that is, a list of test cases and groups to be
+ executed, or a tuple <c>{skip,Reason}</c>.</p>
+
+ <p><c>GroupDefs</c> is what
+ <seealso marker="common_test#Module:groups-0"><c>groups/0</c></seealso>
+ or the <c>post_groups/2</c> hook returned, that is, a list
+ of group definitions.</p>
+
+ <p><c>NewReturn</c> is the possibly modified version of <c>Return</c>.</p>
+
+ <p>This function is called only if the CTH is added before
+ <c>init_per_suite</c> is run. For details, see section
+ <seealso marker="ct_hooks_chapter#scope">CTH Scope</seealso>
+ in the User's Guide.</p>
+
+ <p>Notice that for CTHs that are installed by means of the
+ <seealso marker="common_test#Module:suite-0"><c>suite/0</c></seealso>
+ function, <c>post_all/2</c> is called before
+ the <seealso marker="#Module:init-2"><c>init/2</c></seealso>
+ hook function. However, for CTHs that are installed by means
+ of the CT start flag,
+ the <seealso marker="#Module:init-2"><c>init/2</c></seealso>
+ function is called first.</p>
+
+ <note>
+ <p>Prior to each test execution, Common Test does a
+ simulated test run in order to count test suites, groups
+ and cases for logging purposes. This causes
+ the <c>post_all/3</c> hook function to always be called
+ twice. For this reason, side effects are best avoided in
+ this callback.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP R14B02">Module:pre_init_per_suite(SuiteName, InitData, CTHState) -&gt; Result</name>
<fsummary>Called before init_per_suite.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -161,7 +286,7 @@
</func>
<func>
- <name>Module:post_init_per_suite(SuiteName, Config, Return, CTHState) -&gt; Result</name>
+ <name since="OTP R14B02">Module:post_init_per_suite(SuiteName, Config, Return, CTHState) -&gt; Result</name>
<fsummary>Called after init_per_suite.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -208,7 +333,7 @@
</func>
<func>
- <name>Module:pre_init_per_group(SuiteName, GroupName, InitData, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:pre_init_per_group(SuiteName, GroupName, InitData, CTHState) -&gt; Result</name>
<fsummary>Called before init_per_group.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -241,7 +366,7 @@
</func>
<func>
- <name>Module:post_init_per_group(SuiteName, GroupName, Config, Return, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:post_init_per_group(SuiteName, GroupName, Config, Return, CTHState) -&gt; Result</name>
<fsummary>Called after init_per_group.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -274,7 +399,7 @@
</func>
<func>
- <name>Module:pre_init_per_testcase(SuiteName, TestcaseName, InitData, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:pre_init_per_testcase(SuiteName, TestcaseName, InitData, CTHState) -&gt; Result</name>
<fsummary>Called before init_per_testcase.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -311,7 +436,7 @@
</func>
<func>
- <name>Module:post_init_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:post_init_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -&gt; Result</name>
<fsummary>Called after init_per_testcase.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -344,7 +469,7 @@
</func>
<func>
- <name>Module:pre_end_per_testcase(SuiteName, TestcaseName, EndData, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:pre_end_per_testcase(SuiteName, TestcaseName, EndData, CTHState) -&gt; Result</name>
<fsummary>Called before end_per_testcase.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -380,7 +505,7 @@
</func>
<func>
- <name>Module:post_end_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:post_end_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -&gt; Result</name>
<fsummary>Called after end_per_testcase.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -413,7 +538,7 @@
</func>
<func>
- <name>Module:pre_end_per_group(SuiteName, GroupName, EndData, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:pre_end_per_group(SuiteName, GroupName, EndData, CTHState) -&gt; Result</name>
<fsummary>Called before end_per_group.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -446,7 +571,7 @@
</func>
<func>
- <name>Module:post_end_per_group(SuiteName, GroupName, Config, Return, CTHState) -&gt; Result</name>
+ <name since="OTP 19.3">Module:post_end_per_group(SuiteName, GroupName, Config, Return, CTHState) -&gt; Result</name>
<fsummary>Called after end_per_group.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -479,7 +604,7 @@
</func>
<func>
- <name>Module:pre_end_per_suite(SuiteName, EndData, CTHState) -&gt; Result</name>
+ <name since="OTP R14B02">Module:pre_end_per_suite(SuiteName, EndData, CTHState) -&gt; Result</name>
<fsummary>Called before end_per_suite.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -506,7 +631,7 @@
</func>
<func>
- <name>Module:post_end_per_suite(SuiteName, Config, Return, CTHState) -&gt; Result</name>
+ <name since="OTP R14B02">Module:post_end_per_suite(SuiteName, Config, Return, CTHState) -&gt; Result</name>
<fsummary>Called after end_per_suite.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -533,7 +658,7 @@
</func>
<func>
- <name>Module:on_tc_fail(SuiteName, TestName, Reason, CTHState) -&gt; NewCTHState</name>
+ <name since="OTP 19.3">Module:on_tc_fail(SuiteName, TestName, Reason, CTHState) -&gt; NewCTHState</name>
<fsummary>Called after the CTH scope ends.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -577,7 +702,7 @@
</func>
<func>
- <name>Module:on_tc_skip(SuiteName, TestName, Reason, CTHState) -&gt; NewCTHState</name>
+ <name since="OTP 19.3">Module:on_tc_skip(SuiteName, TestName, Reason, CTHState) -&gt; NewCTHState</name>
<fsummary>Called after the CTH scope ends.</fsummary>
<type>
<v>SuiteName = atom()</v>
@@ -623,7 +748,7 @@
</func>
<func>
- <name>Module:terminate(CTHState)</name>
+ <name since="OTP R14B02">Module:terminate(CTHState)</name>
<fsummary>Called after the CTH scope ends.</fsummary>
<type>
<v>CTHState = term()</v>
@@ -637,7 +762,7 @@
</func>
<func>
- <name>Module:id(Opts) -&gt; Id</name>
+ <name since="OTP R14B02">Module:id(Opts) -&gt; Id</name>
<fsummary>Called before the init function of a CTH.</fsummary>
<type>
<v>Opts = term()</v>
diff --git a/lib/common_test/doc/src/ct_master.xml b/lib/common_test/doc/src/ct_master.xml
index 6bde4644c6..2ab421fe9e 100644
--- a/lib/common_test/doc/src/ct_master.xml
+++ b/lib/common_test/doc/src/ct_master.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_master.xml</file>
</header>
- <module>ct_master</module>
+ <module since="">ct_master</module>
<modulesummary>Distributed test execution control for Common Test.</modulesummary>
<description>
@@ -46,7 +46,7 @@
<funcs>
<func>
- <name>abort() -&gt; ok</name>
+ <name since="">abort() -&gt; ok</name>
<fsummary>Stops all running tests.</fsummary>
<desc><marker id="abort-0"/>
<p>Stops all running tests.</p>
@@ -54,7 +54,7 @@
</func>
<func>
- <name>abort(Nodes) -&gt; ok</name>
+ <name since="">abort(Nodes) -&gt; ok</name>
<fsummary>Stops tests on specified nodes.</fsummary>
<type>
<v>Nodes = atom() | [atom()]</v>
@@ -65,7 +65,7 @@
</func>
<func>
- <name>basic_html(Bool) -&gt; ok</name>
+ <name since="OTP R15B01">basic_html(Bool) -&gt; ok</name>
<fsummary>If set to true, the ct_master logs are written on a primitive
HTML format, not using the <c>Common Test</c> CSS style sheet.</fsummary>
<type>
@@ -79,7 +79,7 @@
</func>
<func>
- <name>get_event_mgr_ref() -&gt; MasterEvMgrRef</name>
+ <name since="OTP 17.5">get_event_mgr_ref() -&gt; MasterEvMgrRef</name>
<fsummary>Gets a reference to the <c>Common Test</c> master event
manager.</fsummary>
<type>
@@ -98,7 +98,7 @@
</func>
<func>
- <name>progress() -&gt; [{Node, Status}]</name>
+ <name since="">progress() -&gt; [{Node, Status}]</name>
<fsummary>Returns test progress.</fsummary>
<type>
<v>Node = atom()</v>
@@ -112,7 +112,7 @@
</func>
<func>
- <name>run(TestSpecs) -&gt; ok</name>
+ <name since="">run(TestSpecs) -&gt; ok</name>
<fsummary>Equivalent to run(TestSpecs, false, [], []).</fsummary>
<type>
<v>TestSpecs = string() | [SeparateOrMerged]</v>
@@ -124,7 +124,7 @@
</func>
<func>
- <name>run(TestSpecs, InclNodes, ExclNodes) -&gt; ok</name>
+ <name since="">run(TestSpecs, InclNodes, ExclNodes) -&gt; ok</name>
<fsummary>Equivalent to run(TestSpecs, false, InclNodes, ExclNodes).
</fsummary>
<type>
@@ -140,7 +140,7 @@
</func>
<func>
- <name>run(TestSpecs, AllowUserTerms, InclNodes, ExclNodes) -&gt; ok</name>
+ <name since="">run(TestSpecs, AllowUserTerms, InclNodes, ExclNodes) -&gt; ok</name>
<fsummary>Tests are spawned on the nodes as specified in TestSpecs.
</fsummary>
<type>
@@ -162,7 +162,7 @@
</func>
<func>
- <name>run_on_node(TestSpecs, Node) -&gt; ok</name>
+ <name since="">run_on_node(TestSpecs, Node) -&gt; ok</name>
<fsummary>Equivalent to run_on_node(TestSpecs, false, Node).</fsummary>
<type>
<v>TestSpecs = string() | [SeparateOrMerged]</v>
@@ -177,7 +177,7 @@
</func>
<func>
- <name>run_on_node(TestSpecs, AllowUserTerms, Node) -&gt; ok</name>
+ <name since="">run_on_node(TestSpecs, AllowUserTerms, Node) -&gt; ok</name>
<fsummary>Tests are spawned on Node according to TestSpecs.</fsummary>
<type>
<v>TestSpecs = string() | [SeparateOrMerged]</v>
@@ -191,7 +191,7 @@
</func>
<func>
- <name>run_test(Node, Opts) -&gt; ok</name>
+ <name since="">run_test(Node, Opts) -&gt; ok</name>
<fsummary>Tests are spawned on Node using ct:run_test/1.</fsummary>
<type>
<v>Node = atom()</v>
diff --git a/lib/common_test/doc/src/ct_netconfc.xml b/lib/common_test/doc/src/ct_netconfc.xml
index 7ec8f23073..8fbe5f3df6 100644
--- a/lib/common_test/doc/src/ct_netconfc.xml
+++ b/lib/common_test/doc/src/ct_netconfc.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_netconfc.xml</file>
</header>
- <module>ct_netconfc</module>
+ <module since="OTP R15B02">ct_netconfc</module>
<modulesummary>NETCONF client module.</modulesummary>
<description>
@@ -312,8 +312,8 @@
<funcs>
<func>
- <name name="action" arity="2"/>
- <name name="action" arity="3"/>
+ <name name="action" arity="2" since="OTP R15B02"/>
+ <name name="action" arity="3" since="OTP R15B02"/>
<fsummary>Executes an action.</fsummary>
<desc>
<p>Executes an action. If the return type is void, <c>ok</c> is
@@ -322,8 +322,8 @@
</func>
<func>
- <name name="close_session" arity="1"/>
- <name name="close_session" arity="2"/>
+ <name name="close_session" arity="1" since="OTP R15B02"/>
+ <name name="close_session" arity="2" since="OTP R15B02"/>
<fsummary>Requests graceful termination of the session associated with
the client.</fsummary>
<desc>
@@ -339,7 +339,7 @@
</func>
<func>
- <name name="connect" arity="1"/>
+ <name name="connect" arity="1" since="OTP 20.0"/>
<fsummary>Opens an SSH connection to a NETCONF server.</fsummary>
<desc>
<p>Opens an SSH connection to a NETCONF server.</p>
@@ -361,7 +361,7 @@
</func>
<func>
- <name name="connect" arity="2"/>
+ <name name="connect" arity="2" since="OTP 20.0"/>
<fsummary>Opens an SSH connection to a named NETCONF server.</fsummary>
<desc>
<p>Open an SSH connection to a named NETCONF server.</p>
@@ -399,8 +399,8 @@
</func>
<func>
- <name name="copy_config" arity="3"/>
- <name name="copy_config" arity="4"/>
+ <name name="copy_config" arity="3" since="OTP R15B02"/>
+ <name name="copy_config" arity="4" since="OTP R15B02"/>
<fsummary>Copies configuration data.</fsummary>
<desc>
<p>Copies configuration data.</p>
@@ -412,12 +412,12 @@
</func>
<func>
- <name>create_subscription(Client) -> Result</name>
- <name>create_subscription(Client, Stream) -> Result</name>
- <name>create_subscription(Client, Stream, Filter) -> Result</name>
- <name>create_subscription(Client, Stream, Filter, Timeout) -> Result</name>
- <name name="create_subscription" arity="5" clause_i="2"/>
- <name name="create_subscription" arity="6"/>
+ <name since="OTP R15B02">create_subscription(Client) -> Result</name>
+ <name since="OTP R15B02">create_subscription(Client, Stream) -> Result</name>
+ <name since="OTP R15B02">create_subscription(Client, Stream, Filter) -> Result</name>
+ <name since="OTP R15B02">create_subscription(Client, Stream, Filter, Timeout) -> Result</name>
+ <name name="create_subscription" arity="5" clause_i="2" since="OTP R15B02"/>
+ <name name="create_subscription" arity="6" since="OTP R15B02"/>
<fsummary>Creates a subscription for event notifications.</fsummary>
<desc>
<p>Creates a subscription for event notifications.</p>
@@ -490,8 +490,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="delete_config" arity="2"/>
- <name name="delete_config" arity="3"/>
+ <name name="delete_config" arity="2" since="OTP R15B02"/>
+ <name name="delete_config" arity="3" since="OTP R15B02"/>
<fsummary>Deletes configuration data.</fsummary>
<desc>
<p>Deletes configuration data.</p>
@@ -502,7 +502,7 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="disconnect" arity="1"/>
+ <name name="disconnect" arity="1" since="OTP 20.0"/>
<fsummary>Closes the given SSH connection.</fsummary>
<desc>
<p>Closes the given SSH connection.</p>
@@ -514,10 +514,10 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="edit_config" arity="3"/>
- <name name="edit_config" arity="4" clause_i="1"/>
- <name name="edit_config" arity="4" clause_i="2"/>
- <name name="edit_config" arity="5"/>
+ <name name="edit_config" arity="3" since="OTP R15B02"/>
+ <name name="edit_config" arity="4" clause_i="1" since="OTP 18.0"/>
+ <name name="edit_config" arity="4" clause_i="2" since="OTP R15B02"/>
+ <name name="edit_config" arity="5" since="OTP 18.0"/>
<fsummary>Edits configuration data.</fsummary>
<desc>
<p>Edits configuration data.</p>
@@ -542,8 +542,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="get" arity="2"/>
- <name name="get" arity="3"/>
+ <name name="get" arity="2" since="OTP R15B02"/>
+ <name name="get" arity="3" since="OTP R15B02"/>
<fsummary>Gets data.</fsummary>
<desc>
<p>Gets data.</p>
@@ -557,8 +557,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="get_capabilities" arity="1"/>
- <name name="get_capabilities" arity="2"/>
+ <name name="get_capabilities" arity="1" since="OTP R15B02"/>
+ <name name="get_capabilities" arity="2" since="OTP R15B02"/>
<fsummary>Returns the server side capabilities.</fsummary>
<desc>
<p>Returns the server side capabilities.</p>
@@ -582,8 +582,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="get_config" arity="3"/>
- <name name="get_config" arity="4"/>
+ <name name="get_config" arity="3" since="OTP R15B02"/>
+ <name name="get_config" arity="4" since="OTP R15B02"/>
<fsummary>Gets configuration data.</fsummary>
<desc>
<p>Gets configuration data.</p>
@@ -597,10 +597,10 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="get_event_streams" arity="1"/>
- <name name="get_event_streams" arity="2" clause_i="1"/>
- <name name="get_event_streams" arity="2" clause_i="2"/>
- <name name="get_event_streams" arity="3"/>
+ <name name="get_event_streams" arity="1" since="OTP 20.0"/>
+ <name name="get_event_streams" arity="2" clause_i="1" since="OTP R15B02"/>
+ <name name="get_event_streams" arity="2" clause_i="2" since="OTP 20.0"/>
+ <name name="get_event_streams" arity="3" since="OTP R15B02"/>
<fsummary>Sends a request to get the specified event streams.</fsummary>
<desc>
<p>Sends a request to get the specified event streams.</p>
@@ -637,8 +637,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="get_session_id" arity="1"/>
- <name name="get_session_id" arity="2"/>
+ <name name="get_session_id" arity="1" since="OTP R15B02"/>
+ <name name="get_session_id" arity="2" since="OTP R15B02"/>
<fsummary>Returns the session Id associated with the specified
client.</fsummary>
<desc>
@@ -647,9 +647,9 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="hello" arity="1"/>
- <name name="hello" arity="2"/>
- <name name="hello" arity="3"/>
+ <name name="hello" arity="1" since="OTP R15B02"/>
+ <name name="hello" arity="2" since="OTP R15B02"/>
+ <name name="hello" arity="3" since="OTP 17.5.3"/>
<fsummary>Exchanges hello messages with the server.</fsummary>
<desc>
<p>Exchanges <c>hello</c> messages with the server.</p>
@@ -660,8 +660,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="kill_session" arity="2"/>
- <name name="kill_session" arity="3"/>
+ <name name="kill_session" arity="2" since="OTP R15B02"/>
+ <name name="kill_session" arity="3" since="OTP R15B02"/>
<fsummary>Forces termination of the session associated with the supplied
session Id.</fsummary>
<desc>
@@ -682,8 +682,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="lock" arity="2"/>
- <name name="lock" arity="3"/>
+ <name name="lock" arity="2" since="OTP R15B02"/>
+ <name name="lock" arity="3" since="OTP R15B02"/>
<fsummary>Locks the configuration target.</fsummary>
<desc>
<p>Locks the configuration target.</p>
@@ -703,7 +703,7 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="only_open" arity="1"/>
+ <name name="only_open" arity="1" since="OTP R15B02"/>
<fsummary>Opens a NETCONF session, but does not send hello.</fsummary>
<desc>
<p>Opens a NETCONF session, but does not send <c>hello</c>.</p>
@@ -714,7 +714,7 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="only_open" arity="2"/>
+ <name name="only_open" arity="2" since="OTP R15B02"/>
<fsummary>Opens a named NETCONF session, but does not send hello.</fsummary>
<desc>
<p>Opens a named NETCONF session, but does not send <c>hello</c>.</p>
@@ -725,7 +725,7 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="open" arity="1"/>
+ <name name="open" arity="1" since="OTP R15B02"/>
<fsummary>Opens a NETCONF session and exchanges hello messages.</fsummary>
<desc>
<p>Opens a NETCONF session and exchanges <c>hello</c> messages.</p>
@@ -749,7 +749,7 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="open" arity="2"/>
+ <name name="open" arity="2" since="OTP R15B02"/>
<fsummary>Opens a named NETCONF session and exchanges hello
messages.</fsummary>
<desc>
@@ -791,8 +791,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="send" arity="2"/>
- <name name="send" arity="3"/>
+ <name name="send" arity="2" since="OTP R16B02"/>
+ <name name="send" arity="3" since="OTP R16B02"/>
<fsummary>Sends an XML document to the server.</fsummary>
<desc>
<p>Sends an XML document to the server.</p>
@@ -804,8 +804,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="send_rpc" arity="2"/>
- <name name="send_rpc" arity="3"/>
+ <name name="send_rpc" arity="2" since="OTP R16B02"/>
+ <name name="send_rpc" arity="3" since="OTP R16B02"/>
<fsummary>Sends a NETCONF rpc request to the server.</fsummary>
<desc>
<p>Sends a NETCONF <c>rpc</c> request to the server.</p>
@@ -820,10 +820,10 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="session" arity="1"/>
- <name name="session" arity="2" clause_i="1"/>
- <name name="session" arity="2" clause_i="2"/>
- <name name="session" arity="3"/>
+ <name name="session" arity="1" since="OTP 20.0"/>
+ <name name="session" arity="2" clause_i="1" since="OTP 20.0"/>
+ <name name="session" arity="2" clause_i="2" since="OTP 20.0"/>
+ <name name="session" arity="3" since="OTP 20.0"/>
<fsummary>Opens a NETCONF session as a channel on the given SSH
connection, and exchanges hello messages with the
server.</fsummary>
@@ -848,8 +848,8 @@ create_subscription(Client, Stream, Filter, StartTime, StopTime, Timeout)</pre>
</func>
<func>
- <name name="unlock" arity="2"/>
- <name name="unlock" arity="3"/>
+ <name name="unlock" arity="2" since="OTP R15B02"/>
+ <name name="unlock" arity="3" since="OTP R15B02"/>
<fsummary>Unlocks the configuration target.</fsummary>
<desc>
<p>Unlocks the configuration target.</p>
diff --git a/lib/common_test/doc/src/ct_property_test.xml b/lib/common_test/doc/src/ct_property_test.xml
index 028e5eb69f..1e01d9a5d7 100644
--- a/lib/common_test/doc/src/ct_property_test.xml
+++ b/lib/common_test/doc/src/ct_property_test.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_property_test.xml</file>
</header>
- <module>ct_property_test</module>
+ <module since="OTP 17.3">ct_property_test</module>
<modulesummary>EXPERIMENTAL support in Common Test for calling
property-based tests.</modulesummary>
@@ -79,7 +79,7 @@
<funcs>
<func>
- <name>init_per_suite(Config) -&gt; Config | {skip, Reason}</name>
+ <name since="OTP 17.3">init_per_suite(Config) -&gt; Config | {skip, Reason}</name>
<fsummary>Initializes Config for property testing.</fsummary>
<desc><marker id="init_per_suite-1"/>
<p>Initializes <c>Config</c> for property testing.</p>
@@ -98,7 +98,7 @@
</func>
<func>
- <name>quickcheck(Property, Config) -&gt; true | {fail, Reason}</name>
+ <name since="OTP 17.3">quickcheck(Property, Config) -&gt; true | {fail, Reason}</name>
<fsummary>Calls quickcheck and returns the result in a form suitable for
Common Test.</fsummary>
<desc><marker id="quickcheck-2"/>
diff --git a/lib/common_test/doc/src/ct_rpc.xml b/lib/common_test/doc/src/ct_rpc.xml
index 90e6b833f7..00a4dcec08 100644
--- a/lib/common_test/doc/src/ct_rpc.xml
+++ b/lib/common_test/doc/src/ct_rpc.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_rpc.xml</file>
</header>
- <module>ct_rpc</module>
+ <module since="">ct_rpc</module>
<modulesummary>Common Test specific layer on Erlang/OTP rpc.</modulesummary>
<description>
@@ -43,7 +43,7 @@
<funcs>
<func>
- <name>app_node(App, Candidates) -&gt; NodeName</name>
+ <name since="">app_node(App, Candidates) -&gt; NodeName</name>
<fsummary>From a set of candidate nodes determines which of them is
running the application App.</fsummary>
<type>
@@ -61,7 +61,7 @@
</func>
<func>
- <name>app_node(App, Candidates, FailOnBadRPC) -&gt; NodeName</name>
+ <name since="">app_node(App, Candidates, FailOnBadRPC) -&gt; NodeName</name>
<fsummary>Same as app_node/2, except that argument FailOnBadRPC
determines if the search for a candidate node is to stop if
badrpc is received at some point.</fsummary>
@@ -81,7 +81,7 @@
</func>
<func>
- <name>app_node(App, Candidates, FailOnBadRPC, Cookie) -&gt; NodeName</name>
+ <name since="">app_node(App, Candidates, FailOnBadRPC, Cookie) -&gt; NodeName</name>
<fsummary>Same as app_node/2, except that argument FailOnBadRPC
determines if the search for a candidate node is to stop if badrpc is
received at some point.</fsummary>
@@ -105,7 +105,7 @@
</func>
<func>
- <name>call(Node, Module, Function, Args) -&gt; term() | {badrpc, Reason}</name>
+ <name since="">call(Node, Module, Function, Args) -&gt; term() | {badrpc, Reason}</name>
<fsummary>Same as call(Node, Module, Function, Args, infinity).</fsummary>
<desc><marker id="call-4"/>
<p>Same as <c>call(Node, Module, Function, Args, infinity)</c>.</p>
@@ -113,7 +113,7 @@
</func>
<func>
- <name>call(Node, Module, Function, Args, TimeOut) -&gt; term() | {badrpc, Reason}</name>
+ <name since="">call(Node, Module, Function, Args, TimeOut) -&gt; term() | {badrpc, Reason}</name>
<fsummary>Evaluates apply(Module, Function, Args) on the node
Node.</fsummary>
<type>
@@ -136,7 +136,7 @@
</func>
<func>
- <name>call(Node, Module, Function, Args, TimeOut, Cookie) -&gt; term() | {badrpc, Reason}</name>
+ <name since="">call(Node, Module, Function, Args, TimeOut, Cookie) -&gt; term() | {badrpc, Reason}</name>
<fsummary>Evaluates apply(Module, Function, Args) on the node
Node.</fsummary>
<type>
@@ -163,7 +163,7 @@
</func>
<func>
- <name>cast(Node, Module, Function, Args) -&gt; ok</name>
+ <name since="">cast(Node, Module, Function, Args) -&gt; ok</name>
<fsummary>Evaluates apply(Module, Function, Args) on the node
Node.</fsummary>
<type>
@@ -187,7 +187,7 @@
</func>
<func>
- <name>cast(Node, Module, Function, Args, Cookie) -&gt; ok</name>
+ <name since="">cast(Node, Module, Function, Args, Cookie) -&gt; ok</name>
<fsummary>Evaluates apply(Module, Function, Args) on the node
Node.</fsummary>
<type>
diff --git a/lib/common_test/doc/src/ct_slave.xml b/lib/common_test/doc/src/ct_slave.xml
index 9d9aa50051..84e619482d 100644
--- a/lib/common_test/doc/src/ct_slave.xml
+++ b/lib/common_test/doc/src/ct_slave.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_slave.xml</file>
</header>
- <module>ct_slave</module>
+ <module since="OTP R14B">ct_slave</module>
<modulesummary>Common Test framework functions for starting and stopping
nodes for Large-Scale Testing.</modulesummary>
@@ -50,7 +50,7 @@
<funcs>
<func>
- <name>start(Node) -&gt; Result</name>
+ <name since="OTP R14B">start(Node) -&gt; Result</name>
<fsummary>Starts an Erlang node with name Node on the local
host.</fsummary>
<type>
@@ -68,7 +68,7 @@
</func>
<func>
- <name>start(HostOrNode, NodeOrOpts) -&gt; Result</name>
+ <name since="OTP R14B">start(HostOrNode, NodeOrOpts) -&gt; Result</name>
<fsummary>Starts an Erlang node with default options on a specified
host, or on the local host with specified options.</fsummary>
<type>
@@ -90,7 +90,7 @@
</func>
<func>
- <name>start(Host, Node, Opts) -&gt; Result</name>
+ <name since="OTP R14B">start(Host, Node, Opts) -&gt; Result</name>
<fsummary>Starts an Erlang node with name Node on host Host as
specified by the combination of options in Opts.</fsummary>
<type>
@@ -184,7 +184,7 @@
</func>
<func>
- <name>stop(Node) -&gt; Result</name>
+ <name since="OTP R14B">stop(Node) -&gt; Result</name>
<fsummary>Stops the running Erlang node with name Node on the local
host.</fsummary>
<type>
@@ -199,7 +199,7 @@
</func>
<func>
- <name>stop(Host, Node) -&gt; Result</name>
+ <name since="OTP R14B">stop(Host, Node) -&gt; Result</name>
<fsummary>Stops the running Erlang node with name Node on host
Host.</fsummary>
<type>
diff --git a/lib/common_test/doc/src/ct_snmp.xml b/lib/common_test/doc/src/ct_snmp.xml
index 0a5e52b16c..343781814a 100644
--- a/lib/common_test/doc/src/ct_snmp.xml
+++ b/lib/common_test/doc/src/ct_snmp.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_snmp.xml</file>
</header>
- <module>ct_snmp</module>
+ <module since="">ct_snmp</module>
<modulesummary>Common Test user interface module for the SNMP application.</modulesummary>
<description>
@@ -240,7 +240,7 @@
<funcs>
<func>
- <name>get_next_values(Agent, Oids, MgrAgentConfName) -&gt; SnmpReply</name>
+ <name since="">get_next_values(Agent, Oids, MgrAgentConfName) -&gt; SnmpReply</name>
<fsummary>Issues a synchronous SNMP get next request.</fsummary>
<type>
<v>Agent = agent_name()</v>
@@ -254,7 +254,7 @@
</func>
<func>
- <name>get_values(Agent, Oids, MgrAgentConfName) -&gt; SnmpReply</name>
+ <name since="">get_values(Agent, Oids, MgrAgentConfName) -&gt; SnmpReply</name>
<fsummary>Issues a synchronous SNMP get request.</fsummary>
<type>
<v>Agent = agent_name()</v>
@@ -268,7 +268,7 @@
</func>
<func>
- <name>load_mibs(Mibs) -&gt; ok | {error, Reason}</name>
+ <name since="">load_mibs(Mibs) -&gt; ok | {error, Reason}</name>
<fsummary>Loads the MIBs into agent snmp_master_agent.</fsummary>
<type>
<v>Mibs = [MibName]</v>
@@ -281,7 +281,7 @@
</func>
<func>
- <name>register_agents(MgrAgentConfName, ManagedAgents) -&gt; ok | {error, Reason}</name>
+ <name since="">register_agents(MgrAgentConfName, ManagedAgents) -&gt; ok | {error, Reason}</name>
<fsummary>Explicitly instructs the manager to handle this
agent.</fsummary>
<type>
@@ -300,7 +300,7 @@
</func>
<func>
- <name>register_users(MgrAgentConfName, Users) -&gt; ok | {error, Reason}</name>
+ <name since="">register_users(MgrAgentConfName, Users) -&gt; ok | {error, Reason}</name>
<fsummary>Registers the manager entity (=user) responsible for specific
agent(s).</fsummary>
<type>
@@ -319,7 +319,7 @@
</func>
<func>
- <name>register_usm_users(MgrAgentConfName, UsmUsers) -&gt; ok | {error, Reason}</name>
+ <name since="">register_usm_users(MgrAgentConfName, UsmUsers) -&gt; ok | {error, Reason}</name>
<fsummary>Explicitly instructs the manager to handle this USM user.</fsummary>
<type>
<v>MgrAgentConfName = atom()</v>
@@ -337,7 +337,7 @@
</func>
<func>
- <name>set_info(Config) -&gt; [{Agent, OldVarsAndVals, NewVarsAndVals}]</name>
+ <name since="">set_info(Config) -&gt; [{Agent, OldVarsAndVals, NewVarsAndVals}]</name>
<fsummary>Returns a list of all successful set requests performed in the
test case in reverse order.</fsummary>
<type>
@@ -357,7 +357,7 @@
</func>
<func>
- <name>set_values(Agent, VarsAndVals, MgrAgentConfName, Config) -&gt; SnmpReply</name>
+ <name since="">set_values(Agent, VarsAndVals, MgrAgentConfName, Config) -&gt; SnmpReply</name>
<fsummary>Issues a synchronous SNMP set request.</fsummary>
<type>
<v>Agent = agent_name()</v>
@@ -372,7 +372,7 @@
</func>
<func>
- <name>start(Config, MgrAgentConfName) -&gt; ok</name>
+ <name since="">start(Config, MgrAgentConfName) -&gt; ok</name>
<fsummary>Equivalent to start(Config, MgrAgentConfName,
undefined).</fsummary>
<desc><marker id="start-2"/>
@@ -383,7 +383,7 @@
</func>
<func>
- <name>start(Config, MgrAgentConfName, SnmpAppConfName) -&gt; ok</name>
+ <name since="">start(Config, MgrAgentConfName, SnmpAppConfName) -&gt; ok</name>
<fsummary>Starts an SNMP manager and/or agent.</fsummary>
<type>
<v>Config = [{Key, Value}]</v>
@@ -415,7 +415,7 @@
</func>
<func>
- <name>stop(Config) -&gt; ok</name>
+ <name since="">stop(Config) -&gt; ok</name>
<fsummary>Stops the SNMP manager and/or agent, and removes all files
created.</fsummary>
<type>
@@ -430,7 +430,7 @@
</func>
<func>
- <name>unload_mibs(Mibs) -&gt; ok | {error, Reason}</name>
+ <name since="OTP R16B">unload_mibs(Mibs) -&gt; ok | {error, Reason}</name>
<fsummary>Unloads the MIBs from agent snmp_master_agent.</fsummary>
<type>
<v>Mibs = [MibName]</v>
@@ -443,7 +443,7 @@
</func>
<func>
- <name>unregister_agents(MgrAgentConfName) -&gt; ok</name>
+ <name since="">unregister_agents(MgrAgentConfName) -&gt; ok</name>
<fsummary>Unregisters all managed agents.</fsummary>
<type>
<v>MgrAgentConfName = atom()</v>
@@ -455,7 +455,7 @@
</func>
<func>
- <name>unregister_agents(MgrAgentConfName, ManagedAgents) -&gt; ok</name>
+ <name since="OTP R16B">unregister_agents(MgrAgentConfName, ManagedAgents) -&gt; ok</name>
<fsummary>Unregisters the specified managed agents.</fsummary>
<type>
<v>MgrAgentConfName = atom()</v>
@@ -468,7 +468,7 @@
</func>
<func>
- <name>unregister_users(MgrAgentConfName) -&gt; ok</name>
+ <name since="">unregister_users(MgrAgentConfName) -&gt; ok</name>
<fsummary>Unregisters all users.</fsummary>
<type>
<v>MgrAgentConfName = atom()</v>
@@ -480,7 +480,7 @@
</func>
<func>
- <name>unregister_users(MgrAgentConfName, Users) -&gt; ok</name>
+ <name since="OTP R16B">unregister_users(MgrAgentConfName, Users) -&gt; ok</name>
<fsummary>Unregisters the specified users.</fsummary>
<type>
<v>MgrAgentConfName = atom()</v>
@@ -493,7 +493,7 @@
</func>
<func>
- <name>unregister_usm_users(MgrAgentConfName) -&gt; ok</name>
+ <name since="OTP R16B">unregister_usm_users(MgrAgentConfName) -&gt; ok</name>
<fsummary>Unregisters all USM users.</fsummary>
<type>
<v>MgrAgentConfName = atom()</v>
@@ -505,7 +505,7 @@
</func>
<func>
- <name>unregister_usm_users(MgrAgentConfName, UsmUsers) -&gt; ok</name>
+ <name since="OTP R16B">unregister_usm_users(MgrAgentConfName, UsmUsers) -&gt; ok</name>
<fsummary>Unregisters the specified USM users.</fsummary>
<type>
<v>MgrAgentConfName = atom()</v>
diff --git a/lib/common_test/doc/src/ct_ssh.xml b/lib/common_test/doc/src/ct_ssh.xml
index 0c7efed154..8d9f31aff8 100644
--- a/lib/common_test/doc/src/ct_ssh.xml
+++ b/lib/common_test/doc/src/ct_ssh.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_ssh.xml</file>
</header>
- <module>ct_ssh</module>
+ <module since="">ct_ssh</module>
<modulesummary>SSH/SFTP client module.</modulesummary>
<description>
@@ -95,7 +95,7 @@
<funcs>
<func>
- <name>apread(SSH, Handle, Position, Length) -&gt; Result</name>
+ <name since="">apread(SSH, Handle, Position, Length) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -109,7 +109,7 @@
</func>
<func>
- <name>apread(SSH, Server, Handle, Position, Length) -&gt; Result</name>
+ <name since="">apread(SSH, Server, Handle, Position, Length) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -123,7 +123,7 @@
</func>
<func>
- <name>apwrite(SSH, Handle, Position, Data) -&gt; Result</name>
+ <name since="">apwrite(SSH, Handle, Position, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -137,7 +137,7 @@
</func>
<func>
- <name>apwrite(SSH, Server, Handle, Position, Data) -&gt; Result</name>
+ <name since="">apwrite(SSH, Server, Handle, Position, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -151,7 +151,7 @@
</func>
<func>
- <name>aread(SSH, Handle, Len) -&gt; Result</name>
+ <name since="">aread(SSH, Handle, Len) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -165,7 +165,7 @@
</func>
<func>
- <name>aread(SSH, Server, Handle, Len) -&gt; Result</name>
+ <name since="">aread(SSH, Server, Handle, Len) -&gt; Result</name>
<fsummary>For inforamtion and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -179,7 +179,7 @@
</func>
<func>
- <name>awrite(SSH, Handle, Data) -&gt; Result</name>
+ <name since="">awrite(SSH, Handle, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -193,7 +193,7 @@
</func>
<func>
- <name>awrite(SSH, Server, Handle, Data) -&gt; Result</name>
+ <name since="">awrite(SSH, Server, Handle, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -207,7 +207,7 @@
</func>
<func>
- <name>close(SSH, Handle) -&gt; Result</name>
+ <name since="">close(SSH, Handle) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -221,7 +221,7 @@
</func>
<func>
- <name>close(SSH, Server, Handle) -&gt; Result</name>
+ <name since="">close(SSH, Server, Handle) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -235,7 +235,7 @@
</func>
<func>
- <name>connect(KeyOrName) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">connect(KeyOrName) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Equivalent to connect(KeyOrName, host, []).</fsummary>
<desc><marker id="connect-1"/>
<p>Equivalent to
@@ -245,7 +245,7 @@
</func>
<func>
- <name>connect(KeyOrName, ConnType) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">connect(KeyOrName, ConnType) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Equivalent to connect(KeyOrName, ConnType, []).</fsummary>
<desc><marker id="connect-2"/>
<p>Equivalent to
@@ -255,7 +255,7 @@
</func>
<func>
- <name>connect(KeyOrName, ConnType, ExtraOpts) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">connect(KeyOrName, ConnType, ExtraOpts) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Opens an SSH or SFTP connection using the information
associated with KeyOrName.</fsummary>
<type>
@@ -301,7 +301,7 @@
</func>
<func>
- <name>del_dir(SSH, Name) -&gt; Result</name>
+ <name since="">del_dir(SSH, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -315,7 +315,7 @@
</func>
<func>
- <name>del_dir(SSH, Server, Name) -&gt; Result</name>
+ <name since="">del_dir(SSH, Server, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -329,7 +329,7 @@
</func>
<func>
- <name>delete(SSH, Name) -&gt; Result</name>
+ <name since="">delete(SSH, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -343,7 +343,7 @@
</func>
<func>
- <name>delete(SSH, Server, Name) -&gt; Result</name>
+ <name since="">delete(SSH, Server, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -357,7 +357,7 @@
</func>
<func>
- <name>disconnect(SSH) -&gt; ok | {error, Reason}</name>
+ <name since="">disconnect(SSH) -&gt; ok | {error, Reason}</name>
<fsummary>Closes an SSH/SFTP connection.</fsummary>
<type>
<v>SSH = connection()</v>
@@ -369,7 +369,7 @@
</func>
<func>
- <name>exec(SSH, Command) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">exec(SSH, Command) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to exec(SSH, Command, DefaultTimeout).</fsummary>
<desc><marker id="exec-2"/>
<p>Equivalent to
@@ -379,7 +379,7 @@
</func>
<func>
- <name>exec(SSH, Command, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">exec(SSH, Command, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Requests server to perform Command.</fsummary>
<type>
<v>SSH = connection()</v>
@@ -396,7 +396,7 @@
</func>
<func>
- <name>exec(SSH, ChannelId, Command, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">exec(SSH, ChannelId, Command, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Requests server to perform Command.</fsummary>
<type>
<v>SSH = connection()</v>
@@ -414,7 +414,7 @@
</func>
<func>
- <name>get_file_info(SSH, Handle) -&gt; Result</name>
+ <name since="">get_file_info(SSH, Handle) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -428,7 +428,7 @@
</func>
<func>
- <name>get_file_info(SSH, Server, Handle) -&gt; Result</name>
+ <name since="">get_file_info(SSH, Server, Handle) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -442,7 +442,7 @@
</func>
<func>
- <name>list_dir(SSH, Path) -&gt; Result</name>
+ <name since="">list_dir(SSH, Path) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -456,7 +456,7 @@
</func>
<func>
- <name>list_dir(SSH, Server, Path) -&gt; Result</name>
+ <name since="">list_dir(SSH, Server, Path) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -470,7 +470,7 @@
</func>
<func>
- <name>make_dir(SSH, Name) -&gt; Result</name>
+ <name since="">make_dir(SSH, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -484,7 +484,7 @@
</func>
<func>
- <name>make_dir(SSH, Server, Name) -&gt; Result</name>
+ <name since="">make_dir(SSH, Server, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -498,7 +498,7 @@
</func>
<func>
- <name>make_symlink(SSH, Name, Target) -&gt; Result</name>
+ <name since="">make_symlink(SSH, Name, Target) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -512,7 +512,7 @@
</func>
<func>
- <name>make_symlink(SSH, Server, Name, Target) -&gt; Result</name>
+ <name since="">make_symlink(SSH, Server, Name, Target) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -526,7 +526,7 @@
</func>
<func>
- <name>open(SSH, File, Mode) -&gt; Result</name>
+ <name since="">open(SSH, File, Mode) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -540,7 +540,7 @@
</func>
<func>
- <name>open(SSH, Server, File, Mode) -&gt; Result</name>
+ <name since="">open(SSH, Server, File, Mode) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -554,7 +554,7 @@
</func>
<func>
- <name>opendir(SSH, Path) -&gt; Result</name>
+ <name since="">opendir(SSH, Path) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -568,7 +568,7 @@
</func>
<func>
- <name>opendir(SSH, Server, Path) -&gt; Result</name>
+ <name since="">opendir(SSH, Server, Path) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -582,7 +582,7 @@
</func>
<func>
- <name>position(SSH, Handle, Location) -&gt; Result</name>
+ <name since="">position(SSH, Handle, Location) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -596,7 +596,7 @@
</func>
<func>
- <name>position(SSH, Server, Handle, Location) -&gt; Result</name>
+ <name since="">position(SSH, Server, Handle, Location) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -610,7 +610,7 @@
</func>
<func>
- <name>pread(SSH, Handle, Position, Length) -&gt; Result</name>
+ <name since="">pread(SSH, Handle, Position, Length) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -624,7 +624,7 @@
</func>
<func>
- <name>pread(SSH, Server, Handle, Position, Length) -&gt; Result</name>
+ <name since="">pread(SSH, Server, Handle, Position, Length) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -638,7 +638,7 @@
</func>
<func>
- <name>pwrite(SSH, Handle, Position, Data) -&gt; Result</name>
+ <name since="">pwrite(SSH, Handle, Position, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -652,7 +652,7 @@
</func>
<func>
- <name>pwrite(SSH, Server, Handle, Position, Data) -&gt; Result</name>
+ <name since="">pwrite(SSH, Server, Handle, Position, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -666,7 +666,7 @@
</func>
<func>
- <name>read(SSH, Handle, Len) -&gt; Result</name>
+ <name since="">read(SSH, Handle, Len) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -680,7 +680,7 @@
</func>
<func>
- <name>read(SSH, Server, Handle, Len) -&gt; Result</name>
+ <name since="">read(SSH, Server, Handle, Len) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -694,7 +694,7 @@
</func>
<func>
- <name>read_file(SSH, File) -&gt; Result</name>
+ <name since="">read_file(SSH, File) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -708,7 +708,7 @@
</func>
<func>
- <name>read_file(SSH, Server, File) -&gt; Result</name>
+ <name since="">read_file(SSH, Server, File) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -722,7 +722,7 @@
</func>
<func>
- <name>read_file_info(SSH, Name) -&gt; Result</name>
+ <name since="">read_file_info(SSH, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -736,7 +736,7 @@
</func>
<func>
- <name>read_file_info(SSH, Server, Name) -&gt; Result</name>
+ <name since="">read_file_info(SSH, Server, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -750,7 +750,7 @@
</func>
<func>
- <name>read_link(SSH, Name) -&gt; Result</name>
+ <name since="">read_link(SSH, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -764,7 +764,7 @@
</func>
<func>
- <name>read_link(SSH, Server, Name) -&gt; Result</name>
+ <name since="">read_link(SSH, Server, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -778,7 +778,7 @@
</func>
<func>
- <name>read_link_info(SSH, Name) -&gt; Result</name>
+ <name since="">read_link_info(SSH, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -792,7 +792,7 @@
</func>
<func>
- <name>read_link_info(SSH, Server, Name) -&gt; Result</name>
+ <name since="">read_link_info(SSH, Server, Name) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -806,7 +806,7 @@
</func>
<func>
- <name>receive_response(SSH, ChannelId) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">receive_response(SSH, ChannelId) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to receive_response(SSH, ChannelId,
close).</fsummary>
<desc><marker id="receive_response-2"/>
@@ -817,7 +817,7 @@ ChannelId, close)</c></seealso>.</p>
</func>
<func>
- <name>receive_response(SSH, ChannelId, End) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">receive_response(SSH, ChannelId, End) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to receive_response(SSH, ChannelId, End,
DefaultTimeout).</fsummary>
<desc><marker id="receive_response-3"/>
@@ -828,7 +828,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>receive_response(SSH, ChannelId, End, Timeout) -&gt; {ok, Data} | {timeout, Data} | {error, Reason}</name>
+ <name since="">receive_response(SSH, ChannelId, End, Timeout) -&gt; {ok, Data} | {timeout, Data} | {error, Reason}</name>
<fsummary>Receives expected data from server on the specified session
channel.</fsummary>
<type>
@@ -863,7 +863,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>rename(SSH, OldName, NewName) -&gt; Result</name>
+ <name since="">rename(SSH, OldName, NewName) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -877,7 +877,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>rename(SSH, Server, OldName, NewName) -&gt; Result</name>
+ <name since="">rename(SSH, Server, OldName, NewName) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -891,7 +891,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>send(SSH, ChannelId, Data) -&gt; ok | {error, Reason}</name>
+ <name since="">send(SSH, ChannelId, Data) -&gt; ok | {error, Reason}</name>
<fsummary>Equivalent to send(SSH, ChannelId, 0, Data,
DefaultTimeout).</fsummary>
<desc><marker id="send-3"/>
@@ -901,7 +901,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>send(SSH, ChannelId, Data, Timeout) -&gt; ok | {error, Reason}</name>
+ <name since="">send(SSH, ChannelId, Data, Timeout) -&gt; ok | {error, Reason}</name>
<fsummary>Equivalent to send(SSH, ChannelId, 0, Data, Timeout).</fsummary>
<desc><marker id="send-4"/>
<p>Equivalent to <seealso marker="#send-5"><c>ct_ssh:send(SSH,
@@ -910,7 +910,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>send(SSH, ChannelId, Type, Data, Timeout) -&gt; ok | {error, Reason}</name>
+ <name since="">send(SSH, ChannelId, Type, Data, Timeout) -&gt; ok | {error, Reason}</name>
<fsummary>Sends data to server on specified session channel.</fsummary>
<type>
<v>SSH = connection()</v>
@@ -926,7 +926,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>send_and_receive(SSH, ChannelId, Data) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">send_and_receive(SSH, ChannelId, Data) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to send_and_receive(SSH, ChannelId, Data,
close).</fsummary>
<desc><marker id="send_and_receive-3"/>
@@ -937,7 +937,7 @@ ChannelId, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>send_and_receive(SSH, ChannelId, Data, End) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">send_and_receive(SSH, ChannelId, Data, End) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to send_and_receive(SSH, ChannelId, 0, Data, End,
DefaultTimeout).</fsummary>
<desc><marker id="send_and_receive-4"/>
@@ -948,7 +948,7 @@ ChannelId, 0, Data, End, DefaultTimeout)</c></seealso>.</p>
</func>
<func>
- <name>send_and_receive(SSH, ChannelId, Data, End, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">send_and_receive(SSH, ChannelId, Data, End, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to send_and_receive(SSH, ChannelId, 0, Data, End,
Timeout).</fsummary>
<desc><marker id="send_and_receive-5"/>
@@ -959,7 +959,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>send_and_receive(SSH, ChannelId, Type, Data, End, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">send_and_receive(SSH, ChannelId, Type, Data, End, Timeout) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Sends data to server on specified session channel and waits
to receive the server response.</fsummary>
<type>
@@ -981,7 +981,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>session_close(SSH, ChannelId) -&gt; ok | {error, Reason}</name>
+ <name since="">session_close(SSH, ChannelId) -&gt; ok | {error, Reason}</name>
<fsummary>Closes an SSH session channel.</fsummary>
<type>
<v>SSH = connection()</v>
@@ -994,7 +994,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>session_open(SSH) -&gt; {ok, ChannelId} | {error, Reason}</name>
+ <name since="">session_open(SSH) -&gt; {ok, ChannelId} | {error, Reason}</name>
<fsummary>Equivalent to session_open(SSH, DefaultTimeout).</fsummary>
<desc><marker id="session_open-1"/>
<p>Equivalent to
@@ -1004,7 +1004,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>session_open(SSH, Timeout) -&gt; {ok, ChannelId} | {error, Reason}</name>
+ <name since="">session_open(SSH, Timeout) -&gt; {ok, ChannelId} | {error, Reason}</name>
<fsummary>Opens a channel for an SSH session.</fsummary>
<type>
<v>SSH = connection()</v>
@@ -1018,7 +1018,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>sftp_connect(SSH) -&gt; {ok, Server} | {error, Reason}</name>
+ <name since="">sftp_connect(SSH) -&gt; {ok, Server} | {error, Reason}</name>
<fsummary>Starts an SFTP session on an already existing SSH
connection.</fsummary>
<type>
@@ -1034,7 +1034,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>shell(SSH, ChannelId) -&gt; ok | {error, Reason}</name>
+ <name since="OTP 20.0">shell(SSH, ChannelId) -&gt; ok | {error, Reason}</name>
<fsummary>Equivalent to shell(SSH, ChannelId, DefaultTimeout).</fsummary>
<desc><marker id="shell-2"/>
<p>Equivalent to
@@ -1044,7 +1044,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>shell(SSH, ChannelId, Timeout) -&gt; ok | {error, Reason}</name>
+ <name since="OTP 20.0">shell(SSH, ChannelId, Timeout) -&gt; ok | {error, Reason}</name>
<fsummary>Requests that the user default shell is executed at the
server end.</fsummary>
<type>
@@ -1061,7 +1061,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>subsystem(SSH, ChannelId, Subsystem) -&gt; Status | {error, Reason}</name>
+ <name since="">subsystem(SSH, ChannelId, Subsystem) -&gt; Status | {error, Reason}</name>
<fsummary>Equivalent to subsystem(SSH, ChannelId, Subsystem,
DefaultTimeout).</fsummary>
<desc><marker id="subsystem-3"/>
@@ -1072,7 +1072,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>subsystem(SSH, ChannelId, Subsystem, Timeout) -&gt; Status | {error, Reason}</name>
+ <name since="">subsystem(SSH, ChannelId, Subsystem, Timeout) -&gt; Status | {error, Reason}</name>
<fsummary>Sends a request to execute a predefined subsystem.</fsummary>
<type>
<v>SSH = connection()</v>
@@ -1088,7 +1088,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>write(SSH, Handle, Data) -&gt; Result</name>
+ <name since="">write(SSH, Handle, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -1102,7 +1102,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>write(SSH, Server, Handle, Data) -&gt; Result</name>
+ <name since="">write(SSH, Server, Handle, Data) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -1116,7 +1116,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>write_file(SSH, File, Iolist) -&gt; Result</name>
+ <name since="">write_file(SSH, File, Iolist) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -1130,7 +1130,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>write_file(SSH, Server, File, Iolist) -&gt; Result</name>
+ <name since="">write_file(SSH, Server, File, Iolist) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -1144,7 +1144,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>write_file_info(SSH, Name, Info) -&gt; Result</name>
+ <name since="">write_file_info(SSH, Name, Info) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
@@ -1158,7 +1158,7 @@ ChannelId, 0, Data, End, Timeout)</c></seealso>.</p>
</func>
<func>
- <name>write_file_info(SSH, Server, Name, Info) -&gt; Result</name>
+ <name since="">write_file_info(SSH, Server, Name, Info) -&gt; Result</name>
<fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
diff --git a/lib/common_test/doc/src/ct_telnet.xml b/lib/common_test/doc/src/ct_telnet.xml
index 8e85cccc99..76f5305c46 100644
--- a/lib/common_test/doc/src/ct_telnet.xml
+++ b/lib/common_test/doc/src/ct_telnet.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_telnet.xml</file>
</header>
- <module>ct_telnet</module>
+ <module since="">ct_telnet</module>
<modulesummary>Common Test specific layer on top of Telnet client ct_telnet_client.erl</modulesummary>
<description>
@@ -205,7 +205,7 @@
<funcs>
<func>
- <name>close(Connection) -&gt; ok | {error, Reason}</name>
+ <name since="">close(Connection) -&gt; ok | {error, Reason}</name>
<fsummary>Closes the Telnet connection and stops the process managing
it.</fsummary>
<type>
@@ -223,7 +223,7 @@
</func>
<func>
- <name>cmd(Connection, Cmd) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">cmd(Connection, Cmd) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to cmd(Connection, Cmd, []).</fsummary>
<desc><marker id="cmd-2"/>
<p>Equivalent to
@@ -233,24 +233,27 @@
</func>
<func>
- <name>cmd(Connection, Cmd, Opts) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">cmd(Connection, Cmd, Opts) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Sends a command through Telnet and waits for prompt.</fsummary>
<type>
<v>Connection = connection()</v>
<v>Cmd = string()</v>
<v>Opts = [Opt]</v>
- <v>Opt = {timeout, timeout()} | {newline, boolean()}</v>
+ <v>Opt = {timeout, timeout()} | {newline, boolean() | string()}</v>
<v>Data = [string()]</v>
<v>Reason = term()</v>
</type>
<desc><marker id="cmd-3"/>
<p>Sends a command through Telnet and waits for prompt.</p>
- <p>By default, this function adds a new line to the end of the
+ <p>By default, this function adds "\n" to the end of the
specified command. If this is not desired, use option
<c>{newline,false}</c>. This is necessary, for example, when
sending Telnet command sequences prefixed with character
- Interprete As Command (IAC).</p>
+ Interpret As Command (IAC). Option <c>{newline,string()}</c>
+ can also be used if a different line end than "\n" is
+ required, for instance <c>{newline,"\r\n"}</c>, to add both
+ carriage return and newline characters.</p>
<p>Option <c>timeout</c> specifies how long the client must wait
for prompt. If the time expires, the function returns
@@ -262,7 +265,7 @@
</func>
<func>
- <name>cmdf(Connection, CmdFormat, Args) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">cmdf(Connection, CmdFormat, Args) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Equivalent to cmdf(Connection, CmdFormat, Args, []).</fsummary>
<desc><marker id="cmdf-3"/>
<p>Equivalent to
@@ -272,7 +275,7 @@
</func>
<func>
- <name>cmdf(Connection, CmdFormat, Args, Opts) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">cmdf(Connection, CmdFormat, Args, Opts) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Sends a Telnet command and waits for prompt (uses a format
string and a list of arguments to build the command).</fsummary>
<type>
@@ -280,7 +283,7 @@
<v>CmdFormat = string()</v>
<v>Args = list()</v>
<v>Opts = [Opt]</v>
- <v>Opt = {timeout, timeout()} | {newline, boolean()}</v>
+ <v>Opt = {timeout, timeout()} | {newline, boolean() | string()}</v>
<v>Data = [string()]</v>
<v>Reason = term()</v>
</type>
@@ -294,7 +297,7 @@
</func>
<func>
- <name>expect(Connection, Patterns) -&gt; term()</name>
+ <name since="">expect(Connection, Patterns) -&gt; term()</name>
<fsummary>Equivalent to expect(Connections, Patterns, []).</fsummary>
<desc><marker id="expect-2"/>
<p>Equivalent to
@@ -304,7 +307,7 @@
</func>
<func>
- <name>expect(Connection, Patterns, Opts) -&gt; {ok, Match} | {ok, MatchList, HaltReason} | {error, Reason}</name>
+ <name since="">expect(Connection, Patterns, Opts) -&gt; {ok, Match} | {ok, MatchList, HaltReason} | {error, Reason}</name>
<fsummary>Gets data from Telnet and waits for the expected
pattern.</fsummary>
<type>
@@ -339,7 +342,7 @@
subexpression number <c>N</c>. Subexpressions are denoted with
<c>'(' ')'</c> in the regular expression.</p>
- <p>If a <c>Tag</c> is speciifed, the returned <c>Match</c> also
+ <p>If a <c>Tag</c> is specified, the returned <c>Match</c> also
includes the matched <c>Tag</c>. Otherwise, only <c>RxMatch</c>
is returned.</p>
@@ -382,7 +385,7 @@
can abort the operation of waiting for prompt.</p></item>
<tag><c>repeat | repeat, N</c></tag>
<item><p>The pattern(s) must be matched multiple times. If <c>N</c>
- is speciified, the pattern(s) are matched <c>N</c> times, and
+ is specified, the pattern(s) are matched <c>N</c> times, and
the function returns <c>HaltReason = done</c>. This option can be
interrupted by one or more <c>HaltPatterns</c>. <c>MatchList</c>
is always returned, that is, a list of <c>Match</c> instead of
@@ -422,7 +425,7 @@
</func>
<func>
- <name>get_data(Connection) -&gt; {ok, Data} | {error, Reason}</name>
+ <name since="">get_data(Connection) -&gt; {ok, Data} | {error, Reason}</name>
<fsummary>Gets all data received by the Telnet client since the last
command was sent.</fsummary>
<type>
@@ -446,7 +449,7 @@
</func>
<func>
- <name>open(Name) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">open(Name) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Equivalent to open(Name, telnet).</fsummary>
<desc><marker id="open-1"/>
<p>Equivalent to
@@ -456,7 +459,7 @@
</func>
<func>
- <name>open(Name, ConnType) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">open(Name, ConnType) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Opens a Telnet connection to the specified target
host.</fsummary>
<type>
@@ -471,7 +474,7 @@
</func>
<func>
- <name>open(KeyOrName, ConnType, TargetMod) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">open(KeyOrName, ConnType, TargetMod) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Equivalent to open(KeyOrName, ConnType, TargetMod, []).</fsummary>
<desc><marker id="open-3"/>
<p>Equivalent to
@@ -481,7 +484,7 @@
</func>
<func>
- <name>open(KeyOrName, ConnType, TargetMod, Extra) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="">open(KeyOrName, ConnType, TargetMod, Extra) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Opens a Telnet connection to the specified target
host.</fsummary>
<type>
@@ -531,7 +534,7 @@
</func>
<func>
- <name>send(Connection, Cmd) -&gt; ok | {error, Reason}</name>
+ <name since="">send(Connection, Cmd) -&gt; ok | {error, Reason}</name>
<fsummary>Equivalent to send(Connection, Cmd, []).</fsummary>
<desc><marker id="send-2"/>
<p>Equivalent to
@@ -541,23 +544,26 @@
</func>
<func>
- <name>send(Connection, Cmd, Opts) -&gt; ok | {error, Reason}</name>
+ <name since="OTP 17.4">send(Connection, Cmd, Opts) -&gt; ok | {error, Reason}</name>
<fsummary>Sends a Telnet command and returns immediately.</fsummary>
<type>
<v>Connection = connection()</v>
<v>Cmd = string()</v>
<v>Opts = [Opt]</v>
- <v>Opt = {newline, boolean()}</v>
+ <v>Opt = {newline, boolean() | string()}</v>
<v>Reason = term()</v>
</type>
<desc><marker id="send-3"/>
<p>Sends a Telnet command and returns immediately.</p>
- <p>By default, this function adds a newline to the end of the
+ <p>By default, this function adds "\n" to the end of the
specified command. If this is not desired, option
<c>{newline,false}</c> can be used. This is necessary, for example,
when sending Telnet command sequences prefixed with character
- Interprete As Command (IAC).</p>
+ Interpret As Command (IAC). Option <c>{newline,string()}</c>
+ can also be used if a different line end than "\n" is
+ required, for instance <c>{newline,"\r\n"}</c>, to add both
+ carriage return and newline characters.</p>
<p>The resulting output from the command can be read with
<seealso marker="#get_data-1"><c>ct_telnet:get_data/2</c></seealso> or
@@ -566,7 +572,7 @@
</func>
<func>
- <name>sendf(Connection, CmdFormat, Args) -&gt; ok | {error, Reason}</name>
+ <name since="">sendf(Connection, CmdFormat, Args) -&gt; ok | {error, Reason}</name>
<fsummary>Equivalent to sendf(Connection, CmdFormat, Args, []).</fsummary>
<desc><marker id="sendf-3"/>
<p>Equivalent to
@@ -576,7 +582,7 @@
</func>
<func>
- <name>sendf(Connection, CmdFormat, Args, Opts) -&gt; ok | {error, Reason}</name>
+ <name since="OTP 17.4">sendf(Connection, CmdFormat, Args, Opts) -&gt; ok | {error, Reason}</name>
<fsummary>Sends a Telnet command and returns immediately (uses a format
string and a list of arguments to build the command).</fsummary>
<type>
@@ -584,12 +590,15 @@
<v>CmdFormat = string()</v>
<v>Args = list()</v>
<v>Opts = [Opt]</v>
- <v>Opt = {newline, boolean()}</v>
+ <v>Opt = {newline, boolean() | string()}</v>
<v>Reason = term()</v>
</type>
<desc><marker id="sendf-4"/>
<p>Sends a Telnet command and returns immediately (uses a format
string and a list of arguments to build the command).</p>
+
+ <p>For details, see
+ <seealso marker="#send-3"><c>ct_telnet:send/3</c></seealso>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/common_test/doc/src/ct_testspec.xml b/lib/common_test/doc/src/ct_testspec.xml
index 36893f66cf..9cb9a2ae9f 100644
--- a/lib/common_test/doc/src/ct_testspec.xml
+++ b/lib/common_test/doc/src/ct_testspec.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ct_testspec.xml</file>
</header>
- <module>ct_testspec</module>
+ <module since="OTP 19.3">ct_testspec</module>
<modulesummary>Parsing of test specifications for Common Test.
</modulesummary>
@@ -46,7 +46,7 @@
<funcs>
<func>
- <name>get_tests(SpecsIn) -&gt; {ok, [{Specs,Tests}]} | {error, Reason}</name>
+ <name since="OTP 19.3">get_tests(SpecsIn) -&gt; {ok, [{Specs,Tests}]} | {error, Reason}</name>
<fsummary>Parse the given test specification files and return the tests to run and skip.</fsummary>
<type>
<v>SpecsIn = [string()] | [[string()]]</v>
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index c8005d8f79..9c74146d73 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -33,6 +33,161 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.17.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The test result when a hook function fails is in general
+ the same as if the function that the hook is associated
+ with fails. For example, if <c>post_init_per_testcase</c>
+ fails the result is that the test case is skipped, as is
+ the case when <c>init_per_testcase</c> fails.This,
+ however, was earlier not true for timetrap timeouts or
+ other error situations where the process running the hook
+ function was killed. This is now corrected, so the error
+ handling should be the same no matter how the hook
+ function fails.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15717 Aux Id: ERIERL-334 </p>
+ </item>
+ <item>
+ <p>
+ In some rare cases, when two common_test nodes used the
+ same log directory, a timing problem could occur which
+ caused common_test to crash because it's log cache file
+ was unexpectedly empty. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15758 Aux Id: ERIERL-342 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Two new common_test hook functions are introduced:</p>
+ <p>
+ <c>post_groups/2</c>, which is called after
+ <c>Suite:groups/0</c><br/> <c>post_all/3</c>, which is
+ called after <c>Suite:all/0</c></p>
+ <p>
+ These functions allow modifying the return values from
+ the <c>groups/0</c> and <c>all/0</c> functions,
+ respectively.</p>
+ <p>
+ A new term, <c>{testcase,TestCase,RepeatProperties}</c>
+ is now also allowed in the return from <c>all/0</c>. This
+ can be used for repeating a single test case a specific
+ number of times, or until it fails or succeeds once.</p>
+ <p>
+ Own Id: OTP-14746 Aux Id: ERIERL-143 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.17.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ OTP internal test improvements.</p>
+ <p>
+ Own Id: OTP-15716</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug caused <c>ct:encrypt_config_file/3</c> and
+ <c>ct:decrypt_config_file/3</c> to fail with
+ <c>badmatch</c> if input parameter <c>KeyOrFile</c> was
+ <c>{key,string()}</c>. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15540</p>
+ </item>
+ <item>
+ <p>
+ The status of a test case which failed with timetrap
+ timeout in <c>end_per_testcase</c> could not be modified
+ by returning <c>{fail,Reason}</c> from a
+ <c>post_end_per_testcase</c> hook function. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-15584 Aux Id: ERIERL-282 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new variant of the <c>newline</c> option to
+ <c>ct_telnet:cmd/3</c> and <c>ct_telnet:send/3</c> is
+ added, which allows to specify a string to append as
+ newline indicator on a command. By default, the value is
+ "\n", but in some cases it is required to be "\r\n",
+ which this option allows.</p>
+ <p>
+ A faulty regular expression given as parameter to
+ <c>ct_telnet:expect/2,3</c> would earlier crash and look
+ like an internal error in common_test. A better error
+ indication is now given, but the test case will still
+ fail.</p>
+ <p>
+ Own Id: OTP-15229 Aux Id: ERIERL-203 </p>
+ </item>
+ <item>
+ <p>
+ Since the yang RFC allows more than one top element of
+ config data in an <c>edit-config</c> element,
+ <c>ct_netconfc:edit_config/3,4,5</c> can now take a list
+ of XML elements.</p>
+ <p>
+ Own Id: OTP-15298</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.16.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The Logger handler cth_log_redirect earlier called the
+ report callback (report_cb) before calling the logger
+ formatter. In some cases this would fail, since
+ cth_log_redirect could not handle report callbacks with
+ two arguments. This is now corrected, so only the
+ formatter will call the report callback.</p>
+ <p>
+ Own Id: OTP-15307</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.16</title>
<section><title>Improvements and New Features</title>
@@ -55,6 +210,44 @@
</section>
+<section><title>Common_Test 1.15.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The status of a test case which failed with timetrap
+ timeout in <c>end_per_testcase</c> could not be modified
+ by returning <c>{fail,Reason}</c> from a
+ <c>post_end_per_testcase</c> hook function. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-15584 Aux Id: ERIERL-282 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.15.4.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The status of a test case which failed with timetrap
+ timeout in <c>end_per_testcase</c> could not be modified
+ by returning <c>{fail,Reason}</c> from a
+ <c>post_end_per_testcase</c> hook function. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-15584 Aux Id: ERIERL-282 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.15.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -4006,8 +4199,3 @@
<section><title>common_test 1.3.0</title>
</section>
</chapter>
-
-
-
-
-
diff --git a/lib/common_test/doc/src/unix_telnet.xml b/lib/common_test/doc/src/unix_telnet.xml
index b2314a53ec..03d91b7dbe 100644
--- a/lib/common_test/doc/src/unix_telnet.xml
+++ b/lib/common_test/doc/src/unix_telnet.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>unix_telnet.xml</file>
</header>
- <module>unix_telnet</module>
+ <module since="">unix_telnet</module>
<modulesummary>Callback module for ct_telnet, for connecting to a Telnet
server on a UNIX host.</modulesummary>
@@ -80,7 +80,7 @@
<funcs>
<func>
- <name>connect(ConnName, Ip, Port, Timeout, KeepAlive, TCPNoDelay, Extra) -&gt; {ok, Handle} | {error, Reason}</name>
+ <name since="OTP 18.3.3">connect(ConnName, Ip, Port, Timeout, KeepAlive, TCPNoDelay, Extra) -&gt; {ok, Handle} | {error, Reason}</name>
<fsummary>Callback for ct_telnet.erl.</fsummary>
<type>
<v>ConnName = target_name()</v>
@@ -107,7 +107,7 @@
</func>
<func>
- <name>get_prompt_regexp() -&gt; PromptRegexp</name>
+ <name since="">get_prompt_regexp() -&gt; PromptRegexp</name>
<fsummary>Callback for ct_telnet.erl.</fsummary>
<type>
<v>PromptRegexp = prompt_regexp()</v>
diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml
index 82dc06834f..5eed748b08 100644
--- a/lib/common_test/doc/src/write_test_chapter.xml
+++ b/lib/common_test/doc/src/write_test_chapter.xml
@@ -455,8 +455,10 @@
GroupDefs = [GroupDef]
GroupDef = {GroupName,Properties,GroupsAndTestCases}
GroupName = atom()
- GroupsAndTestCases = [GroupDef | {group,GroupName} | TestCase]
- TestCase = atom()</pre>
+ GroupsAndTestCases = [GroupDef | {group,GroupName} | TestCase |
+ {testcase,TestCase,TCRepeatProps}]
+ TestCase = atom()
+ TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {repeat_until_fail,N}]</pre>
<p><c>GroupName</c> is the name of the group and must be unique within
the test suite module. Groups can be nested, by including a group definition
@@ -464,11 +466,11 @@
<c>Properties</c> is the list of execution
properties for the group. The possible values are as follows:</p>
<pre>
- Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+ Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]
Shuffle = shuffle | {shuffle,Seed}
Seed = {integer(),integer(),integer()}
- RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
- repeat_until_any_ok | repeat_until_any_fail
+ GroupRepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+ repeat_until_any_ok | repeat_until_any_fail
N = integer() | forever</pre>
<p><em>Explanations:</em></p>
@@ -481,8 +483,8 @@
Dependencies Between Test Cases and Suites.</p></item>
<tag><c>shuffle</c></tag>
<item><p>The cases in the group are executed in random order.</p></item>
- <tag><c>repeat</c></tag>
- <item><p>Orders <c>Common Test</c> to repeat execution of the cases in the
+ <tag><c>repeat, repeat_until_*</c></tag>
+ <item><p>Orders <c>Common Test</c> to repeat execution of all the cases in the
group a given number of times, or until any, or all, cases fail or succeed.</p></item>
</taglist>
@@ -496,7 +498,7 @@
<c>{group,GroupName}</c> to the <c>all/0</c> list.</p>
<p><em>Example:</em></p>
<pre>
- all() -> [testcase1, {group,group1}, testcase2, {group,group2}].</pre>
+ all() -> [testcase1, {group,group1}, {testcase,testcase2,[{repeat,10}]}, {group,group2}].</pre>
<p>Execution properties with a group tuple in
<c>all/0</c>: <c>{group,GroupName,Properties}</c> can also be specified.
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index a10d939919..a07e61199b 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -592,7 +592,7 @@ encrypt_config_file(SrcFileName, EncryptFileName, {file,KeyFile}) ->
encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) ->
_ = crypto:start(),
- {Key,IVec} = make_crypto_key(Key),
+ {CryptoKey,IVec} = make_crypto_key(Key),
case file:read_file(SrcFileName) of
{ok,Bin0} ->
Bin1 = term_to_binary({SrcFileName,Bin0}),
@@ -600,7 +600,7 @@ encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) ->
0 -> Bin1;
N -> list_to_binary([Bin1,random_bytes(8-N)])
end,
- EncBin = crypto:block_encrypt(des3_cbc, Key, IVec, Bin2),
+ EncBin = crypto:block_encrypt(des3_cbc, CryptoKey, IVec, Bin2),
case file:write_file(EncryptFileName, EncBin) of
ok ->
io:format("~ts --(encrypt)--> ~ts~n",
@@ -631,10 +631,10 @@ decrypt_config_file(EncryptFileName, TargetFileName, {file,KeyFile}) ->
decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) ->
_ = crypto:start(),
- {Key,IVec} = make_crypto_key(Key),
+ {CryptoKey,IVec} = make_crypto_key(Key),
case file:read_file(EncryptFileName) of
{ok,Bin} ->
- DecBin = crypto:block_decrypt(des3_cbc, Key, IVec, Bin),
+ DecBin = crypto:block_decrypt(des3_cbc, CryptoKey, IVec, Bin),
case catch binary_to_term(DecBin) of
{'EXIT',_} ->
{error,bad_file};
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 134ae0e1cc..dcf7c97244 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -696,9 +696,16 @@ end_tc(Mod,IPTC={init_per_testcase,_Func},_TCPid,Result,Args,Return) ->
end
end;
-end_tc(Mod,Func0,TCPid,Result,Args,Return) ->
+end_tc(Mod,Func00,TCPid,Result,Args,Return) ->
%% in case Mod == ct_framework, lookup the suite name
Suite = get_suite_name(Mod, Args),
+ {OnlyCleanup,Func0} =
+ case Func00 of
+ {cleanup,F0} ->
+ {true,F0};
+ _ ->
+ {false,Func00}
+ end,
{Func,FuncSpec,HookFunc} =
case Func0 of
{end_per_testcase_not_run,F} ->
@@ -742,6 +749,8 @@ end_tc(Mod,Func0,TCPid,Result,Args,Return) ->
case HookFunc of
undefined ->
{ok,Result};
+ _ when OnlyCleanup ->
+ {ok,Result};
_ ->
case ct_hooks:end_tc(Suite,HookFunc,Args,Result,Return) of
'$ct_no_change' ->
@@ -752,6 +761,8 @@ end_tc(Mod,Func0,TCPid,Result,Args,Return) ->
end,
FinalResult =
case get('$test_server_framework_test') of
+ _ when OnlyCleanup ->
+ Result1;
undefined ->
%% send sync notification so that event handlers may print
%% in the log file before it gets closed
@@ -1056,21 +1067,40 @@ group_or_func(Func, _Config) ->
%%% should be returned.
get_suite(Mod, all) ->
- case catch apply(Mod, groups, []) of
- {'EXIT',_} ->
- get_all(Mod, []);
- GroupDefs when is_list(GroupDefs) ->
- case catch ct_groups:find_groups(Mod, all, all, GroupDefs) of
- {error,_} = Error ->
- %% this makes test_server call error_in_suite as first
- %% (and only) test case so we can report Error properly
- [{?MODULE,error_in_suite,[[Error]]}];
- ConfTests ->
- get_all(Mod, ConfTests)
- end;
- _ ->
+ case safe_apply_groups_0(Mod,{ok,[]}) of
+ {ok,GroupDefs} ->
+ try ct_groups:find_groups(Mod, all, all, GroupDefs) of
+ ConfTests when is_list(ConfTests) ->
+ get_all(Mod, ConfTests)
+ catch
+ throw:{error,Error} ->
+ [{?MODULE,error_in_suite,[[{error,Error}]]}];
+ _:Error:S ->
+ [{?MODULE,error_in_suite,[[{error,{Error,S}}]]}]
+ end;
+ {error,{bad_return,_Bad}} ->
E = "Bad return value from "++atom_to_list(Mod)++":groups/0",
- [{?MODULE,error_in_suite,[[{error,list_to_atom(E)}]]}]
+ [{?MODULE,error_in_suite,[[{error,list_to_atom(E)}]]}];
+ {error,{bad_hook_return,Bad}} ->
+ E = "Bad return value from post_groups/2 hook function",
+ [{?MODULE,error_in_suite,[[{error,{list_to_atom(E),Bad}}]]}];
+ {error,{failed,ExitReason}} ->
+ case ct_util:get_testdata({error_in_suite,Mod}) of
+ undefined ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "~w:groups/0 failed: ~p~n",
+ [Mod,ExitReason]),
+ io:format(?def_gl, ErrStr, []),
+ %% save the error info so it doesn't get printed twice
+ ct_util:set_testdata_async({{error_in_suite,Mod},
+ ExitReason});
+ _ExitReason ->
+ ct_util:delete_testdata({error_in_suite,Mod})
+ end,
+ Reason = list_to_atom(atom_to_list(Mod)++":groups/0 failed"),
+ [{?MODULE,error_in_suite,[[{error,Reason}]]}];
+ {error,What} ->
+ [{?MODULE,error_in_suite,[[{error,What}]]}]
end;
%%!============================================================
@@ -1080,54 +1110,74 @@ get_suite(Mod, all) ->
%% group
get_suite(Mod, Group={conf,Props,_Init,TCs,_End}) ->
- Name = ?val(name, Props),
- case catch apply(Mod, groups, []) of
- {'EXIT',_} ->
- [Group];
- GroupDefs when is_list(GroupDefs) ->
- case catch ct_groups:find_groups(Mod, Name, TCs, GroupDefs) of
- {error,_} = Error ->
- %% this makes test_server call error_in_suite as first
- %% (and only) test case so we can report Error properly
- [{?MODULE,error_in_suite,[[Error]]}];
- [] ->
- [];
- ConfTests ->
- case lists:member(skipped, Props) of
- true ->
- %% a *subgroup* specified *only* as skipped (and not
- %% as an explicit test) should not be returned, or
- %% init/end functions for top groups will be executed
- case catch ?val(name, element(2, hd(ConfTests))) of
- Name -> % top group
- ct_groups:delete_subs(ConfTests, ConfTests);
- _ ->
- []
- end;
- false ->
- ConfTests1 = ct_groups:delete_subs(ConfTests,
- ConfTests),
- case ?val(override, Props) of
- undefined ->
- ConfTests1;
- [] ->
- ConfTests1;
- ORSpec ->
- ORSpec1 = if is_tuple(ORSpec) -> [ORSpec];
- true -> ORSpec end,
- ct_groups:search_and_override(ConfTests1,
- ORSpec1, Mod)
- end
- end
- end;
- _ ->
+ case safe_apply_groups_0(Mod,{ok,[Group]}) of
+ {ok,GroupDefs} ->
+ Name = ?val(name, Props),
+ try ct_groups:find_groups(Mod, Name, TCs, GroupDefs) of
+ [] ->
+ [];
+ ConfTests when is_list(ConfTests) ->
+ case lists:member(skipped, Props) of
+ true ->
+ %% a *subgroup* specified *only* as skipped (and not
+ %% as an explicit test) should not be returned, or
+ %% init/end functions for top groups will be executed
+ try ?val(name, element(2, hd(ConfTests))) of
+ Name -> % top group
+ ct_groups:delete_subs(ConfTests, ConfTests);
+ _ -> []
+ catch
+ _:_ -> []
+ end;
+ false ->
+ ConfTests1 = ct_groups:delete_subs(ConfTests,
+ ConfTests),
+ case ?val(override, Props) of
+ undefined ->
+ ConfTests1;
+ [] ->
+ ConfTests1;
+ ORSpec ->
+ ORSpec1 = if is_tuple(ORSpec) -> [ORSpec];
+ true -> ORSpec end,
+ ct_groups:search_and_override(ConfTests1,
+ ORSpec1, Mod)
+ end
+ end
+ catch
+ throw:{error,Error} ->
+ [{?MODULE,error_in_suite,[[{error,Error}]]}];
+ _:Error:S ->
+ [{?MODULE,error_in_suite,[[{error,{Error,S}}]]}]
+ end;
+ {error,{bad_return,_Bad}} ->
E = "Bad return value from "++atom_to_list(Mod)++":groups/0",
- [{?MODULE,error_in_suite,[[{error,list_to_atom(E)}]]}]
+ [{?MODULE,error_in_suite,[[{error,list_to_atom(E)}]]}];
+ {error,{bad_hook_return,Bad}} ->
+ E = "Bad return value from post_groups/2 hook function",
+ [{?MODULE,error_in_suite,[[{error,{list_to_atom(E),Bad}}]]}];
+ {error,{failed,ExitReason}} ->
+ case ct_util:get_testdata({error_in_suite,Mod}) of
+ undefined ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "~w:groups/0 failed: ~p~n",
+ [Mod,ExitReason]),
+ io:format(?def_gl, ErrStr, []),
+ %% save the error info so it doesn't get printed twice
+ ct_util:set_testdata_async({{error_in_suite,Mod},
+ ExitReason});
+ _ExitReason ->
+ ct_util:delete_testdata({error_in_suite,Mod})
+ end,
+ Reason = list_to_atom(atom_to_list(Mod)++":groups/0 failed"),
+ [{?MODULE,error_in_suite,[[{error,Reason}]]}];
+ {error,What} ->
+ [{?MODULE,error_in_suite,[[{error,What}]]}]
end;
%% testcase
get_suite(Mod, Name) ->
- get_seq(Mod, Name).
+ get_seq(Mod, Name).
%%%-----------------------------------------------------------------
@@ -1161,21 +1211,48 @@ get_all_cases1(_, []) ->
%%%-----------------------------------------------------------------
-get_all(Mod, ConfTests) ->
- case catch apply(Mod, all, []) of
- {'EXIT',{undef,[{Mod,all,[],_} | _]}} ->
+get_all(Mod, ConfTests) ->
+ case safe_apply_all_0(Mod) of
+ {ok,AllTCs} ->
+ %% expand group references using ConfTests
+ try ct_groups:expand_groups(AllTCs, ConfTests, Mod) of
+ {error,_} = Error ->
+ [{?MODULE,error_in_suite,[[Error]]}];
+ Tests0 ->
+ Tests = ct_groups:delete_subs(Tests0, Tests0),
+ expand_tests(Mod, Tests)
+ catch
+ throw:{error,Error} ->
+ [{?MODULE,error_in_suite,[[{error,Error}]]}];
+ _:Error:S ->
+ [{?MODULE,error_in_suite,[[{error,{Error,S}}]]}]
+ end;
+ Skip = {skip,_Reason} ->
+ Skip;
+ {error,undef} ->
+ Reason =
+ case code:which(Mod) of
+ non_existing ->
+ list_to_atom(
+ atom_to_list(Mod)++
+ " cannot be compiled or loaded");
+ _ ->
+ list_to_atom(
+ atom_to_list(Mod)++":all/0 is missing")
+ end,
+ %% this makes test_server call error_in_suite as first
+ %% (and only) test case so we can report Reason properly
+ [{?MODULE,error_in_suite,[[{error,Reason}]]}];
+ {error,{bad_return,_Bad}} ->
Reason =
- case code:which(Mod) of
- non_existing ->
- list_to_atom(atom_to_list(Mod)++
- " can not be compiled or loaded");
- _ ->
- list_to_atom(atom_to_list(Mod)++":all/0 is missing")
- end,
- %% this makes test_server call error_in_suite as first
- %% (and only) test case so we can report Reason properly
+ list_to_atom("Bad return value from "++
+ atom_to_list(Mod)++":all/0"),
[{?MODULE,error_in_suite,[[{error,Reason}]]}];
- {'EXIT',ExitReason} ->
+ {error,{bad_hook_return,Bad}} ->
+ Reason =
+ list_to_atom("Bad return value from post_all/3 hook function"),
+ [{?MODULE,error_in_suite,[[{error,{Reason,Bad}}]]}];
+ {error,{failed,ExitReason}} ->
case ct_util:get_testdata({error_in_suite,Mod}) of
undefined ->
ErrStr = io_lib:format("~n*** ERROR *** "
@@ -1192,28 +1269,8 @@ get_all(Mod, ConfTests) ->
%% this makes test_server call error_in_suite as first
%% (and only) test case so we can report Reason properly
[{?MODULE,error_in_suite,[[{error,Reason}]]}];
- AllTCs when is_list(AllTCs) ->
- case catch save_seqs(Mod,AllTCs) of
- {error,What} ->
- [{?MODULE,error_in_suite,[[{error,What}]]}];
- SeqsAndTCs ->
- %% expand group references in all() using ConfTests
- case catch ct_groups:expand_groups(SeqsAndTCs,
- ConfTests,
- Mod) of
- {error,_} = Error ->
- [{?MODULE,error_in_suite,[[Error]]}];
- Tests ->
- ct_groups:delete_subs(Tests, Tests)
- end
- end;
- Skip = {skip,_Reason} ->
- Skip;
- _ ->
- Reason =
- list_to_atom("Bad return value from "++
- atom_to_list(Mod)++":all/0"),
- [{?MODULE,error_in_suite,[[{error,Reason}]]}]
+ {error,What} ->
+ [{?MODULE,error_in_suite,[[{error,What}]]}]
end.
%%!============================================================
@@ -1571,3 +1628,74 @@ get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) ->
%%% -spec get_log_dir() -> {ok,LogDir}
get_log_dir() ->
ct_logs:get_log_dir(true).
+
+%%%-----------------------------------------------------------------
+%%% Call all and group callbacks and post_* hooks with error handling
+safe_apply_all_0(Mod) ->
+ try apply(Mod, all, []) of
+ AllTCs0 when is_list(AllTCs0) ->
+ try save_seqs(Mod,AllTCs0) of
+ SeqsAndTCs when is_list(SeqsAndTCs) ->
+ all_hook(Mod,SeqsAndTCs)
+ catch throw:{error,What} ->
+ {error,What}
+ end;
+ {skip,_}=Skip ->
+ all_hook(Mod,Skip);
+ Bad ->
+ {error,{bad_return,Bad}}
+ catch
+ _:Reason:Stacktrace ->
+ handle_callback_crash(Reason,Stacktrace,Mod,all,{error,undef})
+ end.
+
+all_hook(Mod, All) ->
+ case ct_hooks:all(Mod, All) of
+ AllTCs when is_list(AllTCs) ->
+ {ok,AllTCs};
+ {skip,_}=Skip ->
+ Skip;
+ {fail,Reason} ->
+ {error,Reason};
+ Bad ->
+ {error,{bad_hook_return,Bad}}
+ end.
+
+safe_apply_groups_0(Mod,Default) ->
+ try apply(Mod, groups, []) of
+ GroupDefs when is_list(GroupDefs) ->
+ case ct_hooks:groups(Mod, GroupDefs) of
+ GroupDefs1 when is_list(GroupDefs1) ->
+ {ok,GroupDefs1};
+ {fail,Reason} ->
+ {error,Reason};
+ Bad ->
+ {error,{bad_hook_return,Bad}}
+ end;
+ Bad ->
+ {error,{bad_return,Bad}}
+ catch
+ _:Reason:Stacktrace ->
+ handle_callback_crash(Reason,Stacktrace,Mod,groups,Default)
+ end.
+
+handle_callback_crash(undef,[{Mod,Func,[],_}|_],Mod,Func,Default) ->
+ case ct_hooks:Func(Mod, []) of
+ [] ->
+ Default;
+ List when is_list(List) ->
+ {ok,List};
+ {fail,Reason} ->
+ {error,Reason};
+ Bad ->
+ {error,{bad_hook_return,Bad}}
+ end;
+handle_callback_crash(Reason,Stacktrace,_Mod,_Func,_Default) ->
+ {error,{failed,{Reason,Stacktrace}}}.
+
+expand_tests(Mod, [{testcase,Case,[Prop]}|Tests]) ->
+ [{repeat,{Mod,Case},Prop}|expand_tests(Mod,Tests)];
+expand_tests(Mod,[Test|Tests]) ->
+ [Test|expand_tests(Mod,Tests)];
+expand_tests(_Mod,[]) ->
+ [].
diff --git a/lib/common_test/src/ct_groups.erl b/lib/common_test/src/ct_groups.erl
index d867069dce..f4b12c41c0 100644
--- a/lib/common_test/src/ct_groups.erl
+++ b/lib/common_test/src/ct_groups.erl
@@ -101,23 +101,34 @@ find(Mod, [], TCs, Tests, _Known, _Defs, false) ->
[{Mod,TC}];
({group,_}) ->
[];
+ ({testcase,TC,[Prop]}) when is_atom(TC), TC ==all ->
+ [{repeat,{Mod,TC},Prop}];
({_,_}=TC) when TCs == all ->
[TC];
- (TC) ->
- if is_atom(TC) ->
- Tuple = {Mod,TC},
- case lists:member(Tuple, TCs) of
- true ->
- [Tuple];
- false ->
- case lists:member(TC, TCs) of
- true -> [{Mod,TC}];
- false -> []
- end
- end;
- true ->
- []
- end
+ (TC) when is_atom(TC) ->
+ Tuple = {Mod,TC},
+ case lists:member(Tuple, TCs) of
+ true ->
+ [Tuple];
+ false ->
+ case lists:member(TC, TCs) of
+ true -> [Tuple];
+ false -> []
+ end
+ end;
+ ({testcase,TC,[Prop]}) when is_atom(TC) ->
+ Tuple = {Mod,TC},
+ case lists:member(Tuple, TCs) of
+ true ->
+ [{repeat,Tuple,Prop}];
+ false ->
+ case lists:member(TC, TCs) of
+ true -> [{repeat,Tuple,Prop}];
+ false -> []
+ end
+ end;
+ (_) ->
+ []
end, Tests),
if Cases == [] -> ['NOMATCH'];
true -> Cases
@@ -172,12 +183,19 @@ find(Mod, GrNames, all, [{M,TC} | Gs], Known,
Defs, FindAll) when is_atom(M), M /= group, is_atom(TC) ->
[{M,TC} | find(Mod, GrNames, all, Gs, Known, Defs, FindAll)];
+%% Save test case
+find(Mod, GrNames, all, [{testcase,TC,[Prop]} | Gs], Known,
+ Defs, FindAll) when is_atom(TC) ->
+ [{repeat,{Mod,TC},Prop} | find(Mod, GrNames, all, Gs, Known, Defs, FindAll)];
+
%% Check if test case should be saved
-find(Mod, GrNames, TCs, [TC | Gs], Known,
- Defs, FindAll) when is_atom(TC) orelse
- ((size(TC) == 2) and (element(1,TC) /= group)) ->
+find(Mod, GrNames, TCs, [TC | Gs], Known, Defs, FindAll)
+ when is_atom(TC) orelse
+ ((size(TC) == 3) andalso (element(1,TC) == testcase)) orelse
+ ((size(TC) == 2) and (element(1,TC) /= group)) ->
Case =
- if is_atom(TC) ->
+ case TC of
+ _ when is_atom(TC) ->
Tuple = {Mod,TC},
case lists:member(Tuple, TCs) of
true ->
@@ -188,7 +206,18 @@ find(Mod, GrNames, TCs, [TC | Gs], Known,
false -> []
end
end;
- true ->
+ {testcase,TC0,[Prop]} when is_atom(TC0) ->
+ Tuple = {Mod,TC0},
+ case lists:member(Tuple, TCs) of
+ true ->
+ {repeat,Tuple,Prop};
+ false ->
+ case lists:member(TC0, TCs) of
+ true -> {repeat,{Mod,TC0},Prop};
+ false -> []
+ end
+ end;
+ _ ->
case lists:member(TC, TCs) of
true -> {Mod,TC};
false -> []
@@ -289,12 +318,22 @@ modify_tc_list(GrSpecTs, TSCs, []) ->
modify_tc_list1(GrSpecTs, TSCs);
modify_tc_list(GrSpecTs, _TSCs, _) ->
- [Test || Test <- GrSpecTs, not is_atom(Test)].
+ [Test || Test <- GrSpecTs, not is_atom(Test), element(1,Test)=/=testcase].
modify_tc_list1(GrSpecTs, TSCs) ->
%% remove all cases in group tc list that should not be executed
GrSpecTs1 =
- lists:flatmap(fun(Test) when is_tuple(Test),
+ lists:flatmap(fun(Test={testcase,TC,_}) ->
+ case lists:keysearch(TC, 2, TSCs) of
+ {value,_} ->
+ [Test];
+ _ ->
+ case lists:member(TC, TSCs) of
+ true -> [Test];
+ false -> []
+ end
+ end;
+ (Test) when is_tuple(Test),
(size(Test) > 2) ->
[Test];
(Test={group,_}) ->
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index 49587b3edd..97c349578f 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -22,6 +22,8 @@
%% API Exports
-export([init/1]).
+-export([groups/2]).
+-export([all/2]).
-export([init_tc/3]).
-export([end_tc/5]).
-export([terminate/1]).
@@ -37,7 +39,8 @@
opts = [],
prio = ctfirst }]).
--record(ct_hook_config, {id, module, prio, scope, opts = [], state = []}).
+-record(ct_hook_config, {id, module, prio, scope, opts = [],
+ state = [], groups = []}).
%% -------------------------------------------------------------------------
%% API Functions
@@ -49,6 +52,48 @@ init(Opts) ->
call(get_builtin_hooks(Opts) ++ get_new_hooks(Opts, undefined),
ok, init, []).
+%% Call the post_groups/2 hook callback
+groups(Mod, Groups) ->
+ Info = try proplists:get_value(ct_hooks, Mod:suite(), []) of
+ CTHooks when is_list(CTHooks) ->
+ [{?config_name,CTHooks}];
+ CTHook when is_atom(CTHook) ->
+ [{?config_name,[CTHook]}]
+ catch _:_ ->
+ %% since this might be the first time Mod:suite()
+ %% is called, and it might just fail or return
+ %% something bad, we allow any failure here - it
+ %% will be catched later if there is something
+ %% really wrong.
+ [{?config_name,[]}]
+ end,
+ case call(fun call_generic/3, Info ++ [{'$ct_groups',Groups}], [post_groups, Mod]) of
+ [{'$ct_groups',NewGroups}] ->
+ NewGroups;
+ Other ->
+ Other
+ end.
+
+%% Call the post_all/3 hook callback
+all(Mod, Tests) ->
+ Info = try proplists:get_value(ct_hooks, Mod:suite(), []) of
+ CTHooks when is_list(CTHooks) ->
+ [{?config_name,CTHooks}];
+ CTHook when is_atom(CTHook) ->
+ [{?config_name,[CTHook]}]
+ catch _:_ ->
+ %% just allow any failure here - it will be catched
+ %% later if there is something really wrong.
+ [{?config_name,[]}]
+ end,
+ case call(fun call_generic/3, Info ++ [{'$ct_all',Tests}], [post_all, Mod]) of
+ [{'$ct_all',NewTests}] ->
+ NewTests;
+ Other ->
+ Other
+ end.
+
+%% Called after all suites are done.
-spec terminate(Hooks :: term()) ->
ok.
terminate(Hooks) ->
@@ -80,6 +125,7 @@ init_tc(Mod, init_per_suite, Config) ->
[{?config_name,[]}]
end,
call(fun call_generic/3, Config ++ Info, [pre_init_per_suite, Mod]);
+
init_tc(Mod, end_per_suite, Config) ->
call(fun call_generic/3, Config, [pre_end_per_suite, Mod]);
init_tc(Mod, {init_per_group, GroupName, Properties}, Config) ->
@@ -153,7 +199,7 @@ call_id(#ct_hook_config{ module = Mod, opts = Opts} = Hook, Config, Scope) ->
{Config, Hook#ct_hook_config{ id = Id, scope = scope(Scope)}}.
call_init(#ct_hook_config{ module = Mod, opts = Opts, id = Id, prio = P} = Hook,
- Config,_Meta) ->
+ Config, _Meta) ->
case Mod:init(Id, Opts) of
{ok, NewState} when P =:= undefined ->
{Config, Hook#ct_hook_config{ state = NewState, prio = 0 } };
@@ -184,6 +230,18 @@ call_generic(Hook, Value, Meta) ->
call_generic_fallback(Hook, Value, Meta) ->
do_call_generic(Hook, Value, Meta, true).
+do_call_generic(#ct_hook_config{ module = Mod} = Hook,
+ [{'$ct_groups',Groups}], [post_groups | Args], Fallback) ->
+ NewGroups = catch_apply(Mod, post_groups, Args ++ [Groups],
+ Groups, Fallback),
+ {[{'$ct_groups',NewGroups}], Hook#ct_hook_config{ groups = NewGroups } };
+
+do_call_generic(#ct_hook_config{ module = Mod, groups = Groups} = Hook,
+ [{'$ct_all',Tests}], [post_all | Args], Fallback) ->
+ NewTests = catch_apply(Mod, post_all, Args ++ [Tests, Groups],
+ Tests, Fallback),
+ {[{'$ct_all',NewTests}], Hook};
+
do_call_generic(#ct_hook_config{ module = Mod, state = State} = Hook,
Value, [Function | Args], Fallback) ->
{NewValue, NewState} = catch_apply(Mod, Function, Args ++ [Value, State],
@@ -218,6 +276,12 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
Rest ++ [{NewId, call_init}]};
ExistingHook when is_tuple(ExistingHook) ->
{Hooks, Rest};
+ _ when hd(Meta)=:=post_groups; hd(Meta)=:=post_all ->
+ %% If CTH is started because of a call from
+ %% groups/2 or all/2, CTH:init/1 must not be
+ %% called (the suite scope should be used).
+ {Hooks ++ [NewHook],
+ Rest ++ [{NewId,NextFun}]};
_ ->
{Hooks ++ [NewHook],
Rest ++ [{NewId, call_init}, {NewId,NextFun}]}
@@ -226,8 +290,8 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
catch Error:Reason:Trace ->
ct_logs:log("Suite Hook","Failed to start a CTH: ~tp:~tp",
[Error,{Reason,Trace}]),
- call([], {fail,"Failed to start CTH"
- ", see the CT Log for details"}, Meta, Hooks)
+ call([], {fail,"Failed to start CTH, "
+ "see the CT Log for details"}, Meta, Hooks)
end;
call([{HookId, call_init} | Rest], Config, Meta, Hooks) ->
call([{HookId, fun call_init/3} | Rest], Config, Meta, Hooks);
@@ -267,6 +331,10 @@ scope([pre_init_per_suite, SuiteName|_]) ->
[post_end_per_suite, SuiteName];
scope([post_init_per_suite, SuiteName|_]) ->
[post_end_per_suite, SuiteName];
+scope([post_groups, SuiteName|_]) ->
+ [post_groups, SuiteName];
+scope([post_all, SuiteName|_]) ->
+ [post_all, SuiteName];
scope(init) ->
none.
@@ -353,6 +421,7 @@ resort(Calls,Hooks,[F|_R]) when F == pre_end_per_testcase;
F == pre_end_per_suite;
F == post_end_per_suite ->
lists:reverse(resort(Calls,Hooks));
+
resort(Calls,Hooks,_Meta) ->
resort(Calls,Hooks).
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index 07a1693d5d..a11613bca2 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -149,7 +149,7 @@ close(Info, StartDir) ->
ok;
CacheBin ->
%% save final version of the log cache to file
- _ = file:write_file(?log_cache_name,CacheBin),
+ write_log_cache(CacheBin),
put(ct_log_cache,undefined)
end
end,
@@ -2022,7 +2022,7 @@ update_all_runs_in_cache(AllRunsData) ->
%% read from file as long as this logger process is alive
put(ct_log_cache,term_to_binary(LogCache));
_ ->
- file:write_file(?log_cache_name,term_to_binary(LogCache))
+ write_log_cache(term_to_binary(LogCache))
end;
SavedLogCache ->
update_all_runs_in_cache(AllRunsData,binary_to_term(SavedLogCache))
@@ -2036,7 +2036,7 @@ update_all_runs_in_cache(AllRunsData, LogCache) ->
%% read from file as long as this logger process is alive
put(ct_log_cache,term_to_binary(LogCache1));
_ ->
- file:write_file(?log_cache_name,term_to_binary(LogCache1))
+ write_log_cache(term_to_binary(LogCache1))
end.
sort_all_runs(Dirs) ->
@@ -2668,7 +2668,7 @@ update_tests_in_cache(TempData,LogCache=#log_cache{tests=Tests}) ->
{_Pid,_Pid} ->
put(ct_log_cache,CacheBin);
_ ->
- file:write_file(?log_cache_name,CacheBin)
+ write_log_cache(CacheBin)
end.
%%
@@ -3400,3 +3400,9 @@ unexpected_io(Pid, _Category, _Importance, Content, CtLogFd, EscChars) ->
Data = io_lib:format("~ts", [lists:foldl(IoFun, [], Content)]),
test_server_io:print_unexpected(Data),
ok.
+
+write_log_cache(LogCacheBin) when is_binary(LogCacheBin) ->
+ TmpFile = ?log_cache_name++".tmp",
+ _ = file:write_file(TmpFile,LogCacheBin),
+ _ = file:rename(TmpFile,?log_cache_name),
+ ok.
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl
index 29188a648e..6a758c4ea3 100644
--- a/lib/common_test/src/ct_netconfc.erl
+++ b/lib/common_test/src/ct_netconfc.erl
@@ -583,7 +583,7 @@ get_config(Client, Source, Filter, Timeout) ->
-spec edit_config(Client, Target, Config) -> Result when
Client :: client(),
Target :: netconf_db(),
- Config :: simple_xml(),
+ Config :: simple_xml() | [simple_xml()],
Result :: ok | {error,error_reason()}.
edit_config(Client, Target, Config) ->
edit_config(Client, Target, Config, ?DEFAULT_TIMEOUT).
@@ -591,7 +591,7 @@ edit_config(Client, Target, Config) ->
-spec edit_config(Client, Target, Config, OptParams) -> Result when
Client :: client(),
Target :: netconf_db(),
- Config :: simple_xml(),
+ Config :: simple_xml() | [simple_xml()],
OptParams :: [simple_xml()],
Result :: ok | {error,error_reason()};
(Client, Target, Config, Timeout) -> Result when
@@ -608,10 +608,12 @@ edit_config(Client, Target, Config, OptParams) when is_list(OptParams) ->
-spec edit_config(Client, Target, Config, OptParams, Timeout) -> Result when
Client :: client(),
Target :: netconf_db(),
- Config :: simple_xml(),
+ Config :: simple_xml() | [simple_xml()],
OptParams :: [simple_xml()],
Timeout :: timeout(),
Result :: ok | {error,error_reason()}.
+edit_config(Client, Target, Config, OptParams, Timeout) when not is_list(Config)->
+ edit_config(Client, Target, [Config], OptParams, Timeout);
edit_config(Client, Target, Config, OptParams, Timeout) ->
call(Client, {send_rpc_op, edit_config, [Target,Config,OptParams], Timeout}).
@@ -1113,7 +1115,7 @@ encode_rpc_operation(get,[Filter]) ->
encode_rpc_operation(get_config,[Source,Filter]) ->
{'get-config',[{source,[Source]}] ++ filter(Filter)};
encode_rpc_operation(edit_config,[Target,Config,OptParams]) ->
- {'edit-config',[{target,[Target]}] ++ OptParams ++ [{config,[Config]}]};
+ {'edit-config',[{target,[Target]}] ++ OptParams ++ [{config,Config}]};
encode_rpc_operation(delete_config,[Target]) ->
{'delete-config',[{target,[Target]}]};
encode_rpc_operation(copy_config,[Target,Source]) ->
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index f9abecfd38..174008c790 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -194,6 +194,15 @@ send(Connection,Cmd,Opts) ->
check_send_opts([{newline,Bool}|Opts]) when is_boolean(Bool) ->
check_send_opts(Opts);
+check_send_opts([{newline,String}|Opts]) when is_list(String) ->
+ case lists:all(fun(I) when is_integer(I), I>=0, I=<127 -> true;
+ (_) -> false
+ end, String) of
+ true ->
+ check_send_opts(Opts);
+ false ->
+ {error,{invalid_option,{newline,String}}}
+ end;
check_send_opts([Invalid|_]) ->
{error,{invalid_option,Invalid}};
check_send_opts([]) ->
@@ -211,10 +220,16 @@ expect(Connection,Patterns) ->
expect(Connection,Patterns,Opts) ->
case get_handle(Connection) of
- {ok,Pid} ->
- call(Pid,{expect,Patterns,Opts});
- Error ->
- Error
+ {ok,Pid} ->
+ case call(Pid,{expect,Patterns,Opts}) of
+ {error,Reason} when element(1,Reason)==bad_pattern ->
+ %% Faulty user input - should fail the test case
+ exit({Reason,{?MODULE,?FUNCTION_NAME,3}});
+ Other ->
+ Other
+ end;
+ Error ->
+ Error
end.
%%%=================================================================
@@ -674,60 +689,68 @@ silent_teln_expect(Name,Pid,Data,Pattern,Prx,Opts) ->
%% 3b) Repeat (sequence): 2) is repeated either N times or until a
%% halt condition is fulfilled.
teln_expect(Name,Pid,Data,Pattern0,Prx,Opts) ->
- HaltPatterns =
+ HaltPatterns0 =
case get_ignore_prompt(Opts) of
true ->
get_haltpatterns(Opts);
false ->
[prompt | get_haltpatterns(Opts)]
end,
-
- PromptCheck = get_prompt_check(Opts),
-
- {WaitForPrompt,Pattern1,Opts1} = wait_for_prompt(Pattern0,Opts),
-
- Seq = get_seq(Opts1),
- Pattern2 = convert_pattern(Pattern1,Seq),
- {IdleTimeout,TotalTimeout} = get_timeouts(Opts1),
-
- EO = #eo{teln_pid=Pid,
- prx=Prx,
- idle_timeout=IdleTimeout,
- total_timeout=TotalTimeout,
- seq=Seq,
- haltpatterns=HaltPatterns,
- prompt_check=PromptCheck},
+ case convert_pattern(HaltPatterns0,false) of
+ {ok,HaltPatterns} ->
+ {WaitForPrompt,Pattern1,Opts1} = wait_for_prompt(Pattern0,Opts),
+ Seq = get_seq(Opts1),
+ case convert_pattern(Pattern1,Seq) of
+ {ok,Pattern2} ->
+ {IdleTimeout,TotalTimeout} = get_timeouts(Opts1),
+ PromptCheck = get_prompt_check(Opts1),
+
+ EO = #eo{teln_pid=Pid,
+ prx=Prx,
+ idle_timeout=IdleTimeout,
+ total_timeout=TotalTimeout,
+ seq=Seq,
+ haltpatterns=HaltPatterns,
+ prompt_check=PromptCheck},
- case get_repeat(Opts1) of
- false ->
- case teln_expect1(Name,Pid,Data,Pattern2,[],EO) of
- {ok,Matched,Rest} when WaitForPrompt ->
- case lists:reverse(Matched) of
- [{prompt,_},Matched1] ->
- {ok,Matched1,Rest};
- [{prompt,_}|Matched1] ->
- {ok,lists:reverse(Matched1),Rest}
- end;
- {ok,Matched,Rest} ->
- {ok,Matched,Rest};
- {halt,Why,Rest} ->
- {error,Why,Rest};
- {error,Reason} ->
- {error,Reason}
- end;
- N ->
- EO1 = EO#eo{repeat=N},
- repeat_expect(Name,Pid,Data,Pattern2,[],EO1)
+ case get_repeat(Opts1) of
+ false ->
+ case teln_expect1(Name,Pid,Data,Pattern2,[],EO) of
+ {ok,Matched,Rest} when WaitForPrompt ->
+ case lists:reverse(Matched) of
+ [{prompt,_},Matched1] ->
+ {ok,Matched1,Rest};
+ [{prompt,_}|Matched1] ->
+ {ok,lists:reverse(Matched1),Rest}
+ end;
+ {ok,Matched,Rest} ->
+ {ok,Matched,Rest};
+ {halt,Why,Rest} ->
+ {error,Why,Rest};
+ {error,Reason} ->
+ {error,Reason}
+ end;
+ N ->
+ EO1 = EO#eo{repeat=N},
+ repeat_expect(Name,Pid,Data,Pattern2,[],EO1)
+ end;
+ Error ->
+ Error
+ end;
+ Error ->
+ Error
end.
-convert_pattern(Pattern,Seq)
- when is_list(Pattern) and not is_integer(hd(Pattern)) ->
- case Seq of
- true -> Pattern;
- false -> rm_dupl(Pattern,[])
- end;
+convert_pattern(Pattern0,Seq)
+ when Pattern0==[] orelse (is_list(Pattern0) and not is_integer(hd(Pattern0))) ->
+ Pattern =
+ case Seq of
+ true -> Pattern0;
+ false -> rm_dupl(Pattern0,[])
+ end,
+ compile_pattern(Pattern,[]);
convert_pattern(Pattern,_Seq) ->
- [Pattern].
+ compile_pattern([Pattern],[]).
rm_dupl([P|Ps],Acc) ->
case lists:member(P,Acc) of
@@ -739,6 +762,25 @@ rm_dupl([P|Ps],Acc) ->
rm_dupl([],Acc) ->
lists:reverse(Acc).
+compile_pattern([prompt|Patterns],Acc) ->
+ compile_pattern(Patterns,[prompt|Acc]);
+compile_pattern([{prompt,_}=P|Patterns],Acc) ->
+ compile_pattern(Patterns,[P|Acc]);
+compile_pattern([{Tag,Pattern}|Patterns],Acc) ->
+ try re:compile(Pattern,[unicode]) of
+ {ok,MP} -> compile_pattern(Patterns,[{Tag,MP}|Acc]);
+ {error,Error} -> {error,{bad_pattern,{Tag,Pattern},Error}}
+ catch error:badarg -> {error,{bad_pattern,{Tag,Pattern}}}
+ end;
+compile_pattern([Pattern|Patterns],Acc) ->
+ try re:compile(Pattern,[unicode]) of
+ {ok,MP} -> compile_pattern(Patterns,[MP|Acc]);
+ {error,Error} -> {error,{bad_pattern,Pattern,Error}}
+ catch error:badarg -> {error,{bad_pattern,Pattern}}
+ end;
+compile_pattern([],Acc) ->
+ {ok,lists:reverse(Acc)}.
+
get_timeouts(Opts) ->
{case lists:keysearch(idle_timeout,1,Opts) of
{value,{_,T}} ->
@@ -772,7 +814,7 @@ get_seq(Opts) ->
get_haltpatterns(Opts) ->
case lists:keysearch(halt,1,Opts) of
{value,{halt,HaltPatterns}} ->
- convert_pattern(HaltPatterns,false);
+ HaltPatterns;
false ->
[]
end.
@@ -1068,7 +1110,7 @@ match_line(Name,Pid,Line,[{prompt,PromptType}|Patterns],FoundPrompt,Term,
when PromptType=/=FoundPrompt ->
match_line(Name,Pid,Line,Patterns,FoundPrompt,Term,EO,RetTag);
match_line(Name,Pid,Line,[{Tag,Pattern}|Patterns],FoundPrompt,Term,EO,RetTag) ->
- case re:run(Line,Pattern,[{capture,all,list},unicode]) of
+ case re:run(Line,Pattern,[{capture,all,list}]) of
nomatch ->
match_line(Name,Pid,Line,Patterns,FoundPrompt,Term,EO,RetTag);
{match,Match} ->
@@ -1076,7 +1118,7 @@ match_line(Name,Pid,Line,[{Tag,Pattern}|Patterns],FoundPrompt,Term,EO,RetTag) ->
{RetTag,{Tag,Match}}
end;
match_line(Name,Pid,Line,[Pattern|Patterns],FoundPrompt,Term,EO,RetTag) ->
- case re:run(Line,Pattern,[{capture,all,list},unicode]) of
+ case re:run(Line,Pattern,[{capture,all,list}]) of
nomatch ->
match_line(Name,Pid,Line,Patterns,FoundPrompt,Term,EO,RetTag);
{match,Match} ->
diff --git a/lib/common_test/src/ct_telnet_client.erl b/lib/common_test/src/ct_telnet_client.erl
index 76e4b9ea70..007477c855 100644
--- a/lib/common_test/src/ct_telnet_client.erl
+++ b/lib/common_test/src/ct_telnet_client.erl
@@ -101,9 +101,11 @@ close(Pid) ->
end.
send_data(Pid, Data) ->
- send_data(Pid, Data, true).
+ send_data(Pid, Data, "\n").
send_data(Pid, Data, true) ->
- send_data(Pid, Data++"\n", false);
+ send_data(Pid, Data, "\n");
+send_data(Pid, Data, Newline) when is_list(Newline) ->
+ send_data(Pid, Data++Newline, false);
send_data(Pid, Data, false) ->
Pid ! {send_data, Data},
ok.
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
index 99c484de48..4980d1ee4b 100644
--- a/lib/common_test/src/cth_log_redirect.erl
+++ b/lib/common_test/src/cth_log_redirect.erl
@@ -184,21 +184,12 @@ handle_call({log,#{meta:=#{gl:=GL}},_}, _From,
{reply, ok, State};
handle_call({log,
- #{msg:=Msg0,
- meta:=#{?MODULE:=#{category:=Category}}=Meta}=Log,
+ #{meta:=#{?MODULE:=#{category:=Category}}}=Log,
#{formatter:={Formatter,FConfig}}},
_From,
#eh_state{log_func=LogFunc}=State) ->
Header = format_header(State),
- Msg =
- case Msg0 of
- {report,R} ->
- Fun=maps:get(report_cb,Meta,fun logger:format_report/1),
- Fun(R);
- _ ->
- Msg0
- end,
- String = Formatter:format(Log#{msg=>Msg},FConfig),
+ String = Formatter:format(Log,FConfig),
case LogFunc of
tc_log ->
ct_logs:tc_log(Category, ?STD_IMPORTANCE,
diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl
index a896a0551b..756cd4d692 100644
--- a/lib/common_test/src/test_server.erl
+++ b/lib/common_test/src/test_server.erl
@@ -384,8 +384,8 @@ run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,TimetrapData}) ->
{Result,DetFail,ProcBef,ProcAft}.
-type tc_status() :: 'starting' | 'running' | 'init_per_testcase' |
- 'end_per_testcase' | {'framework',atom(),atom()} |
- 'tc'.
+ 'end_per_testcase' | {'framework',{atom(),atom(),list}} |
+ 'tc'.
-record(st,
{
ref :: reference(),
@@ -653,8 +653,8 @@ handle_tc_exit({testcase_aborted,{user_timetrap_error,_}=Msg,_}, St) ->
#st{config=Config,mf={Mod,Func},pid=Pid} = St,
spawn_fw_call(Mod, Func, Config, Pid, Msg, unknown, self()),
St;
-handle_tc_exit(Reason, #st{status={framework,FwMod,FwFunc},
- config=Config,pid=Pid}=St) ->
+handle_tc_exit(Reason, #st{status={framework,{FwMod,FwFunc,_}=FwMFA},
+ config=Config,mf={Mod,Func},pid=Pid}=St) ->
R = case Reason of
{timetrap_timeout,TVal,_} ->
{timetrap,TVal};
@@ -666,7 +666,7 @@ handle_tc_exit(Reason, #st{status={framework,FwMod,FwFunc},
Other
end,
Error = {framework_error,R},
- spawn_fw_call(FwMod, FwFunc, Config, Pid, Error, unknown, self()),
+ spawn_fw_call(Mod, Func, Config, Pid, {Error,FwMFA}, unknown, self()),
St;
handle_tc_exit(Reason, #st{status=tc,config=Config0,mf={Mod,Func},pid=Pid}=St)
when is_list(Config0) ->
@@ -850,36 +850,68 @@ spawn_fw_call(Mod,EPTC={end_per_testcase,Func},EndConf,Pid,
"WARNING: end_per_testcase failed!</font>",
{died,W}
end,
- try do_end_tc_call(Mod,EPTC,{Pid,Report,[EndConf]}, Why) of
- _ -> ok
- catch
- _:FwEndTCErr ->
- exit({fw_notify_done,end_tc,FwEndTCErr})
- end,
- FailLoc = proplists:get_value(tc_fail_loc, EndConf),
+ FailLoc0 = proplists:get_value(tc_fail_loc, EndConf),
+ {RetVal1,FailLoc} =
+ try do_end_tc_call(Mod,EPTC,{Pid,Report,[EndConf]}, Why) of
+ Why ->
+ {RetVal,FailLoc0};
+ {failed,_} = R ->
+ {R,[{Mod,Func}]};
+ R ->
+ {R,FailLoc0}
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
%% finished, report back (if end_per_testcase fails, a warning
%% should be printed as part of the comment)
SendTo ! {self(),fw_notify_done,
- {Time,RetVal,FailLoc,[],Warn}}
+ {Time,RetVal1,FailLoc,[],Warn}}
end,
spawn_link(FwCall);
-spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo) ->
+spawn_fw_call(Mod,Func,Conf,Pid,{{framework_error,FwError},
+ {FwMod,FwFunc,[A1,A2|_]}=FwMFA},_,SendTo) ->
FwCall =
fun() ->
ct_util:mark_process(),
- test_server_sup:framework_call(report, [framework_error,
- {{FwMod,FwFunc},
- FwError}]),
+ Time =
+ case FwError of
+ {timetrap,TVal} ->
+ TVal/1000;
+ _ ->
+ died
+ end,
+ {Ret,Loc,WarnOrError} =
+ cleanup_after_fw_error(Mod,Func,Conf,Pid,FwError,FwMFA),
Comment =
- lists:flatten(
- io_lib:format("<font color=\"red\">"
- "WARNING! ~w:~tw failed!</font>",
- [FwMod,FwFunc])),
+ case WarnOrError of
+ warn ->
+ group_leader() !
+ {printout,12,
+ "WARNING! ~w:~tw(~w,~tw,...) failed!\n"
+ " Reason: ~tp\n",
+ [FwMod,FwFunc,A1,A2,FwError]},
+ lists:flatten(
+ io_lib:format("<font color=\"red\">"
+ "WARNING! ~w:~tw(~w,~tw,...) "
+ "failed!</font>",
+ [FwMod,FwFunc,A1,A2]));
+ error ->
+ group_leader() !
+ {printout,12,
+ "Error! ~w:~tw(~w,~tw,...) failed!\n"
+ " Reason: ~tp\n",
+ [FwMod,FwFunc,A1,A2,FwError]},
+ lists:flatten(
+ io_lib:format("<font color=\"red\">"
+ "ERROR! ~w:~tw(~w,~tw,...) "
+ "failed!</font>",
+ [FwMod,FwFunc,A1,A2]))
+ end,
%% finished, report back
SendTo ! {self(),fw_notify_done,
- {died,{error,{FwMod,FwFunc,FwError}},
- {FwMod,FwFunc},[],Comment}}
+ {Time,Ret,Loc,[],Comment}}
end,
spawn_link(FwCall);
@@ -902,17 +934,185 @@ spawn_fw_call(Mod,Func,CurrConf,Pid,Error,Loc,SendTo) ->
FwErrorNotifyErr})
end,
Conf = [{tc_status,{failed,Error}}|CurrConf],
- try do_end_tc_call(Mod,EndTCFunc,{Pid,Error,[Conf]},Error) of
- _ -> ok
- catch
- _:FwEndTCErr ->
- exit({fw_notify_done,end_tc,FwEndTCErr})
- end,
+ {Time,RetVal,Loc1} =
+ try do_end_tc_call(Mod,EndTCFunc,{Pid,Error,[Conf]},Error) of
+ Error ->
+ {died, Error, Loc};
+ {failed,Reason} = NewReturn ->
+ fw_error_notify(Mod,Func1,Conf,Reason),
+ {died, NewReturn, [{Mod,Func}]};
+ NewReturn ->
+ T = case Error of
+ {timetrap_timeout,TT} -> TT;
+ _ -> 0
+ end,
+ {T, NewReturn, Loc}
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
%% finished, report back
- SendTo ! {self(),fw_notify_done,{died,Error,Loc,[],undefined}}
+ SendTo ! {self(),fw_notify_done,{Time,RetVal,Loc1,[],undefined}}
end,
spawn_link(FwCall).
+cleanup_after_fw_error(_Mod,_Func,Conf,Pid,FwError,
+ {FwMod,FwFunc=init_tc,
+ [Mod,{init_per_testcase,Func}=IPTC|_]}) ->
+ %% Failed during pre_init_per_testcase, the test must be skipped
+ Skip = {auto_skip,{failed,{FwMod,FwFunc,FwError}}},
+ try begin do_end_tc_call(Mod,IPTC, {Pid,Skip,[Conf]}, FwError),
+ do_init_tc_call(Mod,{end_per_testcase_not_run,Func},
+ [Conf],{ok,[Conf]}),
+ do_end_tc_call(Mod,{end_per_testcase_not_run,Func},
+ {Pid,Skip,[Conf]}, FwError) end of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ {Skip,{FwMod,FwFunc},error};
+cleanup_after_fw_error(_Mod,_Func,Conf,Pid,FwError,
+ {FwMod,FwFunc=end_tc,[Mod,{init_per_testcase,Func}|_]}) ->
+ %% Failed during post_init_per_testcase, the test must be skipped
+ Skip = {auto_skip,{failed,{FwMod,FwFunc,FwError}}},
+ try begin do_init_tc_call(Mod,{end_per_testcase_not_run,Func},
+ [Conf],{ok,[Conf]}),
+ do_end_tc_call(Mod,{end_per_testcase_not_run,Func},
+ {Pid,Skip,[Conf]}, FwError) end of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ {Skip,{FwMod,FwFunc},error};
+cleanup_after_fw_error(_Mod,_Func,Conf,Pid,FwError,
+ {FwMod,FwFunc=init_tc,[Mod,{end_per_testcase,Func}|_]}) ->
+ %% Failed during pre_end_per_testcase. Warn about it.
+ {RetVal,Loc} =
+ case {proplists:get_value(tc_status, Conf),
+ proplists:get_value(tc_fail_loc, Conf, unknown)} of
+ {undefined,_} ->
+ {{failed,{FwMod,FwFunc,FwError}},{FwMod,FwFunc}};
+ {E = {failed,_Reason},unknown} ->
+ {E,[{Mod,Func}]};
+ {Result,FailLoc} ->
+ {Result,FailLoc}
+ end,
+ try begin do_end_tc_call(Mod,{end_per_testcase_not_run,Func},
+ {Pid,RetVal,[Conf]}, FwError) end of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ {RetVal,Loc,warn};
+cleanup_after_fw_error(Mod,Func,Conf,Pid,FwError,
+ {FwMod,FwFunc=end_tc,[Mod,{end_per_testcase,Func}|_]}) ->
+ %% Failed during post_end_per_testcase. Warn about it.
+ {RetVal,Report,Loc} =
+ case {proplists:get_value(tc_status, Conf),
+ proplists:get_value(tc_fail_loc, Conf, unknown)} of
+ {undefined,_} ->
+ {{failed,{FwMod,FwFunc,FwError}},
+ {{FwMod,FwError},FwError},
+ {FwMod,FwFunc}};
+ {E = {failed,_Reason},unknown} ->
+ {E,{Mod,Func,E},[{Mod,Func}]};
+ {Result,FailLoc} ->
+ {Result,{Mod,Func,Result},FailLoc}
+ end,
+ try begin do_end_tc_call(Mod,{cleanup,{end_per_testcase_not_run,Func}},
+ {Pid,RetVal,[Conf]}, FwError) end of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ test_server_sup:framework_call(report,[framework_error,Report]),
+ {RetVal,Loc,warn};
+cleanup_after_fw_error(Mod,Func,Conf,Pid,FwError,{FwMod,FwFunc=init_tc,_})
+ when Func =:= init_per_suite; Func =:=init_per_group ->
+ %% Failed during pre_init_per_suite or pre_init_per_group
+ RetVal = {failed,{FwMod,FwFunc,FwError}},
+ try do_end_tc_call(Mod,Func,{Pid,RetVal,[Conf]},FwError) of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ {RetVal,{FwMod,FwFunc},error};
+cleanup_after_fw_error(Mod,Func,Conf,Pid,FwError,{FwMod,FwFunc=end_tc,_})
+ when Func =:= init_per_suite; Func =:=init_per_group ->
+ %% Failed during post_init_per_suite or post_init_per_group
+ RetVal = {failed,{FwMod,FwFunc,FwError}},
+ try do_end_tc_call(Mod,{cleanup,Func},{Pid,RetVal,[Conf]},FwError) of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ ReportFunc =
+ case Func of
+ init_per_group ->
+ case proplists:get_value(tc_group_properties,Conf) of
+ undefined ->
+ {Func,unknown,[]};
+ GProps ->
+ Name = proplists:get_value(name,GProps),
+ {Func,Name,proplists:delete(name,GProps)}
+ end;
+ _ ->
+ Func
+ end,
+ test_server_sup:framework_call(report,[framework_error,
+ {Mod,ReportFunc,RetVal}]),
+ {RetVal,{FwMod,FwFunc},error};
+cleanup_after_fw_error(Mod,Func,Conf,Pid,FwError,{FwMod,FwFunc=init_tc,_})
+ when Func =:= end_per_suite; Func =:=end_per_group ->
+ %% Failed during pre_end_per_suite or pre_end_per_group
+ RetVal = {failed,{FwMod,FwFunc,FwError}},
+ try do_end_tc_call(Mod,Func,{Pid,RetVal,[Conf]},FwError) of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ {RetVal,{FwMod,FwFunc},error};
+cleanup_after_fw_error(Mod,Func,Conf,Pid,FwError,{FwMod,FwFunc=end_tc,_})
+ when Func =:= end_per_suite; Func =:=end_per_group ->
+ %% Failed during post_end_per_suite or post_end_per_group
+ RetVal = {failed,{FwMod,FwFunc,FwError}},
+ try do_end_tc_call(Mod,{cleanup,Func},{Pid,RetVal,[Conf]},FwError) of
+ _ -> ok
+ catch
+ _:FwEndTCErr ->
+ exit({fw_notify_done,end_tc,FwEndTCErr})
+ end,
+ ReportFunc =
+ case Func of
+ end_per_group ->
+ case proplists:get_value(tc_group_properties,Conf) of
+ undefined ->
+ {Func,unknown,[]};
+ GProps ->
+ Name = proplists:get_value(name,GProps),
+ {Func,Name,proplists:delete(name,GProps)}
+ end;
+ _ ->
+ Func
+ end,
+ test_server_sup:framework_call(report,[framework_error,
+ {Mod,ReportFunc,RetVal}]),
+ {RetVal,{FwMod,FwFunc},error};
+cleanup_after_fw_error(_Mod,_Func,_Conf,_Pid,FwError,{FwMod,FwFunc,_}) ->
+ %% This is unexpected
+ test_server_sup:framework_call(report,
+ [framework_error,
+ {{FwMod,FwFunc},
+ FwError}]),
+ {FwError,{FwMod,FwFunc},error}.
+
%% The job proxy process forwards messages between the test case
%% process on a shielded node (and its descendants) and the job process.
%%
@@ -1088,6 +1288,9 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
EndConf1 =
user_callback(TCCallback, Mod, Func, 'end', EndConf),
+ %% save updated config in controller loop
+ set_tc_state(tc, EndConf1),
+
%% We can't handle fails or skips here
EndConf2 =
case do_init_tc_call(Mod,{end_per_testcase,Func},
diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl
index 8bd6cd583a..fdcaaab2eb 100644
--- a/lib/common_test/src/test_server_ctrl.erl
+++ b/lib/common_test/src/test_server_ctrl.erl
@@ -1443,6 +1443,8 @@ remove_conf([C={Mod,error_in_suite,_}|Cases], NoConf, Repeats) ->
true ->
remove_conf(Cases, [C|NoConf], Repeats)
end;
+remove_conf([C={repeat,_,_}|Cases], NoConf, _Repeats) ->
+ remove_conf(Cases, [C|NoConf], true);
remove_conf([C|Cases], NoConf, Repeats) ->
remove_conf(Cases, [C|NoConf], Repeats);
remove_conf([], NoConf, true) ->
@@ -2061,6 +2063,14 @@ add_init_and_end_per_suite([SkipCase|Cases], LastMod, LastRef, FwMod)
[SkipCase|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef, FwMod) ->
[Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([{repeat,{Mod,_},_}=Case|Cases], LastMod, LastRef, FwMod)
+ when Mod =/= LastMod, Mod =/= FwMod ->
+ {PreCases, NextMod, NextRef} =
+ do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod),
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod,
+ NextRef, FwMod)];
+add_init_and_end_per_suite([{repeat,_,_}=Case|Cases], LastMod, LastRef, FwMod) ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef, FwMod)
when Mod =/= LastMod, Mod =/= FwMod ->
{PreCases, NextMod, NextRef} =
@@ -2138,7 +2148,7 @@ do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod) ->
%% let's call a "fake" end_per_suite if it exists
case erlang:function_exported(FwMod, end_per_suite, 1) of
true ->
- [{conf,LastRef,[{suite,Mod}],
+ [{conf,LastRef,[{suite,LastMod}],
{FwMod,end_per_suite}}|Init];
false ->
[{conf,LastRef,[],{LastMod,end_per_suite}}|Init]
@@ -2926,6 +2936,29 @@ run_test_cases_loop([{conf,_Ref,_Props,_X}=Conf|_Cases0],
Config, _TimetrapData, _Mode, _Status) ->
erlang:error(badarg, [Conf,Config]);
+run_test_cases_loop([{repeat,Case,{RepeatType,N}}|Cases0], Config,
+ TimeTrapData, Mode, Status) ->
+ Ref = make_ref(),
+ Parallel = check_prop(parallel, Mode) =/= false,
+ Sequence = check_prop(sequence, Mode) =/= false,
+ RepeatStop = RepeatType=:=repeat_until_fail
+ orelse RepeatType=:=repeat_until_ok,
+
+ if Parallel andalso RepeatStop ->
+ %% Cannot check results of test case during parallal
+ %% execution, so only RepeatType=:=repeat is allowed in
+ %% combination with parallel groups.
+ erlang:error({illegal_combination,{parallel,RepeatType}});
+ Sequence andalso RepeatStop ->
+ %% Sequence is stop on fail + skip rest, so only
+ %% RepeatType=:=repeat makes sense inside a sequence.
+ erlang:error({illegal_combination,{sequence,RepeatType}});
+ true ->
+ Mode1 = [{Ref,[{repeat,{RepeatType,1,N}}],?now}|Mode],
+ run_test_cases_loop([Case | Cases0], Config, TimeTrapData,
+ Mode1, Status)
+ end;
+
run_test_cases_loop([{Mod,Case}|Cases], Config, TimetrapData, Mode, Status) ->
ActualCfg =
case get(test_server_create_priv_dir) of
@@ -2938,7 +2971,7 @@ run_test_cases_loop([{Mod,Case}|Cases], Config, TimetrapData, Mode, Status) ->
run_test_cases_loop([{Mod,Case,[ActualCfg]}|Cases], Config,
TimetrapData, Mode, Status);
-run_test_cases_loop([{Mod,Func,Args}|Cases], Config, TimetrapData, Mode, Status) ->
+run_test_cases_loop([{Mod,Func,Args}=Case|Cases], Config, TimetrapData, Mode0, Status) ->
{Num,RunInit} =
case FwMod = get_fw_mod(?MODULE) of
Mod when Func == error_in_suite ->
@@ -2948,6 +2981,14 @@ run_test_cases_loop([{Mod,Func,Args}|Cases], Config, TimetrapData, Mode, Status)
run_init}
end,
+ Mode =
+ case Mode0 of
+ [{_,[{repeat,{_,_,_}}],_}|RestMode] ->
+ RestMode;
+ _ ->
+ Mode0
+ end,
+
%% check the current execution mode and save info about the case if
%% detected that printouts to common log files is handled later
@@ -2975,36 +3016,42 @@ run_test_cases_loop([{Mod,Func,Args}|Cases], Config, TimetrapData, Mode, Status)
if is_tuple(RetVal) -> element(1,RetVal);
true -> undefined
end,
- {Failed,Status1} =
+ {Result,Failed,Status1} =
case RetTag of
Skip when Skip==skip; Skip==skipped ->
- {false,update_status(skipped, Mod, Func, Status)};
+ {skipped,false,update_status(skipped, Mod, Func, Status)};
Fail when Fail=='EXIT'; Fail==failed ->
- {true,update_status(failed, Mod, Func, Status)};
+ {failed,true,update_status(failed, Mod, Func, Status)};
_ when Time==died, RetVal=/=ok ->
- {true,update_status(failed, Mod, Func, Status)};
+ {failed,true,update_status(failed, Mod, Func, Status)};
_ ->
- {false,update_status(ok, Mod, Func, Status)}
+ {ok,false,update_status(ok, Mod, Func, Status)}
end,
case check_prop(sequence, Mode) of
false ->
+ {Cases1,Mode1} =
+ check_repeat_testcase(Case,Result,Cases,Mode0),
stop_minor_log_file(),
- run_test_cases_loop(Cases, Config, TimetrapData, Mode, Status1);
+ run_test_cases_loop(Cases1, Config, TimetrapData, Mode1, Status1);
Ref ->
%% the case is in a sequence; we must check the result and
%% determine if the following cases should run or be skipped
if not Failed -> % proceed with next case
+ {Cases1,Mode1} =
+ check_repeat_testcase(Case,Result,Cases,Mode0),
stop_minor_log_file(),
- run_test_cases_loop(Cases, Config, TimetrapData, Mode, Status1);
+ run_test_cases_loop(Cases1, Config, TimetrapData, Mode1, Status1);
true -> % skip rest of cases in sequence
print(minor, "~n*** ~tw failed.~n"
" Skipping all other cases in sequence.",
[Func]),
+ {Cases1,Mode1} =
+ check_repeat_testcase(Case,Result,Cases,Mode0),
Reason = {failed,{Mod,Func}},
- Cases2 = skip_cases_upto(Ref, Cases, Reason, tc,
+ Cases2 = skip_cases_upto(Ref, Cases1, Reason, tc,
Mode, auto_skip_case),
stop_minor_log_file(),
- run_test_cases_loop(Cases2, Config, TimetrapData, Mode, Status1)
+ run_test_cases_loop(Cases2, Config, TimetrapData, Mode1, Status1)
end
end;
%% the test case is being executed in parallel with the main process (and
@@ -3013,7 +3060,8 @@ run_test_cases_loop([{Mod,Func,Args}|Cases], Config, TimetrapData, Mode, Status)
%% io from Pid will be buffered by the test_server_io process and
%% handled later, so we have to save info about the case
queue_test_case_io(undefined, Pid, Num+1, Mod, Func),
- run_test_cases_loop(Cases, Config, TimetrapData, Mode, Status)
+ {Cases1,Mode1} = check_repeat_testcase(Case,ok,Cases,Mode0),
+ run_test_cases_loop(Cases1, Config, TimetrapData, Mode1, Status)
end;
%% TestSpec processing finished
@@ -3451,9 +3499,19 @@ modify_cases_upto1(Ref, {skip,Reason,FType,Mode,SkipType},
T, Orig, Alt)
end;
-%% next is some other case, ignore or copy
-modify_cases_upto1(Ref, {skip,_,_,_,_}=Op, [_Other|T], Orig, Alt) ->
+%% next is a repeated test case
+modify_cases_upto1(Ref, {skip,Reason,_,Mode,SkipType}=Op,
+ [{repeat,{_M,_F}=MF,_Repeat}|T], Orig, Alt) ->
+ modify_cases_upto1(Ref, Op, T, Orig, [{SkipType,{MF,Reason},Mode}|Alt]);
+
+%% next is an already skipped case, ignore or copy
+modify_cases_upto1(Ref, {skip,_,_,_,_}=Op, [{SkipType,_,_}|T], Orig, Alt)
+ when SkipType=:=skip_case; SkipType=:=auto_skip_case ->
modify_cases_upto1(Ref, Op, T, Orig, Alt);
+
+%% next is some other case, mark as skipped or copy
+modify_cases_upto1(Ref, {skip,Reason,_,Mode,SkipType}=Op, [Other|T], Orig, Alt) ->
+ modify_cases_upto1(Ref, Op, T, Orig, [{SkipType,{Other,Reason},Mode}|Alt]);
modify_cases_upto1(Ref, CopyOp, [C|T], Orig, Alt) ->
modify_cases_upto1(Ref, CopyOp, T, [C|Orig], [C|Alt]).
@@ -3841,6 +3899,10 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
{died,{timetrap_timeout,TimetrapTimeout}} ->
progress(failed, Num, Mod, Func, GrName, Loc,
timetrap_timeout, TimetrapTimeout, Comment, Style);
+ {died,Reason={auto_skip,_Why}} ->
+ %% died in init_per_testcase or in a hook in this context
+ progress(skip, Num, Mod, Func, GrName, Loc, Reason,
+ Time, Comment, Style);
{died,{Skip,Reason}} when Skip==skip; Skip==skipped ->
%% died in init_per_testcase
progress(skip, Num, Mod, Func, GrName, Loc, Reason,
@@ -4798,6 +4860,14 @@ collect_cases({make,InitMFA,CaseList,FinMFA}, St0, Mode) ->
{error,_Reason} = Error -> Error
end;
+collect_cases({repeat,{Module, Case}, Repeat}, St, Mode) ->
+ case catch collect_case([Case], St#cc{mod=Module}, [], Mode) of
+ {ok, [{Module,Case}], _} ->
+ {ok, [{repeat,{Module, Case}, Repeat}], St};
+ Other ->
+ {error,Other}
+ end;
+
collect_cases({Module, Cases}, St, Mode) when is_list(Cases) ->
case (catch collect_case(Cases, St#cc{mod=Module}, [], Mode)) of
Result = {ok,_,_} ->
@@ -5761,3 +5831,42 @@ encoding(File) ->
E ->
E
end.
+
+check_repeat_testcase(Case,Result,Cases,
+ [{Ref,[{repeat,RepeatData0}],StartTime}|Mode0]) ->
+ case do_update_repeat_data(Result,RepeatData0) of
+ false ->
+ {Cases,Mode0};
+ RepeatData ->
+ {[Case|Cases],[{Ref,[{repeat,RepeatData}],StartTime}|Mode0]}
+ end;
+check_repeat_testcase(_,_,Cases,Mode) ->
+ {Cases,Mode}.
+
+do_update_repeat_data(_,{RT,N,N}) when is_integer(N) ->
+ report_repeat_testcase(N,N),
+ report_stop_repeat_testcase(done,{RT,N}),
+ false;
+do_update_repeat_data(ok,{repeat_until_ok=RT,M,N}) ->
+ report_repeat_testcase(M,N),
+ report_stop_repeat_testcase(RT,{RT,N}),
+ false;
+do_update_repeat_data(failed,{repeat_until_fail=RT,M,N}) ->
+ report_repeat_testcase(M,N),
+ report_stop_repeat_testcase(RT,{RT,N}),
+ false;
+do_update_repeat_data(_,{RT,M,N}) when is_integer(M) ->
+ report_repeat_testcase(M,N),
+ {RT,M+1,N};
+do_update_repeat_data(_,{_,M,N}=RepeatData) ->
+ report_repeat_testcase(M,N),
+ RepeatData.
+
+report_stop_repeat_testcase(Reason,RepVal) ->
+ print(minor, "~n*** Stopping test case repeat operation: ~w", [Reason]),
+ print(1, "Stopping test case repeat operation: ~w", [RepVal]).
+
+report_repeat_testcase(M,forever) ->
+ print(minor, "~n=== Repeated test case: ~w of infinity", [M]);
+report_repeat_testcase(M,N) ->
+ print(minor, "~n=== Repeated test case: ~w of ~w", [M,N]).
diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl
index ea7ad8538e..3ae4a047d8 100644
--- a/lib/common_test/src/test_server_node.erl
+++ b/lib/common_test/src/test_server_node.erl
@@ -656,9 +656,19 @@ find_release({unix,linux}, Rel) ->
find_release(_, _) -> none.
find_rel_linux(Rel) ->
- case suse_release() of
- none -> [];
- SuseRel -> find_rel_suse(Rel, SuseRel)
+ try
+ case ubuntu_release() of
+ none -> none;
+ [UbuntuRel |_] -> throw(find_rel_ubuntu(Rel, UbuntuRel))
+ end,
+ case suse_release() of
+ none -> none;
+ SuseRel -> throw(find_rel_suse(Rel, SuseRel))
+ end,
+ []
+ catch
+ throw:Result ->
+ Result
end.
find_rel_suse(Rel, SuseRel) ->
@@ -735,6 +745,93 @@ suse_release(Fd) ->
end
end.
+find_rel_ubuntu(_Rel, UbuntuRel) when is_integer(UbuntuRel), UbuntuRel < 16 ->
+ [];
+find_rel_ubuntu(Rel, UbuntuRel) when is_integer(UbuntuRel) ->
+ Root = "/usr/local/otp/releases/ubuntu",
+ lists:foldl(fun (ChkUbuntuRel, Acc) ->
+ find_rel_ubuntu_aux1(Rel, Root++integer_to_list(ChkUbuntuRel))
+ ++ Acc
+ end,
+ [],
+ lists:seq(16, UbuntuRel)).
+
+find_rel_ubuntu_aux1(Rel, RootWc) ->
+ case erlang:system_info(wordsize) of
+ 4 ->
+ find_rel_ubuntu_aux2(Rel, RootWc++"_32");
+ 8 ->
+ find_rel_ubuntu_aux2(Rel, RootWc++"_64") ++
+ find_rel_ubuntu_aux2(Rel, RootWc++"_32")
+ end.
+
+find_rel_ubuntu_aux2(Rel, RootWc) ->
+ RelDir = filename:dirname(RootWc),
+ Pat = filename:basename(RootWc ++ "_" ++ Rel) ++ ".*",
+ case file:list_dir(RelDir) of
+ {ok,Dirs} ->
+ case lists:filter(fun(Dir) ->
+ case re:run(Dir, Pat, [unicode]) of
+ nomatch -> false;
+ _ -> true
+ end
+ end, Dirs) of
+ [] ->
+ [];
+ [R|_] ->
+ [filename:join([RelDir,R,"bin","erl"])]
+ end;
+ _ ->
+ []
+ end.
+
+ubuntu_release() ->
+ case file:open("/etc/lsb-release", [read]) of
+ {ok,Fd} ->
+ try
+ ubuntu_release(Fd, undefined, undefined)
+ after
+ file:close(Fd)
+ end;
+ {error,_} -> none
+ end.
+
+ubuntu_release(_Fd, DistrId, Rel) when DistrId /= undefined,
+ Rel /= undefined ->
+ Ubuntu = case DistrId of
+ "Ubuntu" -> true;
+ "ubuntu" -> true;
+ _ -> false
+ end,
+ case Ubuntu of
+ false -> none;
+ true -> Rel
+ end;
+ubuntu_release(Fd, DistroId, Rel) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ none;
+ Line when is_list(Line) ->
+ case re:run(Line, "^DISTRIB_ID=(\\w+)$",
+ [{capture,all_but_first,list}]) of
+ {match,[NewDistroId]} ->
+ ubuntu_release(Fd, NewDistroId, Rel);
+ nomatch ->
+ case re:run(Line, "^DISTRIB_RELEASE=(\\d+(?:\\.\\d+)*)$",
+ [{capture,all_but_first,list}]) of
+ {match,[RelList]} ->
+ NewRel = lists:map(fun (N) ->
+ list_to_integer(N)
+ end,
+ string:lexemes(RelList, ".")),
+ ubuntu_release(Fd, DistroId, NewRel);
+ nomatch ->
+ ubuntu_release(Fd, DistroId, Rel)
+ end
+ end
+ end.
+
+
unpack(Bin) ->
{One,Term} = split_binary(Bin, 1),
case binary_to_list(One) of
diff --git a/lib/common_test/src/test_server_sup.erl b/lib/common_test/src/test_server_sup.erl
index 26e7534c6c..ab8066a88d 100644
--- a/lib/common_test/src/test_server_sup.erl
+++ b/lib/common_test/src/test_server_sup.erl
@@ -770,7 +770,7 @@ framework_call(Callback,Func,Args,DefaultReturn) ->
end,
case SetTcState of
true ->
- test_server:set_tc_state({framework,Mod,Func});
+ test_server:set_tc_state({framework,{Mod,Func,Args}});
false ->
ok
end,
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index ecd1f727a2..e510b74d6a 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -74,7 +74,9 @@ MODULES= \
ct_SUITE \
ct_keep_logs_SUITE \
ct_unicode_SUITE \
- ct_auto_clean_SUITE
+ ct_auto_clean_SUITE \
+ ct_util_SUITE \
+ ct_tc_repeat_SUITE
ERL_FILES= $(MODULES:%=%.erl)
HRL_FILES= test_server_test_lib.hrl
diff --git a/lib/common_test/test/ct_auto_compile_SUITE.erl b/lib/common_test/test/ct_auto_compile_SUITE.erl
index dface99b8f..f88f13c889 100644
--- a/lib/common_test/test/ct_auto_compile_SUITE.erl
+++ b/lib/common_test/test/ct_auto_compile_SUITE.erl
@@ -169,7 +169,7 @@ test_events(ac_flag) ->
{?eh,start_info,{1,1,3}},
{?eh,tc_start,{ct_framework,error_in_suite}},
{?eh,tc_done,{ct_framework,error_in_suite,
- {failed,{error,'bad_SUITE can not be compiled or loaded'}}}},
+ {failed,{error,'bad_SUITE cannot be compiled or loaded'}}}},
{?eh,tc_start,{dummy_SUITE,init_per_suite}},
{?eh,tc_done,{dummy_SUITE,init_per_suite,ok}},
{?eh,test_stats,{1,1,{1,0}}},
@@ -186,7 +186,7 @@ test_events(ac_spec) ->
{?eh,start_info,{1,1,3}},
{?eh,tc_start,{ct_framework,error_in_suite}},
{?eh,tc_done,{ct_framework,error_in_suite,
- {failed,{error,'bad_SUITE can not be compiled or loaded'}}}},
+ {failed,{error,'bad_SUITE cannot be compiled or loaded'}}}},
{?eh,tc_start,{dummy_SUITE,init_per_suite}},
{?eh,tc_done,{dummy_SUITE,init_per_suite,ok}},
{?eh,test_stats,{1,1,{1,0}}},
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
index 7468ebe9d9..d31bd26273 100644
--- a/lib/common_test/test/ct_error_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -648,33 +648,35 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_11_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_11_SUITE,end_per_suite,ok}},
{?eh,tc_start,{cfg_error_12_SUITE,tc1}},
- {?eh,tc_done,{ct_framework,init_tc,{framework_error,{timetrap,500}}}},
- {?eh,test_stats,{13,8,{0,19}}},
+ {?eh,tc_done,{cfg_error_12_SUITE,tc1,
+ {auto_skipped,
+ {failed,{ct_framework,init_tc,{timetrap,500}}}}}},
+ {?eh,test_stats,{13,7,{0,20}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc2}},
{?eh,tc_done,{cfg_error_12_SUITE,tc2,{failed,
{cfg_error_12_SUITE,end_per_testcase,
{timetrap_timeout,500}}}}},
- {?eh,test_stats,{14,8,{0,19}}},
+ {?eh,test_stats,{14,7,{0,20}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc3}},
{?eh,tc_done,{cfg_error_12_SUITE,tc3,ok}},
- {?eh,test_stats,{15,8,{0,19}}},
+ {?eh,test_stats,{15,7,{0,20}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc4}},
{?eh,tc_done,{cfg_error_12_SUITE,tc4,{failed,
{cfg_error_12_SUITE,end_per_testcase,
{timetrap_timeout,500}}}}},
- {?eh,test_stats,{16,8,{0,19}}},
+ {?eh,test_stats,{16,7,{0,20}}},
{?eh,tc_start,{cfg_error_13_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_13_SUITE,init_per_suite,ok}},
{?eh,tc_start,{cfg_error_13_SUITE,tc1}},
{?eh,tc_done,{cfg_error_13_SUITE,tc1,ok}},
- {?eh,test_stats,{17,8,{0,19}}},
+ {?eh,test_stats,{17,7,{0,20}}},
{?eh,tc_start,{cfg_error_13_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_13_SUITE,end_per_suite,ok}},
{?eh,tc_start,{cfg_error_14_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_14_SUITE,init_per_suite,ok}},
{?eh,tc_start,{cfg_error_14_SUITE,tc1}},
{?eh,tc_done,{cfg_error_14_SUITE,tc1,ok}},
- {?eh,test_stats,{18,8,{0,19}}},
+ {?eh,test_stats,{18,7,{0,20}}},
{?eh,tc_start,{cfg_error_14_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_14_SUITE,end_per_suite,
{comment,
@@ -728,25 +730,30 @@ test_events(lib_error) ->
{lib_error_1_SUITE,no_lines_throw,{failed,{error,{thrown,catch_me_if_u_can}}}}},
{?eh,test_stats,{0,8,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,init_tc_error}},
- {?eh,tc_done,{ct_framework,init_tc,
- {framework_error,{{badmatch,[1,2]},'_'}}}},
- {?eh,test_stats,{0,9,{0,0}}},
+ {?eh,tc_done,{lib_error_1_SUITE,init_tc_error,
+ {auto_skipped,
+ {failed,
+ {ct_framework,init_tc,
+ {{badmatch,[1,2]},'_'}}}}}},
+ {?eh,test_stats,{0,8,{0,1}}},
{?eh,tc_start,{lib_error_1_SUITE,init_tc_exit}},
- {?eh,tc_done,{ct_framework,init_tc,{framework_error,byebye}}},
- {?eh,test_stats,{0,10,{0,0}}},
+ {?eh,tc_done,{lib_error_1_SUITE,init_tc_exit,
+ {auto_skipped,{failed,{ct_framework,init_tc,byebye}}}}},
+ {?eh,test_stats,{0,8,{0,2}}},
{?eh,tc_start,{lib_error_1_SUITE,init_tc_throw}},
- {?eh,tc_done,{ct_framework,init_tc,{framework_error,catch_me_if_u_can}}},
- {?eh,test_stats,{0,11,{0,0}}},
+ {?eh,tc_done,{lib_error_1_SUITE,init_tc_throw,
+ {auto_skipped,{failed,{ct_framework,init_tc,
+ catch_me_if_u_can}}}}},
+ {?eh,test_stats,{0,8,{0,3}}},
{?eh,tc_start,{lib_error_1_SUITE,end_tc_error}},
- {?eh,tc_done,{ct_framework,end_tc,
- {framework_error,{{badmatch,[1,2]},'_'}}}},
- {?eh,test_stats,{0,12,{0,0}}},
+ {?eh,tc_done,{lib_error_1_SUITE,end_tc_error,ok}}, % warning in comment
+ {?eh,test_stats,{1,8,{0,3}}},
{?eh,tc_start,{lib_error_1_SUITE,end_tc_exit}},
- {?eh,tc_done,{ct_framework,end_tc,{framework_error,byebye}}},
- {?eh,test_stats,{0,13,{0,0}}},
+ {?eh,tc_done,{lib_error_1_SUITE,end_tc_exit,ok}}, % warning in comment
+ {?eh,test_stats,{2,8,{0,3}}},
{?eh,tc_start,{lib_error_1_SUITE,end_tc_throw}},
- {?eh,tc_done,{ct_framework,end_tc,{framework_error,catch_me_if_u_can}}},
- {?eh,test_stats,{0,14,{0,0}}},
+ {?eh,tc_done,{lib_error_1_SUITE,end_tc_throw,ok}}, % warning in comment
+ {?eh,test_stats,{3,8,{0,3}}},
{?eh,tc_start,{lib_error_1_SUITE,end_per_suite}},
{?eh,tc_done,{lib_error_1_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 0f5636a789..340b8f3d52 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -73,18 +73,22 @@ all() ->
all(suite) ->
lists:reverse(
[
+ crash_groups, crash_all, bad_return_groups, bad_return_all,
+ illegal_values_groups, illegal_values_all, alter_groups, alter_all,
+ alter_all_to_skip, alter_all_from_skip,
one_cth, two_cth, faulty_cth_no_init, faulty_cth_id_no_init,
faulty_cth_exit_in_init, faulty_cth_exit_in_id,
faulty_cth_exit_in_init_scope_suite, minimal_cth,
minimal_and_maximal_cth, faulty_cth_undef,
scope_per_suite_cth, scope_per_group_cth, scope_suite_cth,
+ scope_suite_group_only_cth,
scope_per_suite_state_cth, scope_per_group_state_cth,
scope_suite_state_cth,
fail_pre_suite_cth, double_fail_pre_suite_cth,
fail_post_suite_cth, skip_pre_suite_cth, skip_pre_end_cth,
skip_pre_init_tc_cth,
skip_post_suite_cth, recover_post_suite_cth, update_config_cth,
- state_update_cth, options_cth, same_id_cth,
+ state_update_cth, update_result_cth, options_cth, same_id_cth,
fail_n_skip_with_minimal_cth, prio_cth, no_config,
no_init_suite_config, no_init_config, no_end_config,
failed_sequence, repeat_force_stop, config_clash,
@@ -152,6 +156,11 @@ scope_suite_cth(Config) when is_list(Config) ->
do_test(scope_suite_cth, "ct_scope_suite_cth_SUITE.erl",
[],Config).
+scope_suite_group_only_cth(Config) when is_list(Config) ->
+ do_test(scope_suite_group_only_cth,
+ "ct_scope_suite_group_only_cth_SUITE.erl",
+ [],Config,ok,2,[{group,g1}]).
+
scope_per_group_cth(Config) when is_list(Config) ->
do_test(scope_per_group_cth, "ct_scope_per_group_cth_SUITE.erl",
[],Config).
@@ -209,6 +218,10 @@ state_update_cth(Config) when is_list(Config) ->
do_test(state_update_cth, "ct_cth_fail_one_skip_one_SUITE.erl",
[state_update_cth,state_update_cth],Config).
+update_result_cth(Config) ->
+ do_test(update_result_cth, "ct_cth_update_result_post_end_tc_SUITE.erl",
+ [update_result_post_end_tc_cth],Config).
+
options_cth(Config) when is_list(Config) ->
do_test(options_cth, "ct_cth_empty_SUITE.erl",
[{empty_cth,[test]}],Config).
@@ -300,10 +313,74 @@ repeat_force_stop(Config) ->
[{force_stop,skip_rest},{duration,"000009"}]).
%% Test that expected callbacks, and only those, are called when a test
-%% are fails due to clash in config alias names
+%% fails due to clash in config alias names
config_clash(Config) ->
do_test(config_clash, "config_clash_SUITE.erl", [skip_cth], Config).
+%% Test post_groups and post_all hook callbacks, introduced by OTP-14746
+alter_groups(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_groups_return,[{new_group,[tc1,tc2]}]},
+ {post_all_return,[{group,new_group}]}],Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+alter_all(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,[{post_all_return,[tc2]}],Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+alter_all_from_skip(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,[{all_return,{skip,"skipped by all/0"}},
+ {post_all_return,[tc2]}],Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+alter_all_to_skip(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_all_return,{skip,"skipped by post_all/3"}}],
+ Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+bad_return_groups(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,[{post_groups_return,not_a_list}],
+ Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+bad_return_all(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,[{post_all_return,not_a_list}],
+ Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+illegal_values_groups(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_groups_return,[{new_group,[this_test_does_not_exist]},
+ this_is_not_a_group_def]}],
+ Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+illegal_values_all(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_all_return,[{group,this_group_does_not_exist},
+ {this_is_not_a_valid_term}]}],
+ Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+crash_groups(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,[{post_groups_return,crash}],Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
+crash_all(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,[{post_all_return,crash}],Config),
+ do_test(?FUNCTION_NAME, "all_and_groups_SUITE.erl", [all_and_groups_cth],
+ Config, ok, 2, [{config,CfgFile}]).
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
@@ -323,6 +400,7 @@ do_test(Tag, {WhatTag,Wildcard}, CTHs, Config, Res, EC, ExtraOpts) ->
filename:join([DataDir,"cth/tests",Wildcard])),
{Opts,ERPid} =
setup([{WhatTag,Files},{ct_hooks,CTHs},{label,Tag}|ExtraOpts], Config),
+
Res = ct_test_support:run(Opts, Config),
Events = ct_test_support:get_events(ERPid, Config),
@@ -348,6 +426,13 @@ reformat(Events, EH) ->
%reformat(Events, _EH) ->
% Events.
+gen_config(Name,KeyVals,Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ File = filename:join(PrivDir,atom_to_list(Name)++".cfg"),
+ ok = file:write_file(File,[io_lib:format("~p.~n",[{Key,Value}])
+ || {Key,Value} <- KeyVals]),
+ File.
+
%%%-----------------------------------------------------------------
%%% TEST EVENTS
%%%-----------------------------------------------------------------
@@ -366,13 +451,16 @@ test_events(one_empty_cth) ->
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,cth,{empty_cth,id,[[]]}},
{?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ %% check that post_groups and post_all comes after init when hook
+ %% is installed with start flag/option.
+ {?eh,cth,{empty_cth,post_groups,[ct_cth_empty_SUITE,[]]}},
+ {?eh,cth,{empty_cth,post_all,[ct_cth_empty_SUITE,[test_case],[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{empty_cth,pre_init_per_suite,
[ct_cth_empty_SUITE,'$proplist',[]]}},
{?eh,cth,{empty_cth,post_init_per_suite,
[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}},
{?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}},
-
{?eh,tc_start,{ct_cth_empty_SUITE,test_case}},
{?eh,cth,{empty_cth,pre_init_per_testcase,[ct_cth_empty_SUITE,test_case,'$proplist',[]]}},
{?eh,cth,{empty_cth,post_init_per_testcase,[ct_cth_empty_SUITE,test_case,'$proplist','_',[]]}},
@@ -581,6 +669,10 @@ test_events(scope_suite_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ %% check that post_groups and post_all comes before init when hook
+ %% is installed in suite/0
+ {?eh,cth,{'_',post_groups,['_',[]]}},
+ {?eh,cth,{'_',post_all,['_','_',[]]}},
{?eh,tc_start,{ct_scope_suite_cth_SUITE,init_per_suite}},
{?eh,cth,{'_',id,[[]]}},
{?eh,cth,{'_',init,['_',[]]}},
@@ -602,6 +694,34 @@ test_events(scope_suite_cth) ->
{?eh,stop_logging,[]}
];
+test_events(scope_suite_group_only_cth) ->
+ Suite = ct_scope_suite_group_only_cth_SUITE,
+ CTH = empty_cth,
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ %% check that post_groups and post_all comes before init when hook
+ %% is installed in suite/0
+ {?eh,cth,{CTH,post_groups,['_',['_']]}},
+ {negative,
+ {?eh,cth,{CTH,post_all,['_','_','_']}},
+ {?eh,tc_start,{Suite,init_per_suite}}},
+ {?eh,cth,{CTH,id,[[]]}},
+ {?eh,cth,{CTH,init,['_',[]]}},
+ {?eh,cth,{CTH,pre_init_per_suite,[Suite,'$proplist',mystate]}},
+ {?eh,cth,{CTH,post_init_per_suite,[Suite,'$proplist','$proplist',mystate]}},
+ {?eh,tc_done,{Suite,init_per_suite,ok}},
+
+ {?eh,tc_start,{Suite,end_per_suite}},
+ {?eh,cth,{CTH,pre_end_per_suite,[Suite,'$proplist',mystate]}},
+ {?eh,cth,{CTH,post_end_per_suite,[Suite,'$proplist','_',mystate]}},
+ {?eh,cth,{CTH,terminate,[mystate]}},
+ {?eh,tc_done,{Suite,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
test_events(scope_per_group_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
@@ -661,6 +781,8 @@ test_events(scope_suite_state_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',post_groups,['_',[]]}},
+ {?eh,cth,{'_',post_all,['_','_',[]]}},
{?eh,tc_start,{ct_scope_suite_state_cth_SUITE,init_per_suite}},
{?eh,cth,{'_',id,[[test]]}},
{?eh,cth,{'_',init,['_',[test]]}},
@@ -1099,6 +1221,106 @@ test_events(state_update_cth) ->
{?eh,stop_logging,[]}
];
+test_events(update_result_cth) ->
+ Suite = ct_cth_update_result_post_end_tc_SUITE,
+ [
+ {?eh,start_logging,'_'},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
+ {?eh,tc_start,{Suite,init_per_suite}},
+ {?eh,tc_done,{Suite,init_per_suite,ok}},
+
+ {?eh,tc_start,{Suite,tc_ok_to_fail}},
+ {?eh,cth,{'_',post_end_per_testcase,[Suite,tc_ok_to_fail,'_',ok,[]]}},
+ {?eh,tc_done,{Suite,tc_ok_to_fail,{failed,{error,"Test failure"}}}},
+ {?eh,cth,{'_',on_tc_fail,'_'}},
+ {?eh,test_stats,{0,1,{0,0}}},
+
+ {?eh,tc_start,{Suite,tc_ok_to_skip}},
+ {?eh,cth,{'_',post_end_per_testcase,[Suite,tc_ok_to_skip,'_',ok,[]]}},
+ {?eh,tc_done,{Suite,tc_ok_to_skip,{skipped,"Test skipped"}}},
+ {?eh,cth,{'_',on_tc_skip,'_'}},
+ {?eh,test_stats,{0,1,{1,0}}},
+
+ {?eh,tc_start,{Suite,tc_fail_to_ok}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,tc_fail_to_ok,'_',
+ {error,{test_case_failed,"should be changed to ok"}},[]]}},
+ {?eh,tc_done,{Suite,tc_fail_to_ok,ok}},
+ {?eh,test_stats,{1,1,{1,0}}},
+
+ {?eh,tc_start,{Suite,tc_fail_to_skip}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,tc_fail_to_skip,'_',
+ {error,{test_case_failed,"should be changed to skip"}},[]]}},
+ {?eh,tc_done,{Suite,tc_fail_to_skip,{skipped,"Test skipped"}}},
+ {?eh,cth,{'_',on_tc_skip,'_'}},
+ {?eh,test_stats,{1,1,{2,0}}},
+
+ {?eh,tc_start,{Suite,tc_timetrap_to_ok}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,tc_timetrap_to_ok,'_',{timetrap_timeout,3000},[]]}},
+ {?eh,tc_done,{Suite,tc_timetrap_to_ok,ok}},
+ {?eh,test_stats,{2,1,{2,0}}},
+
+ {?eh,tc_start,{Suite,tc_timetrap_to_skip}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,tc_timetrap_to_skip,'_',{timetrap_timeout,3000},[]]}},
+ {?eh,tc_done,{Suite,tc_timetrap_to_skip,{skipped,"Test skipped"}}},
+ {?eh,cth,{'_',on_tc_skip,'_'}},
+ {?eh,test_stats,{2,1,{3,0}}},
+
+ {?eh,tc_start,{Suite,tc_skip_to_fail}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,tc_skip_to_fail,'_',
+ {skip,"should be changed to fail"},[]]}},
+ {?eh,tc_done,{Suite,tc_skip_to_fail,{failed,{error,"Test failure"}}}},
+ {?eh,cth,{'_',on_tc_fail,'_'}},
+ {?eh,test_stats,{2,2,{3,0}}},
+
+ {?eh,tc_start,{Suite,end_fail_to_fail}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,end_fail_to_fail,'_',
+ {failed,
+ {Suite,end_per_testcase,
+ {'EXIT',{test_case_failed,"change result when end fails"}}}},[]]}},
+ {?eh,tc_done,{Suite,end_fail_to_fail,{failed,{error,"Test failure"}}}},
+ {?eh,cth,{'_',on_tc_fail,'_'}},
+ {?eh,test_stats,{2,3,{3,0}}},
+
+ {?eh,tc_start,{Suite,end_fail_to_skip}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,end_fail_to_skip,'_',
+ {failed,
+ {Suite,end_per_testcase,
+ {'EXIT',{test_case_failed,"change result when end fails"}}}},[]]}},
+ {?eh,tc_done,{Suite,end_fail_to_skip,{skipped,"Test skipped"}}},
+ {?eh,cth,{'_',on_tc_skip,'_'}},
+ {?eh,test_stats,{2,3,{4,0}}},
+
+ {?eh,tc_start,{Suite,end_timetrap_to_fail}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,end_timetrap_to_fail,'_',
+ {failed,{Suite,end_per_testcase,{timetrap_timeout,3000}}},[]]}},
+ {?eh,tc_done,{Suite,end_timetrap_to_fail,{failed,{error,"Test failure"}}}},
+ {?eh,cth,{'_',on_tc_fail,'_'}},
+ {?eh,test_stats,{2,4,{4,0}}},
+
+ {?eh,tc_start,{Suite,end_timetrap_to_skip}},
+ {?eh,cth,{'_',post_end_per_testcase,
+ [Suite,end_timetrap_to_skip,'_',
+ {failed,{Suite,end_per_testcase,{timetrap_timeout,3000}}},[]]}},
+ {?eh,tc_done,{Suite,end_timetrap_to_skip,{skipped,"Test skipped"}}},
+ {?eh,cth,{'_',on_tc_skip,'_'}},
+ {?eh,test_stats,{2,4,{5,0}}},
+
+ {?eh,tc_start,{Suite,end_per_suite}},
+ {?eh,tc_done,{Suite,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{'_',terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
test_events(options_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
@@ -2209,6 +2431,229 @@ test_events(config_clash) ->
%% Make sure no 'cth_error' events are received!
[{negative,{?eh,cth_error,'_'},E} || E <- Events];
+test_events(alter_groups) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,
+ [{new_group,[tc1,tc2]}]]}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,[{group,new_group}],
+ [{new_group,[tc1,tc2]}]]}},
+ {?eh,start_info,{1,1,2}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,
+ [{new_group,[tc1,tc2]}]]}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,[{group,new_group}],
+ [{new_group,[tc1,tc2]}]]}},
+ {?eh,tc_start,{all_and_groups_SUITE,{init_per_group,new_group,[]}}},
+ {?eh,tc_done,{all_and_groups_SUITE,
+ {init_per_group,new_group,'$proplist'},ok}},
+ {?eh,tc_start,{all_and_groups_SUITE,tc1}},
+ {?eh,tc_done,{all_and_groups_SUITE,tc1,ok}},
+ {?eh,tc_start,{all_and_groups_SUITE,tc2}},
+ {?eh,tc_done,{all_and_groups_SUITE,tc2,ok}},
+ {?eh,tc_start,{all_and_groups_SUITE,{end_per_group,new_group,[]}}},
+ {?eh,tc_done,{all_and_groups_SUITE,
+ {end_per_group,new_group,'$proplist'},ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(alter_all) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,
+ [{test_group,[tc1]}]]}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,[tc2],
+ [{test_group,[tc1]}]]}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,[tc2],'_']}},
+ {?eh,tc_start,{all_and_groups_SUITE,tc2}},
+ {?eh,tc_done,{all_and_groups_SUITE,tc2,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(alter_all_from_skip) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,
+ [{test_group,[tc1]}]]}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,[tc2],
+ [{test_group,[tc1]}]]}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,[tc2],'_']}},
+ {?eh,tc_start,{all_and_groups_SUITE,tc2}},
+ {?eh,tc_done,{all_and_groups_SUITE,tc2,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(alter_all_to_skip) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,
+ [{test_group,[tc1]}]]}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,
+ {skip,"skipped by post_all/3"},
+ [{test_group,[tc1]}]]}},
+ {?eh,start_info,{1,1,0}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,
+ {skip,"skipped by post_all/3"},
+ '_']}},
+ {?eh,tc_user_skip,{all_and_groups_SUITE,all,"skipped by post_all/3"}},
+ {?eh,cth,{'_',on_tc_skip,[all_and_groups_SUITE,all,
+ {tc_user_skip,"skipped by post_all/3"},
+ []]}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(illegal_values_groups) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,
+ [all_and_groups_SUITE,
+ [{new_group,[this_test_does_not_exist]},
+ this_is_not_a_group_def]]}},
+ {?eh,start_info,{1,0,0}},
+ {?eh,cth,{empty_cth,post_groups,
+ [all_and_groups_SUITE,
+ [{new_group,[this_test_does_not_exist]},
+ this_is_not_a_group_def]]}},
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,tc_done,{ct_framework,error_in_suite,{failed,{error,'_'}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(illegal_values_all) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,
+ [all_and_groups_SUITE,
+ [{group,this_group_does_not_exist},
+ {this_is_not_a_valid_term}],'_']}},
+ {?eh,start_info,{1,0,0}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,
+ [all_and_groups_SUITE,
+ [{group,this_group_does_not_exist},
+ {this_is_not_a_valid_term}],'_']}},
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,tc_done,
+ {ct_framework,error_in_suite,
+ {failed,
+ {error,'Invalid reference to group this_group_does_not_exist in all_and_groups_SUITE:all/0'}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(bad_return_groups) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,not_a_list]}},
+ {?eh,start_info,{1,0,0}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,not_a_list]}},
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,tc_done,
+ {ct_framework,error_in_suite,
+ {failed,
+ {error,
+ {'Bad return value from post_groups/2 hook function',not_a_list}}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(bad_return_all) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,not_a_list,'_']}},
+ {?eh,start_info,{1,0,0}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,not_a_list,'_']}},
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,tc_done,
+ {ct_framework,error_in_suite,
+ {failed,
+ {error,{'Bad return value from post_all/3 hook function',not_a_list}}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(crash_groups) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,crash]}},
+ {?eh,start_info,{1,0,0}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,crash]}},
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,tc_done,{ct_framework,error_in_suite,
+ {failed,
+ {error,"all_and_groups_cth:post_groups/2 CTH call failed"}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(crash_all) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
+ {?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,crash,'_']}},
+ {?eh,start_info,{1,0,0}},
+ {?eh,cth,{empty_cth,post_groups,[all_and_groups_SUITE,'_']}},
+ {?eh,cth,{empty_cth,post_all,[all_and_groups_SUITE,crash,'_']}},
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,tc_done,{ct_framework,error_in_suite,
+ {failed,
+ {error,"all_and_groups_cth:post_all/3 CTH call failed"}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,cth,{empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
test_events(ok) ->
ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_SUITE.erl
new file mode 100644
index 0000000000..adc86005f9
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_SUITE.erl
@@ -0,0 +1,47 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(all_and_groups_SUITE).
+
+-suite_defaults([{timetrap, {minutes, 10}}]).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+init_per_group(_Group,Config) ->
+ Config.
+
+end_per_group(_Group,Config) ->
+ ok.
+
+all() ->
+ ct:get_config(all_return,[{group,test_group}]).
+
+groups() ->
+ [{test_group,[tc1]}].
+
+%% Test cases starts here.
+tc1(Config) ->
+ ok.
+
+tc2(Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_cth.erl
new file mode 100644
index 0000000000..9ebc00e9de
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/all_and_groups_cth.erl
@@ -0,0 +1,100 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(all_and_groups_cth).
+
+
+-include_lib("common_test/src/ct_util.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+%% Send a cth_error event if a callback is called with unexpected arguments
+-define(fail(Info),
+ gen_event:notify(
+ ?CT_EVMGR_REF,
+ #event{ name = cth_error,
+ node = node(),
+ data = {illegal_hook_callback,{?MODULE,?FUNCTION_NAME,Info}}})).
+
+%% CT Hooks
+-compile(export_all).
+
+id(Opts) ->
+ empty_cth:id(Opts).
+
+post_groups(Suite,Groups) ->
+ case empty_cth:post_groups(Suite,ct:get_config(post_groups_return,Groups)) of
+ crash -> error(crash_in_post_groups);
+ R -> R
+ end.
+
+post_all(Suite,Tests,Groups) ->
+ case empty_cth:post_all(Suite,ct:get_config(post_all_return,Tests),Groups) of
+ crash -> error(crash_in_post_all);
+ R -> R
+ end.
+
+init(Id, Opts) ->
+ empty_cth:init(Id, Opts).
+
+pre_init_per_suite(Suite, Config, State) ->
+ empty_cth:pre_init_per_suite(Suite,Config,State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_init_per_suite(Suite,Config,Return,State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ empty_cth:pre_end_per_suite(Suite,Config,State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Suite,Group,Config,State) ->
+ empty_cth:pre_init_per_group(Suite,Group,Config,State).
+
+post_init_per_group(Suite,Group,Config,Return,State) ->
+ empty_cth:post_init_per_group(Suite,Group,Config,Return,State).
+
+pre_end_per_group(Suite,Group,Config,State) ->
+ empty_cth:pre_end_per_group(Suite,Group,Config,State).
+
+post_end_per_group(Suite,Group,Config,Return,State) ->
+ empty_cth:post_end_per_group(Suite,Group,Config,Return,State).
+
+pre_init_per_testcase(Suite,TC,Config,State) ->
+ empty_cth:pre_init_per_testcase(Suite,TC,Config,State).
+
+post_init_per_testcase(Suite,TC,Config,Return,State) ->
+ empty_cth:post_init_per_testcase(Suite,TC,Config,Return,State).
+
+pre_end_per_testcase(Suite,TC,Config,State) ->
+ empty_cth:pre_end_per_testcase(Suite,TC,Config,State).
+
+post_end_per_testcase(Suite,TC,Config,Return,State) ->
+ empty_cth:post_end_per_testcase(Suite,TC,Config,Return,State).
+
+on_tc_fail(Suite,TC,Reason,State) ->
+ empty_cth:on_tc_fail(Suite,TC,Reason,State).
+
+on_tc_skip(Suite,TC,Reason,State) ->
+ empty_cth:on_tc_skip(Suite,TC,Reason,State).
+
+terminate(State) ->
+ empty_cth:terminate(State).
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_update_result_post_end_tc_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_update_result_post_end_tc_SUITE.erl
new file mode 100644
index 0000000000..a16138ce6f
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_update_result_post_end_tc_SUITE.erl
@@ -0,0 +1,101 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_cth_update_result_post_end_tc_SUITE).
+
+-compile(export_all).
+
+-include("ct.hrl").
+
+suite() ->
+ [{timetrap,{seconds,3}}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(Config) ->
+ ok.
+
+init_per_group(_,Config) ->
+ Config.
+
+end_per_group(_,_) ->
+ ok.
+
+init_per_testcase(_,Config) ->
+ Config.
+
+end_per_testcase(EndTimetrap,_) when EndTimetrap==end_timetrap_to_fail;
+ EndTimetrap==end_timetrap_to_skip->
+ timer:sleep(10000);
+end_per_testcase(EndFail,_) when EndFail==end_fail_to_fail;
+ EndFail==end_fail_to_skip->
+ ct:fail("change result when end fails");
+end_per_testcase(_,_) ->
+ ok.
+
+all() ->
+ [tc_ok_to_fail,
+ tc_ok_to_skip,
+ tc_fail_to_ok,
+ tc_fail_to_skip,
+ tc_timetrap_to_ok,
+ tc_timetrap_to_skip,
+ tc_skip_to_fail,
+ end_fail_to_fail,
+ end_fail_to_skip,
+ end_timetrap_to_fail,
+ end_timetrap_to_skip].
+
+%% Test cases starts here.
+tc_ok_to_fail(_Config) ->
+ ok.
+
+tc_ok_to_skip(_Config) ->
+ ok.
+
+tc_fail_to_ok(_Config) ->
+ ct:fail("should be changed to ok").
+
+tc_fail_to_skip(_Config) ->
+ ct:fail("should be changed to skip").
+
+tc_timetrap_to_ok(_Config) ->
+ timer:sleep(10000), % will time out after 3 sek
+ ok.
+
+tc_timetrap_to_skip(_Config) ->
+ timer:sleep(10000), % will time out after 3 sek
+ ok.
+
+tc_skip_to_fail(_Config) ->
+ {skip,"should be changed to fail"}.
+
+end_fail_to_fail(_Config) ->
+ ok.
+
+end_fail_to_skip(_Config) ->
+ ok.
+
+end_timetrap_to_fail(_Config) ->
+ ok.
+
+end_timetrap_to_skip(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_match_state_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_match_state_cth.erl
new file mode 100644
index 0000000000..38c9da903d
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_match_state_cth.erl
@@ -0,0 +1,58 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(ct_match_state_cth).
+
+
+-include_lib("common_test/src/ct_util.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-compile(export_all).
+
+id(Opts) ->
+ empty_cth:id(Opts).
+
+post_groups(Suite, Groups) ->
+ empty_cth:post_groups(Suite, Groups).
+
+post_all(Suite, Tests, Groups) ->
+ empty_cth:post_all(Suite, Tests, Groups).
+
+init(Id, Opts) ->
+ empty_cth:init(Id, Opts),
+ {ok,mystate}.
+
+%% In the following, always match against the state value, to ensure
+%% that init has indeed been called before the rest of the hooks.
+pre_init_per_suite(Suite,Config,mystate) ->
+ empty_cth:pre_init_per_suite(Suite,Config,mystate).
+
+post_init_per_suite(Suite,Config,Return,mystate) ->
+ empty_cth:post_init_per_suite(Suite,Config,Return,mystate).
+
+pre_end_per_suite(Suite,Config,mystate) ->
+ empty_cth:pre_end_per_suite(Suite,Config,mystate).
+
+post_end_per_suite(Suite,Config,Return,mystate) ->
+ empty_cth:post_end_per_suite(Suite,Config,Return,mystate).
+
+terminate(mystate) ->
+ empty_cth:terminate(mystate).
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_group_only_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_group_only_cth_SUITE.erl
new file mode 100644
index 0000000000..537c97d3f0
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_group_only_cth_SUITE.erl
@@ -0,0 +1,54 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_scope_suite_group_only_cth_SUITE).
+
+-suite_defaults([{timetrap, {minutes, 10}}]).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+%% Test server callback functions
+suite() ->
+ [{ct_hooks,[ct_match_state_cth]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+all() ->
+ [test_case].
+
+groups() ->
+ [{g1,[test_case]}].
+
+%% Test cases starts here.
+test_case(Config) when is_list(Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
index c648367838..60488e84c6 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
@@ -39,6 +39,9 @@
-export([id/1]).
-export([init/2]).
+-export([post_all/3]).
+-export([post_groups/2]).
+
-export([pre_init_per_suite/3]).
-export([post_init_per_suite/4]).
-export([pre_end_per_suite/3]).
@@ -71,6 +74,31 @@
-record(state, { id = ?MODULE :: term()}).
+%% Called after groups/0.
+%% You can change the return value in this function.
+-spec post_groups(Suite :: atom(), Groups :: list()) -> list().
+post_groups(Suite,Groups) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_groups,
+ [Suite,Groups]}}),
+ ct:log("~w:post_groups(~w) called", [?MODULE,Suite]),
+ Groups.
+
+%% Called after all/0.
+%% You can change the return value in this function.
+-spec post_all(Suite :: atom(),
+ Tests :: list(),
+ Groups :: term()) ->
+ list().
+post_all(Suite,Tests,Groups) ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_all,
+ [Suite,Tests,Groups]}}),
+ ct:log("~w:post_all(~w) called", [?MODULE,Suite]),
+ Tests.
+
%% Always called before any other callback function. Use this to initiate
%% any common state. It should return an state for this CTH.
-spec init(Id :: term(), Opts :: proplists:proplist()) ->
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_result_post_end_tc_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_result_post_end_tc_cth.erl
new file mode 100644
index 0000000000..7afb3d8781
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/update_result_post_end_tc_cth.erl
@@ -0,0 +1,98 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(update_result_post_end_tc_cth).
+
+
+-include_lib("common_test/src/ct_util.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+
+%% CT Hooks
+-compile(export_all).
+
+init(Id, Opts) ->
+ empty_cth:init(Id, Opts).
+
+pre_init_per_suite(Suite, Config, State) ->
+ empty_cth:pre_init_per_suite(Suite,Config,State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_init_per_suite(Suite,Config,Return,State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ empty_cth:pre_end_per_suite(Suite,Config,State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Suite,Group,Config,State) ->
+ empty_cth:pre_init_per_group(Suite,Group,Config,State).
+
+post_init_per_group(Suite,Group,Config,Return,State) ->
+ empty_cth:post_init_per_group(Suite,Group,Config,Return,State).
+
+pre_end_per_group(Suite,Group,Config,State) ->
+ empty_cth:pre_end_per_group(Suite,Group,Config,State).
+
+post_end_per_group(Suite,Group,Config,Return,State) ->
+ empty_cth:post_end_per_group(Suite,Group,Config,Return,State).
+
+pre_init_per_testcase(Suite,TC,Config,State) ->
+ empty_cth:pre_init_per_testcase(Suite,TC,Config,State).
+
+post_end_per_testcase(Suite,TC,Config,Return,State) ->
+ empty_cth:post_end_per_testcase(Suite,TC,Config,Return,State),
+ change_result(TC,Config,State).
+
+on_tc_fail(Suite,TC, Reason, State) ->
+ empty_cth:on_tc_fail(Suite,TC,Reason,State).
+
+on_tc_skip(Suite,TC, Reason, State) ->
+ empty_cth:on_tc_skip(Suite,TC,Reason,State).
+
+terminate(State) ->
+ empty_cth:terminate(State).
+
+%%%-----------------------------------------------------------------
+%%%
+change_result(tc_ok_to_fail,_Config,State) ->
+ {{fail, "Test failure"}, State};
+change_result(tc_ok_to_skip,_Config,State) ->
+ {{skip, "Test skipped"}, State};
+change_result(tc_fail_to_ok,Config,State) ->
+ {lists:keydelete(tc_status,1,Config),State};
+change_result(tc_fail_to_skip,Config,State) ->
+ {{skip,"Test skipped"},State};
+change_result(tc_timetrap_to_ok,Config,State) ->
+ {lists:keydelete(tc_status,1,Config),State};
+change_result(tc_timetrap_to_skip,Config,State) ->
+ {{skip,"Test skipped"},State};
+change_result(tc_skip_to_fail,_Config,State) ->
+ {{fail, "Test failure"}, State};
+change_result(end_fail_to_fail,_Config,State) ->
+ {{fail, "Test failure"}, State};
+change_result(end_fail_to_skip,_Config,State) ->
+ {{skip, "Test skipped"}, State};
+change_result(end_timetrap_to_fail,_Config,State) ->
+ {{fail, "Test failure"}, State};
+change_result(end_timetrap_to_skip,_Config,State) ->
+ {{skip, "Test skipped"}, State}.
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
index a2fa099a8c..0d17481e95 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -440,6 +440,12 @@ edit_config(Config) ->
?ok = ct_netconfc:edit_config(Client,running,
{server,[{xmlns,"myns"}],
[{name,["myserver"]}]}),
+ ?NS:expect_reply('edit-config',ok),
+ ?ok = ct_netconfc:edit_config(Client,running,
+ [{server,[{xmlns,"myns"}],
+ [{name,["server1"]}]},
+ {server,[{xmlns,"myns"}],
+ [{name,["server2"]}]}]),
?NS:expect_do_reply('close-session',close,ok),
?ok = ct_netconfc:close_session(Client),
ok.
diff --git a/lib/common_test/test/ct_tc_repeat_SUITE.erl b/lib/common_test/test/ct_tc_repeat_SUITE.erl
new file mode 100644
index 0000000000..433b5456fe
--- /dev/null
+++ b/lib/common_test/test/ct_tc_repeat_SUITE.erl
@@ -0,0 +1,438 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(ct_tc_repeat_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ DataDir = ?config(data_dir, Config),
+ ct_test_support:init_per_suite([{path_dirs,[DataDir]} | Config]).
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+
+suite() ->
+ [{timetrap,{minutes,1}}].
+
+all() ->
+ all(suite).
+
+all(suite) ->
+ [
+ repeat,
+ repeat_parallel_until_ok,
+ repeat_parallel_until_fail,
+ repeat_sequence_until_ok,
+ repeat_sequence_until_fail,
+ pick_one_test_from_group,
+ pick_one_test_from_subgroup
+ ].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+%% Test post_groups and post_all hook callbacks, introduced by OTP-14746
+repeat(Config) ->
+ ok = do_test(?FUNCTION_NAME, "tc_repeat_SUITE", [], [], Config).
+
+repeat_parallel_until_ok(Config) ->
+ {error,{{illegal_combination,{parallel,repeat_until_ok}},_}} =
+ do_test(?FUNCTION_NAME, "tc_repeat_SUITE", [{group,g_parallel_until_ok}],
+ [], Config, 1, []).
+
+repeat_parallel_until_fail(Config) ->
+ {error,{{illegal_combination,{parallel,repeat_until_fail}},_}} =
+ do_test(?FUNCTION_NAME, "tc_repeat_SUITE", [{group,g_parallel_until_fail}],
+ [], Config, 1, []).
+
+repeat_sequence_until_ok(Config) ->
+ {error,{{illegal_combination,{sequence,repeat_until_ok}},_}} =
+ do_test(?FUNCTION_NAME, "tc_repeat_SUITE", [{group,g_sequence_until_ok}],
+ [], Config, 1, []).
+
+repeat_sequence_until_fail(Config) ->
+ {error,{{illegal_combination,{sequence,repeat_until_fail}},_}} =
+ do_test(?FUNCTION_NAME, "tc_repeat_SUITE", [{group,g_sequence_until_fail}],
+ [], Config, 1, []).
+
+pick_one_test_from_group(Config) ->
+ do_test(?FUNCTION_NAME, "tc_repeat_SUITE", [{group,g_mixed},{testcase,tc2}],
+ [], Config, 1, []).
+
+pick_one_test_from_subgroup(Config) ->
+ do_test(?FUNCTION_NAME, "tc_repeat_SUITE",
+ [{group,[[g_mixed,subgroup]]},{testcase,tc2}],
+ [], Config, 1, []).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+do_test(Tag, Suite, WTT, CTHs, Config) ->
+ do_test(Tag, Suite, WTT, CTHs, Config, 2, []).
+
+do_test(Tag, Suite0, WTT, CTHs, Config, EC, ExtraOpts) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join([DataDir,Suite0]),
+ {Opts,ERPid} =
+ setup([{suite,Suite}|WTT]++[{ct_hooks,CTHs},{label,Tag}|ExtraOpts],
+ Config),
+ Res = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+ %% io:format("~p~n",[Events]),
+
+ ct_test_support:log_events(Tag,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Tag, EC),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config),
+ Res.
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+gen_config(Name,KeyVals,Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ File = filename:join(PrivDir,atom_to_list(Name)++".cfg"),
+ ok = file:write_file(File,[io_lib:format("~p.~n",[{Key,Value}])
+ || {Key,Value} <- KeyVals]),
+ File.
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(repeat) ->
+ S = tc_repeat_SUITE,
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+
+ %% tc1, {repeat,2}
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ %% tc2, {repeat_until_ok,3}
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ %% tc3, {repeat_until_ok,3}
+ {?eh,tc_start,{S,tc3}},
+ {?eh,tc_done,{tc_repeat_SUITE,tc3,
+ {failed,{error,{test_case_failed,always_fail}}}}},
+ {?eh,test_stats,{3,1,{0,0}}},
+ {?eh,tc_start,{S,tc3}},
+ {?eh,tc_done,{S,tc3,{failed,{error,{test_case_failed,always_fail}}}}},
+ {?eh,test_stats,{3,2,{0,0}}},
+ {?eh,tc_start,{S,tc3}},
+ {?eh,tc_done,{S,tc3,{failed,{error,{test_case_failed,always_fail}}}}},
+ {?eh,test_stats,{3,3,{0,0}}},
+ %% tc4, {repeat_until_fail,3}
+ {?eh,tc_start,{S,tc4}},
+ {?eh,tc_done,{S,tc4,ok}},
+ {?eh,test_stats,{4,3,{0,0}}},
+ {?eh,tc_start,{S,tc4}},
+ {?eh,tc_done,{S,tc4,{failed,{error,{test_case_failed,second_time_fail}}}}},
+ {?eh,test_stats,{4,4,{0,0}}},
+ %% g, tc1, {repeat,2}
+ {?eh,tc_start,{S,{init_per_group,g,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{5,4,{0,0}}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{6,4,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g,[]}}},
+ {?eh,tc_done,{S,{end_per_group,g,[]},ok}},
+ %% g_until_ok, tc2, {repeat_until_ok,3}
+ {?eh,tc_start,{S,{init_per_group,g_until_ok,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g_until_ok,[]},ok}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{7,4,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g_until_ok,[]}}},
+ {?eh,tc_done,{S,{end_per_group,g_until_ok,[]},ok}},
+ %% g_until_fail, tc4, {repeat_until_fail,3}
+ {?eh,tc_start,{S,{init_per_group,g_until_fail,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g_until_fail,[]},ok}},
+ {?eh,tc_start,{S,tc4}},
+ {?eh,tc_done,{S,tc4,ok}},
+ {?eh,test_stats,{8,4,{0,0}}},
+ {?eh,tc_start,{S,tc4}},
+ {?eh,tc_done,{S,tc4,{failed,{error,{test_case_failed,second_time_fail}}}}},
+ {?eh,test_stats,{8,5,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g_until_fail,[]}}},
+ {?eh,tc_done,{S,{end_per_group,g_until_fail,[]},ok}},
+ %% g, parallel, tc1, {repeat,2}
+ {parallel,
+ [{?eh,tc_start,{S,{init_per_group,g,[parallel]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[parallel]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{9,5,{0,0}}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{10,5,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g,[parallel]}}},
+ {?eh,tc_done,{S,{end_per_group,g,[parallel]},ok}}]},
+ %% g, sequence, tc1, {repeat,2}
+ {?eh,tc_start,{S,{init_per_group,g,[sequence]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[sequence]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{11,5,{0,0}}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{12,5,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g,[sequence]}}},
+ {?eh,tc_done,{S,{end_per_group,g,[sequence]},ok}},
+ %% g_sequence_skip_rest,
+ {?eh,tc_start,{S,{init_per_group,g_mixed,[sequence]}}},
+ {?eh,tc_done,{S,{init_per_group,g_mixed,[sequence]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{13,5,{0,0}}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{14,5,{0,0}}},
+ {?eh,tc_start,{S,tc4}},
+ {?eh,tc_done,{S,tc4,ok}},
+ {?eh,test_stats,{15,5,{0,0}}},
+ {?eh,tc_start,{S,tc4}},
+ {?eh,tc_done,{S,tc4,{failed,{error,{test_case_failed,second_time_fail}}}}},
+ {?eh,test_stats,{15,6,{0,0}}},
+ %% ----> fail in sequence, so skip rest
+ {?eh,tc_auto_skip,{S,{tc4,g_mixed}, % last of current repeat tc4
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,1}}},
+ {?eh,tc_auto_skip,{S,{tc1,g_mixed}, % single tc1
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,2}}},
+ {?eh,tc_auto_skip,{S,{tc1,g}, % group g, tc1, {repeat,2}
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,3}}},
+ {?eh,tc_auto_skip,{S,{tc1,subgroup}, % subgroup, single tc1
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,4}}},
+ {?eh,tc_auto_skip,{S,{tc2,subgroup}, % subgroup, tc2, {repeat,2}
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,5}}},
+ {?eh,tc_auto_skip,{S,{tc2,g_mixed}, % tc2, {repeat,2}
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,6}}},
+ {?eh,tc_auto_skip,{S,{tc2,g_mixed}, % single tc2
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,7}}},
+ {?eh,tc_auto_skip,{S,{tc1,g_mixed}, % tc1, {repeat,2}
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,8}}},
+ {?eh,tc_auto_skip,{S,{tc1,g_mixed}, % single tc1
+ {failed,{tc_repeat_SUITE,tc4}}}},
+ {?eh,test_stats,{15,6,{0,9}}},
+ {?eh,tc_start,{S,{end_per_group,g_mixed,'_'}}},
+ {?eh,tc_done,{S,{end_per_group,g_mixed,'_'},ok}},
+ %% done
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(repeat_parallel_until_ok) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,tc_start,{'_',{init_per_group,g_parallel_until_ok,[parallel]}}},
+ {?eh,tc_done,{'_',{init_per_group,g_parallel_until_ok,[parallel]},ok}},
+ {?eh,severe_error,{{illegal_combination,{parallel,repeat_until_ok}},'_'}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(repeat_parallel_until_fail) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,tc_start,{'_',{init_per_group,g_parallel_until_fail,[parallel]}}},
+ {?eh,tc_done,{'_',{init_per_group,g_parallel_until_fail,[parallel]},ok}},
+ {?eh,severe_error,{{illegal_combination,{parallel,repeat_until_fail}},'_'}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(repeat_sequence_until_ok) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,tc_start,{'_',{init_per_group,g_sequence_until_ok,[sequence]}}},
+ {?eh,tc_done,{'_',{init_per_group,g_sequence_until_ok,[sequence]},ok}},
+ {?eh,severe_error,{{illegal_combination,{sequence,repeat_until_ok}},'_'}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(repeat_sequence_until_fail) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,tc_start,{'_',{init_per_group,g_sequence_until_fail,[sequence]}}},
+ {?eh,tc_done,{'_',{init_per_group,g_sequence_until_fail,[sequence]},ok}},
+ {?eh,severe_error,{{illegal_combination,{sequence,repeat_until_fail}},'_'}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(pick_one_test_from_group) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,tc_start,{'_',{init_per_group,g_mixed,[]}}},
+ {?eh,tc_done,{'_',{init_per_group,g_mixed,[]},ok}},
+ {negative,
+ {?eh,tc_start,{'_',tc1}},
+ {?eh,tc_start,{'_',tc2}}}, % single tc2
+ {?eh,tc_done,{'_',tc2,ok}},
+ {?eh,tc_start,{'_',tc2}}, % tc2, {repeat,2}
+ {?eh,tc_done,{'_',tc2,ok}},
+ {?eh,tc_start,{'_',tc2}},
+ {?eh,tc_done,{'_',tc2,ok}},
+ {negative,
+ {?eh,tc_start,{'_',tc1}},
+ {?eh,tc_start,{'_',{end_per_group,g_mixed,[]}}}},
+ {?eh,tc_done,{'_',{end_per_group,g_mixed,[]},ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(pick_one_test_from_subgroup) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,tc_start,{'_',{init_per_group,g_mixed,[]}}},
+ {?eh,tc_done,{'_',{init_per_group,g_mixed,[]},ok}},
+ {negative,
+ {?eh,tc_start,{'_',tc2}},
+ {?eh,tc_start,{'_',{init_per_group,subgroup,[]}}}},
+ {?eh,tc_done,{'_',{init_per_group,subgroup,[]},ok}},
+ {negative,
+ {?eh,tc_start,{'_',tc1}},
+ {?eh,tc_start,{'_',tc2}}}, % tc2, {repeat,2}
+ {?eh,tc_done,{'_',tc2,ok}},
+ {?eh,tc_start,{'_',tc2}},
+ {?eh,tc_done,{'_',tc2,ok}},
+ {negative,
+ {?eh,tc_start,{'_',tc1}},
+ {?eh,tc_start,{'_',{end_per_group,subgroup,[]}}}},
+ {?eh,tc_done,{'_',{end_per_group,subgroup,[]},ok}},
+ {negative,
+ {?eh,tc_start,{'_',tc2}},
+ {?eh,tc_start,{'_',{end_per_group,g_mixed,[]}}}},
+ {?eh,tc_done,{'_',{end_per_group,g_mixed,[]},ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(ok) ->
+ ok.
+
+%% test events help functions
+contains(List) ->
+ fun(Proplist) when is_list(Proplist) ->
+ contains(List,Proplist)
+ end.
+
+contains([{not_in_order,List}|T],Rest) ->
+ contains_parallel(List,Rest),
+ contains(T,Rest);
+contains([{Ele,Pos}|T] = L,[H|T2]) ->
+ case element(Pos,H) of
+ Ele ->
+ contains(T,T2);
+ _ ->
+ contains(L,T2)
+ end;
+contains([Ele|T],[{Ele,_}|T2])->
+ contains(T,T2);
+contains([Ele|T],[Ele|T2])->
+ contains(T,T2);
+contains(List,[_|T]) ->
+ contains(List,T);
+contains([],_) ->
+ match.
+
+contains_parallel([Key | T], Elems) ->
+ contains([Key],Elems),
+ contains_parallel(T,Elems);
+contains_parallel([],_Elems) ->
+ match.
+
+not_contains(List) ->
+ fun(Proplist) when is_list(Proplist) ->
+ [] = [Ele || {Ele,_} <- Proplist,
+ Test <- List,
+ Test =:= Ele]
+ end.
diff --git a/lib/common_test/test/ct_tc_repeat_SUITE_data/tc_repeat_SUITE.erl b/lib/common_test/test/ct_tc_repeat_SUITE_data/tc_repeat_SUITE.erl
new file mode 100644
index 0000000000..f5d960d12f
--- /dev/null
+++ b/lib/common_test/test/ct_tc_repeat_SUITE_data/tc_repeat_SUITE.erl
@@ -0,0 +1,85 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(tc_repeat_SUITE).
+
+-suite_defaults([{timetrap, {minutes, 10}}]).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+init_per_group(_Group,Config) ->
+ Config.
+
+end_per_group(_Group,Config) ->
+ ok.
+
+all() ->
+ [{testcase,tc1,[{repeat,2}]},
+ {testcase,tc2,[{repeat_until_ok,3}]},
+ {testcase,tc3,[{repeat_until_ok,3}]},
+ {testcase,tc4,[{repeat_until_fail,3}]},
+ {group,g},
+ {group,g_until_ok},
+ {group,g_until_fail},
+ {group,g,[parallel]},
+ {group,g,[sequence]},
+ {group,g_mixed,[sequence]}].
+
+groups() ->
+ [{g,[{testcase,tc1,[{repeat,2}]}]},
+ {g_until_ok,[{testcase,tc2,[{repeat_until_ok,3}]}]},
+ {g_until_fail,[{testcase,tc4,[{repeat_until_fail,3}]}]},
+ {g_parallel_until_ok,[parallel],[{testcase,tc2,[{repeat_until_ok,3}]}]},
+ {g_parallel_until_fail,[parallel],[{testcase,tc1,[{repeat_until_fail,2}]}]},
+ {g_sequence_until_ok,[sequence],[{testcase,tc2,[{repeat_until_ok,3}]}]},
+ {g_sequence_until_fail,[sequence],[{testcase,tc1,[{repeat_until_fail,2}]}]},
+ {g_mixed,[{testcase,tc1,[{repeat,2}]},
+ {testcase,tc4,[{repeat,3}]},
+ tc1,
+ {group,g},
+ {subgroup,[tc1,{testcase,tc2,[{repeat,2}]}]},
+ {testcase,tc2,[{repeat,2}]},
+ tc2,
+ {testcase,tc1,[{repeat,2}]},
+ tc1]}].
+
+%% Test cases starts here.
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
+
+tc3(_Config) ->
+ ct:fail(always_fail).
+
+tc4(Config) ->
+ case ?config(saved_config,Config) of
+ {tc4,_} ->
+ ct:fail(second_time_fail);
+ undefined ->
+ {save_config,Config}
+ end.
+
+tc5(_Config) ->
+ {skip,"just skip this"}.
diff --git a/lib/common_test/test/ct_telnet_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE.erl
index a0089c9bc9..f71b7c370f 100644
--- a/lib/common_test/test/ct_telnet_SUITE.erl
+++ b/lib/common_test/test/ct_telnet_SUITE.erl
@@ -50,10 +50,10 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
groups() ->
- [{legacy, [], [unix_telnet,own_server,timetrap]},
- {raw, [], [unix_telnet,own_server,timetrap]},
- {html, [], [unix_telnet,own_server]},
- {silent, [], [unix_telnet,own_server]}].
+ [{legacy, [], [unix_telnet,own_server,faulty_regexp,timetrap]},
+ {raw, [], [unix_telnet,own_server,faulty_regexp,timetrap]},
+ {html, [], [unix_telnet,own_server,faulty_regexp]},
+ {silent, [], [unix_telnet,own_server,faulty_regexp]}].
all() ->
[
@@ -119,6 +119,12 @@ own_server(Config) ->
all_tests_in_suite(own_server,"ct_telnet_own_server_SUITE",
CfgFile,Config).
+faulty_regexp(Config) ->
+ CfgFile = "telnet.faulty_regexp." ++
+ atom_to_list(groupname(Config)) ++ ".cfg",
+ all_tests_in_suite(faulty_regexp,"ct_telnet_faulty_regexp_SUITE",
+ CfgFile,Config).
+
timetrap(Config) ->
CfgFile = "telnet.timetrap." ++
atom_to_list(groupname(Config)) ++ ".cfg",
@@ -225,6 +231,31 @@ events_to_check(unix_telnet,Config) ->
all_cases(ct_telnet_basic_SUITE,Config);
events_to_check(own_server,Config) ->
all_cases(ct_telnet_own_server_SUITE,Config);
+events_to_check(faulty_regexp,_Config) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,tc_done,
+ {ct_telnet_faulty_regexp_SUITE,expect_pattern,
+ {failed,
+ {error,{{bad_pattern,"invalid(pattern",{"missing )",15}},
+ {ct_telnet,expect,3}}}}}},
+ {?eh,tc_done,
+ {ct_telnet_faulty_regexp_SUITE,expect_pattern_no_string,
+ {failed,
+ {error,{{bad_pattern,invalid_pattern},
+ {ct_telnet,expect,3}}}}}},
+ {?eh,tc_done,
+ {ct_telnet_faulty_regexp_SUITE,expect_tag_pattern,
+ {failed,
+ {error,{{bad_pattern,{tag,"invalid(pattern"},{"missing )",15}},
+ {ct_telnet,expect,3}}}}}},
+ {?eh,tc_done,
+ {ct_telnet_faulty_regexp_SUITE,expect_tag_pattern_no_string,
+ {failed,
+ {error,{{bad_pattern,{tag,invalid_pattern}},
+ {ct_telnet,expect,3}}}}}},
+ {?eh,tc_done,{ct_telnet_faulty_regexp_SUITE,expect_pattern_unicode,ok}},
+ {?eh,tc_done,{ct_telnet_faulty_regexp_SUITE,expect_tag_pattern_unicode,ok}},
+ {?eh,stop_logging,[]}];
events_to_check(timetrap,_Config) ->
[{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,tc_done,{ct_telnet_timetrap_SUITE,expect_timetrap,
diff --git a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_faulty_regexp_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_faulty_regexp_SUITE.erl
new file mode 100644
index 0000000000..a5c9451a9c
--- /dev/null
+++ b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_faulty_regexp_SUITE.erl
@@ -0,0 +1,79 @@
+-module(ct_telnet_faulty_regexp_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(name, telnet_server_conn1).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+suite() -> [{require,?name,{unix,[telnet]}},
+ {require,ct_conn_log},
+ {ct_hooks, [{cth_conn_log,[]}]}].
+
+all() ->
+ [expect_pattern,
+ expect_pattern_no_string,
+ expect_tag_pattern,
+ expect_tag_pattern_no_string,
+ expect_pattern_unicode,
+ expect_tag_pattern_unicode].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_testcase(_,Config) ->
+ ct:log("init_per_testcase: opening telnet connection...",[]),
+ {ok,_} = ct_telnet:open(?name),
+ ct:log("...done",[]),
+ Config.
+
+end_per_testcase(_,_Config) ->
+ ct:log("end_per_testcase: closing telnet connection...",[]),
+ _ = ct_telnet:close(?name),
+ ct:log("...done",[]),
+ ok.
+
+expect_pattern(_) ->
+ ok = ct_telnet:send(?name, "echo ayt"),
+ ok = ct_telnet:expect(?name, "invalid(pattern").
+
+expect_pattern_no_string(_) ->
+ ok = ct_telnet:send(?name, "echo ayt"),
+ ok = ct_telnet:expect(?name, invalid_pattern).
+
+expect_tag_pattern(_) ->
+ ok = ct_telnet:send(?name, "echo ayt"),
+ ok = ct_telnet:expect(?name, {tag,"invalid(pattern"}).
+
+expect_tag_pattern_no_string(_) ->
+ ok = ct_telnet:send(?name, "echo ayt"),
+ ok = ct_telnet:expect(?name, {tag,invalid_pattern}).
+
+%% Test that a unicode pattern can be given without the testcase
+%% failing. Do however notice that there is no real unicode support
+%% in ct_telnet yet, that is, the telnet binary mode is not supported.
+expect_pattern_unicode(_) ->
+ ok = ct_telnet:send(?name, "echo ayt"),
+ {error,{prompt,_}} = ct_telnet:expect(?name, "pattern_with_unicode_αβ"),
+ ok.
+
+expect_tag_pattern_unicode(_) ->
+ ok = ct_telnet:send(?name, "echo ayt"),
+ {error,{prompt,_}} = ct_telnet:expect(?name, "pattern_with_unicode_αβ"),
+ ok.
diff --git a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl
index 985fa40ad2..34df57027e 100644
--- a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl
+++ b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_own_server_SUITE.erl
@@ -58,7 +58,8 @@ all() ->
server_speaks,
server_disconnects,
newline_ayt,
- newline_break
+ newline_break,
+ newline_string
].
groups() ->
@@ -393,3 +394,11 @@ newline_break(_) ->
"> " = lists:flatten(R),
ok = ct_telnet:close(Handle),
ok.
+
+%% Test option {newline,String} to specify an own newline, e.g. "\r\n"
+newline_string(_) ->
+ {ok, Handle} = ct_telnet:open(telnet_server_conn1),
+ ok = ct_telnet:send(Handle, "echo hello-", [{newline,"own_nl\n"}]),
+ {ok,["hello-own_nl"]} = ct_telnet:expect(Handle, ["hello-own_nl"]),
+ ok = ct_telnet:close(Handle),
+ ok.
diff --git a/lib/common_test/test/ct_util_SUITE.erl b/lib/common_test/test/ct_util_SUITE.erl
new file mode 100644
index 0000000000..1d773855da
--- /dev/null
+++ b/lib/common_test/test/ct_util_SUITE.erl
@@ -0,0 +1,490 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(ct_util_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CTHs = filelib:wildcard(filename:join(DataDir,"*_cth.erl")),
+ io:format("CTHs: ~p",[CTHs]),
+ [io:format("Compiling ~p: ~p",
+ [FileName,compile:file(FileName,[{outdir,DataDir},debug_info])]) ||
+ FileName <- CTHs],
+ ct_test_support:init_per_suite([{path_dirs,[DataDir]} | Config]).
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+
+suite() ->
+ [{timetrap,{minutes,1}}].
+
+all() ->
+ all(suite).
+
+all(suite) ->
+ [
+ pre_init_per_suite,
+ post_init_per_suite,
+ pre_end_per_suite,
+ post_end_per_suite,
+ pre_init_per_group,
+ post_init_per_group,
+ pre_end_per_group,
+ post_end_per_group,
+ pre_init_per_testcase,
+ post_init_per_testcase,
+ pre_end_per_testcase,
+ post_end_per_testcase
+ ].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+pre_init_per_suite(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{pre_init_per_suite,
+ {curr_tc_SUITE,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+post_init_per_suite(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_init_per_suite,
+ {curr_tc_SUITE,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+pre_end_per_suite(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{pre_end_per_suite,
+ {curr_tc_SUITE,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+post_end_per_suite(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_end_per_suite,
+ {curr_tc_SUITE,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+
+pre_init_per_group(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{pre_init_per_group,
+ {curr_tc_SUITE,g,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+post_init_per_group(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_init_per_group,
+ {curr_tc_SUITE,g,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+pre_end_per_group(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{pre_end_per_group,
+ {curr_tc_SUITE,g,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+post_end_per_group(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_end_per_group,
+ {curr_tc_SUITE,g,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+pre_init_per_testcase(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{pre_init_per_testcase,
+ {curr_tc_SUITE,tc1,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+post_init_per_testcase(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_init_per_testcase,
+ {curr_tc_SUITE,tc1,{timeout,5000}}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+pre_end_per_testcase(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{pre_end_per_testcase,
+ {curr_tc_SUITE,tc1,{timeout,5000}}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+post_end_per_testcase(Config) ->
+ CfgFile = gen_config(?FUNCTION_NAME,
+ [{post_end_per_testcase,
+ {curr_tc_SUITE,tc1,kill}}],
+ Config),
+ ok = do_test(?FUNCTION_NAME,
+ "curr_tc_SUITE.erl",
+ [{ct_hooks,[ct_util_cth]},{config,CfgFile}],
+ Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+do_test(Tag, Suite, RunTestArgs, Config) ->
+ do_test(Tag, Suite, RunTestArgs, Config, 2).
+
+do_test(Tag, Suite0, RunTestArgs, Config, EC) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join([DataDir,Suite0]),
+ {Opts,ERPid} = setup([{suite,Suite}]++[{label,Tag}|RunTestArgs],Config),
+ Res = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+ %% io:format("~p~n",[Events]),
+
+ ct_test_support:log_events(Tag,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Tag, EC),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config),
+ Res.
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+gen_config(Name,KeyVals,Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ File = filename:join(PrivDir,atom_to_list(Name)++".cfg"),
+ ok = file:write_file(File,[io_lib:format("~p.~n",[{Key,Value}])
+ || {Key,Value} <- KeyVals]),
+ File.
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(IPS) when IPS=:=pre_init_per_suite; IPS=:=post_init_per_suite ->
+ S = curr_tc_SUITE,
+ FwFunc =
+ case IPS of
+ pre_init_per_suite -> init_tc;
+ post_init_per_suite -> end_tc
+ end,
+ E = {failed,{ct_framework,FwFunc,{test_case_failed,hahahahahah}}},
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,4}},
+ {?eh,tc_start,{S,init_per_suite}},
+ {?eh,tc_done,{S,init_per_suite,E}},
+ {?eh,tc_auto_skip,{S,tc1,{failed,{S,init_per_suite,E}}}},
+ {?eh,tc_auto_skip,{S,tc2,{failed,{S,init_per_suite,E}}}},
+ {?eh,tc_auto_skip,{S,{tc1,g},{failed,{S,init_per_suite,E}}}},
+ {?eh,tc_auto_skip,{S,{tc2,g},{failed,{S,init_per_suite,E}}}},
+ {?eh,test_stats,{0,0,{0,4}}},
+ {?eh,tc_auto_skip,{S,end_per_suite,{failed,{S,init_per_suite,E}}}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(EPS) when EPS=:=pre_end_per_suite; EPS=:=post_end_per_suite ->
+ S = curr_tc_SUITE,
+ FwFunc =
+ case EPS of
+ pre_end_per_suite -> init_tc;
+ post_end_per_suite -> end_tc
+ end,
+ E = {failed,{ct_framework,FwFunc,{test_case_failed,hahahahahah}}},
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,4}},
+ {?eh,tc_start,{S,init_per_suite}},
+ {?eh,tc_done,{S,init_per_suite,ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ [{?eh,tc_start,{S,{init_per_group,g,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g,[]}}},
+ {?eh,tc_done,{S,{end_per_group,g,[]},ok}}],
+ {?eh,tc_start,{S,end_per_suite}},
+ {?eh,tc_done,{S,end_per_suite,E}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(IPG) when IPG=:=pre_init_per_group; IPG=:=post_init_per_group ->
+ S = curr_tc_SUITE,
+ FwFunc =
+ case IPG of
+ pre_init_per_group -> init_tc;
+ post_init_per_group -> end_tc
+ end,
+ E = {failed,{ct_framework,FwFunc,{test_case_failed,hahahahahah}}},
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,4}},
+ {?eh,tc_start,{S,init_per_suite}},
+ {?eh,tc_done,{S,init_per_suite,ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ [{?eh,tc_start,{S,{init_per_group,g,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[]},E}},
+ {?eh,tc_auto_skip,{S,{tc1,g},{failed,{S,init_per_group,E}}}},
+ {?eh,tc_auto_skip,{S,{tc2,g},{failed,{S,init_per_group,E}}}},
+ {?eh,test_stats,{2,0,{0,2}}},
+ {?eh,tc_auto_skip,{S,{end_per_group,g},{failed,{S,init_per_group,E}}}}],
+ {?eh,tc_start,{S,end_per_suite}},
+ {?eh,tc_done,{S,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(EPG) when EPG=:=pre_end_per_group; EPG=:=post_end_per_group ->
+ S = curr_tc_SUITE,
+ FwFunc =
+ case EPG of
+ pre_end_per_group -> init_tc;
+ post_end_per_group -> end_tc
+ end,
+ E = {failed,{ct_framework,FwFunc,{test_case_failed,hahahahahah}}},
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,4}},
+ {?eh,tc_start,{S,init_per_suite}},
+ {?eh,tc_done,{S,init_per_suite,ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ [{?eh,tc_start,{S,{init_per_group,g,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g,[]}}},
+ {?eh,tc_done,{S,{end_per_group,g,[]},E}}],
+ {?eh,tc_start,{S,end_per_suite}},
+ {?eh,tc_done,{S,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(IPTC) when IPTC=:=pre_init_per_testcase;
+ IPTC=:=post_init_per_testcase ->
+ S = curr_tc_SUITE,
+ E = case IPTC of
+ pre_init_per_testcase ->
+ {failed,{ct_framework,init_tc,{test_case_failed,hahahahahah}}};
+ post_init_per_testcase ->
+ {failed,{ct_framework,end_tc,{timetrap,3000}}}
+ end,
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,4}},
+ {?eh,tc_start,{S,init_per_suite}},
+ {?eh,tc_done,{S,init_per_suite,ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,{auto_skipped,E}}},
+ {?eh,test_stats,{0,0,{0,1}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{1,0,{0,1}}},
+ [{?eh,tc_start,{S,{init_per_group,g,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,{auto_skipped,E}}},
+ {?eh,test_stats,{1,0,{0,2}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,2}}},
+ {?eh,tc_start,{S,{end_per_group,g,[]}}},
+ {?eh,tc_done,{S,{end_per_group,g,[]},ok}}],
+ {?eh,tc_start,{S,end_per_suite}},
+ {?eh,tc_done,{S,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(EPTC) when EPTC=:=pre_end_per_testcase; EPTC=:=post_end_per_testcase->
+ S = curr_tc_SUITE,
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,4}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ [{?eh,tc_start,{S,{init_per_group,g,[]}}},
+ {?eh,tc_done,{S,{init_per_group,g,[]},ok}},
+ {?eh,tc_start,{S,tc1}},
+ {?eh,tc_done,{S,tc1,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{S,tc2}},
+ {?eh,tc_done,{S,tc2,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{S,{end_per_group,g,[]}}},
+ {?eh,tc_done,{S,{end_per_group,g,[]},ok}}],
+ {?eh,tc_start,{S,end_per_suite}},
+ {?eh,tc_done,{S,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
+
+%% test events help functions
+contains(List) ->
+ fun(Proplist) when is_list(Proplist) ->
+ contains(List,Proplist)
+ end.
+
+contains([{not_in_order,List}|T],Rest) ->
+ contains_parallel(List,Rest),
+ contains(T,Rest);
+contains([{Ele,Pos}|T] = L,[H|T2]) ->
+ case element(Pos,H) of
+ Ele ->
+ contains(T,T2);
+ _ ->
+ contains(L,T2)
+ end;
+contains([Ele|T],[{Ele,_}|T2])->
+ contains(T,T2);
+contains([Ele|T],[Ele|T2])->
+ contains(T,T2);
+contains(List,[_|T]) ->
+ contains(List,T);
+contains([],_) ->
+ match.
+
+contains_parallel([Key | T], Elems) ->
+ contains([Key],Elems),
+ contains_parallel(T,Elems);
+contains_parallel([],_Elems) ->
+ match.
+
+not_contains(List) ->
+ fun(Proplist) when is_list(Proplist) ->
+ [] = [Ele || {Ele,_} <- Proplist,
+ Test <- List,
+ Test =:= Ele]
+ end.
diff --git a/lib/common_test/test/ct_util_SUITE_data/ct_util_cth.erl b/lib/common_test/test/ct_util_SUITE_data/ct_util_cth.erl
new file mode 100644
index 0000000000..34c1568a87
--- /dev/null
+++ b/lib/common_test/test/ct_util_SUITE_data/ct_util_cth.erl
@@ -0,0 +1,105 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+-module(ct_util_cth).
+
+
+-include_lib("common_test/src/ct_util.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+%% Send a cth_error event if a callback is called with unexpected arguments
+
+%% CT Hooks
+-compile(export_all).
+
+id(Opts) ->
+ erlang:system_time(second).
+
+init(Id, Opts) ->
+ {ok,ok}.
+
+pre_init_per_suite(Suite,Config,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite),
+ {Config, State}.
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite),
+ {Return, State}.
+
+pre_end_per_suite(Suite,Config,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite),
+ {Config, State}.
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite),
+ {Return, State}.
+
+pre_init_per_group(Suite, Group, Config, State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,Group),
+ {Config,State}.
+
+post_init_per_group(Suite, Group, Config,Return,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,Group),
+ {Return,State}.
+
+pre_end_per_group(Suite, Group, Config, State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,Group),
+ {Config,State}.
+
+post_end_per_group(Suite, Group, Config,Return,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,Group),
+ {Return,State}.
+
+pre_init_per_testcase(Suite, TC, Config, State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,TC),
+ {Config,State}.
+
+post_init_per_testcase(Suite, TC, Config,Return,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,TC),
+ {Return,State}.
+
+pre_end_per_testcase(Suite, TC, Config, State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,TC),
+ {Config,State}.
+
+post_end_per_testcase(Suite, TC, Config,Return,State) ->
+ maybe_sleep(?FUNCTION_NAME,Suite,TC),
+ {Return,State}.
+
+%%%-----------------------------------------------------------------
+maybe_sleep(FuncName,Suite) ->
+ maybe_sleep(FuncName,Suite,undefined).
+maybe_sleep(FuncName,Suite,GroupOrTC) ->
+ case ct:get_config(FuncName) of
+ {Suite,GroupOrTC,Fail} ->
+ fail(Fail);
+ {Suite,Fail} when GroupOrTC=:=undefined ->
+ fail(Fail);
+ _ ->
+ ok
+ end.
+
+fail({timeout,T}) ->
+ timer:sleep(T);
+fail(kill) ->
+ spawn_link(fun() -> ct:fail(hahahahahah) end),
+ timer:sleep(10000).
+
diff --git a/lib/common_test/test/ct_util_SUITE_data/curr_tc_SUITE.erl b/lib/common_test/test/ct_util_SUITE_data/curr_tc_SUITE.erl
new file mode 100644
index 0000000000..b48ba4d24e
--- /dev/null
+++ b/lib/common_test/test/ct_util_SUITE_data/curr_tc_SUITE.erl
@@ -0,0 +1,59 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(curr_tc_SUITE).
+
+-suite_defaults([{timetrap, {seconds, 3}}]).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+init_per_suite(Config) ->
+ [{?MODULE,?FUNCTION_NAME}] = ct_util:get_testdata(curr_tc),
+ Config.
+
+end_per_suite(Config) ->
+ [{?MODULE,?FUNCTION_NAME}] = ct_util:get_testdata(curr_tc),
+ ok.
+
+init_per_group(_Group,Config) ->
+ [{?MODULE,?FUNCTION_NAME}] = ct_util:get_testdata(curr_tc),
+ Config.
+
+end_per_group(_Group,Config) ->
+ [{?MODULE,?FUNCTION_NAME}] = ct_util:get_testdata(curr_tc),
+ ok.
+
+all() ->
+ [tc1,tc2,{group,g}].
+
+groups() ->
+ [{g,[tc1,tc2]}].
+
+%% Test cases starts here.
+tc1(_Config) ->
+ [{?MODULE,?FUNCTION_NAME}] = ct_util:get_testdata(curr_tc),
+ ok.
+
+tc2(_Config) ->
+ [{?MODULE,?FUNCTION_NAME}] = ct_util:get_testdata(curr_tc),
+ ok.
diff --git a/lib/common_test/test_server/configure.in b/lib/common_test/test_server/configure.in
index 0511d126b4..e07bd4c2aa 100644
--- a/lib/common_test/test_server/configure.in
+++ b/lib/common_test/test_server/configure.in
@@ -459,11 +459,11 @@ dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a
dnl AC_LANG_JAVA instead...)
AC_DEFUN(ERL_TRY_LINK_JAVA,
[java_link='$JAVAC conftest.java 1>&AC_FD_CC'
-changequote(�, �)dnl
+changequote(, )dnl
cat > conftest.java <<EOF
-�$1�
+$1
class conftest { public static void main(String[] args) {
- �$2�
+ $2
; return; }}
EOF
changequote([, ])dnl
diff --git a/lib/common_test/test_server/ts_erl_config.erl b/lib/common_test/test_server/ts_erl_config.erl
index 537628e39a..f3972bea4e 100644
--- a/lib/common_test/test_server/ts_erl_config.erl
+++ b/lib/common_test/test_server/ts_erl_config.erl
@@ -208,7 +208,11 @@ erl_interface(Vars,OsType) ->
{filename:join(Dir, "lib"),
filename:join([Dir, "src", "eidefs.mk"])};
{srctree, _Root, Target} ->
- {filename:join([Dir, "obj", Target]),
+ Obj = case is_debug_build() of
+ true -> "obj.debug";
+ false -> "obj"
+ end,
+ {filename:join([Dir, Obj, Target]),
filename:join([Dir, "src", Target, "eidefs.mk"])}
end}
end,
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 2dc1965878..73a442a29c 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.16
+COMMON_TEST_VSN = 1.17.2
diff --git a/lib/compiler/doc/src/Makefile b/lib/compiler/doc/src/Makefile
index 13210de040..32f150eef8 100644
--- a/lib/compiler/doc/src/Makefile
+++ b/lib/compiler/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -89,6 +89,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 1a71c83521..7f3d6aa60e 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -29,7 +29,7 @@
<rev>A</rev>
<file>compile.sgml</file>
</header>
- <module>compile</module>
+ <module since="">compile</module>
<modulesummary>Erlang Compiler</modulesummary>
<description>
<p>This module provides an interface to the standard Erlang
@@ -40,7 +40,7 @@
<funcs>
<func>
- <name>env_compiler_options()</name>
+ <name since="OTP 19.0">env_compiler_options()</name>
<fsummary>
Compiler options defined via the environment variable
<c>ERL_COMPILER_OPTIONS</c>
@@ -53,7 +53,7 @@
</desc>
</func>
<func>
- <name>file(File)</name>
+ <name since="">file(File)</name>
<fsummary>Compiles a file.</fsummary>
<desc>
<p>Is the same as
@@ -63,7 +63,7 @@
</func>
<func>
- <name>file(File, Options) -> CompRet</name>
+ <name since="">file(File, Options) -> CompRet</name>
<fsummary>Compiles a file.</fsummary>
<type>
<v>CompRet = ModRet | BinRet | ErrRet</v>
@@ -203,7 +203,8 @@
<tag><c>deterministic</c></tag>
<item>
<p>Omit the <c>options</c> and <c>source</c> tuples in
- the list returned by <c>Module:module_info(compile)</c>.
+ the list returned by <c>Module:module_info(compile)</c>, and
+ reduce the paths in stack traces to the module name alone.
This option will make it easier to achieve reproducible builds.
</p>
</item>
@@ -347,8 +348,8 @@ module.beam: module.erl \
<tag><c>{source,FileName}</c></tag>
<item>
- <p>Sets the value of the source, as returned by
- <c>module_info(compile)</c>.</p>
+ <p>Overrides the source file name as presented in
+ <c>module_info(compile)</c> and stack traces.</p>
</item>
<tag><c>{outdir,Dir}</c></tag>
@@ -717,7 +718,7 @@ module.beam: module.erl \
</func>
<func>
- <name>forms(Forms)</name>
+ <name since="">forms(Forms)</name>
<fsummary>Compiles a list of forms.</fsummary>
<desc>
<p>Is the same as
@@ -727,7 +728,7 @@ module.beam: module.erl \
</func>
<func>
- <name>forms(Forms, Options) -> CompRet</name>
+ <name since="">forms(Forms, Options) -> CompRet</name>
<fsummary>Compiles a list of forms.</fsummary>
<type>
<v>Forms = [Form]</v>
@@ -748,7 +749,7 @@ module.beam: module.erl \
</func>
<func>
- <name>format_error(ErrorDescriptor) -> chars()</name>
+ <name since="">format_error(ErrorDescriptor) -> chars()</name>
<fsummary>Formats an error descriptor.</fsummary>
<type>
<v>ErrorDescriptor = errordesc()</v>
@@ -763,7 +764,7 @@ module.beam: module.erl \
</func>
<func>
- <name>output_generated(Options) -> true | false</name>
+ <name since="">output_generated(Options) -> true | false</name>
<fsummary>Determines whether the compiler generates an output file.</fsummary>
<type>
<v>Options = [term()]</v>
@@ -778,7 +779,7 @@ module.beam: module.erl \
</func>
<func>
- <name>noenv_file(File, Options) -> CompRet</name>
+ <name since="">noenv_file(File, Options) -> CompRet</name>
<fsummary>Compiles a file (ignoring <c>ERL_COMPILER_OPTIONS)</c>.</fsummary>
<desc>
<p>Works like <seealso marker="#file/2">file/2</seealso>,
@@ -788,7 +789,7 @@ module.beam: module.erl \
</func>
<func>
- <name>noenv_forms(Forms, Options) -> CompRet</name>
+ <name since="">noenv_forms(Forms, Options) -> CompRet</name>
<fsummary>Compiles a list of forms (ignoring <c>ERL_COMPILER_OPTIONS)</c>.</fsummary>
<desc>
<p>Works like <seealso marker="#forms/2">forms/2</seealso>,
@@ -798,7 +799,7 @@ module.beam: module.erl \
</func>
<func>
- <name>noenv_output_generated(Options) -> true | false</name>
+ <name since="">noenv_output_generated(Options) -> true | false</name>
<fsummary>Determines whether the compiler generates an output file
(ignoring <c>ERL_COMPILER_OPTIONS)</c>.</fsummary>
<type>
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 997a506181..d45dfef8f3 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -32,6 +32,275 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 7.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>An expression such as <c>(A / B) band 16#ff</c> would
+ crash the compiler.</p>
+ <p>
+ Own Id: OTP-15518 Aux Id: ERL-829 </p>
+ </item>
+ <item>
+ <p>There could be an incorrect warning when the
+ <c>tuple_calls</c> option was given. The generated code
+ would be correct. Here is an example of code that would
+ trigger the warning:</p>
+ <p><c>(list_to_atom("prefix_" ++
+ atom_to_list(suffix))):doit(X)</c>.</p>
+ <p>
+ Own Id: OTP-15552 Aux Id: ERL-838 </p>
+ </item>
+ <item>
+ <p>Optimize (again) Dialyzer's handling of
+ left-associative use of <c>andalso</c> and <c>orelse</c>
+ in guards.</p>
+ <p>
+ Own Id: OTP-15577 Aux Id: ERL-851, PR-2141, PR-1944 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>An optimization that avoided allocation of a stack
+ frame for some <c>case</c> expressions was introduced in
+ OTP 21. (ERL-504/OTP-14808) It turns out that in rare
+ circumstances, this optimization is not safe. Therefore,
+ this optimization has been disabled.</p>
+ <p>A similar optimization will be included in OTP 22 in a
+ safe way.</p>
+ <p>
+ Own Id: OTP-15501 Aux Id: ERL-807, ERL-514, OTP-14808 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a rare internal consistency failure caused by a
+ bug in the <c>beam_jump</c> pass. (Thanks to Simon
+ Cornish for reporting this bug.)</p>
+ <p>
+ Own Id: OTP-15400 Aux Id: ERL-759 </p>
+ </item>
+ <item>
+ <p>The compiler could fail with an internal consistency
+ check failure when compiling code that used the
+ <c>is_function/2</c> BIF.</p>
+ <p>
+ Own Id: OTP-15435 Aux Id: ERL-778 </p>
+ </item>
+ <item>
+ <p>When an external fun was used, warnings for unused
+ variables could be suppressed.</p>
+ <p>
+ Own Id: OTP-15437 Aux Id: ERL-762 </p>
+ </item>
+ <item>
+ <p>The compiler would crash when compiling an
+ <c>after</c> block that called <c>erlang:raise/3</c> like
+ this: <c>erlang:raise(Class, Stacktrace,
+ Stacktrace)</c></p>
+ <p>
+ Own Id: OTP-15481</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>When specified, the <c>+{source,Name}</c> option will
+ now override the actual file name in stack traces,
+ instead of only affecting the return value of
+ <c>Mod:module_info()</c>.</p>
+ <p>The <c>+deterministic</c> flag will also affect stack
+ traces now, omitting all path information except the file
+ name, fixing a long-standing issue where deterministic
+ builds required deterministic paths.</p>
+ <p>
+ Own Id: OTP-15245 Aux Id: ERL-706 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug where incorrect code was generated
+ following a binary match guard.</p>
+ <p>
+ Own Id: OTP-15353 Aux Id: ERL-753 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>In rare circumstances, the matched out tail of a
+ binary could be the entire original binary. (There was
+ partial correction to this problem in version 7.2.5 of
+ the compiler application.)</p>
+ <p>
+ Own Id: OTP-15335 Aux Id: ERL-689, OTP-15219 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that prevented certain variable-sized
+ binary comprehensions from compiling.</p>
+ <p>
+ Own Id: OTP-15186 Aux Id: ERL-665 </p>
+ </item>
+ <item>
+ <p>When compiling from Core Erlang, funs created in
+ certain expressions that were only used for their
+ side-effects were subtly broken.</p>
+ <p>
+ Own Id: OTP-15188 Aux Id: ERL-658 </p>
+ </item>
+ <item>
+ <p>There could be an internal consistency failure when a
+ <c>receive</c> was nested in a
+ <c>try</c>/<c>catch</c>.</p>
+ <p>
+ Own Id: OTP-15218 Aux Id: ERL-684 </p>
+ </item>
+ <item>
+ <p>In rare circumstances, the matched out tail of a
+ binary could be the entire original binary.</p>
+ <p>
+ Own Id: OTP-15219 Aux Id: ERL-689 </p>
+ </item>
+ <item>
+ <p>When <c>is_map_key/2</c> was used in a guard together
+ with the <c>not/1</c> or <c>or/2</c> operators, the error
+ behavior could be wrong when <c>is_map_key/2</c> was
+ passed a non-map as the second argument. </p>
+ <p>In rare circumstances, compiling code that uses
+ <c>is_map_key/2</c> could cause an internal consistency
+ check failure.</p>
+ <p>
+ Own Id: OTP-15227 Aux Id: ERL-699 </p>
+ </item>
+ <item>
+ <p>The compiler could crash when compiling a function
+ with multiple receives in multiple clauses.</p>
+ <p>
+ Own Id: OTP-15235 Aux Id: ERL-703 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix a regression in OTP-15204 that removed
+ <c>.beam</c> file metadata that some external build tools
+ relied on.</p>
+ <p>
+ Own Id: OTP-15292</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed an issue where files compiled with the
+ <c>+deterministic</c> option differed if they were
+ compiled in a different directory but were otherwise
+ identical.</p>
+ <p>
+ Own Id: OTP-15204 Aux Id: ERL-679 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>In rare cases involving matching of binary literal
+ strings, the compiler could optimize away code that
+ should be executed.</p>
+ <p>
+ Own Id: OTP-15156 Aux Id: ERL-655 </p>
+ </item>
+ <item>
+ <p>There could be an internal consistency check failure
+ when compiling code that called <c>map_get(Key, Map)</c>
+ and then updated the same map.</p>
+ <p>
+ Own Id: OTP-15157</p>
+ </item>
+ <item>
+ <p>In rare circumstances, the compiler could crash in
+ <c>beam_jump</c> when compiling a floating point
+ operation.</p>
+ <p>
+ Own Id: OTP-15166 Aux Id: ERL-660 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The could could crash when compiling a complicated
+ function that used the binary syntax.</p>
+ <p>
+ Own Id: OTP-15150 Aux Id: ERL-650 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -252,6 +521,39 @@
</section>
+<section><title>Compiler 7.1.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix a regression in OTP-15204 that removed
+ <c>.beam</c> file metadata that some external build tools
+ relied on.</p>
+ <p>
+ Own Id: OTP-15292</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed an issue where files compiled with the
+ <c>+deterministic</c> option differed if they were
+ compiled in a different directory but were otherwise
+ identical.</p>
+ <p>
+ Own Id: OTP-15204 Aux Id: ERL-679 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 9eee56d604..22974da398 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -128,7 +128,7 @@
%%% on the program state.
%%%
--import(lists, [reverse/1,reverse/2,foldl/3]).
+-import(lists, [dropwhile/2,reverse/1,reverse/2,foldl/3]).
-type instruction() :: beam_utils:instruction().
@@ -411,14 +411,19 @@ opt_useless_loads([{test,_,{f,L},_}=I|Is], L, St) ->
opt_useless_loads(Is, _L, St) ->
{Is,St}.
-opt_useless_block_loads([{set,[Dst],_,_}=I|Is], L, Index) ->
- BlockJump = [{block,Is},{jump,{f,L}}],
+opt_useless_block_loads([{set,[Dst],_,_}=I|Is0], L, Index) ->
+ BlockJump = [{block,Is0},{jump,{f,L}}],
case beam_utils:is_killed(Dst, BlockJump, Index) of
true ->
- %% The register is killed and not used, we can remove the load
+ %% The register is killed and not used, we can remove the load.
+ %% Remove any `put` instructions in case we just
+ %% removed a `put_tuple` instruction.
+ Is = dropwhile(fun({set,_,_,put}) -> true;
+ (_) -> false
+ end, Is0),
opt_useless_block_loads(Is, L, Index);
false ->
- [I|opt_useless_block_loads(Is, L, Index)]
+ [I|opt_useless_block_loads(Is0, L, Index)]
end;
opt_useless_block_loads([I|Is], L, Index) ->
[I|opt_useless_block_loads(Is, L, Index)];
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index b8c3ca1325..a1e9eff8f3 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -559,7 +559,7 @@ update({bs_save2,_,_}, Ts) ->
update({bs_restore2,_,_}, Ts) ->
Ts;
update({bs_context_to_binary,Dst}, Ts) ->
- tdb_store(Dst, {binary,1}, Ts);
+ tdb_store(Dst, any, Ts);
update({test,bs_start_match2,_,_,[Src,_],Dst}, Ts0) ->
Ts = tdb_meet(Src, {binary,1}, Ts0),
tdb_copy(Src, Dst, Ts);
@@ -1114,4 +1114,5 @@ verified_type(nonempty_list=T) -> T;
verified_type({tuple,_,Sz,[]}=T) when is_integer(Sz) -> T;
verified_type({tuple,_,Sz,[_]}=T) when is_integer(Sz) -> T;
verified_type({tuple_element,_,_}=T) -> T;
-verified_type(float=T) -> T.
+verified_type(float=T) -> T;
+verified_type(none=T) -> T.
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 5510624b2d..6b2ab5a2a4 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -355,6 +355,9 @@ split_even(Rs) -> split_even(Rs, [], []).
%% exit BIF will raise an exception
%% used - Reg is used
+check_liveness({fr,_}, _, St) ->
+ %% Conservatively always consider the floating point register used.
+ {used,St};
check_liveness(R, [{block,Blk}|Is], St0) ->
case check_liveness_block(R, Blk, St0) of
{transparent,St1} ->
@@ -742,8 +745,11 @@ check_liveness_block_2(R, {gc_bif,Op,{f,Lbl}}, Ss, St) ->
check_liveness_block_3(R, Lbl, {Op,length(Ss)}, St);
check_liveness_block_2(R, {bif,Op,{f,Lbl}}, Ss, St) ->
Arity = length(Ss),
+
+ %% Note that is_function/2 is a type test but is not safe.
case erl_internal:comp_op(Op, Arity) orelse
- erl_internal:new_type_test(Op, Arity) of
+ (erl_internal:new_type_test(Op, Arity) andalso
+ erl_bifs:is_safe(erlang, Op, Arity)) of
true ->
{killed,St};
false ->
@@ -1105,9 +1111,17 @@ defs([{bif,_,{f,Fail},_Src,Dst}=I|Is], Regs0, D) ->
defs([{block,Block0}|Is], Regs0, D0) ->
{Block,Regs,D} = defs_list(Block0, Regs0, D0),
[{block,[make_anno({def,Regs0})|Block]}|defs(Is, Regs, D)];
-defs([{bs_init,{f,L},_,_,_,Dst}=I|Is], Regs0, D) ->
- Regs = def_regs([Dst], Regs0),
+defs([{bs_init,{f,L},_,Live,_,Dst}=I|Is], Regs0, D) ->
+ Regs1 = case Live of
+ none -> Regs0;
+ _ -> init_def_regs(Live)
+ end,
+ Regs = def_regs([Dst], Regs1),
[I|defs(Is, Regs, update_regs(L, Regs, D))];
+defs([{test,bs_start_match2,{f,L},Live,_,Dst}=I|Is], _Regs, D) ->
+ Regs0 = init_def_regs(Live),
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, update_regs(L, Regs0, D))];
defs([{bs_put,{f,L},_,_}=I|Is], Regs, D) ->
[I|defs(Is, Regs, update_regs(L, Regs, D))];
defs([build_stacktrace=I|Is], _Regs, D) ->
@@ -1157,7 +1171,7 @@ defs([{loop_rec,{f,L},{x,0}}=I|Is], _Regs, D0) ->
D = update_regs(L, RegsAtLabel, D0),
[I|defs(Is, init_def_regs(1), D)];
defs([{loop_rec_end,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 0, D)];
+ [I|defs_unreachable(Is, D)];
defs([{make_fun2,_,_,_,_}=I|Is], _Regs, D) ->
[I|defs(Is, 1, D)];
defs([{move,_,Dst}=I|Is], Regs0, D) ->
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index b03fadb197..fb2e7df65c 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -451,6 +451,19 @@ valfun_1({try_case,Reg}, #vst{current=#st{ct=[Fail|Fails]}}=Vst0) ->
Type ->
error({bad_type,Type})
end;
+valfun_1({get_list,Src,D1,D2}, Vst0) ->
+ assert_type(cons, Src, Vst0),
+ Vst = set_type_reg(term, Src, D1, Vst0),
+ set_type_reg(term, Src, D2, Vst);
+valfun_1({get_hd,Src,Dst}, Vst) ->
+ assert_type(cons, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
+valfun_1({get_tl,Src,Dst}, Vst) ->
+ assert_type(cons, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
+valfun_1({get_tuple_element,Src,I,Dst}, Vst) ->
+ assert_type({tuple_element,I+1}, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
valfun_1(I, Vst) ->
valfun_2(I, Vst).
@@ -546,6 +559,18 @@ valfun_4({bif,raise,{f,0},Src,_Dst}, Vst) ->
kill_state(Vst);
valfun_4(raw_raise=I, Vst) ->
call(I, 3, Vst);
+valfun_4({bif,map_get,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(map, Map, Vst1),
+ Type = propagate_fragility(term, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
+valfun_4({bif,is_map_key,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(map, Map, Vst1),
+ Type = propagate_fragility(bool, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
valfun_4({bif,Op,{f,Fail},Src,Dst}, Vst0) ->
validate_src(Src, Vst0),
Vst = branch_state(Fail, Vst0),
@@ -603,19 +628,6 @@ valfun_4({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
valfun_4({select_tuple_arity,Tuple,{f,Fail},{list,Choices}}, Vst) ->
assert_type(tuple, Tuple, Vst),
kill_state(branch_arities(Choices, Tuple, branch_state(Fail, Vst)));
-valfun_4({get_list,Src,D1,D2}, Vst0) ->
- assert_type(cons, Src, Vst0),
- Vst = set_type_reg(term, Src, D1, Vst0),
- set_type_reg(term, Src, D2, Vst);
-valfun_4({get_hd,Src,Dst}, Vst) ->
- assert_type(cons, Src, Vst),
- set_type_reg(term, Src, Dst, Vst);
-valfun_4({get_tl,Src,Dst}, Vst) ->
- assert_type(cons, Src, Vst),
- set_type_reg(term, Src, Dst, Vst);
-valfun_4({get_tuple_element,Src,I,Dst}, Vst) ->
- assert_type({tuple_element,I+1}, Src, Vst),
- set_type_reg(term, Src, Dst, Vst);
%% New bit syntax matching instructions.
valfun_4({test,bs_start_match2,{f,Fail},Live,[Ctx,NeedSlots],Ctx}, Vst0) ->
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 5ef9611504..6510571441 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -931,11 +931,17 @@ parse_module(_Code, St0) ->
end.
do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
+ SourceName0 = proplists:get_value(source, Opts, File),
+ SourceName = case member(deterministic, Opts) of
+ true -> filename:basename(SourceName0);
+ false -> SourceName0
+ end,
R = epp:parse_file(File,
- [{includes,[".",Dir|inc_paths(Opts)]},
- {macros,pre_defs(Opts)},
- {default_encoding,DefEncoding},
- extra]),
+ [{includes,[".",Dir|inc_paths(Opts)]},
+ {source_name, SourceName},
+ {macros,pre_defs(Opts)},
+ {default_encoding,DefEncoding},
+ extra]),
case R of
{ok,Forms,Extra} ->
Encoding = proplists:get_value(encoding, Extra),
@@ -1432,16 +1438,30 @@ encrypt_debug_info(DebugInfo, Key, Opts) ->
end.
cleanup_compile_options(Opts) ->
- lists:filter(fun keep_compile_option/1, Opts).
-
+ IsDeterministic = lists:member(deterministic, Opts),
+ lists:filter(fun(Opt) ->
+ keep_compile_option(Opt, IsDeterministic)
+ end, Opts).
+
+%% Include paths and current directory don't affect compilation, but they might
+%% be helpful so we include them unless we're doing a deterministic build.
+keep_compile_option({i, _}, Deterministic) ->
+ not Deterministic;
+keep_compile_option({cwd, _}, Deterministic) ->
+ not Deterministic;
%% We are storing abstract, not asm or core.
-keep_compile_option(from_asm) -> false;
-keep_compile_option(from_core) -> false;
+keep_compile_option(from_asm, _Deterministic) ->
+ false;
+keep_compile_option(from_core, _Deterministic) ->
+ false;
%% Parse transform and macros have already been applied.
-keep_compile_option({parse_transform, _}) -> false;
-keep_compile_option({d, _, _}) -> false;
+keep_compile_option({parse_transform, _}, _Deterministic) ->
+ false;
+keep_compile_option({d, _, _}, _Deterministic) ->
+ false;
%% Do not affect compilation result on future calls.
-keep_compile_option(Option) -> effects_code_generation(Option).
+keep_compile_option(Option, _Deterministic) ->
+ effects_code_generation(Option).
start_crypto() ->
try crypto:start() of
diff --git a/lib/compiler/src/sys_core_bsm.erl b/lib/compiler/src/sys_core_bsm.erl
index d7b26c3a56..62657933ee 100644
--- a/lib/compiler/src/sys_core_bsm.erl
+++ b/lib/compiler/src/sys_core_bsm.erl
@@ -44,6 +44,14 @@ function([{#c_var{name={F,Arity}}=Name,B0}|Fs], FsAcc, Ws0) ->
{B,Ws} ->
function(Fs, [{Name,B}|FsAcc], Ws)
catch
+ throw:unsafe_bs_context_to_binary ->
+ %% Unsafe bs_context_to_binary (in the sense that the
+ %% contents of the binary will probably be wrong).
+ %% Disable binary optimizations for the entire function.
+ %% We don't generate an INFO message, because this happens
+ %% very infrequently and it would be hard to explain in
+ %% a comprehensible way in an INFO message.
+ function(Fs, [{Name,B0}|FsAcc], Ws0);
Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
@@ -116,12 +124,66 @@ move_from_col(Pos, L) ->
[Col|First] ++ Rest.
bsm_do_an([#c_var{name=Vname}=V0|Vs0], Cs0, Case) ->
+ bsm_inner_context_to_binary(Cs0),
Cs = bsm_do_an_var(Vname, Cs0),
V = bsm_annotate_for_reuse(V0),
Vs = core_lib:make_values([V|Vs0]),
Case#c_case{arg=Vs,clauses=Cs};
bsm_do_an(_Vs, _Cs, Case) -> Case.
+bsm_inner_context_to_binary([#c_clause{body=B}|Cs]) ->
+ %% Consider:
+ %%
+ %% foo(<<Length, Data/binary>>) -> %Line 1
+ %% case {Data, Length} of %Line 2
+ %% {_, 0} -> Data; %Line 3
+ %% {<<...>>, 4} -> ... %Line 4
+ %% end.
+ %%
+ %% No sub binary will be created for Data in line 1. The match
+ %% context will be passed on to the `case` in line 2. In line 3,
+ %% this pass inserts a `bs_context_to_binary` instruction to
+ %% convert the match context representing Data to a binary before
+ %% returning it. The problem is that the binary created will be
+ %% the original binary (including the matched out Length field),
+ %% not the tail of the binary as it is supposed to be.
+ %%
+ %% Here follows a heuristic to disable the binary optimizations
+ %% for the entire function if this code kind of code is found.
+
+ case cerl_trees:free_variables(B) of
+ [] ->
+ %% Since there are no free variables in the body of
+ %% this clause, there can't be any troublesome
+ %% bs_context_to_binary instructions.
+ bsm_inner_context_to_binary(Cs);
+ [_|_]=Free ->
+ %% One of the free variables could refer to a match context
+ %% created by the outer binary match.
+ F = fun(#c_primop{name=#c_literal{val=bs_context_to_binary},
+ args=[#c_var{name=V}]}, _) ->
+ case member(V, Free) of
+ true ->
+ %% This bs_context_to_binary instruction will
+ %% make a binary of the match context from an
+ %% outer binary match. It is very likely that
+ %% the contents of the binary will be wrong
+ %% (the original binary as opposed to only
+ %% the tail binary).
+ throw(unsafe_bs_context_to_binary);
+ false ->
+ %% Safe. This bs_context_to_binary instruction
+ %% will make a binary from a match context
+ %% defined in the body of the clause.
+ ok
+ end;
+ (_, _) ->
+ ok
+ end,
+ cerl_trees:fold(F, ok, B)
+ end;
+bsm_inner_context_to_binary([]) -> ok.
+
bsm_do_an_var(V, [#c_clause{pats=[P|_],guard=G,body=B0}=C0|Cs]) ->
case P of
#c_var{name=VarName} ->
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index ceb7d56221..1681d97efb 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -115,13 +115,6 @@ module(#c_module{defs=Ds0}=Mod, Opts) ->
{ok,Mod#c_module{defs=Ds1},get_warnings()}.
function_1({#c_var{name={F,Arity}}=Name,B0}) ->
- %% Find a suitable starting value for the variable counter. Note
- %% that this pass assumes that new_var_name/1 returns a variable
- %% name distinct from any variable used in the entire body of
- %% the function. We use integers as variable names to avoid
- %% filling up the atom table when compiling huge functions.
- Count = cerl_trees:next_free_variable_name(B0),
- put(new_var_num, Count),
try
%% Find a suitable starting value for the variable
%% counter. Note that this pass assumes that new_var_name/1
@@ -352,7 +345,12 @@ expr(#c_letrec{body=#c_var{}}=Letrec, effect, _Sub) ->
void();
expr(#c_letrec{defs=Fs0,body=B0}=Letrec, Ctxt, Sub) ->
Fs1 = map(fun ({Name,Fb}) ->
- {Name,expr(Fb, {letrec,Ctxt}, Sub)}
+ case Ctxt =:= effect andalso is_fun_effect_safe(Name, B0) of
+ true ->
+ {Name,expr(Fb, {letrec, effect}, Sub)};
+ false ->
+ {Name,expr(Fb, {letrec, value}, Sub)}
+ end
end, Fs0),
B1 = body(B0, Ctxt, Sub),
Letrec#c_letrec{defs=Fs1,body=B1};
@@ -483,6 +481,86 @@ expr(#c_try{anno=A,arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=Try, _, Sub0)
Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}
end.
+
+%% If a fun or its application is used as an argument, then it's unsafe to
+%% handle it in effect context as the side-effects may rely on its return
+%% value. The following is a minimal example of where it can go wrong:
+%%
+%% do letrec 'f'/0 = fun () -> ... whatever ...
+%% in call 'side':'effect'(apply 'f'/0())
+%% 'ok'
+%%
+%% This function returns 'true' if Body definitely does not rely on a
+%% value produced by FVar, or 'false' if Body depends on or might depend on
+%% a value produced by FVar.
+
+is_fun_effect_safe(#c_var{}=FVar, Body) ->
+ ifes_1(FVar, Body, true).
+
+ifes_1(FVar, #c_alias{pat=Pat}, _Safe) ->
+ ifes_1(FVar, Pat, false);
+ifes_1(FVar, #c_apply{op=Op,args=Args}, Safe) ->
+ %% FVar(...) is safe as long its return value is ignored, but it's never
+ %% okay to pass FVar as an argument.
+ ifes_list(FVar, Args, false) andalso ifes_1(FVar, Op, Safe);
+ifes_1(FVar, #c_binary{segments=Segments}, _Safe) ->
+ ifes_list(FVar, Segments, false);
+ifes_1(FVar, #c_bitstr{val=Val,size=Size,unit=Unit}, _Safe) ->
+ ifes_list(FVar, [Val, Size, Unit], false);
+ifes_1(FVar, #c_call{args=Args}, _Safe) ->
+ ifes_list(FVar, Args, false);
+ifes_1(FVar, #c_case{arg=Arg,clauses=Clauses}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_list(FVar, Clauses, Safe);
+ifes_1(FVar, #c_catch{body=Body}, _Safe) ->
+ ifes_1(FVar, Body, false);
+ifes_1(FVar, #c_clause{pats=Pats,guard=Guard,body=Body}, Safe) ->
+ ifes_list(FVar, Pats, false) andalso
+ ifes_1(FVar, Guard, false) andalso
+ ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_cons{hd=Hd,tl=Tl}, _Safe) ->
+ ifes_1(FVar, Hd, false) andalso ifes_1(FVar, Tl, false);
+ifes_1(FVar, #c_fun{body=Body}, _Safe) ->
+ ifes_1(FVar, Body, false);
+ifes_1(FVar, #c_let{arg=Arg,body=Body}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_letrec{defs=Defs,body=Body}, Safe) ->
+ Funs = [Fun || {_,Fun} <- Defs],
+ ifes_list(FVar, Funs, false) andalso ifes_1(FVar, Body, Safe);
+ifes_1(_FVar, #c_literal{}, _Safe) ->
+ true;
+ifes_1(FVar, #c_map{arg=Arg,es=Elements}, _Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_list(FVar, Elements, false);
+ifes_1(FVar, #c_map_pair{key=Key,val=Val}, _Safe) ->
+ ifes_1(FVar, Key, false) andalso ifes_1(FVar, Val, false);
+ifes_1(FVar, #c_primop{args=Args}, _Safe) ->
+ ifes_list(FVar, Args, false);
+ifes_1(FVar, #c_receive{timeout=Timeout,action=Action,clauses=Clauses}, Safe) ->
+ ifes_1(FVar, Timeout, false) andalso
+ ifes_1(FVar, Action, Safe) andalso
+ ifes_list(FVar, Clauses, Safe);
+ifes_1(FVar, #c_seq{arg=Arg,body=Body}, Safe) ->
+ %% Arg of a #c_seq{} has no effect so it's okay to use FVar there even if
+ %% Safe=false.
+ ifes_1(FVar, Arg, true) andalso ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_try{arg=Arg,handler=Handler,body=Body}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso
+ ifes_1(FVar, Handler, Safe) andalso
+ ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_tuple{es=Elements}, _Safe) ->
+ ifes_list(FVar, Elements, false);
+ifes_1(FVar, #c_values{es=Elements}, _Safe) ->
+ ifes_list(FVar, Elements, false);
+ifes_1(#c_var{name=Name}, #c_var{name=Name}, Safe) ->
+ %% It's safe to return FVar if it's unused.
+ Safe;
+ifes_1(_FVar, #c_var{}, _Safe) ->
+ true.
+
+ifes_list(FVar, [E|Es], Safe) ->
+ ifes_1(FVar, E, Safe) andalso ifes_list(FVar, Es, Safe);
+ifes_list(_FVar, [], _Safe) ->
+ true.
+
expr_list(Es, Ctxt, Sub) ->
[expr(E, Ctxt, Sub) || E <- Es].
@@ -2557,12 +2635,20 @@ opt_build_stacktrace(#c_let{vars=[#c_var{name=Cooked}],
#c_call{module=#c_literal{val=erlang},
name=#c_literal{val=raise},
args=[Class,Exp,#c_var{name=Cooked}]} ->
- %% The stacktrace is only used in a call to erlang:raise/3.
- %% There is no need to build the stacktrace. Replace the
- %% call to erlang:raise/3 with the the raw_raise/3 instruction,
- %% which will use a raw stacktrace.
- #c_primop{name=#c_literal{val=raw_raise},
- args=[Class,Exp,RawStk]};
+ case core_lib:is_var_used(Cooked, #c_cons{hd=Class,tl=Exp}) of
+ true ->
+ %% Not safe. The stacktrace is used in the class or
+ %% reason.
+ Let;
+ false ->
+ %% The stacktrace is only used in the last
+ %% argument for erlang:raise/3. There is no need
+ %% to build the stacktrace. Replace the call to
+ %% erlang:raise/3 with the the raw_raise/3
+ %% instruction, which will use a raw stacktrace.
+ #c_primop{name=#c_literal{val=raw_raise},
+ args=[Class,Exp,RawStk]}
+ end;
#c_let{vars=[#c_var{name=V}],arg=Arg,body=B0} when V =/= Cooked ->
case core_lib:is_var_used(Cooked, Arg) of
false ->
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 6cd114abf7..d7a7778740 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -79,13 +79,9 @@ function(#k_fdef{anno=#k{a=Anno},func=Name,arity=Arity,
try
#k_match{} = Kb, %Assertion.
- %% Try to suppress the stack frame unless it is
- %% really needed.
- Body0 = avoid_stack_frame(Kb),
-
%% Annotate kernel records with variable usage.
Vdb0 = init_vars(As),
- {Body,_,Vdb} = body(Body0, 1, Vdb0),
+ {Body,_,Vdb} = body(Kb, 1, Vdb0),
%% Generate the BEAM assembly code.
{Asm,EntryLabel,St} = cg_fun(Body, As, Vdb, AtomMod,
@@ -98,136 +94,6 @@ function(#k_fdef{anno=#k{a=Anno},func=Name,arity=Arity,
erlang:raise(Class, Error, Stack)
end.
-
-%% avoid_stack_frame(Kernel) -> Kernel'
-%% If possible, avoid setting up a stack frame. Functions
-%% that only do matching, calls to guard BIFs, and tail-recursive
-%% calls don't need a stack frame.
-
-avoid_stack_frame(#k_match{body=Body}=M) ->
- try
- M#k_match{body=avoid_stack_frame_1(Body)}
- catch
- impossible ->
- M
- end.
-
-avoid_stack_frame_1(#k_alt{first=First0,then=Then0}=Alt) ->
- First = avoid_stack_frame_1(First0),
- Then = avoid_stack_frame_1(Then0),
- Alt#k_alt{first=First,then=Then};
-avoid_stack_frame_1(#k_bif{op=Op}=Bif) ->
- case Op of
- #k_internal{} ->
- %% Most internal BIFs clobber the X registers.
- throw(impossible);
- _ ->
- Bif
- end;
-avoid_stack_frame_1(#k_break{anno=Anno,args=Args}) ->
- #k_guard_break{anno=Anno,args=Args};
-avoid_stack_frame_1(#k_guard_break{}=Break) ->
- Break;
-avoid_stack_frame_1(#k_enter{}=Enter) ->
- %% Tail-recursive calls don't need a stack frame.
- Enter;
-avoid_stack_frame_1(#k_guard{clauses=Cs0}=Guard) ->
- Cs = avoid_stack_frame_list(Cs0),
- Guard#k_guard{clauses=Cs};
-avoid_stack_frame_1(#k_guard_clause{guard=G0,body=B0}=C) ->
- G = avoid_stack_frame_1(G0),
- B = avoid_stack_frame_1(B0),
- C#k_guard_clause{guard=G,body=B};
-avoid_stack_frame_1(#k_match{anno=A,vars=Vs,body=B0,ret=Ret}) ->
- %% Use #k_guard_match{} instead to avoid saving the X registers
- %% to the stack before matching.
- B = avoid_stack_frame_1(B0),
- #k_guard_match{anno=A,vars=Vs,body=B,ret=Ret};
-avoid_stack_frame_1(#k_guard_match{body=B0}=M) ->
- B = avoid_stack_frame_1(B0),
- M#k_guard_match{body=B};
-avoid_stack_frame_1(#k_protected{arg=Arg0}=Prot) ->
- Arg = avoid_stack_frame_1(Arg0),
- Prot#k_protected{arg=Arg};
-avoid_stack_frame_1(#k_put{}=Put) ->
- Put;
-avoid_stack_frame_1(#k_return{}=Ret) ->
- Ret;
-avoid_stack_frame_1(#k_select{var=#k_var{anno=Vanno},types=Types0}=Select) ->
- case member(reuse_for_context, Vanno) of
- false ->
- Types = avoid_stack_frame_list(Types0),
- Select#k_select{types=Types};
- true ->
- %% Including binary patterns that overwrite the register containing
- %% the binary with the match context may not be safe. For example,
- %% bs_match_SUITE:bin_tail_e/1 with inlining will be rejected by
- %% beam_validator.
- %%
- %% Essentially the following code is produced:
- %%
- %% bs_match {x,0} => {x,0}
- %% ...
- %% bs_match {x,0} => {x,1} %% ILLEGAL
- %%
- %% A bs_match instruction will only accept a match context as the
- %% source operand if the source and destination registers are the
- %% the same (as in the first bs_match instruction above).
- %% The second bs_match instruction is therefore illegal.
- %%
- %% This situation is avoided if there is a stack frame:
- %%
- %% move {x,0} => {y,0}
- %% bs_match {x,0} => {x,0}
- %% ...
- %% bs_match {y,0} => {x,1} %% LEGAL
- %%
- throw(impossible)
- end;
-avoid_stack_frame_1(#k_seq{arg=#k_call{anno=Anno,op=Op}=Call,
- body=#k_break{args=BrArgs0}}=Seq) ->
- case Op of
- #k_remote{mod=#k_atom{val=Mod},
- name=#k_atom{val=Name},
- arity=Arity} ->
- case erl_bifs:is_exit_bif(Mod, Name, Arity) of
- false ->
- %% Will clobber X registers. Must have a stack frame.
- throw(impossible);
- true ->
- %% The call to this BIF will never return. It is safe
- %% to suppress the stack frame.
- Bif = #k_bif{anno=Anno,
- op=#k_internal{name=guard_error,arity=1},
- args=[Call],ret=[]},
- BrArgs = lists:duplicate(length(BrArgs0), #k_nil{}),
- GB = #k_guard_break{anno=#k{us=[],ns=[],a=[]},args=BrArgs},
- Seq#k_seq{arg=Bif,body=GB}
- end;
- _ ->
- %% Will clobber X registers. Must have a stack frame.
- throw(impossible)
- end;
-avoid_stack_frame_1(#k_seq{arg=A0,body=B0}=Seq) ->
- A = avoid_stack_frame_1(A0),
- B = avoid_stack_frame_1(B0),
- Seq#k_seq{arg=A,body=B};
-avoid_stack_frame_1(#k_test{}=Test) ->
- Test;
-avoid_stack_frame_1(#k_type_clause{values=Values0}=TC) ->
- Values = avoid_stack_frame_list(Values0),
- TC#k_type_clause{values=Values};
-avoid_stack_frame_1(#k_val_clause{body=B0}=VC) ->
- B = avoid_stack_frame_1(B0),
- VC#k_val_clause{body=B};
-avoid_stack_frame_1(_Body) ->
- throw(impossible).
-
-avoid_stack_frame_list([H|T]) ->
- [avoid_stack_frame_1(H)|avoid_stack_frame_list(T)];
-avoid_stack_frame_list([]) -> [].
-
-
%% This pass creates beam format annotated with variable lifetime
%% information. Each thing is given an index and for each variable we
%% store the first and last index for its occurrence. The variable
@@ -1621,11 +1487,6 @@ test_cg(is_boolean, [#k_atom{val=Val}], Fail, I, Vdb, Bef, St) ->
false -> [{jump,{f,Fail}}]
end,
{Is,Aft,St};
-test_cg(is_map_key, As, Fail, I, Vdb, Bef, St) ->
- [Key,Map] = cg_reg_args(As, Bef),
- Aft = clear_dead(Bef, I, Vdb),
- F = {f,Fail},
- {[{test,is_map,F,[Map]},{test,has_map_fields,F,Map,{list,[Key]}}],Aft,St};
test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
Args = cg_reg_args(As, Bef),
Aft = clear_dead(Bef, I, Vdb),
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 0196e7fdfd..66e578b776 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -328,14 +328,16 @@ gexpr({protect,Line,Arg}, Bools0, St0) ->
Anno = lineno_anno(Line, St),
{#iprotect{anno=#a{anno=Anno},body=Eps++[E]},[],Bools0,St}
end;
-gexpr({op,L,'andalso',E1,E2}, Bools, St0) ->
+gexpr({op,_,'andalso',_,_}=E0, Bools, St0) ->
+ {op,L,'andalso',E1,E2} = right_assoc(E0, 'andalso', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
False = {atom,L,false},
E = make_bool_switch_guard(L, E1, V, E2, False),
gexpr(E, Bools, St);
-gexpr({op,L,'orelse',E1,E2}, Bools, St0) ->
+gexpr({op,_,'orelse',_,_}=E0, Bools, St0) ->
+ {op,L,'orelse',E1,E2} = right_assoc(E0, 'orelse', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
@@ -764,14 +766,16 @@ expr({op,_,'++',{lc,Llc,E,Qs0},More}, St0) ->
{Qs,St2} = preprocess_quals(Llc, Qs0, St1),
{Y,Yps,St} = lc_tq(Llc, E, Qs, Mc, St2),
{Y,Mps++Yps,St};
-expr({op,L,'andalso',E1,E2}, St0) ->
+expr({op,_,'andalso',_,_}=E0, St0) ->
+ {op,L,'andalso',E1,E2} = right_assoc(E0, 'andalso', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
False = {atom,L,false},
E = make_bool_switch(L, E1, V, E2, False, St0),
expr(E, St);
-expr({op,L,'orelse',E1,E2}, St0) ->
+expr({op,_,'orelse',_,_}=E0, St0) ->
+ {op,L,'orelse',E1,E2} = right_assoc(E0, 'orelse', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
@@ -1501,7 +1505,7 @@ bc_initial_size(E0, Q, St0) ->
end.
bc_elem_size({bin,_,El}, St0) ->
- case bc_elem_size_1(El, 0, []) of
+ case bc_elem_size_1(El, ordsets:new(), 0, []) of
{Bits,[]} ->
{#c_literal{val=Bits},[],[],St0};
{Bits,Vars0} ->
@@ -1515,19 +1519,33 @@ bc_elem_size(_, _) ->
throw(impossible).
bc_elem_size_1([{bin_element,_,{string,_,String},{integer,_,N},_}=El|Es],
- Bits, Vars) ->
+ DefVars, Bits, SizeVars) ->
U = get_unit(El),
- bc_elem_size_1(Es, Bits+U*N*length(String), Vars);
-bc_elem_size_1([{bin_element,_,_,{integer,_,N},_}=El|Es], Bits, Vars) ->
+ bc_elem_size_1(Es, DefVars, Bits+U*N*length(String), SizeVars);
+bc_elem_size_1([{bin_element,_,Expr,{integer,_,N},_}=El|Es],
+ DefVars0, Bits, SizeVars) ->
U = get_unit(El),
- bc_elem_size_1(Es, Bits+U*N, Vars);
-bc_elem_size_1([{bin_element,_,_,{var,_,Var},_}=El|Es], Bits, Vars) ->
- U = get_unit(El),
- bc_elem_size_1(Es, Bits, [{U,#c_var{name=Var}}|Vars]);
-bc_elem_size_1([_|_], _, _) ->
+ DefVars = bc_elem_size_def_var(Expr, DefVars0),
+ bc_elem_size_1(Es, DefVars, Bits+U*N, SizeVars);
+bc_elem_size_1([{bin_element,_,Expr,{var,_,Src},_}=El|Es],
+ DefVars0, Bits, SizeVars) ->
+ case ordsets:is_element(Src, DefVars0) of
+ false ->
+ U = get_unit(El),
+ DefVars = bc_elem_size_def_var(Expr, DefVars0),
+ bc_elem_size_1(Es, DefVars, Bits, [{U,#c_var{name=Src}}|SizeVars]);
+ true ->
+ throw(impossible)
+ end;
+bc_elem_size_1([_|_], _, _, _) ->
throw(impossible);
-bc_elem_size_1([], Bits, Vars) ->
- {Bits,Vars}.
+bc_elem_size_1([], _DefVars, Bits, SizeVars) ->
+ {Bits,SizeVars}.
+
+bc_elem_size_def_var({var,_,Var}, DefVars) ->
+ ordsets:add_element(Var, DefVars);
+bc_elem_size_def_var(_Expr, DefVars) ->
+ DefVars.
bc_elem_size_combine([{U,V}|T], U, UVars, Acc) ->
bc_elem_size_combine(T, U, [V|UVars], Acc);
@@ -2040,6 +2058,19 @@ fail_clause(Pats, Anno, Arg) ->
body=[#iprimop{anno=#a{anno=Anno},name=#c_literal{val=match_fail},
args=[Arg]}]}.
+%% Optimization for Dialyzer.
+right_assoc(E, Op, St) ->
+ case member(dialyzer, St#core.opts) of
+ true ->
+ right_assoc2(E, Op);
+ false ->
+ E
+ end.
+
+right_assoc2({op,L1,Op,{op,L2,Op,E1,E2},E3}, Op) ->
+ right_assoc2({op,L2,Op,E1,{op,L1,Op,E2,E3}}, Op);
+right_assoc2(E, _Op) -> E.
+
annotate_tuple(A, Es, St) ->
case member(dialyzer, St#core.opts) of
true ->
@@ -2597,7 +2628,8 @@ cfun(#ifun{anno=A,id=Id,vars=Args,clauses=Lcs,fc=Lfc}, _As, St0) ->
[],A#a.us,St2}.
c_call_erl(Fun, Args) ->
- cerl:c_call(cerl:c_atom(erlang), cerl:c_atom(Fun), Args).
+ As = [compiler_generated],
+ cerl:ann_c_call(As, cerl:c_atom(erlang), cerl:c_atom(Fun), Args).
%% lit_vars(Literal) -> [Var].
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
index 05c087104d..5c463063c1 100644
--- a/lib/compiler/test/andor_SUITE.erl
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -38,6 +37,7 @@ groups() ->
combined,in_case,slow_compilation]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
index cca92e4713..0f82a56fb7 100644
--- a/lib/compiler/test/apply_SUITE.erl
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,13 +29,13 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[mfa, fun_apply].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_block_SUITE.erl b/lib/compiler/test/beam_block_SUITE.erl
index d40addf119..40a30b65d7 100644
--- a/lib/compiler/test/beam_block_SUITE.erl
+++ b/lib/compiler/test/beam_block_SUITE.erl
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -46,6 +45,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl
index 47367d6eab..2b4a780899 100644
--- a/lib/compiler/test/beam_except_SUITE.erl
+++ b/lib/compiler/test/beam_except_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -35,6 +34,7 @@ groups() ->
coverage]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl
index 088f63606c..faedc0c1f1 100644
--- a/lib/compiler/test/beam_jump_SUITE.erl
+++ b/lib/compiler/test/beam_jump_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,22 +21,24 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
- undefined_label/1,ambiguous_catch_try_state/1]).
+ undefined_label/1,ambiguous_catch_try_state/1,
+ build_tuple/1]).
suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
[{p,[parallel],
[undefined_label,
- ambiguous_catch_try_state
+ ambiguous_catch_try_state,
+ build_tuple
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -72,3 +74,16 @@ river() -> song.
checks(Wanted) ->
%% Must be one line to cause the unsafe optimization.
{catch case river() of sheet -> begin +Wanted, if "da" -> Wanted end end end, catch case river() of sheet -> begin + Wanted, if "da" -> Wanted end end end}.
+
+-record(message2, {id, p1}).
+-record(message3, {id, p1, p2}).
+
+build_tuple(_Config) ->
+ {'EXIT',{{badrecord,message3},_}} = (catch do_build_tuple(#message2{})),
+ ok.
+
+do_build_tuple(Message) ->
+ if is_record(Message, message2) ->
+ Res = {res, rand:uniform(100)},
+ {Message#message3.id, Res}
+ end.
diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl
index 27ce51eec3..c8a4f9a75f 100644
--- a/lib/compiler/test/beam_reorder_SUITE.erl
+++ b/lib/compiler/test/beam_reorder_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -36,6 +35,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 499b9b41df..9f691716e3 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -23,12 +23,11 @@
init_per_group/2,end_per_group/2,
integers/1,coverage/1,booleans/1,setelement/1,cons/1,
tuple/1,record_float/1,binary_float/1,float_compare/1,
- arity_checks/1,elixir_binaries/1]).
+ arity_checks/1,elixir_binaries/1,find_best/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -43,10 +42,12 @@ groups() ->
binary_float,
float_compare,
arity_checks,
- elixir_binaries
+ elixir_binaries,
+ find_best
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -156,6 +157,10 @@ coverage(Config) ->
[_|_] ->
ok
end,
+
+ %% Cover beam_type:verified_type(none).
+ {'EXIT',{badarith,_}} = (catch (id(2) / id(1)) band 16#ff),
+
ok.
booleans(_Config) ->
@@ -292,6 +297,33 @@ elixir_bitstring_3(Bar) when is_bitstring(Bar) ->
list_to_bitstring(Rewrite)
end/bitstring>>.
+find_best(_Config) ->
+ ok = find_best([a], nil),
+ ok = find_best([<<"a">>], nil),
+ {error,_} = find_best([], nil),
+ ok.
+
+%% Failed because beam_type assumed that the operand
+%% for bs_context_binary must be a binary. Not true!
+find_best([a|Tail], Best) ->
+ find_best(Tail,
+ case Best of
+ X when X =:= nil orelse X =:= false -> a;
+ X -> X
+ end);
+find_best([<<"a">>|Tail], Best) ->
+ find_best(Tail,
+ case Best of
+ X when X =:= nil orelse X =:= false -> <<"a">>;
+ X -> X
+ end);
+find_best([], a) ->
+ ok;
+find_best([], <<"a">>) ->
+ ok;
+find_best([], nil) ->
+ {error,<<"should not get here">>}.
+
id(I) ->
I.
diff --git a/lib/compiler/test/beam_utils_SUITE.erl b/lib/compiler/test/beam_utils_SUITE.erl
index 3d35b546fc..ff0f72d519 100644
--- a/lib/compiler/test/beam_utils_SUITE.erl
+++ b/lib/compiler/test/beam_utils_SUITE.erl
@@ -25,13 +25,13 @@
is_not_killed/1,is_not_used_at/1,
select/1,y_catch/1,otp_8949_b/1,liveopt/1,coverage/1,
y_registers/1,user_predef/1,scan_f/1,cafu/1,
- receive_label/1,read_size_file_version/1,not_used/1]).
+ receive_label/1,read_size_file_version/1,not_used/1,
+ is_used_fr/1,unsafe_is_function/1]).
-export([id/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -52,10 +52,13 @@ groups() ->
scan_f,
cafu,
read_size_file_version,
- not_used
+ not_used,
+ is_used_fr,
+ unsafe_is_function
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -132,6 +135,15 @@ bs_init(_Config) ->
<<"foo/foo">> = do_bs_init_4(<<"foo">>, true),
error = do_bs_init_4([], not_boolean),
+ Id = 17575,
+ Domain = -8798798,
+ [<<10,1:16,Id:16/signed>>,<<8,2:16,Domain:32/signed>>] =
+ do_bs_init_5(#{tag=>value,id=>Id,domain=>Domain}),
+ {'EXIT',{{required,id},[_|_]}} =
+ (catch do_bs_init_5(#{tag=>value,id=>nil,domain=>Domain})),
+ {'EXIT',{{required,domain},[_|_]}} =
+ (catch do_bs_init_5(#{tag=>value,id=>Id,domain=>nil})),
+
ok.
do_bs_init_1([?MODULE], Sz) ->
@@ -189,6 +201,20 @@ do_bs_init_4(Arg1, Arg2) ->
error
end.
+do_bs_init_5(#{tag := value, id := Id, domain := Domain}) ->
+ [case Id of
+ nil ->
+ error(id({required, id}));
+ _ ->
+ <<10, 1:16/signed, Id:16/signed>>
+ end,
+ case Domain of
+ nil ->
+ error(id({required, domain}));
+ _ ->
+ <<8, 2:16/signed, Domain:32/signed>>
+ end].
+
bs_save(_Config) ->
{a,30,<<>>} = do_bs_save(<<1:1,30:5>>),
{b,127,<<>>} = do_bs_save(<<1:1,31:5,0:1,127:7>>),
@@ -527,5 +553,42 @@ not_used_p(_C, S, K, L) when is_record(K, k) ->
id(K)
end.
+is_used_fr(Config) ->
+ 1 = is_used_fr(self(), self()),
+ 1 = is_used_fr(self(), other),
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ ok.
+
+is_used_fr(X, Y) ->
+ %% beam_utils:is_used({fr,R}, Code) would crash.
+ _ = 0 / (X ! 1),
+ _ = case Y of
+ X -> ok;
+ _ -> error
+ end,
+ X ! 1.
+
+%% ERL-778.
+unsafe_is_function(Config) ->
+ {undefined,any} = unsafe_is_function(undefined, any),
+ {ok,any} = unsafe_is_function(fun() -> ok end, any),
+ {'EXIT',{{case_clause,_},_}} = (catch unsafe_is_function(fun(_) -> ok end, any)),
+ ok.
+
+unsafe_is_function(F, M) ->
+ %% There would be an internal consistency failure:
+ %% Instruction: {bif,is_function,{f,0},[{x,0},{integer,0}],{x,2}}
+ %% Error: {uninitialized_reg,{y,0}}:
+
+ NewValue = case is_function(F, 0) of
+ true -> F();
+ false when F =:= undefined -> undefined
+ end,
+ {NewValue,M}.
+
+
%% The identity function.
id(I) -> I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 374f7645d8..d3e544a9cc 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -49,7 +49,6 @@ suite() ->
{timetrap,{minutes,10}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -67,6 +66,7 @@ groups() ->
receive_stacked]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index bba2058f2f..42ba5d5365 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,6 +39,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index dd1d245f88..0419b16eea 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,22 +26,22 @@
init_per_group/2,end_per_group/2,
byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
extended_bit_aligned/1,mixed/1,filters/1,trim_coverage/1,
- nomatch/1,sizes/1,general_expressions/1]).
+ nomatch/1,sizes/1,general_expressions/1,matched_out_size/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[byte_aligned, bit_aligned, extended_byte_aligned,
extended_bit_aligned, mixed, filters, trim_coverage,
- nomatch, sizes, general_expressions].
+ nomatch, sizes, general_expressions, matched_out_size].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -338,6 +338,13 @@ general_expressions(_) ->
-undef(BAD).
+matched_out_size(Config) when is_list(Config) ->
+ <<1, 2>> = matched_out_size_1(<<4, 1:4, 4, 2:4>>),
+ ok.
+
+matched_out_size_1(Binary) ->
+ << <<X>> || <<S, X:S>> <= Binary>>.
+
cs_init() ->
erts_debug:set_internal_state(available_internal_state, true),
ok.
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
index 208d8c5487..526769f3a6 100644
--- a/lib/compiler/test/bs_bit_binaries_SUITE.erl
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -43,9 +42,10 @@ groups() ->
asymmetric_tests,big_asymmetric_tests,
binary_to_and_from_list,big_binary_to_and_from_list,
send_and_receive,send_and_receive_alot]}].
-
+
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index aa41baf7f0..ccc49df005 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -38,11 +38,10 @@ suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
-all() ->
- test_lib:recompile(?MODULE),
+all() ->
[{group,p}].
-groups() ->
+groups() ->
[{p,[parallel],
[two,test1,fail,float_bin,in_guard,in_catch,
nasty_literals,side_effect,opt,otp_7556,float_arith,
@@ -50,6 +49,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 861fafb867..a751f6fda5 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -40,7 +40,8 @@
map_and_binary/1,unsafe_branch_caching/1,
bad_literals/1,good_literals/1,constant_propagation/1,
parse_xml/1,get_payload/1,escape/1,num_slots_different/1,
- beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1]).
+ beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1,erl_689/1,
+ bs_start_match2_defs/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -53,7 +54,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -73,10 +73,12 @@ groups() ->
map_and_binary,unsafe_branch_caching,
bad_literals,good_literals,constant_propagation,parse_xml,
get_payload,escape,num_slots_different,
- beam_bsm,guard,is_ascii,non_opt_eq]}].
+ beam_bsm,guard,is_ascii,non_opt_eq,erl_689,
+ bs_start_match2_defs]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -1688,6 +1690,80 @@ non_opt_eq([_|_], <<_,_/binary>>) ->
non_opt_eq([], <<>>) ->
true.
+%% ERL-689
+
+erl_689(_Config) ->
+ {{0, 0, 0}, <<>>} = do_erl_689_1(<<0>>, ?MODULE),
+ {{2018, 8, 7}, <<>>} = do_erl_689_1(<<4,2018:16/little,8,7>>, ?MODULE),
+ {{0, 0, 0}, <<>>} = do_erl_689_2(?MODULE, <<0>>),
+ {{2018, 8, 7}, <<>>} = do_erl_689_2(?MODULE, <<4,2018:16/little,8,7>>),
+ ok.
+
+do_erl_689_1(Arg1, Arg2) ->
+ Res = do_erl_689_1a(Arg1, Arg2),
+ Res = do_erl_689_1b(Arg1, Arg2).
+
+do_erl_689_2(Arg1, Arg2) ->
+ Res = do_erl_689_2a(Arg1, Arg2),
+ Res = do_erl_689_2b(Arg1, Arg2).
+
+do_erl_689_1a(<<Length, Data/binary>>, _) ->
+ case {Data, Length} of
+ {_, 0} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ {{0, 0, 0}, Data};
+ {<<Y:16/little, M, D, Rest/binary>>, 4} ->
+ {{Y, M, D}, Rest}
+ end.
+
+do_erl_689_1b(<<Length, Data/binary>>, _) ->
+ case {Data, Length} of
+ {_, 0} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ id(0),
+ {{0, 0, 0}, Data};
+ {<<Y:16/little, M, D, Rest/binary>>, 4} ->
+ id(1),
+ {{Y, M, D}, Rest}
+ end.
+
+do_erl_689_2a(_, <<Length, Data/binary>>) ->
+ case {Length, Data} of
+ {0, _} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ {{0, 0, 0}, Data};
+ {4, <<Y:16/little, M, D, Rest/binary>>} ->
+ {{Y, M, D}, Rest}
+ end.
+
+do_erl_689_2b(_, <<Length, Data/binary>>) ->
+ case {Length, Data} of
+ {0, _} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ id(0),
+ {{0, 0, 0}, Data};
+ {4, <<Y:16/little, M, D, Rest/binary>>} ->
+ id(1),
+ {{Y, M, D}, Rest}
+ end.
+
+%% ERL-753
+
+bs_start_match2_defs(_Config) ->
+ {<<"http://127.0.0.1:1234/vsaas/hello">>} = api_url(<<"hello">>, dummy),
+ {"https://127.0.0.1:4321/vsaas/hello"} = api_url({https, "hello"}, dummy).
+
+api_url(URL, Auth) ->
+ Header = [],
+ case URL of
+ <<_/binary>> -> {<<"http://127.0.0.1:1234/vsaas/",URL/binary>>};
+ {https, [_|_] = URL1} -> {"https://127.0.0.1:4321/vsaas/"++URL1}
+ end.
+
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index ef3fc54b37..8ea4a849ec 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[utf8_roundtrip, unused_utf_char, utf16_roundtrip,
utf32_roundtrip, guard, extreme_tripping, literals,
coverage].
@@ -40,6 +39,7 @@ groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index a4de125d32..139f7af0d4 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -66,7 +66,6 @@ suite() ->
{timetrap,{minutes,10}}].
all() ->
- test_lib:recompile(?MODULE),
[self_compile_old_inliner,self_compile,
{group,p}].
@@ -88,6 +87,7 @@ groups() ->
string_table,otp_8949_a,split_cases]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 5373df01d6..6b230710b3 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -36,7 +36,7 @@
core_roundtrip/1, asm/1, optimized_guards/1,
sys_pre_attributes/1, dialyzer/1,
warnings/1, pre_load_check/1, env_compiler_options/1,
- bc_options/1
+ bc_options/1, deterministic_include/1, deterministic_paths/1
]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -46,7 +46,6 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> all_return_type().
all() ->
- test_lib:recompile(?MODULE),
[app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, kernel_listing, encrypted_abstr, tuple_calls,
@@ -54,12 +53,13 @@ all() ->
cover, env, core_pp, core_roundtrip, asm, optimized_guards,
sys_pre_attributes, dialyzer, warnings, pre_load_check,
env_compiler_options, custom_debug_info, bc_options,
- custom_compile_info].
+ custom_compile_info, deterministic_include, deterministic_paths].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -1514,6 +1514,47 @@ highest_opcode(DataDir, Mod, Opt) ->
<<16:32,0:32,HighestOpcode:32,_/binary>> = Code,
HighestOpcode.
+deterministic_include(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ Simple = filename:join(DataDir, "simple"),
+
+ %% Files without +deterministic should differ if their include paths do,
+ %% as their debug info will be different.
+ {ok,_,NonDetA} = compile:file(Simple, [binary, {i,"gurka"}]),
+ {ok,_,NonDetB} = compile:file(Simple, [binary, {i,"gaffel"}]),
+ true = NonDetA =/= NonDetB,
+
+ %% ... but files with +deterministic shouldn't.
+ {ok,_,DetC} = compile:file(Simple, [binary, deterministic, {i,"gurka"}]),
+ {ok,_,DetD} = compile:file(Simple, [binary, deterministic, {i,"gaffel"}]),
+ true = DetC =:= DetD,
+
+ ok.
+
+deterministic_paths(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+
+ %% Files without +deterministic should differ if they were compiled from a
+ %% different directory.
+ true = deterministic_paths_1(DataDir, "simple", []),
+
+ %% ... but files with +deterministic shouldn't.
+ false = deterministic_paths_1(DataDir, "simple", [deterministic]),
+
+ ok.
+
+deterministic_paths_1(DataDir, Name, Opts) ->
+ Simple = filename:join(DataDir, "simple"),
+ {ok, Cwd} = file:get_cwd(),
+ try
+ {ok,_,A} = compile:file(Simple, [binary | Opts]),
+ ok = file:set_cwd(DataDir),
+ {ok,_,B} = compile:file(Name, [binary | Opts]),
+ A =/= B
+ after
+ file:set_cwd(Cwd)
+ end.
+
%%%
%%% Utilities.
%%%
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index 9d872b860b..e5611e99d1 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -29,7 +29,7 @@
bs_shadowed_size_var/1,
cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1,
cover_v3_kernel_4/1,cover_v3_kernel_5/1,
- non_variable_apply/1,name_capture/1]).
+ non_variable_apply/1,name_capture/1,fun_letrec_effect/1]).
-include_lib("common_test/include/ct.hrl").
@@ -47,7 +47,6 @@ suite() ->
{timetrap,{minutes,5}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -58,11 +57,12 @@ groups() ->
bs_shadowed_size_var,
cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3,
cover_v3_kernel_4,cover_v3_kernel_5,
- non_variable_apply,name_capture
+ non_variable_apply,name_capture,fun_letrec_effect
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -94,6 +94,7 @@ end_per_group(_GroupName, Config) ->
?comp(cover_v3_kernel_5).
?comp(non_variable_apply).
?comp(name_capture).
+?comp(fun_letrec_effect).
try_it(Mod, Conf) ->
Src = filename:join(proplists:get_value(data_dir, Conf),
diff --git a/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core
new file mode 100644
index 0000000000..ab6f5b7940
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core
@@ -0,0 +1,25 @@
+module 'fun_letrec_effect' ['fun_letrec_effect'/0, 'ok'/0, 'wat'/0]
+attributes []
+
+'fun_letrec_effect'/0 =
+ fun () ->
+ do apply 'wat'/0()
+ receive
+ <'bar'> when 'true' -> 'ok'
+ <_0> when 'true' -> 'failed'
+ after 'infinity' ->
+ 'true'
+
+%% The return value (bar) of the fun was optimized away because the result of
+%% the `letrec ... in` was unused, despite the fun's return value being
+%% relevant for the side-effect of the expression.
+'wat'/0 =
+ fun () ->
+ let <Self> = call 'erlang':'self'() in
+ do letrec 'f'/0 = fun () ->
+ do call 'maps':'put'('foo', 'bar', ~{}~)
+ 'bar'
+ in call 'erlang':'send'(Self, apply 'f'/0())
+ 'undefined'
+
+end
diff --git a/lib/compiler/test/core_alias_SUITE.erl b/lib/compiler/test/core_alias_SUITE.erl
index f3f15ef0f8..737b1567d4 100644
--- a/lib/compiler/test/core_alias_SUITE.erl
+++ b/lib/compiler/test/core_alias_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -36,6 +35,7 @@ groups() ->
[tuples, cons]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index dfff8236e8..47606014c3 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -28,7 +28,7 @@
mixed_matching_clauses/1,unnecessary_building/1,
no_no_file/1,configuration/1,supplies/1,
redundant_stack_frame/1,export_from_case/1,
- empty_values/1]).
+ empty_values/1,cover_letrec_effect/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -37,7 +37,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -49,10 +48,11 @@ groups() ->
mixed_matching_clauses,unnecessary_building,
no_no_file,configuration,supplies,
redundant_stack_frame,export_from_case,
- empty_values]}].
+ empty_values,cover_letrec_effect]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -598,5 +598,25 @@ empty_values(_Config) ->
do_empty_values() when (#{})#{} ->
c.
+cover_letrec_effect(_Config) ->
+ self() ! {tag,42},
+ _ = try
+ try
+ ignore
+ after
+ receive
+ {tag,Int}=Term ->
+ Res = #{k => {Term,<<Int:16>>}},
+ self() ! Res
+ end
+ end
+ after
+ ok
+ end,
+ receive
+ Any ->
+ #{k := {{tag,42},<<42:16>>}} = Any
+ end,
+ ok.
id(I) -> I.
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index 01c779b181..8b9dbe4aa0 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,6 +39,7 @@ groups() ->
transforms,maps_warnings,bad_utf8]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 08c3dd8593..012810aba2 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[pending, bif_calls, math_functions,
mixed_float_and_int].
@@ -35,6 +34,7 @@ groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 17bd1656f8..e00885fcd6 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -41,6 +40,7 @@ groups() ->
eep37_dup,badarity,badfun]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 0d6f8c6f98..6ad73b46f7 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,7 +41,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -59,6 +58,7 @@ groups() ->
cover_beam_dead]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index ae59cc8026..dcc703c3e1 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -42,6 +41,7 @@ groups() ->
coverage]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
{ok,Node} = start_node(compiler, Pa),
[{testing_node,Node}|Config].
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index 2801a7fda4..c80b7cc59e 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -33,7 +33,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -48,6 +47,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 6badc7a8b8..3e0ab78390 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -76,7 +76,6 @@
suite() -> [].
all() ->
- test_lib:recompile(?MODULE),
[
%% literals
t_build_and_match_literals, t_build_and_match_literals_large,
@@ -130,8 +129,12 @@ all() ->
groups() -> [].
-init_per_suite(Config) -> Config.
-end_per_suite(_Config) -> ok.
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
init_per_group(_GroupName, Config) -> Config.
end_per_group(_GroupName, Config) -> Config.
@@ -706,6 +709,12 @@ t_map_get(Config) when is_list(Config) ->
{'EXIT',{{badmap,[]},_}} = (catch map_get(a, [])),
{'EXIT',{{badmap,<<1,2,3>>},_}} = (catch map_get(a, <<1,2,3>>)),
{'EXIT',{{badmap,1},_}} = (catch map_get(a, 1)),
+
+ %% Test that beam_validator understands that NewMap is
+ %% a map after seeing map_get(a, NewMap).
+ NewMap = id(#{a=>b}),
+ b = map_get(a, NewMap),
+ #{a:=z} = NewMap#{a:=z},
ok.
check_map_value(Map, Key, Value) when map_get(Key, Map) =:= Value -> true;
@@ -1203,10 +1212,25 @@ t_guard_bifs(Config) when is_list(Config) ->
true = map_guard_empty_2(),
true = map_guard_head(#{a=>1}),
false = map_guard_head([]),
+
true = map_get_head(#{a=>1}),
+ false = map_get_head(#{}),
false = map_get_head([]),
+
+ true = map_get_head_not(#{a=>false}),
+ false = map_get_head_not(#{a=>true}),
+ false = map_get_head(#{}),
+ false = map_get_head([]),
+
true = map_is_key_head(#{a=>1}),
false = map_is_key_head(#{}),
+ false = map_is_key_head(not_a_map),
+
+ false = map_is_key_head_not(#{a=>1}),
+ true = map_is_key_head_not(#{b=>1}),
+ true = map_is_key_head_not(#{}),
+ false = map_is_key_head_not(not_a_map),
+
true = map_guard_body(#{a=>1}),
false = map_guard_body({}),
true = map_guard_pattern(#{a=>1, <<"hi">> => "hi" }),
@@ -1215,6 +1239,57 @@ t_guard_bifs(Config) when is_list(Config) ->
true = map_guard_ill_map_size(),
true = map_field_check_sequence(#{a=>1}),
false = map_field_check_sequence(#{}),
+
+ %% The guard BIFs used in a body.
+
+ v = map_get(a, id(#{a=>v})),
+ {'EXIT',{{badkey,a},_}} =
+ (catch map_get(a, id(#{}))),
+ {'EXIT',{{badmap,not_a_map},_}} =
+ (catch map_get(a, id(not_a_map))),
+
+ true = is_map_key(a, id(#{a=>1})),
+ false = is_map_key(b, id(#{a=>1})),
+ false = is_map_key(b, id(#{})),
+ {'EXIT',{{badmap,not_a_map},_}} =
+ (catch is_map_key(b, id(not_a_map))),
+
+ {true,v} = erl_699(#{k=>v}),
+ {'EXIT',{{badkey,k},_}} = (catch erl_699(#{})),
+ {'EXIT',{{badmap,not_a_map},_}} = (catch erl_699(not_a_map)),
+
+ %% Cover optimizations in beam_dead.
+
+ ok = beam_dead_1(#{a=>any,k=>true}),
+ error = beam_dead_1(#{a=>any,k=>false}),
+ error = beam_dead_1(#{a=>any}),
+ error = beam_dead_1(#{}),
+
+ ok = beam_dead_2(#{a=>any,k=>true}),
+ error = beam_dead_2(#{a=>any,k=>false}),
+ error = beam_dead_2(#{a=>any}),
+ error = beam_dead_2(#{}),
+
+ ok = beam_dead_3(#{k=>true}),
+ error = beam_dead_3(#{k=>false}),
+ error = beam_dead_3(#{}),
+
+ ok = beam_dead_4(#{k=>true}),
+ error = beam_dead_4(#{k=>false}),
+ error = beam_dead_4(#{}),
+ error = beam_dead_4(not_a_map),
+
+ ok = beam_dead_5(#{k=>true}),
+ error = beam_dead_5(#{k=>false}),
+ error = beam_dead_3(#{}),
+
+ %% Test is_map_key/2 followed by map update.
+
+ Used0 = map_usage(var, #{other=>value}),
+ Used0 = #{other=>value,var=>dead},
+ Used1 = map_usage(var, #{var=>live}),
+ Used1 = #{var=>live},
+
ok.
map_guard_empty() when is_map(#{}); false -> true.
@@ -1227,8 +1302,14 @@ map_guard_head(_) -> false.
map_get_head(M) when map_get(a, M) =:= 1 -> true;
map_get_head(_) -> false.
+map_get_head_not(M) when not map_get(a, M) -> true;
+map_get_head_not(_) -> false.
+
map_is_key_head(M) when is_map_key(a, M) -> true;
-map_is_key_head(M) -> false.
+map_is_key_head(_) -> false.
+
+map_is_key_head_not(M) when not is_map_key(a, M) -> true;
+map_is_key_head_not(_) -> false.
map_guard_body(M) -> is_map(M).
@@ -1245,6 +1326,52 @@ map_field_check_sequence(M)
map_field_check_sequence(_) ->
false.
+erl_699(M) ->
+ %% Used to cause an internal consistency failure.
+ {is_map_key(k, M),maps:get(k, M)}.
+
+beam_dead_1(#{a:=_,k:=_}=M) when map_get(k, M) ->
+ ok;
+beam_dead_1(#{}) ->
+ error.
+
+beam_dead_2(M) ->
+ case M of
+ #{a:=_,k:=_} when map_get(k, M) ->
+ ok;
+ #{} ->
+ error
+ end.
+
+beam_dead_3(M) ->
+ case M of
+ #{k:=_} when map_get(k, M) ->
+ ok;
+ #{} ->
+ error
+ end.
+
+beam_dead_4(M) ->
+ case M of
+ #{} when map_get(k, M) ->
+ ok;
+ _ ->
+ error
+ end.
+
+beam_dead_5(#{}=M) when map_get(k, M) ->
+ ok;
+beam_dead_5(#{}) ->
+ error.
+
+%% Test is_map_key/2, followed by an update of the map.
+map_usage(Def, Used) ->
+ case is_map_key(Def, Used) of
+ true -> Used;
+ false -> Used#{Def=>dead}
+ end.
+
+
t_guard_sequence(Config) when is_list(Config) ->
{1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}),
{2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}),
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 88a96d1ca9..72e5356a8d 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -45,6 +44,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -378,6 +378,13 @@ untuplify(Config) when is_list(Config) ->
%% We do this to cover sys_core_fold:unalias_pat/1.
{1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias),
error = untuplify_1([1,2], {3,4}, 42),
+
+ %% Test that a previous bug in v3_codegen is gone. (The sinking of
+ %% stack frames into only the case arms that needed them was not always
+ %% safe.)
+ [33, -1, -33, 1] = untuplify_2(32, 65),
+ {33, 1, -33, -1} = untuplify_2(65, 32),
+
ok.
untuplify_1(A, B, C) ->
@@ -390,6 +397,21 @@ untuplify_1(A, B, C) ->
error
end.
+untuplify_2(V1, V2) ->
+ {D1,D2,D3,D4} =
+ if V1 > V2 ->
+ %% The 1 value was overwritten by the value of V2-V1.
+ {V1-V2, 1, V2-V1, -1};
+ true ->
+ {V2-V1, -1, V1-V2, 1}
+ end,
+ if
+ D2 > D4 ->
+ {D1, D2, D3, D4};
+ true ->
+ [D1, D2, D3, D4]
+ end.
+
%% Coverage of beam_dead:shortcut_boolean_label/4.
shortcut_boolean(Config) when is_list(Config) ->
false = shortcut_boolean_1([0]),
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index a87a2252b7..a1d931b994 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -61,7 +61,6 @@ suite() ->
-spec all() -> misc_SUITE_test_cases().
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -70,6 +69,7 @@ groups() ->
confused_literals,integer_encoding,override_bif]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/overridden_bif_SUITE.erl b/lib/compiler/test/overridden_bif_SUITE.erl
index ce18916515..6b8a9591c9 100644
--- a/lib/compiler/test/overridden_bif_SUITE.erl
+++ b/lib/compiler/test/overridden_bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -45,6 +44,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index fe875abddb..4219768d6f 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -25,7 +25,7 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1,
- wait/1]).
+ wait/1,recv_in_try/1,double_recv/1]).
-include_lib("common_test/include/ct.hrl").
@@ -40,15 +40,16 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
[{p,test_lib:parallel(),
- [recv,coverage,otp_7980,ref_opt,export,wait]}].
+ [recv,coverage,otp_7980,ref_opt,export,wait,
+ recv_in_try,double_recv]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -305,4 +306,76 @@ wait_1(r, _, _) ->
wait_1(A, B, C) ->
{A,B,C}.
+recv_in_try(_Config) ->
+ self() ! {ok,fh}, {ok,fh} = recv_in_try(infinity, native),
+ self() ! {ok,ignored}, {ok,42} = recv_in_try(infinity, plain),
+ self() ! {error,ignored}, nok = recv_in_try(infinity, plain),
+ timeout = recv_in_try(1, plain),
+ ok.
+
+recv_in_try(Timeout, Format) ->
+ try
+ receive
+ {Status,History} ->
+ %% {test,is_tuple,{f,148},[{x,0}]}.
+ %% {test,test_arity,{f,148},[{x,0},2]}.
+ %% {get_tuple_element,{x,0},0,{y,1}}. %y1 is fragile.
+ %%
+ %% %% Here the fragility of y1 would be be progated to
+ %% %% the 'catch' below. Incorrect, since get_tuple_element
+ %% %% can't fail.
+ %% {get_tuple_element,{x,0},1,{x,2}}.
+ %%
+ %% remove_message. %y1 fragility cleared.
+ FH = case Format of
+ native ->
+ id(History);
+ plain ->
+ id(42)
+ end,
+ case Status of
+ ok ->
+ {ok,FH};
+ error ->
+ nok
+ end
+ after Timeout ->
+ timeout
+ end
+ catch
+ %% The fragility of y1 incorrectly propagated to here.
+ %% beam_validator would complain.
+ throw:{error,Reason} ->
+ {nok,Reason}
+ end.
+
+%% ERL-703. The compiler would crash because beam_utils:anno_defs/1
+%% failed to take into account that code after loop_rec_end is
+%% unreachable.
+
+double_recv(_Config) ->
+ self() ! {more,{a,term}},
+ ok = do_double_recv({more,{a,term}}, any),
+ self() ! message,
+ ok = do_double_recv(whatever, message),
+
+ error = do_double_recv({more,42}, whatever),
+ error = do_double_recv(whatever, whatever),
+ ok.
+
+do_double_recv({more, Rest}, _Msg) ->
+ receive
+ {more, Rest} ->
+ ok
+ after 0 ->
+ error
+ end;
+do_double_recv(_, Msg) ->
+ receive
+ Msg ->
+ ok
+ after 0 ->
+ error
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 5546765f26..4ed7f39780 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,7 +41,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -52,6 +51,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/regressions_SUITE.erl b/lib/compiler/test/regressions_SUITE.erl
index 7a6fe08c73..9b0b9b0c38 100644
--- a/lib/compiler/test/regressions_SUITE.erl
+++ b/lib/compiler/test/regressions_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,13 +21,29 @@
-module(regressions_SUITE).
-include_lib("common_test/include/ct.hrl").
--export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,suite/0]).
+-export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2,
+ suite/0]).
-export([maps/1]).
groups() ->
[{p,test_lib:parallel(),
[maps]}].
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
init_per_testcase(_Case, Config) ->
Config.
@@ -39,7 +55,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
%%% test cases
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index 5528af3f3c..8f9cd9ab1e 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -34,7 +34,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -48,6 +47,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -1189,7 +1189,8 @@ bad_raise(Expr) ->
test_raise(Expr) ->
test_raise_1(Expr),
test_raise_2(Expr),
- test_raise_3(Expr).
+ test_raise_3(Expr),
+ test_raise_4(Expr).
test_raise_1(Expr) ->
erase(exception),
@@ -1263,5 +1264,28 @@ do_test_raise_3(Expr) ->
erlang:raise(exit, {exception,C,E}, Stk)
end.
+test_raise_4(Expr) ->
+ try
+ do_test_raise_4(Expr)
+ catch
+ exit:{exception,C,E,Stk}:Stk ->
+ try
+ Expr()
+ catch
+ C:E:S ->
+ [StkTop|_] = S,
+ [StkTop|_] = Stk
+ end
+ end.
+
+do_test_raise_4(Expr) ->
+ try
+ Expr()
+ catch
+ C:E:Stk ->
+ %% Here the stacktrace must be built.
+ erlang:raise(exit, {exception,C,E,Stk}, Stk)
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 857995b6a6..1c23eba06d 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@
comprehensions/1,maps/1,maps_bin_opt_info/1,
redundant_boolean_clauses/1,
latin1_fallback/1,underscore/1,no_warnings/1,
- bit_syntax/1,inlining/1]).
+ bit_syntax/1,inlining/1,tuple_calls/1]).
init_per_testcase(_Case, Config) ->
Config.
@@ -55,7 +55,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -65,9 +64,11 @@ groups() ->
bin_opt_info,bin_construction,comprehensions,maps,
maps_bin_opt_info,
redundant_boolean_clauses,latin1_fallback,
- underscore,no_warnings,bit_syntax,inlining]}].
+ underscore,no_warnings,bit_syntax,inlining,
+ tuple_calls]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -952,6 +953,20 @@ inlining(Config) ->
run(Config, Ts),
ok.
+tuple_calls(Config) ->
+ %% Make sure that no spurious warnings are generated.
+ Ts = [{inlining_1,
+ <<"-compile(tuple_calls).
+ dispatch(X) ->
+ (list_to_atom(\"prefix_\" ++
+ atom_to_list(suffix))):doit(X).
+ ">>,
+ [],
+ []}
+ ],
+ run(Config, Ts),
+ ok.
+
%%%
%%% End of test cases.
%%%
diff --git a/lib/compiler/test/z_SUITE.erl b/lib/compiler/test/z_SUITE.erl
index 150ab26ff8..bfa8e279e8 100644
--- a/lib/compiler/test/z_SUITE.erl
+++ b/lib/compiler/test/z_SUITE.erl
@@ -26,13 +26,13 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[loaded].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index a26cb09dff..a523627384 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 7.2
+COMPILER_VSN = 7.3.2
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 6eeebb67a2..194a3d30e9 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -148,6 +148,23 @@
# define HAVE_DES_ede3_cfb_encrypt
#endif
+// SHA3:
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,1)
+// An error in beta releases of 1.1.1 fixed in production release
+# ifdef NID_sha3_224
+# define HAVE_SHA3_224
+# endif
+# ifdef NID_sha3_256
+# define HAVE_SHA3_256
+# endif
+#endif
+# ifdef NID_sha3_384
+# define HAVE_SHA3_384
+# endif
+# ifdef NID_sha3_512
+# define HAVE_SHA3_512
+# endif
+
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \
&& !defined(OPENSSL_NO_EC) \
&& !defined(OPENSSL_NO_ECDH) \
@@ -155,12 +172,15 @@
# define HAVE_EC
#endif
-// (test for == 1.1.1pre8)
-#if OPENSSL_VERSION_NUMBER == (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \
+// (test for >= 1.1.1pre8)
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) -7) \
&& !defined(HAS_LIBRESSL) \
&& defined(HAVE_EC)
-// EXPERIMENTAL:
-# define HAVE_EDDH
+# define HAVE_ED_CURVE_DH
+# if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1)) \
+ && !defined(FIPS_SUPPORT)
+# define HAVE_EDDSA
+# endif
#endif
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'c')
@@ -169,8 +189,14 @@
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
# define HAVE_EVP_AES_CTR
+# define HAVE_AEAD
# define HAVE_GCM
+# define HAVE_CCM
# define HAVE_CMAC
+# if defined(RSA_PKCS1_OAEP_PADDING)
+# define HAVE_RSA_OAEP_PADDING
+# endif
+# define HAVE_RSA_MGF1_MD
# if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION(1,0,1,'d')
# define HAVE_GCM_EVP_DECRYPT_BUG
# endif
@@ -178,7 +204,16 @@
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
# ifndef HAS_LIBRESSL
+# define HAVE_CHACHA20
# define HAVE_CHACHA20_POLY1305
+# define HAVE_RSA_OAEP_MD
+# endif
+#endif
+
+// OPENSSL_VERSION_NUMBER >= 1.1.1-pre8
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1)-7)
+# ifndef HAS_LIBRESSL
+# define HAVE_POLY1305
# endif
#endif
@@ -186,10 +221,16 @@
# define HAVE_ECB_IVEC_BUG
#endif
-#define HAVE_RSA_SSLV23_PADDING
-#if defined(HAS_LIBRESSL) \
- && LIBRESSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(2,6,1)
-# undef HAVE_RSA_SSLV23_PADDING
+#ifndef HAS_LIBRESSL
+# ifdef RSA_SSLV23_PADDING
+# define HAVE_RSA_SSLV23_PADDING
+# endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+# ifdef RSA_PKCS1_PSS_PADDING
+# define HAVE_RSA_PKCS1_PSS_PADDING
+# endif
#endif
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'h') \
@@ -514,14 +555,16 @@ static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#ifdef HAVE_GCM_EVP_DECRYPT_BUG
static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif
-static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -536,6 +579,7 @@ static ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
static ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
/* helpers */
@@ -592,10 +636,8 @@ static ErlNifFunc nif_funcs[] = {
{"rsa_generate_key_nif", 2, rsa_generate_key_nif},
{"dh_generate_key_nif", 4, dh_generate_key_nif},
{"dh_compute_key_nif", 3, dh_compute_key_nif},
-
{"evp_compute_key_nif", 3, evp_compute_key_nif},
{"evp_generate_key_nif", 1, evp_generate_key_nif},
-
{"privkey_to_pubkey_nif", 2, privkey_to_pubkey_nif},
{"srp_value_B_nif", 5, srp_value_B_nif},
{"srp_user_secret_nif", 7, srp_user_secret_nif},
@@ -606,11 +648,14 @@ static ErlNifFunc nif_funcs[] = {
{"rand_seed_nif", 1, rand_seed_nif},
- {"aes_gcm_encrypt", 5, aes_gcm_encrypt},
- {"aes_gcm_decrypt", 5, aes_gcm_decrypt},
+ {"aead_encrypt", 6, aead_encrypt},
+ {"aead_decrypt", 6, aead_decrypt},
+
+ {"chacha20_stream_init", 2, chacha20_stream_init},
+ {"chacha20_stream_encrypt", 2, chacha20_stream_crypt},
+ {"chacha20_stream_decrypt", 2, chacha20_stream_crypt},
- {"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt},
- {"chacha20_poly1305_decrypt", 5, chacha20_poly1305_decrypt},
+ {"poly1305_nif", 2, poly1305_nif},
{"engine_by_id_nif", 1, engine_by_id_nif},
{"engine_init_nif", 1, engine_init_nif},
@@ -625,6 +670,7 @@ static ErlNifFunc nif_funcs[] = {
{"engine_get_first_nif", 0, engine_get_first_nif},
{"engine_get_next_nif", 1, engine_get_next_nif},
{"engine_get_id_nif", 1, engine_get_id_nif},
+ {"engine_get_name_nif", 1, engine_get_name_nif},
{"engine_get_all_methods_nif", 0, engine_get_all_methods_nif}
};
@@ -674,6 +720,15 @@ static ERL_NIF_TERM atom_onbasis;
static ERL_NIF_TERM atom_aes_cfb8;
static ERL_NIF_TERM atom_aes_cfb128;
+#ifdef HAVE_GCM
+static ERL_NIF_TERM atom_aes_gcm;
+#endif
+#ifdef HAVE_CCM
+static ERL_NIF_TERM atom_aes_ccm;
+#endif
+#ifdef HAVE_CHACHA20_POLY1305
+static ERL_NIF_TERM atom_chacha20_poly1305;
+#endif
#ifdef HAVE_ECB_IVEC_BUG
static ERL_NIF_TERM atom_aes_ecb;
static ERL_NIF_TERM atom_des_ecb;
@@ -684,12 +739,17 @@ static ERL_NIF_TERM atom_rsa;
static ERL_NIF_TERM atom_dss;
static ERL_NIF_TERM atom_ecdsa;
-#ifdef HAVE_EDDH
-static ERL_NIF_TERM atom_eddh;
+#ifdef HAVE_ED_CURVE_DH
static ERL_NIF_TERM atom_x25519;
static ERL_NIF_TERM atom_x448;
#endif
+static ERL_NIF_TERM atom_eddsa;
+#ifdef HAVE_EDDSA
+static ERL_NIF_TERM atom_ed25519;
+static ERL_NIF_TERM atom_ed448;
+#endif
+
static ERL_NIF_TERM atom_rsa_mgf1_md;
static ERL_NIF_TERM atom_rsa_oaep_label;
static ERL_NIF_TERM atom_rsa_oaep_md;
@@ -705,6 +765,10 @@ static ERL_NIF_TERM atom_sha224;
static ERL_NIF_TERM atom_sha256;
static ERL_NIF_TERM atom_sha384;
static ERL_NIF_TERM atom_sha512;
+static ERL_NIF_TERM atom_sha3_224;
+static ERL_NIF_TERM atom_sha3_256;
+static ERL_NIF_TERM atom_sha3_384;
+static ERL_NIF_TERM atom_sha3_512;
static ERL_NIF_TERM atom_md5;
static ERL_NIF_TERM atom_ripemd160;
@@ -790,6 +854,35 @@ static struct digest_type_t digest_types[] =
{NULL}
#endif
},
+ {{"sha3_224"},
+#ifdef HAVE_SHA3_224
+ {&EVP_sha3_224}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_256"},
+#ifdef HAVE_SHA3_256
+ {&EVP_sha3_256}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_384"},
+#ifdef HAVE_SHA3_384
+ {&EVP_sha3_384}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_512"},
+#ifdef HAVE_SHA3_512
+ {&EVP_sha3_512}
+#else
+ {NULL}
+#endif
+ },
+
{{NULL}}
};
@@ -1080,8 +1173,18 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_ppbasis = enif_make_atom(env,"ppbasis");
atom_onbasis = enif_make_atom(env,"onbasis");
#endif
+
atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8");
atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128");
+#ifdef HAVE_GCM
+ atom_aes_gcm = enif_make_atom(env, "aes_gcm");
+#endif
+#ifdef HAVE_CCM
+ atom_aes_ccm = enif_make_atom(env, "aes_ccm");
+#endif
+#ifdef HAVE_CHACHA20_POLY1305
+ atom_chacha20_poly1305 = enif_make_atom(env,"chacha20_poly1305");
+#endif
#ifdef HAVE_ECB_IVEC_BUG
atom_aes_ecb = enif_make_atom(env, "aes_ecb");
atom_des_ecb = enif_make_atom(env, "des_ecb");
@@ -1097,11 +1200,15 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_rsa = enif_make_atom(env,"rsa");
atom_dss = enif_make_atom(env,"dss");
atom_ecdsa = enif_make_atom(env,"ecdsa");
-#ifdef HAVE_EDDH
- atom_eddh = enif_make_atom(env,"eddh");
+#ifdef HAVE_ED_CURVE_DH
atom_x25519 = enif_make_atom(env,"x25519");
atom_x448 = enif_make_atom(env,"x448");
#endif
+ atom_eddsa = enif_make_atom(env,"eddsa");
+#ifdef HAVE_EDDSA
+ atom_ed25519 = enif_make_atom(env,"ed25519");
+ atom_ed448 = enif_make_atom(env,"ed448");
+#endif
atom_rsa_mgf1_md = enif_make_atom(env,"rsa_mgf1_md");
atom_rsa_oaep_label = enif_make_atom(env,"rsa_oaep_label");
atom_rsa_oaep_md = enif_make_atom(env,"rsa_oaep_md");
@@ -1117,6 +1224,10 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_sha256 = enif_make_atom(env,"sha256");
atom_sha384 = enif_make_atom(env,"sha384");
atom_sha512 = enif_make_atom(env,"sha512");
+ atom_sha3_224 = enif_make_atom(env,"sha3_224");
+ atom_sha3_256 = enif_make_atom(env,"sha3_256");
+ atom_sha3_384 = enif_make_atom(env,"sha3_384");
+ atom_sha3_512 = enif_make_atom(env,"sha3_512");
atom_md5 = enif_make_atom(env,"md5");
atom_ripemd160 = enif_make_atom(env,"ripemd160");
@@ -1237,15 +1348,17 @@ static void unload(ErlNifEnv* env, void* priv_data)
}
static int algo_hash_cnt, algo_hash_fips_cnt;
-static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */
+static ERL_NIF_TERM algo_hash[12]; /* increase when extending the list */
static int algo_pubkey_cnt, algo_pubkey_fips_cnt;
-static ERL_NIF_TERM algo_pubkey[11]; /* increase when extending the list */
+static ERL_NIF_TERM algo_pubkey[12]; /* increase when extending the list */
static int algo_cipher_cnt, algo_cipher_fips_cnt;
-static ERL_NIF_TERM algo_cipher[24]; /* increase when extending the list */
+static ERL_NIF_TERM algo_cipher[25]; /* increase when extending the list */
static int algo_mac_cnt, algo_mac_fips_cnt;
-static ERL_NIF_TERM algo_mac[2]; /* increase when extending the list */
+static ERL_NIF_TERM algo_mac[3]; /* increase when extending the list */
static int algo_curve_cnt, algo_curve_fips_cnt;
-static ERL_NIF_TERM algo_curve[87]; /* increase when extending the list */
+static ERL_NIF_TERM algo_curve[89]; /* increase when extending the list */
+static int algo_rsa_opts_cnt, algo_rsa_opts_fips_cnt;
+static ERL_NIF_TERM algo_rsa_opts[11]; /* increase when extending the list */
static void init_algorithms_types(ErlNifEnv* env)
{
@@ -1264,6 +1377,18 @@ static void init_algorithms_types(ErlNifEnv* env)
#ifdef HAVE_SHA512
algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512");
#endif
+#ifdef HAVE_SHA3_224
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_224");
+#endif
+#ifdef HAVE_SHA3_256
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_256");
+#endif
+#ifdef HAVE_SHA3_384
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_384");
+#endif
+#ifdef HAVE_SHA3_512
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_512");
+#endif
// Non-validated algorithms follow
algo_hash_fips_cnt = algo_hash_cnt;
algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4");
@@ -1283,8 +1408,9 @@ static void init_algorithms_types(ErlNifEnv* env)
#endif
// Non-validated algorithms follow
algo_pubkey_fips_cnt = algo_pubkey_cnt;
-#ifdef HAVE_EDDH
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "eddh");
+ // Don't know if Edward curves are fips validated
+#if defined(HAVE_EDDSA)
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "eddsa");
#endif
algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp");
@@ -1300,19 +1426,22 @@ static void init_algorithms_types(ErlNifEnv* env)
#endif
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc");
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc128");
- algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8");
- algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128");
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc256");
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ctr");
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ecb");
#if defined(HAVE_GCM)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm");
#endif
+#if defined(HAVE_CCM)
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ccm");
+#endif
// Non-validated algorithms follow
algo_cipher_fips_cnt = algo_cipher_cnt;
#ifdef HAVE_AES_IGE
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ige256");
#endif
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128");
#ifndef OPENSSL_NO_DES
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cbc");
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cfb");
@@ -1331,33 +1460,162 @@ static void init_algorithms_types(ErlNifEnv* env)
#if defined(HAVE_CHACHA20_POLY1305)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20_poly1305");
#endif
-
+#if defined(HAVE_CHACHA20)
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20");
+#endif
+
// Validated algorithms first
algo_mac_cnt = 0;
algo_mac[algo_mac_cnt++] = enif_make_atom(env,"hmac");
#ifdef HAVE_CMAC
algo_mac[algo_mac_cnt++] = enif_make_atom(env,"cmac");
#endif
+#ifdef HAVE_POLY1305
+ algo_mac[algo_mac_cnt++] = enif_make_atom(env,"poly1305");
+#endif
// Non-validated algorithms follow
algo_mac_fips_cnt = algo_mac_cnt;
-
// Validated algorithms first
algo_curve_cnt = 0;
+#if defined(HAVE_EC)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp384r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp521r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime256v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls7");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls9");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls12");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512t1");
+#if !defined(OPENSSL_NO_EC2M)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect239k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb176v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb208w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb272w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb304w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb359v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb368w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb431r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls5");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls10");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls11");
+#endif
+#endif
// Non-validated algorithms follow
algo_curve_fips_cnt = algo_curve_cnt;
+#if defined(HAVE_EC)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls6");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls8");
+#if !defined(OPENSSL_NO_EC2M)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls4");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec4");
+#endif
+#endif
//--
-#ifdef HAVE_EDDH
+#ifdef HAVE_EDDSA
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ed25519");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ed448");
+#endif
+#ifdef HAVE_ED_CURVE_DH
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x25519");
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x448");
#endif
+ // Validated algorithms first
+ algo_rsa_opts_cnt = 0;
+#ifdef HAS_EVP_PKEY_CTX
+# ifdef HAVE_RSA_PKCS1_PSS_PADDING
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_pss_padding");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pss_saltlen");
+# endif
+# ifdef HAVE_RSA_MGF1_MD
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_mgf1_md");
+# endif
+# ifdef HAVE_RSA_OAEP_PADDING
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_oaep_padding");
+# endif
+# ifdef HAVE_RSA_OAEP_MD
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_label");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_md");
+# endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"signature_md");
+#endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_padding");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_x931_padding");
+#ifdef HAVE_RSA_SSLV23_PADDING
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_sslv23_padding");
+#endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_no_padding");
+ algo_rsa_opts_fips_cnt = algo_rsa_opts_cnt;
+
+
// Check that the max number of algos is updated
ASSERT(algo_hash_cnt <= sizeof(algo_hash)/sizeof(ERL_NIF_TERM));
ASSERT(algo_pubkey_cnt <= sizeof(algo_pubkey)/sizeof(ERL_NIF_TERM));
ASSERT(algo_cipher_cnt <= sizeof(algo_cipher)/sizeof(ERL_NIF_TERM));
ASSERT(algo_mac_cnt <= sizeof(algo_mac)/sizeof(ERL_NIF_TERM));
ASSERT(algo_curve_cnt <= sizeof(algo_curve)/sizeof(ERL_NIF_TERM));
+ ASSERT(algo_rsa_opts_cnt <= sizeof(algo_rsa_opts)/sizeof(ERL_NIF_TERM));
}
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1369,19 +1627,22 @@ static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
int cipher_cnt = fips_mode ? algo_cipher_fips_cnt : algo_cipher_cnt;
int mac_cnt = fips_mode ? algo_mac_fips_cnt : algo_mac_cnt;
int curve_cnt = fips_mode ? algo_curve_fips_cnt : algo_curve_cnt;
+ int rsa_opts_cnt = fips_mode ? algo_rsa_opts_fips_cnt : algo_rsa_opts_cnt;
#else
int hash_cnt = algo_hash_cnt;
int pubkey_cnt = algo_pubkey_cnt;
int cipher_cnt = algo_cipher_cnt;
int mac_cnt = algo_mac_cnt;
int curve_cnt = algo_curve_cnt;
+ int rsa_opts_cnt = algo_rsa_opts_cnt;
#endif
- return enif_make_tuple5(env,
+ return enif_make_tuple6(env,
enif_make_list_from_array(env, algo_hash, hash_cnt),
enif_make_list_from_array(env, algo_pubkey, pubkey_cnt),
enif_make_list_from_array(env, algo_cipher, cipher_cnt),
enif_make_list_from_array(env, algo_mac, mac_cnt),
- enif_make_list_from_array(env, algo_curve, curve_cnt)
+ enif_make_list_from_array(env, algo_curve, curve_cnt),
+ enif_make_list_from_array(env, algo_rsa_opts, rsa_opts_cnt)
);
}
@@ -1989,6 +2250,62 @@ static ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
#endif
}
+/* For OpenSSL >= 1.1.1 the hmac_nif and cmac_nif could be integrated into poly1305 (with 'type' as parameter) */
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Text) */
+#ifdef HAVE_POLY1305
+ ErlNifBinary key_bin, text, ret_bin;
+ ERL_NIF_TERM ret = atom_error;
+ EVP_PKEY *key = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ const EVP_MD *md = NULL;
+ size_t size;
+ int type;
+
+ type = EVP_PKEY_POLY1305;
+
+ if (!enif_inspect_binary(env, argv[0], &key_bin) ||
+ !(key_bin.size == 32) ) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_inspect_binary(env, argv[1], &text) ) {
+ return enif_make_badarg(env);
+ }
+
+ key = EVP_PKEY_new_raw_private_key(type, /*engine*/ NULL, key_bin.data, key_bin.size);
+
+ if (!key ||
+ !(mctx = EVP_MD_CTX_new()) ||
+ !EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) ||
+ !EVP_DigestSignUpdate(mctx, text.data, text.size)) {
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(mctx, NULL, &size) ||
+ !enif_alloc_binary(size, &ret_bin) ||
+ !EVP_DigestSignFinal(mctx, ret_bin.data, &size)) {
+ goto err;
+ }
+
+ if ((size != ret_bin.size) &&
+ !enif_realloc_binary(&ret_bin, size)) {
+ goto err;
+ }
+
+ ret = enif_make_binary(env, &ret_bin);
+
+ err:
+ EVP_MD_CTX_free(mctx);
+ EVP_PKEY_free(key);
+ return ret;
+
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */
struct cipher_type_t *cipherp = NULL;
@@ -2009,21 +2326,24 @@ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
return enif_raise_exception(env, atom_notsup);
}
- if (argv[0] == atom_aes_cfb8
- && (key.size == 24 || key.size == 32)) {
- /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
- * Fall back on low level API
- */
- return aes_cfb_8_crypt(env, argc-1, argv+1);
+ if (argv[0] == atom_aes_cfb8) {
+ CHECK_NO_FIPS_MODE();
+ if ((key.size == 24 || key.size == 32)) {
+ /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
+ * Fall back on low level API
+ */
+ return aes_cfb_8_crypt(env, argc-1, argv+1);
+ }
+ }
+ else if (argv[0] == atom_aes_cfb128) {
+ CHECK_NO_FIPS_MODE();
+ if ((key.size == 24 || key.size == 32)) {
+ /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
+ * Fall back on low level API
+ */
+ return aes_cfb_128_crypt_nif(env, argc-1, argv+1);
+ }
}
- else if (argv[0] == atom_aes_cfb128
- && (key.size == 24 || key.size == 32)) {
- /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
- * Fall back on low level API
- */
- return aes_cfb_128_crypt_nif(env, argc-1, argv+1);
- }
-
ivec_size = EVP_CIPHER_iv_length(cipher);
#ifdef HAVE_ECB_IVEC_BUG
@@ -2282,66 +2602,102 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
}
#endif /* !HAVE_EVP_AES_CTR */
-static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In) */
-#if defined(HAVE_GCM)
+static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type,Key,Iv,AAD,In) */
+#if defined(HAVE_AEAD)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in;
unsigned int tag_len;
unsigned char *outp, *tagp;
- ERL_NIF_TERM out, out_tag;
- int len;
+ ERL_NIF_TERM type, out, out_tag;
+ int len, ctx_ctrl_set_ivlen, ctx_ctrl_get_tag;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || (key.size != 16 && key.size != 24 && key.size != 32)
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_get_uint(env, argv[4], &tag_len) || tag_len < 1 || tag_len > 16) {
+ type = argv[0];
+
+ if (!enif_is_atom(env, type)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !enif_inspect_binary(env, argv[2], &iv)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_get_uint(env, argv[5], &tag_len)) {
return enif_make_badarg(env);
}
- if (key.size == 16)
- cipher = EVP_aes_128_gcm();
- else if (key.size == 24)
- cipher = EVP_aes_192_gcm();
- else if (key.size == 32)
- cipher = EVP_aes_256_gcm();
-
+ /* Use cipher_type some day. Must check block_encrypt|decrypt first */
+#if defined(HAVE_GCM)
+ if (type == atom_aes_gcm) {
+ if ((iv.size > 0)
+ && (1 <= tag_len && tag_len <= 16)) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_gcm();
+ else if (key.size == 24) cipher = EVP_aes_192_gcm();
+ else if (key.size == 32) cipher = EVP_aes_256_gcm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if ((7 <= iv.size && iv.size <= 13)
+ && (4 <= tag_len && tag_len <= 16)
+ && ((tag_len & 1) == 0)
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_ccm();
+ else if (key.size == 24) cipher = EVP_aes_192_ccm();
+ else if (key.size == 32) cipher = EVP_aes_256_ccm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_chacha20_poly1305) {
+ if ((key.size == 32)
+ && (1 <= iv.size && iv.size <= 16)
+ && (tag_len == 16)
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_AEAD_GET_TAG,
+ cipher = EVP_chacha20_poly1305();
+ } else enif_make_badarg(env);
+ } else
+#endif
+ return enif_raise_exception(env, atom_notsup);
+
ctx = EVP_CIPHER_CTX_new();
+ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err;
+
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) goto out_err;
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
+ if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in.size) != 1) goto out_err;
+ } else
+#endif
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
- if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_set_padding(ctx, 0);
-
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
+ if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err;
outp = enif_make_new_binary(env, in.size, &out);
- if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
+ if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err;
+ if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1) goto out_err;
tagp = enif_make_new_binary(env, tag_len, &out_tag);
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
- goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, tag_len, tagp) != 1) goto out_err;
EVP_CIPHER_CTX_free(ctx);
-
CONSUME_REDS(env, in);
-
return enif_make_tuple2(env, out, out_tag);
-out_err:
+out_err:
EVP_CIPHER_CTX_free(ctx);
return atom_error;
@@ -2350,58 +2706,103 @@ out_err:
#endif
}
-static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
- return aes_gcm_decrypt_NO_EVP(env, argc, argv);
-#elif defined(HAVE_GCM)
+static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type,Key,Iv,AAD,In,Tag) */
+#if defined(HAVE_AEAD)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in, tag;
unsigned char *outp;
- ERL_NIF_TERM out;
- int len;
+ ERL_NIF_TERM type, out;
+ int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || (key.size != 16 && key.size != 24 && key.size != 32)
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
+ type = argv[0];
+#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
+ if (type == atom_aes_gcm)
+ return aes_gcm_decrypt_NO_EVP(env, argc, argv);
+#endif
+
+ if (!enif_is_atom(env, type)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !enif_inspect_binary(env, argv[2], &iv)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) {
return enif_make_badarg(env);
}
- if (key.size == 16)
- cipher = EVP_aes_128_gcm();
- else if (key.size == 24)
- cipher = EVP_aes_192_gcm();
- else if (key.size == 32)
- cipher = EVP_aes_256_gcm();
+ /* Use cipher_type some day. Must check block_encrypt|decrypt first */
+#if defined(HAVE_GCM)
+ if (type == atom_aes_gcm) {
+ if (iv.size > 0) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN;
+ ctx_ctrl_set_tag = EVP_CTRL_GCM_SET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_gcm();
+ else if (key.size == 24) cipher = EVP_aes_192_gcm();
+ else if (key.size == 32) cipher = EVP_aes_256_gcm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (iv.size > 0) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN;
+ if (key.size == 16) cipher = EVP_aes_128_ccm();
+ else if (key.size == 24) cipher = EVP_aes_192_ccm();
+ else if (key.size == 32) cipher = EVP_aes_256_ccm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_chacha20_poly1305) {
+ if ((key.size == 32)
+ && (1 <= iv.size && iv.size <= 16)
+ && tag.size == 16
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN;
+ ctx_ctrl_set_tag = EVP_CTRL_AEAD_SET_TAG;
+ cipher = EVP_chacha20_poly1305();
+ } else enif_make_badarg(env);
+ } else
+#endif
+ return enif_raise_exception(env, atom_notsup);
+
+ outp = enif_make_new_binary(env, in.size, &out);
ctx = EVP_CIPHER_CTX_new();
+ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err;
- if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag.size, tag.data) != 1) goto out_err;
+ }
+#endif
- outp = enif_make_new_binary(env, in.size, &out);
+ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
- if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
- goto out_err;
- if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, in.size)) goto out_err;
+ }
+#endif
+
+ if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err;
+ if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err;
+#if defined(HAVE_GCM) || defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_aes_gcm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, tag.size, tag.data) != 1) goto out_err;
+ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) goto out_err;
+ }
+#endif
EVP_CIPHER_CTX_free(ctx);
CONSUME_REDS(env, in);
-
return out;
out_err:
@@ -2414,19 +2815,19 @@ out_err:
#ifdef HAVE_GCM_EVP_DECRYPT_BUG
static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{
+{/* (Type,Key,Iv,AAD,In,Tag) */
GCM128_CONTEXT *ctx;
ErlNifBinary key, iv, aad, in, tag;
AES_KEY aes_key;
unsigned char *outp;
ERL_NIF_TERM out;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
+ || !enif_inspect_binary(env, argv[2], &iv) || iv.size == 0
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) {
return enif_make_badarg(env);
}
@@ -2460,118 +2861,67 @@ out_err:
#endif /* HAVE_GCM_EVP_DECRYPT_BUG */
-static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In) */
-#if defined(HAVE_CHACHA20_POLY1305)
- EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in;
- unsigned char *outp, *tagp;
- ERL_NIF_TERM out, out_tag;
- int len;
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IV) */
+#if defined(HAVE_CHACHA20)
+ ErlNifBinary key_bin, ivec_bin;
+ struct evp_cipher_ctx *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)) {
- return enif_make_badarg(env);
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || key_bin.size != 32
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
}
- cipher = EVP_chacha20_poly1305();
-
- ctx = EVP_CIPHER_CTX_new();
-
- if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_set_padding(ctx, 0);
+ cipher = EVP_chacha20();
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
-
- outp = enif_make_new_binary(env, in.size, &out);
-
- if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
-
- tagp = enif_make_new_binary(env, 16, &out_tag);
-
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tagp) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_free(ctx);
-
- CONSUME_REDS(env, in);
+ ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ ctx->ctx = EVP_CIPHER_CTX_new();
- return enif_make_tuple2(env, out, out_tag);
-out_err:
- EVP_CIPHER_CTX_free(ctx);
- return atom_error;
+ EVP_CipherInit_ex(ctx->ctx, cipher, NULL,
+ key_bin.data, ivec_bin.data, 1);
+ EVP_CIPHER_CTX_set_padding(ctx->ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
#else
return enif_raise_exception(env, atom_notsup);
#endif
-}
+};
-static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_CHACHA20_POLY1305)
- EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in, tag;
- unsigned char *outp;
- ERL_NIF_TERM out;
- int len;
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (State, Data) */
+#if defined(HAVE_CHACHA20)
+ struct evp_cipher_ctx *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+ int outl = 0;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != 16) {
- return enif_make_badarg(env);
+ if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
}
+ new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ new_ctx->ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx);
+ out = enif_make_new_binary(env, data_bin.size, &cipher_term);
+ EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, data_bin.size);
+ ASSERT(outl == data_bin.size);
- cipher = EVP_chacha20_poly1305();
-
- ctx = EVP_CIPHER_CTX_new();
-
- if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
-
- outp = enif_make_new_binary(env, in.size, &out);
-
- if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size, tag.data) != 1)
- goto out_err;
- if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_free(ctx);
-
- CONSUME_REDS(env, in);
-
- return out;
-
-out_err:
- EVP_CIPHER_CTX_free(ctx);
- return atom_error;
+ ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env,data_bin);
+ return ret;
#else
return enif_raise_exception(env, atom_notsup);
#endif
-}
+};
+
static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
@@ -2890,6 +3240,36 @@ static int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
return 1;
}
+#ifdef HAVE_EDDSA
+ static int get_eddsa_key(ErlNifEnv* env, int public, ERL_NIF_TERM key, EVP_PKEY **pkey)
+{
+ /* key=[K] */
+ ERL_NIF_TERM head, tail, tail2, algo;
+ ErlNifBinary bin;
+ int type;
+
+ if (!enif_get_list_cell(env, key, &head, &tail)
+ || !enif_inspect_binary(env, head, &bin)
+ || !enif_get_list_cell(env, tail, &algo, &tail2)
+ || !enif_is_empty_list(env, tail2)) {
+ return 0;
+ }
+ if (algo == atom_ed25519) type = EVP_PKEY_ED25519;
+ else if (algo == atom_ed448) type = EVP_PKEY_ED448;
+ else
+ return 0;
+
+ if (public)
+ *pkey = EVP_PKEY_new_raw_public_key(type, NULL, bin.data, bin.size);
+ else
+ *pkey = EVP_PKEY_new_raw_private_key(type, NULL, bin.data, bin.size);
+
+ if (!pkey)
+ return 0;
+ return 1;
+}
+#endif
+
static int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa)
{
/* key=[P,Q,G,KEY] */
@@ -3810,7 +4190,7 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
int i;
EC_GROUP *group;
const BIGNUM *priv_key;
- EC_POINT *my_ecpoint;
+ EC_POINT *my_ecpoint = NULL;
EC_KEY *other_ecdh = NULL;
if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
@@ -3853,15 +4233,14 @@ out_err:
#endif
}
-// EXPERIMENTAL!
static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* (Curve, PeerBin, MyBin) */
{
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
int type;
- EVP_PKEY_CTX *ctx;
+ EVP_PKEY_CTX *ctx = NULL;
ErlNifBinary peer_bin, my_bin, key_bin;
- EVP_PKEY *peer_key, *my_key;
+ EVP_PKEY *peer_key = NULL, *my_key = NULL;
size_t max_size;
if (argv[0] == atom_x25519) type = EVP_PKEY_X25519;
@@ -3869,53 +4248,54 @@ static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
else return enif_make_badarg(env);
if (!enif_inspect_binary(env, argv[1], &peer_bin) ||
- !enif_inspect_binary(env, argv[2], &my_bin)) {
- return enif_make_badarg(env);
- }
+ !enif_inspect_binary(env, argv[2], &my_bin))
+ goto return_badarg;
if (!(my_key = EVP_PKEY_new_raw_private_key(type, NULL, my_bin.data, my_bin.size)) ||
- !(ctx = EVP_PKEY_CTX_new(my_key, NULL))) {
- return enif_make_badarg(env);
- }
+ !(ctx = EVP_PKEY_CTX_new(my_key, NULL)))
+ goto return_badarg;
- if (!EVP_PKEY_derive_init(ctx)) {
- return enif_make_badarg(env);
- }
+ if (!EVP_PKEY_derive_init(ctx))
+ goto return_badarg;
if (!(peer_key = EVP_PKEY_new_raw_public_key(type, NULL, peer_bin.data, peer_bin.size)) ||
- !EVP_PKEY_derive_set_peer(ctx, peer_key)) {
- return enif_make_badarg(env);
- }
+ !EVP_PKEY_derive_set_peer(ctx, peer_key))
+ goto return_badarg;
- if (!EVP_PKEY_derive(ctx, NULL, &max_size)) {
- return enif_make_badarg(env);
- }
+ if (!EVP_PKEY_derive(ctx, NULL, &max_size))
+ goto return_badarg;
if (!enif_alloc_binary(max_size, &key_bin) ||
- !EVP_PKEY_derive(ctx, key_bin.data, &key_bin.size)) {
- return enif_make_badarg(env);
- }
+ !EVP_PKEY_derive(ctx, key_bin.data, &key_bin.size))
+ goto return_badarg;
if (key_bin.size < max_size) {
size_t actual_size = key_bin.size;
- if (!enif_realloc_binary(&key_bin, actual_size)) {
- return enif_make_badarg(env);
- }
+ if (!enif_realloc_binary(&key_bin, actual_size))
+ goto return_badarg;
}
+ EVP_PKEY_free(my_key);
+ EVP_PKEY_free(peer_key);
+ EVP_PKEY_CTX_free(ctx);
return enif_make_binary(env, &key_bin);
+
+return_badarg:
+ if (my_key) EVP_PKEY_free(my_key);
+ if (peer_key) EVP_PKEY_free(peer_key);
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return enif_make_badarg(env);
#else
return atom_notsup;
#endif
}
-// EXPERIMENTAL!
static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* (Curve) */
{
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
int type;
- EVP_PKEY_CTX *ctx;
+ EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
ERL_NIF_TERM ret_pub, ret_prv;
size_t key_len;
@@ -3926,24 +4306,30 @@ static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
if (!(ctx = EVP_PKEY_CTX_new_id(type, NULL))) return enif_make_badarg(env);
- if (!EVP_PKEY_keygen_init(ctx)) return enif_make_atom(env,"EVP_PKEY_keygen_init failed");
- if (!EVP_PKEY_keygen(ctx, &pkey)) return enif_make_atom(env,"EVP_PKEY_keygen failed");
+ if (!EVP_PKEY_keygen_init(ctx)) goto return_error;
+ if (!EVP_PKEY_keygen(ctx, &pkey)) goto return_error;
- if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 1 failed");
+ if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len)) goto return_error;
if (!EVP_PKEY_get_raw_public_key(pkey,
enif_make_new_binary(env, key_len, &ret_pub),
&key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 2 failed");
+ goto return_error;
- if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 1 failed");
+ if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len)) goto return_error;
if (!EVP_PKEY_get_raw_private_key(pkey,
enif_make_new_binary(env, key_len, &ret_prv),
&key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 2 failed");
+ goto return_error;
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
return enif_make_tuple2(env, ret_pub, ret_prv);
+
+return_error:
+ if (pkey) EVP_PKEY_free(pkey);
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return atom_error;
+
#else
return atom_notsup;
#endif
@@ -3975,7 +4361,12 @@ static int get_pkey_digest_type(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_
*md = NULL;
if (type == atom_none && algorithm == atom_rsa) return PKEY_OK;
-
+ if (algorithm == atom_eddsa)
+#ifdef HAVE_EDDSA
+ return PKEY_OK;
+#else
+ return PKEY_NOTSUP;
+#endif
digp = get_digest_type(type);
if (!digp) return PKEY_BADARG;
if (!digp->md.p) return PKEY_NOTSUP;
@@ -4092,7 +4483,7 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF
if (tpl_terms[1] == atom_rsa_pkcs1_padding) {
opt->rsa_padding = RSA_PKCS1_PADDING;
} else if (tpl_terms[1] == atom_rsa_pkcs1_pss_padding) {
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+#ifdef HAVE_RSA_PKCS1_PSS_PADDING
opt->rsa_padding = RSA_PKCS1_PSS_PADDING;
if (opt->rsa_mgf1_md == NULL) {
opt->rsa_mgf1_md = md;
@@ -4150,7 +4541,7 @@ static int get_engine_and_key_id(ErlNifEnv *env, ERL_NIF_TERM key, char ** id, E
static char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key) {
ERL_NIF_TERM tmp_term;
ErlNifBinary pwd_bin;
- char *pwd;
+ char *pwd = NULL;
if (enif_get_map_value(env, key, atom_password, &tmp_term) &&
enif_inspect_binary(env, tmp_term, &pwd_bin) &&
zero_terminate(pwd_bin, &pwd)
@@ -4175,16 +4566,17 @@ static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_
#ifdef HAS_ENGINE_SUPPORT
/* Use key stored in engine */
ENGINE *e;
- char *id;
+ char *id = NULL;
char *password;
if (!get_engine_and_key_id(env, key, &id, &e))
return PKEY_BADARG;
password = get_key_password(env, key);
*pkey = ENGINE_load_private_key(e, id, NULL, password);
+ if (password) enif_free(password);
+ enif_free(id);
if (!*pkey)
return PKEY_BADARG;
- enif_free(id);
#else
return PKEY_BADARG;
#endif
@@ -4225,6 +4617,14 @@ static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_
#else
return PKEY_NOTSUP;
#endif
+ } else if (algorithm == atom_eddsa) {
+#if defined(HAVE_EDDSA)
+ if (!get_eddsa_key(env, 0, key, pkey)) {
+ return PKEY_BADARG;
+ }
+#else
+ return PKEY_NOTSUP;
+#endif
} else if (algorithm == atom_dss) {
DSA *dsa = DSA_new();
@@ -4254,16 +4654,17 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T
#ifdef HAS_ENGINE_SUPPORT
/* Use key stored in engine */
ENGINE *e;
- char *id;
+ char *id = NULL;
char *password;
if (!get_engine_and_key_id(env, key, &id, &e))
return PKEY_BADARG;
password = get_key_password(env, key);
*pkey = ENGINE_load_public_key(e, id, NULL, password);
+ if (password) enif_free(password);
+ enif_free(id);
if (!pkey)
return PKEY_BADARG;
- enif_free(id);
#else
return PKEY_BADARG;
#endif
@@ -4303,6 +4704,14 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T
#else
return PKEY_NOTSUP;
#endif
+ } else if (algorithm == atom_eddsa) {
+#if defined(HAVE_EDDSA)
+ if (!get_eddsa_key(env, 1, key, pkey)) {
+ return PKEY_BADARG;
+ }
+#else
+ return PKEY_NOTSUP;
+#endif
} else if (algorithm == atom_dss) {
DSA *dsa = DSA_new();
@@ -4376,35 +4785,65 @@ printf("\r\n");
ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!ctx) goto badarg;
- if (EVP_PKEY_sign_init(ctx) <= 0) goto badarg;
- if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg;
+ if (argv[0] != atom_eddsa) {
+ if (EVP_PKEY_sign_init(ctx) <= 0) goto badarg;
+ if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg;
+ }
if (argv[0] == atom_rsa) {
if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg;
+# ifdef HAVE_RSA_PKCS1_PSS_PADDING
if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
if (sig_opt.rsa_mgf1_md != NULL) {
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
+# ifdef HAVE_RSA_MGF1_MD
if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) <= 0) goto badarg;
-#else
+# else
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return atom_notsup;
-#endif
+# endif
}
if (sig_opt.rsa_pss_saltlen > -2
&& EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0)
goto badarg;
}
+#endif
}
- if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) <= 0) goto badarg;
- enif_alloc_binary(siglen, &sig_bin);
+ if (argv[0] == atom_eddsa) {
+#ifdef HAVE_EDDSA
+ EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
+ if (!EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey)) {
+ if (mdctx) EVP_MD_CTX_free(mdctx);
+ goto badarg;
+ }
+
+ if (!EVP_DigestSign(mdctx, NULL, &siglen, tbs, tbslen)) {
+ EVP_MD_CTX_free(mdctx);
+ goto badarg;
+ }
+ enif_alloc_binary(siglen, &sig_bin);
- if (md != NULL) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ if (!EVP_DigestSign(mdctx, sig_bin.data, &siglen, tbs, tbslen)) {
+ EVP_MD_CTX_free(mdctx);
+ goto badarg;
+ }
+ EVP_MD_CTX_free(mdctx);
+#else
+ goto badarg;
+#endif
}
- i = EVP_PKEY_sign(ctx, sig_bin.data, &siglen, tbs, tbslen);
+ else
+ {
+ if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) <= 0) goto badarg;
+ enif_alloc_binary(siglen, &sig_bin);
+ if (md != NULL) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ }
+ i = EVP_PKEY_sign(ctx, sig_bin.data, &siglen, tbs, tbslen);
+ }
+
EVP_PKEY_CTX_free(ctx);
#else
/*printf("Old interface\r\n");
@@ -4512,20 +4951,23 @@ static ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
*/
ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!ctx) goto badarg;
- if (EVP_PKEY_verify_init(ctx) <= 0) goto badarg;
- if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg;
+
+ if (argv[0] != atom_eddsa) {
+ if (EVP_PKEY_verify_init(ctx) <= 0) goto badarg;
+ if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg;
+ }
if (argv[0] == atom_rsa) {
if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg;
if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
if (sig_opt.rsa_mgf1_md != NULL) {
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
+# ifdef HAVE_RSA_MGF1_MD
if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) <= 0) goto badarg;
-#else
+# else
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
return atom_notsup;
-#endif
+# endif
}
if (sig_opt.rsa_pss_saltlen > -2
&& EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0)
@@ -4533,10 +4975,28 @@ static ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
}
}
- if (md != NULL) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
- }
- i = EVP_PKEY_verify(ctx, sig_bin.data, sig_bin.size, tbs, tbslen);
+ if (argv[0] == atom_eddsa) {
+#ifdef HAVE_EDDSA
+ EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
+
+ if (!EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey)) {
+ if (mdctx) EVP_MD_CTX_destroy(mdctx);
+ goto badarg;
+ }
+
+ i = EVP_DigestVerify(mdctx, sig_bin.data, sig_bin.size, tbs, tbslen);
+ EVP_MD_CTX_destroy(mdctx);
+#else
+ goto badarg;
+#endif
+ }
+ else
+ {
+ if (md != NULL) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ }
+ i = EVP_PKEY_verify(ctx, sig_bin.data, sig_bin.size, tbs, tbslen);
+ }
EVP_PKEY_CTX_free(ctx);
#else
@@ -4618,8 +5078,10 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI
) {
if (tpl_terms[1] == atom_rsa_pkcs1_padding) {
opt->rsa_padding = RSA_PKCS1_PADDING;
+#ifdef HAVE_RSA_OAEP_PADDING
} else if (tpl_terms[1] == atom_rsa_pkcs1_oaep_padding) {
opt->rsa_padding = RSA_PKCS1_OAEP_PADDING;
+#endif
#ifdef HAVE_RSA_SSLV23_PADDING
} else if (tpl_terms[1] == atom_rsa_sslv23_padding) {
opt->rsa_padding = RSA_SSLV23_PADDING;
@@ -4638,7 +5100,7 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI
}
opt->signature_md = opt_md;
} else if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) {
-#ifndef HAVE_RSA_OAEP_MD
+#ifndef HAVE_RSA_MGF1_MD
if (tpl_terms[1] != atom_sha)
return PKEY_NOTSUP;
#endif
@@ -4678,6 +5140,15 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI
return PKEY_OK;
}
+static size_t size_of_RSA(EVP_PKEY *pkey) {
+ size_t tmplen;
+ RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL) return 0;
+ tmplen = RSA_size(rsa);
+ RSA_free(rsa);
+ return tmplen;
+}
+
static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{/* (Algorithm, Data, PublKey=[E,N]|[E,N,D]|[E,N,D,P1,P2,E1,E2,C], Options, IsPrivate, IsEncrypt) */
int i;
@@ -4775,9 +5246,8 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
#ifdef HAVE_RSA_SSLV23_PADDING
if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) {
if (is_encrypt) {
- RSA *rsa = EVP_PKEY_get1_RSA(pkey);
- if (rsa == NULL) goto badarg;
- tmplen = RSA_size(rsa);
+ tmplen = size_of_RSA(pkey);
+ if (tmplen == 0) goto badarg;
if (!enif_alloc_binary(tmplen, &tmp_bin)) goto badarg;
if (RSA_padding_add_SSLv23(tmp_bin.data, tmplen, in_bin.data, in_bin.size) <= 0)
goto badarg;
@@ -4797,7 +5267,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
if (crypt_opt.rsa_mgf1_md != NULL
&& EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, crypt_opt.rsa_mgf1_md) <= 0) goto badarg;
if (crypt_opt.rsa_oaep_label.data != NULL && crypt_opt.rsa_oaep_label.size > 0) {
- unsigned char *label_copy;
+ unsigned char *label_copy = NULL;
label_copy = OPENSSL_malloc(crypt_opt.rsa_oaep_label.size);
if (label_copy == NULL) goto badarg;
memcpy((void *)(label_copy), (const void *)(crypt_opt.rsa_oaep_label.data),
@@ -4876,7 +5346,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
} else {
/* non-evp rsa private decrypt */
i = RSA_private_decrypt(in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
+ out_bin.data, rsa, crypt_opt.rsa_padding);
if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
enif_realloc_binary(&out_bin, i);
@@ -4894,7 +5364,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
} else {
/* non-evp rsa public decrypt */
i = RSA_public_decrypt(in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
+ out_bin.data, rsa, crypt_opt.rsa_padding);
if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
enif_realloc_binary(&out_bin, i);
@@ -4909,11 +5379,11 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
if ((i > 0) && argv[0] == atom_rsa && !is_encrypt) {
#ifdef HAVE_RSA_SSLV23_PADDING
if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) {
- RSA *rsa = EVP_PKEY_get1_RSA(pkey);
unsigned char *p;
- if (rsa == NULL) goto badarg;
- tmplen = RSA_size(rsa);
- if (!enif_alloc_binary(tmplen, &tmp_bin)) goto badarg;
+ tmplen = size_of_RSA(pkey);
+ if (tmplen == 0) goto badarg;
+ if (!enif_alloc_binary(tmplen, &tmp_bin))
+ goto badarg;
p = out_bin.data;
p++;
i = RSA_padding_check_SSLv23(tmp_bin.data, tmplen, p, out_bin.size - 1, tmplen);
@@ -4986,6 +5456,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
RSA_get0_key(rsa, &n, &e, &d);
result[0] = bin_from_bn(env, e); // Exponent E
result[1] = bin_from_bn(env, n); // Modulus N = p*q
+ RSA_free(rsa);
EVP_PKEY_free(pkey);
return enif_make_list_from_array(env, result, 2);
}
@@ -5000,6 +5471,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
result[1] = bin_from_bn(env, q);
result[2] = bin_from_bn(env, g);
result[3] = bin_from_bn(env, pub_key);
+ DSA_free(dsa);
EVP_PKEY_free(pkey);
return enif_make_list_from_array(env, result, 4);
}
@@ -5012,7 +5484,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
/ * Example of result:
{
Curve = {Field, Prime, Point, Order, CoFactor} =
- {
+ {
Field = {prime_field,<<255,...,255>>},
Prime = {<<255,...,252>>,
<<90,...,75>>,
@@ -5025,9 +5497,9 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
Key = <<151,...,62>>
}
or
- {
+ {
Curve =
- {characteristic_two_field,
+ {characteristic_two_field,
M,
Basis = {tpbasis, _}
| {ppbasis, k1, k2, k3}
@@ -5040,7 +5512,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
*/
#endif
}
-
+
if (pkey) EVP_PKEY_free(pkey);
return enif_make_badarg(env);
}
@@ -5221,7 +5693,7 @@ static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const
error:
for(i = 0; cmds != NULL && cmds[i] != NULL; i++)
- enif_free(cmds[i]);
+ enif_free(cmds[i]);
enif_free(cmds);
return ret;
#else
@@ -5539,7 +6011,7 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
if (!engine_id) {
enif_alloc_binary(0, &engine_id_bin);
engine_id_bin.size = 0;
- return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin));
+ return enif_make_binary(env, &engine_id_bin);
}
size = strlen(engine_id);
@@ -5547,7 +6019,39 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
engine_id_bin.size = size;
memcpy(engine_id_bin.data, engine_id, size);
- return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin));
+ return enif_make_binary(env, &engine_id_bin);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ErlNifBinary engine_name_bin;
+ const char *engine_name;
+ int size;
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ engine_name = ENGINE_get_name(ctx->engine);
+ if (!engine_name) {
+ enif_alloc_binary(0, &engine_name_bin);
+ engine_name_bin.size = 0;
+ return enif_make_binary(env, &engine_name_bin);
+ }
+
+ size = strlen(engine_name);
+ enif_alloc_binary(size, &engine_name_bin);
+ engine_name_bin.size = size;
+ memcpy(engine_name_bin.data, engine_name, size);
+
+ return enif_make_binary(env, &engine_name_bin);
#else
return atom_notsup;
#endif
diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c
index 23d2bed057..0cc7dd609d 100644
--- a/lib/crypto/c_src/crypto_callback.c
+++ b/lib/crypto/c_src/crypto_callback.c
@@ -179,6 +179,10 @@ DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks)
/* This is not really a NIF library, but we use ERL_NIF_INIT in order to
* get access to the erl_nif API (on Windows).
*/
-ERL_NIF_INIT(dummy, (ErlNifFunc*)NULL , NULL, NULL, NULL, NULL)
+static struct {
+ int dummy__;
+ ErlNifFunc funcv[0];
+} empty;
+ERL_NIF_INIT(dummy, empty.funcv, NULL, NULL, NULL, NULL)
#endif
diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c
index b6c9067964..f452fb2d0c 100644
--- a/lib/crypto/c_src/otp_test_engine.c
+++ b/lib/crypto/c_src/otp_test_engine.c
@@ -35,7 +35,12 @@
#if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0) \
|| defined(LIBRESSL_VERSION_NUMBER)
-#define OLD
+# define OLD
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0) \
+ && !defined(LIBRESSL_VERSION_NUMBER)
+# define FAKE_RSA_IMPL
#endif
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \
@@ -56,15 +61,44 @@
static const char *test_engine_id = "MD5";
static const char *test_engine_name = "MD5 test engine";
-/* The callback that does the job of fetching keys on demand by the Engine */
-EVP_PKEY* test_key_load(ENGINE *er, const char *id, UI_METHOD *ui_method, void *callback_data);
+#if defined(FAKE_RSA_IMPL)
+/*-------- test of private/public keys and RSA in engine ---------*/
+static RSA_METHOD *test_rsa_method = NULL;
+
+/* Our on "RSA" implementation */
+static int test_rsa_sign(int dtype, const unsigned char *m,
+ unsigned int m_len, unsigned char *sigret,
+ unsigned int *siglen, const RSA *rsa);
+static int test_rsa_verify(int dtype, const unsigned char *m,
+ unsigned int m_len, const unsigned char *sigret,
+ unsigned int siglen, const RSA *rsa);
+static int test_rsa_free(RSA *rsa);
+#endif /* if defined(FAKE_RSA_IMPL) */
+
+/* The callbacks that does the job of fetching keys on demand by the Engine */
+EVP_PKEY* test_privkey_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY* test_pubkey_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY* test_key_load(ENGINE *er, const char *id, UI_METHOD *ui_method, void *callback_data, int priv);
+
+/*----------------------------------------------------------------*/
static int test_init(ENGINE *e) {
printf("OTP Test Engine Initializatzion!\r\n");
+#if defined(FAKE_RSA_IMPL)
+ if ( !RSA_meth_set_finish(test_rsa_method, test_rsa_free)
+ || !RSA_meth_set_sign(test_rsa_method, test_rsa_sign)
+ || !RSA_meth_set_verify(test_rsa_method, test_rsa_verify)
+ ) {
+ fprintf(stderr, "Setup RSA_METHOD failed\r\n");
+ return 0;
+ }
+#endif /* if defined(FAKE_RSA_IMPL) */
+
/* Load all digest and cipher algorithms. Needed for password protected private keys */
- OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_ciphers();
+ OpenSSL_add_all_digests();
return 111;
}
@@ -78,6 +112,19 @@ static void add_test_data(unsigned char *md, unsigned int len)
}
}
+#if defined(FAKE_RSA_IMPL)
+static int chk_test_data(const unsigned char *md, unsigned int len)
+{
+ unsigned int i;
+
+ for (i=0; i<len; i++) {
+ if (md[i] != (unsigned char)(i & 0xff))
+ return 0;
+ }
+ return 1;
+}
+#endif /* if defined(FAKE_RSA_IMPL) */
+
/* MD5 part */
#undef data
#ifdef OLD
@@ -183,19 +230,34 @@ static int test_engine_digest_selector(ENGINE *e, const EVP_MD **digest,
return ok;
}
-
static int bind_helper(ENGINE * e, const char *id)
{
- if (!ENGINE_set_id(e, test_engine_id) ||
- !ENGINE_set_name(e, test_engine_name) ||
- !ENGINE_set_init_function(e, test_init) ||
- !ENGINE_set_digests(e, &test_engine_digest_selector) ||
+#if defined(FAKE_RSA_IMPL)
+ test_rsa_method = RSA_meth_new("OTP test RSA method", 0);
+ if (test_rsa_method == NULL) {
+ fprintf(stderr, "RSA_meth_new failed\r\n");
+ return 0;
+ }
+#endif /* if defined(FAKE_RSA_IMPL) */
+
+ if (!ENGINE_set_id(e, test_engine_id)
+ || !ENGINE_set_name(e, test_engine_name)
+ || !ENGINE_set_init_function(e, test_init)
+ || !ENGINE_set_digests(e, &test_engine_digest_selector)
/* For testing of key storage in an Engine: */
- !ENGINE_set_load_privkey_function(e, &test_key_load) ||
- !ENGINE_set_load_pubkey_function(e, &test_key_load)
- )
+ || !ENGINE_set_load_privkey_function(e, &test_privkey_load)
+ || !ENGINE_set_load_pubkey_function(e, &test_pubkey_load)
+ )
return 0;
+#if defined(FAKE_RSA_IMPL)
+ if ( !ENGINE_set_RSA(e, test_rsa_method) ) {
+ RSA_meth_free(test_rsa_method);
+ test_rsa_method = NULL;
+ return 0;
+ }
+#endif /* if defined(FAKE_RSA_IMPL) */
+
return 1;
}
@@ -210,24 +272,29 @@ IMPLEMENT_DYNAMIC_BIND_FN(bind_helper);
*/
int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password);
-EVP_PKEY* test_key_load(ENGINE *er, const char *id, UI_METHOD *ui_method, void *callback_data)
+EVP_PKEY* test_privkey_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void *callback_data) {
+ return test_key_load(eng, id, ui_method, callback_data, 1);
+}
+
+EVP_PKEY* test_pubkey_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void *callback_data) {
+ return test_key_load(eng, id, ui_method, callback_data, 0);
+}
+
+EVP_PKEY* test_key_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void *callback_data, int priv)
{
EVP_PKEY *pkey = NULL;
FILE *f = fopen(id, "r");
if (!f) {
- fprintf(stderr, "%s:%d fopen(%s) failed\r\n", __FILE__,__LINE__,id);
- return NULL;
+ fprintf(stderr, "%s:%d fopen(%s) failed\r\n", __FILE__,__LINE__,id);
+ return NULL;
}
- /* First try to read as a private key. If that fails, try to read as a public key: */
- pkey = PEM_read_PrivateKey(f, NULL, pem_passwd_cb_fun, callback_data);
- if (!pkey) {
- /* ERR_print_errors_fp (stderr); */
- fclose(f);
- f = fopen(id, "r");
- pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
- }
+ pkey =
+ priv
+ ? PEM_read_PrivateKey(f, NULL, pem_passwd_cb_fun, callback_data)
+ : PEM_read_PUBKEY(f, NULL, NULL, NULL);
+
fclose(f);
if (!pkey) {
@@ -277,3 +344,71 @@ int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password)
}
#endif
+
+#if defined(FAKE_RSA_IMPL)
+/* RSA sign. This returns a fixed string so the test case can test that it was called
+ instead of the cryptolib default RSA sign */
+
+unsigned char fake_flag[] = {255,3,124,180,35,10,180,151,101,247,62,59,80,122,220,
+ 142,24,180,191,34,51,150,112,27,43,142,195,60,245,213,80,179};
+
+int test_rsa_sign(int dtype,
+ /* The digest to sign */
+ const unsigned char *m, unsigned int m_len,
+ /* The allocated buffer to fill with the signature */
+ unsigned char *sigret, unsigned int *siglen,
+ /* The key */
+ const RSA *rsa)
+{
+ int slen;
+ fprintf(stderr, "test_rsa_sign (dtype=%i) called m_len=%u *siglen=%u\r\n", dtype, m_len, *siglen);
+ if (!sigret) {
+ fprintf(stderr, "sigret = NULL\r\n");
+ return -1;
+ }
+
+ /* {int i;
+ fprintf(stderr, "Digest =\r\n");
+ for(i=0; i<m_len; i++)
+ fprintf(stderr, "%i,", m[i]);
+ fprintf(stderr, "\r\n");
+ } */
+
+ if ((sizeof(fake_flag) == m_len)
+ && memcmp(m,fake_flag,m_len) == 0) {
+ printf("To be faked\r\n");
+ /* To be faked */
+ slen = RSA_size(rsa);
+ add_test_data(sigret, slen); /* The signature is 0,1,2...255,0,1... */
+ *siglen = slen; /* Must set this. Why? */
+ return 1; /* 1 = success */
+ }
+ return 0;
+}
+
+int test_rsa_verify(int dtype,
+ /* The digest to verify */
+ const unsigned char *m, unsigned int m_len,
+ /* The signature */
+ const unsigned char *sigret, unsigned int siglen,
+ /* The key */
+ const RSA *rsa)
+{
+ printf("test_rsa_verify (dtype=%i) called m_len=%u siglen=%u\r\n", dtype, m_len, siglen);
+
+ if ((sizeof(fake_flag) == m_len)
+ && memcmp(m,fake_flag,m_len) == 0) {
+ printf("To be faked\r\n");
+ return (siglen == RSA_size(rsa))
+ && chk_test_data(sigret, siglen);
+ }
+ return 0;
+}
+
+static int test_rsa_free(RSA *rsa)
+{
+ printf("test_rsa_free called\r\n");
+ return 1;
+}
+
+#endif /* if defined(FAKE_RSA_IMPL) */
diff --git a/lib/crypto/doc/specs/.gitignore b/lib/crypto/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/crypto/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
index aa987d2b39..cbcafb7375 100644
--- a/lib/crypto/doc/src/Makefile
+++ b/lib/crypto/doc/src/Makefile
@@ -39,7 +39,7 @@ XML_REF3_FILES = crypto.xml
XML_REF6_FILES = crypto_app.xml
XML_PART_FILES = usersguide.xml
-XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml
+XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml algorithm_details.xml
BOOK_FILES = book.xml
@@ -62,11 +62,17 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
+#in ssh it looks like this: SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../..
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -89,9 +95,11 @@ debug opt valgrind:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
# ----------------------------------------------------
diff --git a/lib/crypto/doc/src/algorithm_details.xml b/lib/crypto/doc/src/algorithm_details.xml
new file mode 100644
index 0000000000..854bfbb4b1
--- /dev/null
+++ b/lib/crypto/doc/src/algorithm_details.xml
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2014</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Algorithm Details</title>
+ <prepared>Hans Nilsson</prepared>
+ <docno></docno>
+ <date>2018-08-22</date>
+ <rev>A</rev>
+ <file>algorithm_details.xml</file>
+ </header>
+ <p>
+ This chapter describes details of algorithms in the crypto application.
+ </p>
+ <p>The tables only documents the supported cryptos and key lengths. The user should not draw any conclusion
+ on security from the supplied tables.
+ </p>
+
+ <section>
+ <title>Ciphers</title>
+ <section>
+ <title>Block Ciphers</title>
+ <p>To be used in
+ <seealso marker="crypto#block_encrypt-3">block_encrypt/3</seealso>,
+ <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso>,
+ <seealso marker="crypto#block_decrypt-3">block_decrypt/3</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>any</cell></row>
+
+ <row><cell><c>aes_ecb</c></cell><cell>16, 24, 32</cell><cell> </cell><cell>16</cell></row>
+
+ <row><cell><c>aes_ige256</c></cell><cell>16</cell><cell>32</cell><cell>16</cell></row>
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>&#8805;1</cell> <cell>8</cell> <cell>any</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>&#8805;1</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>&#8805;1</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>8</cell><cell>any</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>des_ede3</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>&#8805;1</cell><cell>8</cell><cell>8</cell></row>
+ <tcaption>Block cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>AEAD Ciphers</title>
+ <p>To be used in <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>AAD length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Tag length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_ccm</c></cell> <cell>16,24,32</cell> <cell>7-13</cell> <cell>any</cell> <cell>even 4-16<br/>default: 12</cell> <cell>any</cell><cell>&#8805;1.1.0</cell></row>
+ <row><cell><c>aes_gcm</c></cell> <cell>16,24,32</cell> <cell>&#8805;1</cell> <cell>any</cell> <cell>1-16<br/>default: 16</cell> <cell>any</cell><cell>&#8805;1.1.0</cell></row>
+ <row><cell><c>chacha20_poly1305</c></cell><cell>32</cell> <cell>1-16</cell> <cell>any</cell> <cell>16</cell> <cell>any</cell><cell>&#8805;1.1.0</cell></row>
+ <tcaption>AEAD cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Stream Ciphers</title>
+ <p>To be used in <seealso marker="crypto#stream_init-2">stream_init/2</seealso> and
+ <seealso marker="crypto#stream_init/3">stream_init/3</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_ctr</c></cell><cell>16, 24, 32</cell><cell>16</cell><cell>&#8805;1.0.1</cell></row>
+ <row><cell><c>rc4</c></cell><cell>&#8805;1</cell><cell> </cell> <cell>all</cell></row>
+ <tcaption>Stream cipher key lengths</tcaption>
+ </table>
+ </section>
+ </section>
+
+ <section>
+ <title>Message Authentication Codes (MACs)</title>
+
+ <section>
+ <title>CMAC</title>
+ <p>To be used in <seealso marker="crypto#cmac-3">cmac/3</seealso> and
+ <seealso marker="crypto#cmac-3">cmac/4</seealso>.
+ </p>
+ <p>CMAC with the following ciphers are available with OpenSSL 1.0.1 or later if not disabled by configuration.
+ </p>
+
+ <p>To dynamically check availability, check that the name <c>cmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ Also check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Max Mac Length</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16</cell><cell>1</cell></row>
+
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>&#8805;1</cell> <cell>1</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>&#8805;1</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>&#8805;1</cell> <cell>1</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>1</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell></row>
+
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>&#8805;1</cell><cell>8</cell></row>
+ <tcaption>CMAC cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>HMAC</title>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>hmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>POLY1305</title>
+ <p>POLY1305 is available with OpenSSL 1.1.1 or later if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>poly1305</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+ <section>
+ <title>Hash</title>
+
+ <p>To dynamically check availability, check that the wanted name in the <i>Names</i> column is present in the
+ list with the <c>hashs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+
+ <table>
+ <row><cell><strong>Type</strong></cell>
+ <cell><strong>Names</strong></cell>
+ <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell>
+ </row>
+ <row><cell>SHA1</cell><cell>sha</cell><cell>all</cell></row>
+ <row><cell>SHA2</cell><cell>sha224, sha256, sha384, sha512</cell><cell>all</cell></row>
+ <row><cell>SHA3</cell><cell>sha3_224, sha3_256, sha3_384, sha3_512</cell><cell>&#8805;1.1.1</cell></row>
+ <row><cell>MD4</cell><cell>md4</cell><cell>all</cell></row>
+ <row><cell>MD5</cell><cell>md5</cell><cell>all</cell></row>
+ <row><cell>RIPEMD</cell><cell>ripemd160</cell><cell>all</cell></row>
+ <tcaption></tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Public Key Cryptography</title>
+
+ <section>
+ <title>RSA</title>
+ <p>RSA is available with all OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>rsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ <table>
+ <row><cell><strong>Option</strong></cell>
+ <cell><strong>sign/verify</strong></cell>
+ <cell><strong>public encrypt</strong><br/><strong>private decrypt</strong></cell>
+ <cell><strong>private encrypt</strong><br/><strong>public decrypt</strong></cell>
+ </row>
+ <row><cell>{rsa_padding,rsa_x931_padding}</cell>
+ <cell>x</cell>
+ <cell></cell>
+ <cell>x</cell>
+ </row>
+ <row><cell>{rsa_padding,rsa_pkcs1_padding}</cell>
+ <cell>x</cell>
+ <cell>x</cell>
+ <cell>x</cell>
+ </row>
+ <row><cell>{rsa_padding,rsa_pkcs1_pss_padding}<br/>
+ {rsa_pss_saltlen, -2..}<br/>
+ {rsa_mgf1_md, atom()}
+ </cell>
+ <cell>x (2)<br/>
+ x (2)<br/>
+ x (2)</cell>
+ <cell></cell>
+ <cell></cell>
+ </row>
+ <row><cell>{rsa_padding,rsa_pkcs1_oaep_padding}<br/>
+ {rsa_mgf1_md, atom()}<br/>
+ {rsa_oaep_label, binary()}}<br/>
+ {rsa_oaep_md, atom()}
+ </cell>
+ <cell></cell>
+ <cell>x (2)<br/>
+ x (2)<br/>
+ x (3)<br/>
+ x (3)
+ </cell>
+ <cell></cell>
+ </row>
+ <row><cell>{rsa_padding,rsa_no_padding}</cell>
+ <cell>x (1)</cell>
+ <cell></cell>
+ <cell></cell>
+ </row>
+ <!-- row><cell>{rsa_padding,rsa_sslv23_padding}</cell>
+ <cell></cell>
+ <cell></cell>
+ <cell></cell>
+ </row -->
+ <tcaption></tcaption>
+ </table>
+ <p>Notes:</p>
+ <list type="ordered">
+ <item>(1) OpenSSL &#8804; 1.0.0</item>
+ <item>(2) OpenSSL &#8805; 1.0.1</item>
+ <item>(3) OpenSSL &#8805; 1.1.0</item>
+ </list>
+ </section>
+
+ <section>
+ <title>DSS</title>
+ <p>DSS is available with OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dss</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>ECDSA</title>
+ <p>ECDSA is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ If the atom <c>ec_gf2m</c> characteristic two field curves are available.
+ </p>
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>EdDSA</title>
+ <p>EdDSA is available with OpenSSL 1.1.1 or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>eddsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <p>Support for the curves ed25519 and ed448 is implemented.
+ The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Diffie-Hellman</title>
+ <p>Diffie-Hellman computations are available with OpenSSL versions compatible with Erlang CRYPTO
+ if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Elliptic Curve Diffie-Hellman</title>
+ <p>Elliptic Curve Diffie-Hellman is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+ <p>The Edward curves <c>x25519</c> and <c>x448</c> are supported with OpenSSL 1.1.1 or later
+ if not disabled by configuration.
+ </p>
+
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+
+</chapter>
+
+
+
+
+
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 42e411a0e3..5c1909fc7f 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -23,231 +23,542 @@
<title>crypto</title>
</header>
- <module>crypto</module>
+ <module since="">crypto</module>
<modulesummary>Crypto Functions</modulesummary>
<description>
<p>This module provides a set of cryptographic functions.
</p>
- <list type="bulleted">
- <item>
- <p>Hash functions -
- <url href="http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf"> Secure Hash Standard</url>,
- <url href="http://www.ietf.org/rfc/rfc1321.txt"> The MD5 Message Digest Algorithm (RFC 1321)</url> and
- <url href="http://www.ietf.org/rfc/rfc1320.txt">The MD4 Message Digest Algorithm (RFC 1320)</url>
- </p>
- </item>
- <item>
- <p>Hmac functions - <url href="http://www.ietf.org/rfc/rfc2104.txt"> Keyed-Hashing for Message Authentication (RFC 2104) </url></p>
- </item>
- <item>
- <p>Cmac functions - <url href="http://www.ietf.org/rfc/rfc4493.txt">The AES-CMAC Algorithm (RFC 4493)</url></p>
- </item>
- <item>
- <p>Block ciphers - <url href="http://csrc.nist.gov/groups/ST/toolkit/block_ciphers.html"> </url> DES and AES in
- Block Cipher Modes - <url href="http://csrc.nist.gov/groups/ST/toolkit/BCM/index.html"> ECB, CBC, CFB, OFB, CTR and GCM </url></p>
- </item>
- <item>
- <p><url href="http://www.ietf.org/rfc/rfc1321.txt"> RSA encryption RFC 1321 </url> </p>
- </item>
- <item>
- <p>Digital signatures <url href="http://csrc.nist.gov/publications/drafts/fips186-3/fips_186-3.pdf">Digital Signature Standard (DSS)</url> and<url href="http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf"> Elliptic Curve Digital
- Signature Algorithm (ECDSA) </url> </p>
- </item>
- <item>
- <p><url href="http://www.ietf.org/rfc/rfc2945.txt"> Secure Remote Password Protocol (SRP - RFC 2945) </url></p>
- </item>
- <item>
- <p>gcm: Dworkin, M., "Recommendation for Block Cipher Modes of
- Operation: Galois/Counter Mode (GCM) and GMAC",
- National Institute of Standards and Technology SP 800-
- 38D, November 2007.</p>
- </item>
- </list>
- </description>
+ <taglist>
+ <tag>Hash functions</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>SHA1, SHA2</tag>
+ <item>
+ <url href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">
+ Secure Hash Standard [FIPS PUB 180-4]
+ </url>
+ </item>
+ <tag>SHA3</tag>
+ <item>
+ <url href="https://www.nist.gov/publications/sha-3-standard-permutation-based-hash-and-extendable-output-functions?pub_id=919061">
+ SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions [FIPS PUB 202]
+ </url>
+ </item>
+ <tag>MD5</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc1321.txt">The MD5 Message Digest Algorithm [RFC 1321]</url>
+ </item>
+ <tag>MD4</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc1320.txt">The MD4 Message Digest Algorithm [RFC 1320]</url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>MACs - Message Authentication Codes</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>Hmac functions</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc2104.txt">
+ Keyed-Hashing for Message Authentication [RFC 2104]
+ </url>
+ </item>
+ <tag>Cmac functions</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc4493.txt">
+ The AES-CMAC Algorithm [RFC 4493]
+ </url>
+ </item>
+ <tag>POLY1305</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Symmetric Ciphers</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>DES, 3DES and AES</tag>
+ <item>
+ <url href="https://csrc.nist.gov/projects/block-cipher-techniques">Block Cipher Techniques [NIST]</url>
+ </item>
+ <tag>Blowfish</tag>
+ <item>
+ <url href="https://www.schneier.com/academic/archives/1994/09/description_of_a_new.html">
+ Fast Software Encryption, Cambridge Security Workshop Proceedings (December 1993), Springer-Verlag, 1994, pp. 191-204.
+ </url>
+ </item>
+ <tag>Chacha20</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ <tag>Chacha20_poly1305</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Modes</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>ECB, CBC, CFB, OFB and CTR</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/sp/800-38a/final">
+ Recommendation for Block Cipher Modes of Operation: Methods and Techniques [NIST SP 800-38A]
+ </url>
+ </item>
+ <tag>GCM</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/sp/800-38d/final">
+ Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC [NIST SP 800-38D]
+ </url>
+ </item>
+ <tag>CCM</tag>
+ <item>
+ <url href="https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38c.pdf">
+ Recommendation for Block Cipher Modes of Operation:
+ The CCM Mode for Authentication and Confidentiality [NIST SP 800-38C]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Asymetric Ciphers - Public Key Techniques</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>RSA</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc3447.txt">
+ PKCS #1: RSA Cryptography Specifications [RFC 3447]
+ </url>
+ </item>
+ <tag>DSS</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/fips/186/4/final">
+ Digital Signature Standard (DSS) [FIPS 186-4]
+ </url>
+ </item>
+ <tag>ECDSA</tag>
+ <item>
+ <url href="http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf">
+ Elliptic Curve Digital Signature Algorithm [ECDSA]
+ </url>
+ </item>
+ <tag>SRP</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc2945.txt">
+ The SRP Authentication and Key Exchange System [RFC 2945]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+ </taglist>
+
+ <note>
+ <p>The actual supported algorithms and features depends on their availability in the actual libcrypto used.
+ See the <seealso marker="crypto:crypto_app">crypto (App)</seealso> about dependencies.
+ </p>
+ <p>Enabling FIPS mode will also disable algorithms and features.
+ </p>
+ </note>
- <section>
- <title>DATA TYPES </title>
+ <p>The <seealso marker="users_guide">CRYPTO User's Guide</seealso> has more information on
+ FIPS, Engines and Algorithm Details like key lengths.
+ </p>
+ </description>
- <code>key_value() = integer() | binary() </code>
- <p>Always <c>binary()</c> when used as return value</p>
+ <datatypes>
+ <datatype_title>Ciphers</datatype_title>
+ <datatype>
+ <name name="stream_cipher"/>
+ <desc>
+ <p>Stream ciphers for
+ <seealso marker="#stream_encrypt-2">stream_encrypt/2</seealso> and
+ <seealso marker="#stream_decrypt-2">stream_decrypt/2</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_public() = [key_value()] = [E, N] </code>
- <p> Where E is the public exponent and N is public modulus. </p>
+ <datatype>
+ <name name="block_cipher_with_iv"/>
+ <name name="cbc_cipher"/>
+ <name name="cfb_cipher"/>
+ <desc>
+ <p>Block ciphers with initialization vector for
+ <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] </code>
- <p>Where E is the public exponent, N is public modulus and D is
- the private exponent. The longer key format contains redundant
- information that will make the calculation faster. P1,P2 are first
- and second prime factors. E1,E2 are first and second exponents. C
- is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p>
+ <datatype>
+ <name name="block_cipher_without_iv"/>
+ <name name="ecb_cipher"/>
+ <desc>
+ <p>Block ciphers without initialization vector for
+ <seealso marker="#block_encrypt-3">block_encrypt/3</seealso> and
+ <seealso marker="#block_decrypt-3">block_decrypt/3</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>dss_public() = [key_value()] = [P, Q, G, Y] </code>
- <p>Where P, Q and G are the dss parameters and Y is the public key.</p>
+ <datatype>
+ <name name="aead_cipher"/>
+ <desc>
+ <p>Ciphers with simultaneous MAC-calculation or MAC-checking.
+ <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>dss_private() = [key_value()] = [P, Q, G, X] </code>
- <p>Where P, Q and G are the dss parameters and X is the private key.</p>
+ <datatype_title>Digests</datatype_title>
+ <datatype>
+ <name name="sha1"/>
+ <name name="sha2"/>
+ <name name="sha3"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>srp_public() = key_value() </code>
- <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ <datatype>
+ <name name="compatibility_only_hash"/>
+ <desc>
+ <p>The <c>compatibility_only_hash()</c> algorithms are recommended only for compatibility with existing applications.</p>
+ </desc>
+ </datatype>
- <code>srp_private() = key_value() </code>
- <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ <datatype>
+ <name name="rsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is
- <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url>
- Version = '3' | '6' | '6a'
- </p>
+ <datatype>
+ <name name="dss_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_public() = key_value() </code>
+ <datatype>
+ <name name="ecdsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_private() = key_value() </code>
+ <datatype_title>Elliptic Curves</datatype_title>
+ <datatype>
+ <name name="ec_named_curve"/>
+ <name name="edwards_curve_dh"/>
+ <name name="edwards_curve_ed"/>
+ <desc>
+ <p>Note that some curves are disabled if FIPS is enabled.</p>
+ </desc>
+ </datatype>
- <code>dh_params() = [key_value()] = [P, G] | [P, G, PrivateKeyBitLength]</code>
+ <datatype>
+ <name name="ec_explicit_curve"/>
+ <name name="ec_field"/>
+ <name name="ec_curve"/>
+ <desc>
+ <p>Parametric curve definition.</p>
+ </desc>
+ </datatype>
- <code>ecdh_public() = key_value() </code>
+ <datatype>
+ <name name="ec_prime_field"/>
+ <name name="ec_characteristic_two_field"/>
+ <name name="ec_basis"/>
+ <desc>
+ <p>Curve definition details.</p>
+ </desc>
+ </datatype>
- <code>ecdh_private() = key_value() </code>
+ <datatype_title>Keys</datatype_title>
+ <datatype>
+ <name name="key"/>
+ <name name="des3_key"/>
+ <desc>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
+ <p>A key for des3 is a list of three iolists</p>
+ </desc>
+ </datatype>
- <code>ecdh_params() = ec_named_curve() | ec_explicit_curve()</code>
+ <datatype>
+ <name name="key_integer"/>
+ <desc>
+ <p>Always <c>binary()</c> when used as return value</p>
+ </desc>
+ </datatype>
- <code>ec_explicit_curve() =
- {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(),
- CoFactor :: none | integer()} </code>
+ <datatype_title>Public/Private Keys</datatype_title>
+ <datatype>
+ <name name="rsa_public"/>
+ <name name="rsa_private"/>
+ <name name="rsa_params"/>
+ <desc>
+ <code>rsa_public() = [E, N]</code>
+ <code>rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]</code>
+ <p>Where E is the public exponent, N is public modulus and D is
+ the private exponent. The longer key format contains redundant
+ information that will make the calculation faster. P1,P2 are first
+ and second prime factors. E1,E2 are first and second exponents. C
+ is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p>
+ </desc>
+ </datatype>
- <code>ec_field() = {prime_field, Prime :: integer()} |
- {characteristic_two_field, M :: integer(), Basis :: ec_basis()}</code>
+ <datatype>
+ <name name="dss_public"/>
+ <name name="dss_private"/>
+ <desc>
+ <code>dss_public() = [P, Q, G, Y] </code>
+ <p>Where P, Q and G are the dss parameters and Y is the public key.</p>
- <code>ec_basis() = {tpbasis, K :: non_neg_integer()} |
- {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} |
- onbasis</code>
+ <code>dss_private() = [P, Q, G, X] </code>
+ <p>Where P, Q and G are the dss parameters and X is the private key.</p>
+ </desc>
+ </datatype>
- <code>ec_named_curve() ->
- sect571r1| sect571k1| sect409r1| sect409k1| secp521r1| secp384r1| secp224r1| secp224k1|
- secp192k1| secp160r2| secp128r2| secp128r1| sect233r1| sect233k1| sect193r2| sect193r1|
- sect131r2| sect131r1| sect283r1| sect283k1| sect163r2| secp256k1| secp160k1| secp160r1|
- secp112r2| secp112r1| sect113r2| sect113r1| sect239k1| sect163r1| sect163k1| secp256r1|
- secp192r1|
- brainpoolP160r1| brainpoolP160t1| brainpoolP192r1| brainpoolP192t1| brainpoolP224r1|
- brainpoolP224t1| brainpoolP256r1| brainpoolP256t1| brainpoolP320r1| brainpoolP320t1|
- brainpoolP384r1| brainpoolP384t1| brainpoolP512r1| brainpoolP512t1
- </code>
- <p>Note that the <em>sect</em> curves are GF2m (characteristic two) curves and are only supported if the
- underlying OpenSSL has support for them.
- See also <seealso marker="#supports-0">crypto:supports/0</seealso>
- </p>
+ <datatype>
+ <name name="ecdsa_public"/>
+ <name name="ecdsa_private"/>
+ <name name="ecdsa_params"/>
+ <desc>
+ </desc>
+ </datatype>
- <marker id="type-engine_key_ref"/>
- <marker id="engine_key_ref_type"/>
- <code>engine_key_ref() = #{engine := engine_ref(),
- key_id := key_id(),
- password => password()}</code>
+ <datatype>
+ <name name="eddsa_public"/>
+ <name name="eddsa_private"/>
+ <name name="eddsa_params"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>engine_ref() = term()</code>
- <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>.
- </p>
+ <datatype>
+ <name name="srp_public"/>
+ <name name="srp_private"/>
+ <desc>
+ <code>srp_public() = key_integer() </code>
+ <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+
+ <code>srp_private() = key_integer() </code>
+ <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ </desc>
+ </datatype>
- <code>key_id() = string() | binary()</code>
- <p>Identifies the key to be used. The format depends on the loaded engine. It is passed to
- the <c>ENGINE_load_(private|public)_key</c> functions in libcrypto.
- </p>
+ <datatype>
+ <name name="srp_gen_params"/>
+ <name name="srp_comp_params"/>
+ <desc>
+ <marker id="type-srp_user_gen_params"/>
+ <code>srp_user_gen_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom()]</code>
+ <marker id="type-srp_host_gen_params"/>
+ <code>srp_host_gen_params() = [Verifier::binary(), Prime::binary(), Version::atom() ]</code>
+ <marker id="type-srp_user_comp_params"/>
+ <code>srp_user_comp_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | ScramblerArg::list()]</code>
+ <marker id="type-srp_host_comp_params"/>
+ <code>srp_host_comp_params() = [Verifier::binary(), Prime::binary(), Version::atom() | ScramblerArg::list()]</code>
+ <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is
+ <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ Version = '3' | '6' | '6a'
+ </p>
+ </desc>
+ </datatype>
- <code>password() = string() | binary()</code>
- <p>The key's password
- </p>
+ <datatype_title>Public Key Ciphers</datatype_title>
- <code>stream_cipher() = rc4 | aes_ctr </code>
+ <datatype>
+ <name name="pk_encrypt_decrypt_algs"/>
+ <desc>
+ <p>Algorithms for public key encrypt/decrypt. Only RSA is supported.</p>
+ </desc>
+ </datatype>
- <code>block_cipher() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
- blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc </code>
+ <datatype>
+ <name name="pk_encrypt_decrypt_opts"/>
+ <name name="rsa_opt"/>
+ <name name="rsa_padding"/>
+ <desc>
+ <p>Options for public key encrypt/decrypt. Only RSA is supported.</p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ </desc>
+ </datatype>
- <code>aead_cipher() = aes_gcm | chacha20_poly1305 </code>
+ <datatype>
+ <name name="rsa_compat_opts"/>
+ <desc>
+ <p>Those option forms are kept only for compatibility and should not be used in new code.</p>
+ </desc>
+ </datatype>
- <code>stream_key() = aes_key() | rc4_key() </code>
+ <datatype_title>Public Key Sign and Verify</datatype_title>
- <code>block_key() = aes_key() | blowfish_key() | des_key()| des3_key() </code>
+ <datatype>
+ <name name="pk_sign_verify_algs"/>
+ <desc>
+ <p>Algorithms for sign and verify.</p>
+ </desc>
+ </datatype>
- <code>aes_key() = iodata() </code> <p>Key length is 128, 192 or 256 bits</p>
+ <datatype>
+ <name name="pk_sign_verify_opts"/>
+ <name name="rsa_sign_verify_opt"/>
+ <name name="rsa_sign_verify_padding"/>
+ <desc>
+ <p>Options for sign and verify.</p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ </desc>
+ </datatype>
- <code>rc4_key() = iodata() </code> <p>Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)</p>
+ <datatype_title>Diffie-Hellman Keys and parameters</datatype_title>
+ <datatype>
+ <name name="dh_public"/>
+ <name name="dh_private"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>blowfish_key() = iodata() </code> <p>Variable key length from 32 bits up to 448 bits</p>
+ <datatype>
+ <name name="dh_params"/>
+ <desc>
+ <code>dh_params() = [P, G] | [P, G, PrivateKeyBitLength]</code>
+ </desc>
+ </datatype>
- <code>des_key() = iodata() </code> <p>Key length is 64 bits (in CBC mode only 8 bits are used)</p>
+ <datatype>
+ <name name="ecdh_public"/>
+ <name name="ecdh_private"/>
+ <name name="ecdh_params"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>des3_key() = [binary(), binary(), binary()] </code> <p>Each key part is 64 bits (in CBC mode only 8 bits are used)</p>
+ <datatype_title>Types for Engines</datatype_title>
- <code>digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512</code>
+ <datatype>
+ <name name="engine_key_ref"/>
+ <name name="engine_ref"/>
+ <desc>
+ <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_digest_type() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</code>
+ <datatype>
+ <name name="key_id"/>
+ <desc>
+ <p>Identifies the key to be used. The format depends on the loaded engine. It is passed to
+ the <c>ENGINE_load_(private|public)_key</c> functions in libcrypto.
+ </p>
+ </desc>
+ </datatype>
- <code>dss_digest_type() = sha | sha224 | sha256 | sha384 | sha512</code> <p>Note that the actual supported
- dss_digest_type depends on the underlying crypto library. In OpenSSL version >= 1.0.1 the listed digest are supported, while in 1.0.0 only sha, sha224 and sha256 are supported. In version 0.9.8 only sha is supported.</p>
+ <datatype>
+ <name name="password"/>
+ <desc>
+ <p>The password of the key stored in an engine.
+ </p>
+ </desc>
+ </datatype>
- <code>ecdsa_digest_type() = sha | sha224 | sha256 | sha384 | sha512</code>
+ <datatype>
+ <name name="engine_method_type"/>
+ </datatype>
- <code>sign_options() = [{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}]</code>
+ <datatype>
+ <name name="engine_cmnd"/>
+ <desc>
+ <p>Pre and Post commands for <seealso marker="#engine_load-3">engine_load/3 and /4</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_sign_padding() = rsa_pkcs1_padding | rsa_pkcs1_pss_padding</code>
+ <datatype_title>Internal data types</datatype_title>
- <code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 </code> <p>md4 is also supported for hash_init/1 and hash/2.
- Note that both md4 and md5 are recommended only for compatibility with existing applications.
- </p>
- <code> cipher_algorithms() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ctr | aes_gcm |
- aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20_poly1305 | des_cbc |
- des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc | rc4 </code>
- <code> mac_algorithms() = hmac | cmac</code>
- <code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code>
- <p>Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported
- with ecdsa and ecdh.
- </p>
- <code>engine_method_type() = engine_method_rsa | engine_method_dsa | engine_method_dh |
- engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
- engine_method_ciphers | engine_method_digests | engine_method_store |
- engine_method_pkey_meths | engine_method_pkey_asn1_meths</code>
+ <datatype>
+ <name name="stream_state"/>
+ <name name="hmac_state"/>
+ <name name="hash_state"/>
+ <desc>
+ <p>Contexts with an internal state that should not be manipulated but passed between function calls.
+ </p>
+ </desc>
+ </datatype>
- </section>
+ </datatypes>
+ <!--================ FUNCTIONS ================-->
<funcs>
<func>
- <name>block_encrypt(Type, Key, PlainText) -> CipherText</name>
+ <name name="block_encrypt" arity="3" since="OTP 18.0"/>
<fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary>
- <type>
- <v>Type = des_ecb | blowfish_ecb | aes_ecb </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
- </type>
<desc>
- <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>block_decrypt(Type, Key, CipherText) -> PlainText</name>
+ <name name="block_decrypt" arity="3" since="OTP 18.0"/>
<fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary>
- <type>
- <v>Type = des_ecb | blowfish_ecb | aes_ecb </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
- </type>
<desc>
<p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>block_encrypt(Type, Key, Ivec, PlainText) -> CipherText</name>
- <name>block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag}</name>
- <name>block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name>
+ <name since="OTP R16B01">block_encrypt(Type, Key, Ivec, PlainText) -> CipherText</name>
+ <name since="OTP R16B01">block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag}</name>
+ <name since="OTP R16B01">block_encrypt(aes_gcm | aes_ccm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name>
<fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary>
<type>
- <v>Type = block_cipher() </v>
- <v>AeadType = aead_cipher() </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
+ <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v>
+ <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v>
+ <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v>
+ <v>PlainText = iodata()</v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
<v>TagLength = 1..16</v>
</type>
@@ -257,20 +568,23 @@
<p>In AEAD (Authenticated Encryption with Associated Data) mode, encrypt
<c>PlainText</c>according to <c>Type</c> block cipher and calculate
<c>CipherTag</c> that also authenticates the <c>AAD</c> (Associated Authenticated Data).</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>block_decrypt(Type, Key, Ivec, CipherText) -> PlainText</name>
- <name>block_decrypt(AeadType, Key, Ivec, {AAD, CipherText, CipherTag}) -> PlainText | error</name>
+ <name since="OTP R16B01">block_decrypt(Type, Key, Ivec, CipherText) -> PlainText</name>
+ <name since="OTP R16B01">block_decrypt(AeadType, Key, Ivec, {AAD, CipherText, CipherTag}) -> PlainText | error</name>
<fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary>
<type>
- <v>Type = block_cipher() </v>
- <v>AeadType = aead_cipher() </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
+ <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v>
+ <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v>
+ <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v>
+ <v>PlainText = iodata()</v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
</type>
<desc>
@@ -280,19 +594,17 @@
<c>CipherText</c>according to <c>Type</c> block cipher and check the authenticity
the <c>PlainText</c> and <c>AAD</c> (Associated Authenticated Data) using the
<c>CipherTag</c>. May return <c>error</c> if the decryption or validation fail's</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>bytes_to_integer(Bin) -> Integer </name>
+ <name name="bytes_to_integer" arity="1" since="OTP R16B01"/>
<fsummary>Convert binary representation, of an integer, to an Erlang integer.</fsummary>
- <type>
- <v>Bin = binary() - as returned by crypto functions</v>
-
- <v>Integer = integer() </v>
- </type>
<desc>
<p>Convert binary representation, of an integer, to an Erlang integer.
</p>
@@ -300,17 +612,8 @@
</func>
<func>
- <name>compute_key(Type, OthersPublicKey, MyKey, Params) -> SharedSecret</name>
+ <name name="compute_key" arity="4" since="OTP R16B01"/>
<fsummary>Computes the shared secret</fsummary>
- <type>
- <v> Type = dh | ecdh | srp </v>
- <v>OthersPublicKey = dh_public() | ecdh_public() | srp_public() </v>
- <v>MyKey = dh_private() | ecdh_private() | {srp_public(),srp_private()}</v>
- <v>Params = dh_params() | ecdh_params() | SrpUserParams | SrpHostParams</v>
- <v>SrpUserParams = {user, [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | [Scrambler:binary()]]} </v>
- <v>SrpHostParams = {host, [Verifier::binary(), Prime::binary(), Version::atom() | [Scrambler::binary]]} </v>
- <v>SharedSecret = binary()</v>
- </type>
<desc>
<p>Computes the shared secret from the private key and the other party's public key.
See also <seealso marker="public_key:public_key#compute_key-2">public_key:compute_key/2</seealso>
@@ -319,85 +622,61 @@
</func>
<func>
- <name>exor(Data1, Data2) -> Result</name>
+ <name name="exor" arity="2" since=""/>
<fsummary>XOR data</fsummary>
- <type>
- <v>Data1, Data2 = iodata()</v>
- <v>Result = binary()</v>
- </type>
<desc>
<p>Performs bit-wise XOR (exclusive or) on the data supplied.</p>
</desc>
</func>
- <func>
- <name>generate_key(Type, Params) -> {PublicKey, PrivKeyOut} </name>
- <name>generate_key(Type, Params, PrivKeyIn) -> {PublicKey, PrivKeyOut} </name>
+
+ <func>
+ <name name="generate_key" arity="2" since="OTP R16B01"/>
+ <name name="generate_key" arity="3" since="OTP R16B01"/>
<fsummary>Generates a public key of type <c>Type</c></fsummary>
- <type>
- <v> Type = dh | ecdh | rsa | srp </v>
- <v>Params = dh_params() | ecdh_params() | RsaParams | SrpUserParams | SrpHostParams </v>
- <v>RsaParams = {ModulusSizeInBits::integer(), PublicExponent::key_value()}</v>
- <v>SrpUserParams = {user, [Generator::binary(), Prime::binary(), Version::atom()]}</v>
- <v>SrpHostParams = {host, [Verifier::binary(), Generator::binary(), Prime::binary(), Version::atom()]}</v>
- <v>PublicKey = dh_public() | ecdh_public() | rsa_public() | srp_public() </v>
- <v>PrivKeyIn = undefined | dh_private() | ecdh_private() | srp_private() </v>
- <v>PrivKeyOut = dh_private() | ecdh_private() | rsa_private() | srp_private() </v>
- </type>
<desc>
<p>Generates a public key of type <c>Type</c>.
See also <seealso marker="public_key:public_key#generate_key-1">public_key:generate_key/1</seealso>.
- May throw exception an exception of class <c>error</c>:
+ May raise exception:
</p>
<list type="bulleted">
- <item><c>badarg</c>: an argument is of wrong type or has an illegal value,</item>
- <item><c>low_entropy</c>: the random generator failed due to lack of secure "randomness",</item>
- <item><c>computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item>
+ <item><c>error:badarg</c>: an argument is of wrong type or has an illegal value,</item>
+ <item><c>error:low_entropy</c>: the random generator failed due to lack of secure "randomness",</item>
+ <item><c>error:computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item>
</list>
<note>
<p>RSA key generation is only available if the runtime was
built with dirty scheduler support. Otherwise, attempting to
- generate an RSA key will throw exception <c>error:notsup</c>.</p>
+ generate an RSA key will raise exception <c>error:notsup</c>.</p>
</note>
</desc>
</func>
<func>
- <name>hash(Type, Data) -> Digest</name>
+ <name name="hash" arity="2" since="OTP R15B02"/>
<fsummary></fsummary>
- <type>
- <v>Type = md4 | hash_algorithms()</v>
- <v>Data = iodata()</v>
- <v>Digest = binary()</v>
- </type>
<desc>
<p>Computes a message digest of type <c>Type</c> from <c>Data</c>.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
<func>
- <name>hash_init(Type) -> Context</name>
+ <name name="hash_init" arity="1" since="OTP R15B02"/>
<fsummary></fsummary>
- <type>
- <v>Type = md4 | hash_algorithms()</v>
- </type>
<desc>
<p>Initializes the context for streaming hash operations. <c>Type</c> determines
which digest to use. The returned context should be used as argument
to <seealso marker="#hash_update-2">hash_update</seealso>.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
<func>
- <name>hash_update(Context, Data) -> NewContext</name>
+ <name name="hash_update" arity="2" since="OTP R15B02"/>
<fsummary></fsummary>
- <type>
- <v>Data = iodata()</v>
- </type>
<desc>
<p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using <seealso marker="#hash_init-1">hash_init</seealso>
@@ -406,12 +685,10 @@
or <seealso marker="#hash_final-1">hash_final</seealso>.</p>
</desc>
</func>
+
<func>
- <name>hash_final(Context) -> Digest</name>
+ <name name="hash_final" arity="1" since="OTP R15B02"/>
<fsummary></fsummary>
- <type>
- <v>Digest = binary()</v>
- </type>
<desc>
<p>Finalizes the hash operation referenced by <c>Context</c> returned
from a previous call to <seealso marker="#hash_update-2">hash_update</seealso>.
@@ -421,16 +698,9 @@
</func>
<func>
- <name>hmac(Type, Key, Data) -> Mac</name>
- <name>hmac(Type, Key, Data, MacLength) -> Mac</name>
+ <name name="hmac" arity="3" since="OTP R16B"/>
+ <name name="hmac" arity="4" since="OTP R16B"/>
<fsummary></fsummary>
- <type>
- <v>Type = hash_algorithms() - except ripemd160</v>
- <v>Key = iodata()</v>
- <v>Data = iodata()</v>
- <v>MacLength = integer()</v>
- <v>Mac = binary()</v>
- </type>
<desc>
<p>Computes a HMAC of type <c>Type</c> from <c>Data</c> using
<c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
@@ -439,13 +709,8 @@
</func>
<func>
- <name>hmac_init(Type, Key) -> Context</name>
+ <name name="hmac_init" arity="2" since="OTP R14B03"/>
<fsummary></fsummary>
- <type>
- <v>Type = hash_algorithms() - except ripemd160</v>
- <v>Key = iodata()</v>
- <v>Context = binary()</v>
- </type>
<desc>
<p>Initializes the context for streaming HMAC operations. <c>Type</c> determines
which hash function to use in the HMAC operation. <c>Key</c> is the authentication
@@ -454,12 +719,8 @@
</func>
<func>
- <name>hmac_update(Context, Data) -> NewContext</name>
+ <name name="hmac_update" arity="2" since="OTP R14B03"/>
<fsummary></fsummary>
- <type>
- <v>Context = NewContext = binary()</v>
- <v>Data = iodata()</v>
- </type>
<desc>
<p>Updates the HMAC represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using an HMAC init function (such as
@@ -472,16 +733,13 @@
call to hmac_update or hmac_final. The semantics of reusing old contexts
in any way is undefined and could even crash the VM in earlier releases.
The reason for this limitation is a lack of support in the underlying
- OpenSSL API.</p></warning>
+ libcrypto API.</p></warning>
</desc>
</func>
<func>
- <name>hmac_final(Context) -> Mac</name>
+ <name name="hmac_final" arity="1" since="OTP R14B03"/>
<fsummary></fsummary>
- <type>
- <v>Context = Mac = binary()</v>
- </type>
<desc>
<p>Finalizes the HMAC operation referenced by <c>Context</c>. The size of the resultant MAC is
determined by the type of hash function used to generate it.</p>
@@ -489,12 +747,8 @@
</func>
<func>
- <name>hmac_final_n(Context, HashLen) -> Mac</name>
+ <name name="hmac_final_n" arity="2" since="OTP R14B03"/>
<fsummary></fsummary>
- <type>
- <v>Context = Mac = binary()</v>
- <v>HashLen = non_neg_integer()</v>
- </type>
<desc>
<p>Finalizes the HMAC operation referenced by <c>Context</c>. <c>HashLen</c> must be greater than
zero. <c>Mac</c> will be a binary with at most <c>HashLen</c> bytes. Note that if HashLen is greater than the actual number of bytes returned from the underlying hash, the returned hash will have fewer than <c>HashLen</c> bytes.</p>
@@ -502,16 +756,9 @@
</func>
<func>
- <name>cmac(Type, Key, Data) -> Mac</name>
- <name>cmac(Type, Key, Data, MacLength) -> Mac</name>
+ <name name="cmac" arity="3" since="OTP 20.0"/>
+ <name name="cmac" arity="4" since="OTP 20.0"/>
<fsummary>Calculates the Cipher-based Message Authentication Code.</fsummary>
- <type>
- <v>Type = block_cipher()</v>
- <v>Key = iodata()</v>
- <v>Data = iodata()</v>
- <v>MacLength = integer()</v>
- <v>Mac = binary()</v>
- </type>
<desc>
<p>Computes a CMAC of type <c>Type</c> from <c>Data</c> using
<c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
@@ -520,20 +767,21 @@
</func>
<func>
- <name>info_fips() -> Status</name>
+ <name name="info_fips" arity="0" since="OTP 20.0"/>
<fsummary>Provides information about the FIPS operating status.</fsummary>
- <type>
- <v>Status = enabled | not_enabled | not_supported</v>
- </type>
<desc>
<p>Provides information about the FIPS operating status of
- crypto and the underlying OpenSSL library. If crypto was built
+ crypto and the underlying libcrypto library. If crypto was built
with FIPS support this can be either <c>enabled</c> (when
running in FIPS mode) or <c>not_enabled</c>. For other builds
- this value is always <c>not_supported</c>.</p>
+ this value is always <c>not_supported</c>.
+ </p>
+ <p>See <seealso marker="#enable_fips_mode-1">enable_fips_mode/1</seealso> about how to enable
+ FIPS mode.
+ </p>
<warning>
<p>In FIPS mode all non-FIPS compliant algorithms are
- disabled and throw exception <c>not_supported</c>. Check
+ disabled and raise exception <c>error:notsup</c>. Check
<seealso marker="#supports-0">supports</seealso> that in
FIPS mode returns the restricted list of available
algorithms.</p>
@@ -542,13 +790,23 @@
</func>
<func>
- <name>info_lib() -> [{Name,VerNum,VerStr}]</name>
+ <name name="enable_fips_mode" arity="1" since="OTP 21.1"/>
+ <fsummary>Change FIPS mode.</fsummary>
+ <desc>
+ <p>Enables (<c>Enable = true</c>) or disables (<c>Enable = false</c>) FIPS mode. Returns <c>true</c> if
+ the operation was successful or <c>false</c> otherwise.
+ </p>
+ <p>Note that to enable FIPS mode succesfully, OTP must be built with the configure option <c>--enable-fips</c>,
+ and the underlying libcrypto must also support FIPS.
+ </p>
+ <p>See also <seealso marker="#info_fips-0">info_fips/0</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="info_lib" arity="0" since=""/>
<fsummary>Provides information about the libraries used by crypto.</fsummary>
- <type>
- <v>Name = binary()</v>
- <v>VerNum = integer()</v>
- <v>VerStr = binary()</v>
- </type>
<desc>
<p>Provides the name and version of the libraries used by crypto.</p>
<p><c>Name</c> is the name of the library. <c>VerNum</c> is
@@ -561,52 +819,45 @@
<note><p>
From OTP R16 the <em>numeric version</em> represents the version of the OpenSSL
<em>header files</em> (<c>openssl/opensslv.h</c>) used when crypto was compiled.
- The text variant represents the OpenSSL library used at runtime.
+ The text variant represents the libcrypto library used at runtime.
In earlier OTP versions both numeric and text was taken from the library.
</p></note>
</desc>
</func>
<func>
- <name>mod_pow(N, P, M) -> Result</name>
+ <name name="mod_pow" arity="3" since="OTP R16B01"/>
<fsummary>Computes the function: N^P mod M</fsummary>
- <type>
- <v>N, P, M = binary() | integer()</v>
- <v>Result = binary() | error</v>
- </type>
<desc>
<p>Computes the function <c>N^P mod M</c>.</p>
</desc>
</func>
<func>
- <name>next_iv(Type, Data) -> NextIVec</name>
- <name>next_iv(Type, Data, IVec) -> NextIVec</name>
- <fsummary></fsummary>
- <type>
- <v>Type = des_cbc | des3_cbc | aes_cbc | des_cfb</v>
- <v>Data = iodata()</v>
- <v>IVec = NextIVec = binary()</v>
- </type>
- <desc>
- <p>Returns the initialization vector to be used in the next
- iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the
- encrypted data from the previous iteration step. The <c>IVec</c>
- argument is only needed for <c>des_cfb</c> as the vector used
- in the previous iteration step.</p>
- </desc>
+ <name name="next_iv" arity="2" since="OTP R16B01"/>
+ <name name="next_iv" arity="3" since="OTP R16B01"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Returns the initialization vector to be used in the next
+ iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the
+ encrypted data from the previous iteration step. The <c>IVec</c>
+ argument is only needed for <c>des_cfb</c> as the vector used
+ in the previous iteration step.</p>
+ </desc>
</func>
<func>
- <name>private_decrypt(Type, CipherText, PrivateKey, Padding) -> PlainText</name>
+ <name name="poly1305" arity="2" since="OTP 21.1"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Computes a POLY1305 message authentication code (<c>Mac</c>) from <c>Data</c> using
+ <c>Key</c> as the authentication key.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="private_decrypt" arity="4" since="OTP R16B01"/>
<fsummary>Decrypts CipherText using the private Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>CipherText = binary()</v>
- <v>PrivateKey = rsa_private() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seealso marker="#public_encrypt-4">public_encrypt/4</seealso> (or equivalent function)
@@ -619,34 +870,8 @@
</func>
<func>
- <name>privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey</name>
- <fsummary>Fetches a public key from an Engine stored private key.</fsummary>
- <type>
- <v>Type = rsa | dss</v>
- <v>EnginePrivateKeyRef = engine_key_ref()</v>
- <v>PublicKey = rsa_public() | dss_public()</v>
- </type>
- <desc>
- <p>Fetches the corresponding public key from a private key stored in an Engine.
- The key must be of the type indicated by the Type parameter.
- </p>
- </desc>
- </func>
-
- <func>
- <name>private_encrypt(Type, PlainText, PrivateKey, Padding) -> CipherText</name>
+ <name name="private_encrypt" arity="4" since="OTP R16B01"/>
<fsummary>Encrypts PlainText using the private Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PrivateKey = rsa_private() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
and returns the ciphertext. This is a low level signature operation
@@ -656,16 +881,10 @@
</p>
</desc>
</func>
+
<func>
- <name>public_decrypt(Type, CipherText, PublicKey, Padding) -> PlainText</name>
+ <name name="public_decrypt" arity="4" since="OTP R16B01"/>
<fsummary>Decrypts CipherText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>CipherText = binary()</v>
- <v>PublicKey = rsa_public() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seealso marker="#private_encrypt-4">private_encrypt/4</seealso>(or equivalent function)
@@ -678,19 +897,8 @@
</func>
<func>
- <name>public_encrypt(Type, PlainText, PublicKey, Padding) -> CipherText</name>
+ <name name="public_encrypt" arity="4" since="OTP R16B01"/>
<fsummary>Encrypts PlainText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PublicKey = rsa_public() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c>
and returns the <c>CipherText</c>. This is a low level signature operation
@@ -701,23 +909,20 @@
</func>
<func>
- <name>rand_seed(Seed) -> ok</name>
+ <name name="rand_seed" arity="1" since="OTP 17.0"/>
<fsummary>Set the seed for random bytes generation</fsummary>
- <type>
- <v>Seed = binary()</v>
- </type>
<desc>
<p>Set the seed for PRNG to the given binary. This calls the
RAND_seed function from openssl. Only use this if the system
you are running on does not have enough "randomness" built in.
Normally this is when
<seealso marker="#strong_rand_bytes/1">strong_rand_bytes/1</seealso>
- throws <c>low_entropy</c></p>
+ raises <c>error:low_entropy</c></p>
</desc>
</func>
<func>
- <name>rand_uniform(Lo, Hi) -> N</name>
+ <name since="">rand_uniform(Lo, Hi) -> N</name>
<fsummary>Generate a random number</fsummary>
<type>
<v>Lo, Hi, N = integer()</v>
@@ -730,36 +935,15 @@
</func>
<func>
- <name>sign(Algorithm, DigestType, Msg, Key) -> binary()</name>
- <name>sign(Algorithm, DigestType, Msg, Key, Options) -> binary()</name>
- <fsummary> Create digital signature.</fsummary>
- <type>
- <v>Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data to be
- signed or it is the hashed value of "cleartext" i.e. the
- digest (plaintext).</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Key = rsa_private() | dss_private() | [ecdh_private(),ecdh_params()] | engine_key_ref()</v>
- <v>Options = sign_options()</v>
- </type>
- <desc>
- <p>Creates a digital signature.</p>
- <p>Algorithm <c>dss</c> can only be used together with digest type
- <c>sha</c>.</p>
- <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name>start() -> ok</name>
+ <name name="start" arity="0" since=""/>
<fsummary> Equivalent to application:start(crypto). </fsummary>
<desc>
<p> Equivalent to application:start(crypto).</p>
</desc>
</func>
+
<func>
- <name>stop() -> ok</name>
+ <name name="stop" arity="0" since=""/>
<fsummary> Equivalent to application:stop(crypto).</fsummary>
<desc>
<p> Equivalent to application:stop(crypto).</p>
@@ -767,23 +951,20 @@
</func>
<func>
- <name>strong_rand_bytes(N) -> binary()</name>
+ <name name="strong_rand_bytes" arity="1" since="OTP R14B03"/>
<fsummary>Generate a binary of random bytes</fsummary>
- <type>
- <v>N = integer()</v>
- </type>
<desc>
<p>Generates N bytes randomly uniform 0..255, and returns the
result in a binary. Uses a cryptographically secure prng seeded and
periodically mixed with operating system provided entropy. By default
this is the <c>RAND_bytes</c> method from OpenSSL.</p>
- <p>May throw exception <c>low_entropy</c> in case the random generator
+ <p>May raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".</p>
</desc>
</func>
<func>
- <name>rand_seed() -> rand:state()</name>
+ <name name="rand_seed" arity="0" since="OTP 20.0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -799,7 +980,7 @@
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p><em>Example</em></p>
@@ -811,7 +992,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>rand_seed_s() -> rand:state()</name>
+ <name name="rand_seed_s" arity="0" since="OTP 20.0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -825,7 +1006,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<note>
@@ -846,7 +1027,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>rand_seed_alg(Alg) -> rand:state()</name>
+ <name since="OTP 21.0">rand_seed_alg(Alg) -> rand:state()</name>
<fsummary>Strong random number generation plugin state</fsummary>
<type>
<v>Alg = crypto | crypto_cache</v>
@@ -864,7 +1045,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p>
@@ -882,7 +1063,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>rand_seed_alg_s(Alg) -> rand:state()</name>
+ <name since="OTP 21.0">rand_seed_alg_s(Alg) -> rand:state()</name>
<fsummary>Strong random number generation plugin state</fsummary>
<type>
<v>Alg = crypto | crypto_cache</v>
@@ -909,7 +1090,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p>
@@ -940,45 +1121,36 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>stream_init(Type, Key) -> State</name>
+ <name name="stream_init" arity="2" since="OTP R16B01"/>
<fsummary></fsummary>
- <type>
- <v>Type = rc4 </v>
- <v>State = opaque() </v>
- <v>Key = iodata()</v>
- </type>
<desc>
<p>Initializes the state for use in RC4 stream encryption
<seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
<seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p>
+ <p>For keylengths see the
+ <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>stream_init(Type, Key, IVec) -> State</name>
+ <name name="stream_init" arity="3" since="OTP R16B01"/>
<fsummary></fsummary>
- <type>
- <v>Type = aes_ctr </v>
- <v>State = opaque() </v>
- <v>Key = iodata()</v>
- <v>IVec = binary()</v>
- </type>
<desc>
<p>Initializes the state for use in streaming AES encryption using Counter mode (CTR).
<c>Key</c> is the AES key and must be either 128, 192, or 256 bits long. <c>IVec</c> is
an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with
<seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
<seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p>
+ <p>For keylengths and iv-sizes see the
+ <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>stream_encrypt(State, PlainText) -> { NewState, CipherText}</name>
+ <name name="stream_encrypt" arity="2" since="OTP R16B01"/>
<fsummary></fsummary>
- <type>
- <v>Text = iodata()</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>Text</c> can be any number of bytes. The initial <c>State</c> is created using
@@ -988,12 +1160,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>stream_decrypt(State, CipherText) -> { NewState, PlainText }</name>
+ <name name="stream_decrypt" arity="2" since="OTP R16B01"/>
<fsummary></fsummary>
- <type>
- <v>CipherText = iodata()</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using
@@ -1003,60 +1171,57 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>supports() -> AlgorithmList </name>
+ <name name="supports" arity="0" since="OTP R16B01"/>
<fsummary>Provide a list of available crypto algorithms.</fsummary>
- <type>
- <v> AlgorithmList = [{hashs, [hash_algorithms()]},
- {ciphers, [cipher_algorithms()]},
- {public_keys, [public_key_algorithms()]},
- {macs, [mac_algorithms()]}]
- </v>
- </type>
<desc>
<p> Can be used to determine which crypto algorithms that are supported
- by the underlying OpenSSL library</p>
+ by the underlying libcrypto library</p>
+ <p>Note: the <c>rsa_opts</c> entry is in an experimental state and may change or be removed without notice.
+ No guarantee for the accuarcy of the rsa option's value list should be assumed.
+ </p>
</desc>
</func>
<func>
- <name>ec_curves() -> EllipticCurveList </name>
+ <name name="ec_curves" arity="0" since="OTP 17.0"/>
<fsummary>Provide a list of available named elliptic curves.</fsummary>
- <type>
- <v>EllipticCurveList = [ec_named_curve()]</v>
- </type>
<desc>
<p>Can be used to determine which named elliptic curves are supported.</p>
</desc>
</func>
<func>
- <name>ec_curve(NamedCurve) -> EllipticCurve </name>
+ <name name="ec_curve" arity="1" since="OTP 17.0"/>
<fsummary>Get the defining parameters of a elliptic curve.</fsummary>
- <type>
- <v>NamedCurve = ec_named_curve()</v>
- <v>EllipticCurve = ec_explicit_curve()</v>
- </type>
<desc>
<p>Return the defining parameters of a elliptic curve.</p>
</desc>
</func>
- <func>
- <name>verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean()</name>
- <name>verify(Algorithm, DigestType, Msg, Signature, Key, Options) -> boolean()</name>
+ <func>
+ <name name="sign" arity="4" since="OTP R16B01"/>
+ <name name="sign" arity="5" since="OTP 20.1"/>
+ <fsummary> Create digital signature.</fsummary>
+ <desc>
+ <p>Creates a digital signature.</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
+ <p>Algorithm <c>dss</c> can only be used together with digest type
+ <c>sha</c>.</p>
+ <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="verify" arity="5" since="OTP R16B01"/>
+ <name name="verify" arity="6" since="OTP 20.1"/>
<fsummary>Verifies a digital signature.</fsummary>
- <type>
- <v> Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data
- or it is the hashed value of "cleartext" i.e. the digest (plaintext).</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Signature = binary()</v>
- <v>Key = rsa_public() | dss_public() | [ecdh_public(),ecdh_params()] | engine_key_ref()</v>
- <v>Options = sign_options()</v>
- </type>
<desc>
<p>Verifies a digital signature</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
@@ -1066,17 +1231,24 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<!-- Engine functions -->
<func>
- <name>engine_get_all_methods() -> Result</name>
+ <name name="privkey_to_pubkey" arity="2" since="OTP 20.2"/>
+ <fsummary>Fetches a public key from an Engine stored private key.</fsummary>
+ <desc>
+ <p>Fetches the corresponding public key from a private key stored in an Engine.
+ The key must be of the type indicated by the Type parameter.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_all_methods" arity="0" since="OTP 20.2"/>
<fsummary>Return list of all possible engine methods</fsummary>
- <type>
- <v>Result = [EngineMethod::atom()]</v>
- </type>
<desc>
<p>
Returns a list of all possible engine methods.
</p>
- <p>
- May throw exception notsup in case there is
+ <p>
+ May raise exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1087,23 +1259,18 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_load(EngineId, PreCmds, PostCmds) -> Result</name>
+ <name name="engine_load" arity="3" since="OTP 20.2"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
- an engine handle. This function is the same as calling <c>engine_load/4</c> with
- <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ an engine handle. This function is the same as calling <c>engine_load/4</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1114,22 +1281,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_load(EngineId, PreCmds, PostCmds, EngineMethods) -> Result</name>
+ <name name="engine_load" arity="4" since="OTP 20.2"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>EngineMethods = [engine_method_type()]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
an engine handle. An error tuple is returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1140,20 +1301,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_unload(Engine) -> Result</name>
+ <name name="engine_unload" arity="1" since="OTP 20.2"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>Engine = term()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
- Unloads the OpenSSL engine given by <c>EngineId</c>.
+ Unloads the OpenSSL engine given by <c>Engine</c>.
An error tuple is returned if the engine can't be unloaded.
</p>
<p>
- The function throws a badarg if the parameter is in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1164,146 +1321,225 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_list() -> Result</name>
- <fsummary>List the known engine ids</fsummary>
- <type>
- <v>Result = [EngineId::unicode:chardata()]</v>
- </type>
+ <name name="engine_by_id" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Get a reference to an already loaded engine</fsummary>
<desc>
- <p>List the id's of all engines in OpenSSL's internal list.</p>
<p>
- It may also throw the exception notsup in case there is
+ Get a reference to an already loaded engine with <c>EngineId</c>.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
- See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
in the User's Guide.
</p>
</desc>
</func>
<func>
- <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> Result</name>
+ <name name="engine_ctrl_cmd_string" arity="3" since="OTP 20.2"/>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
- <type>
- <v>Engine = term()</v>
- <v>CmdName = unicode:chardata()</v>
- <v>CmdArg = unicode:chardata()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
- This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
+ This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
<c>Optional</c> set to <c>false</c>.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> Result</name>
+ <name name="engine_ctrl_cmd_string" arity="4" since="OTP 20.2"/>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
- <type>
- <v>Engine = term()</v>
- <v>CmdName = unicode:chardata()</v>
- <v>CmdArg = unicode:chardata()</v>
- <v>Optional = boolean()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
- <c>Optional</c> is a boolean argument that can relax the semantics of the function.
- If set to <c>true</c> it will only return failure if the ENGINE supported the given
- command name but failed while executing it, if the ENGINE doesn't support the command
- name it will simply return success without doing anything. In this case we assume
+ <c>Optional</c> is a boolean argument that can relax the semantics of the function.
+ If set to <c>true</c> it will only return failure if the ENGINE supported the given
+ command name but failed while executing it, if the ENGINE doesn't support the command
+ name it will simply return success without doing anything. In this case we assume
the user is only supplying commands specific to the given ENGINE so we set this to
<c>false</c>.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_add" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Add engine to OpenSSL internal list</fsummary>
+ <desc>
+ <p>Add the engine to OpenSSL's internal list.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_remove" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Remove engine to OpenSSL internal list</fsummary>
+ <desc>
+ <p>Remove the engine from OpenSSL's internal list.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_id" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Fetch engine ID</fsummary>
+ <desc>
+ <p>Return the ID for the engine, or an empty binary if there is no id set.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_name" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Fetch engine name</fsummary>
+ <desc>
+ <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_list" arity="0" since="OTP 20.2"/>
+ <fsummary>List the known engine ids</fsummary>
+ <desc>
+ <p>List the id's of all engines in OpenSSL's internal list.</p>
+ <p>
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ <p>
+ May raise exception <c>error:notsup</c> in case engine functionality is not supported by the underlying
+ OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_loaded" arity="2" since="OTP 21.0.6"/>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function is the same as calling <c>ensure_engine_loaded/3</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_loaded" arity="3" since="OTP 21.0.6"/>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function differs from the normal engine_load in that sense it
+ also add the engine id to the internal list in OpenSSL. Then in the following calls to the function
+ it just fetch the reference to the engine instead of loading it again.
+ An error tuple is returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_unloaded" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ This function is the same as calling <c>ensure_engine_unloaded/2</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_unloaded" arity="2" since="OTP 21.0.6"/>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
</desc>
</func>
</funcs>
- <!-- Maybe put this in the users guide -->
- <!-- <section> -->
- <!-- <title>DES in CBC mode</title> -->
- <!-- <p>The Data Encryption Standard (DES) defines an algorithm for -->
- <!-- encrypting and decrypting an 8 byte quantity using an 8 byte key -->
- <!-- (actually only 56 bits of the key is used). -->
- <!-- </p> -->
- <!-- <p>When it comes to encrypting and decrypting blocks that are -->
- <!-- multiples of 8 bytes various modes are defined (NIST SP -->
- <!-- 800-38A). One of those modes is the Cipher Block Chaining (CBC) -->
- <!-- mode, where the encryption of an 8 byte segment depend not only -->
- <!-- of the contents of the segment itself, but also on the result of -->
- <!-- encrypting the previous segment: the encryption of the previous -->
- <!-- segment becomes the initializing vector of the encryption of the -->
- <!-- current segment. -->
- <!-- </p> -->
- <!-- <p>Thus the encryption of every segment depends on the encryption -->
- <!-- key (which is secret) and the encryption of the previous -->
- <!-- segment, except the first segment which has to be provided with -->
- <!-- an initial initializing vector. That vector could be chosen at -->
- <!-- random, or be a counter of some kind. It does not have to be -->
- <!-- secret. -->
- <!-- </p> -->
- <!-- <p>The following example is drawn from the old FIPS 81 standard -->
- <!-- (replaced by NIST SP 800-38A), where both the plain text and the -->
- <!-- resulting cipher text is settled. The following code fragment -->
- <!-- returns `true'. -->
- <!-- </p> -->
- <!-- <pre><![CDATA[ -->
-
- <!-- Key = <<16#01,16#23,16#45,16#67,16#89,16#ab,16#cd,16#ef>>, -->
- <!-- IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>, -->
- <!-- P = "Now is the time for all ", -->
- <!-- C = crypto:des_cbc_encrypt(Key, IVec, P), -->
- <!-- % Which is the same as -->
- <!-- P1 = "Now is t", P2 = "he time ", P3 = "for all ", -->
- <!-- C1 = crypto:des_cbc_encrypt(Key, IVec, P1), -->
- <!-- C2 = crypto:des_cbc_encrypt(Key, C1, P2), -->
- <!-- C3 = crypto:des_cbc_encrypt(Key, C2, P3), -->
-
- <!-- C = <<C1/binary, C2/binary, C3/binary>>, -->
- <!-- C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c, -->
- <!-- 16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f, -->
- <!-- 16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>, -->
- <!-- <<"Now is the time for all ">> == -->
- <!-- crypto:des_cbc_decrypt(Key, IVec, C). -->
- <!-- ]]></pre> -->
- <!-- <p>The following is true for the DES CBC mode. For all -->
- <!-- decompositions <c>P1 ++ P2 = P</c> of a plain text message -->
- <!-- <c>P</c> (where the length of all quantities are multiples of 8 -->
- <!-- bytes), the encryption <c>C</c> of <c>P</c> is equal to <c>C1 ++ -->
- <!-- C2</c>, where <c>C1</c> is obtained by encrypting <c>P1</c> with -->
- <!-- <c>Key</c> and the initializing vector <c>IVec</c>, and where -->
- <!-- <c>C2</c> is obtained by encrypting <c>P2</c> with <c>Key</c> -->
- <!-- and the initializing vector <c>last8(C1)</c>, -->
- <!-- where <c>last(Binary)</c> denotes the last 8 bytes of the -->
- <!-- binary <c>Binary</c>. -->
- <!-- </p> -->
- <!-- <p>Similarly, for all decompositions <c>C1 ++ C2 = C</c> of a -->
- <!-- cipher text message <c>C</c> (where the length of all quantities -->
- <!-- are multiples of 8 bytes), the decryption <c>P</c> of <c>C</c> -->
- <!-- is equal to <c>P1 ++ P2</c>, where <c>P1</c> is obtained by -->
- <!-- decrypting <c>C1</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>IVec</c>, and where <c>P2</c> is obtained by decrypting -->
- <!-- <c>C2</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>last8(C1)</c>, where <c>last8(Binary)</c> is as above. -->
- <!-- </p> -->
- <!-- <p>For DES3 (which uses three 64 bit keys) the situation is the -->
- <!-- same. -->
- <!-- </p> -->
- <!-- </section> -->
+
</erlref>
diff --git a/lib/crypto/doc/src/engine_keys.xml b/lib/crypto/doc/src/engine_keys.xml
index 38714fed8a..5ac690eb90 100644
--- a/lib/crypto/doc/src/engine_keys.xml
+++ b/lib/crypto/doc/src/engine_keys.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2017</year><year>2017</year>
+ <year>2017</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -51,7 +51,7 @@
<p>
OTP/Crypto requires that the user provides two or three items of information about the key. The application used
by the user is usually on a higher level, for example in
- <seealso marker="ssl:ssl#key_option_def">SSL</seealso>. If using
+ <seealso marker="ssl:ssl#type-key">SSL</seealso>. If using
the crypto application directly, it is required that:
</p>
<list>
@@ -62,7 +62,7 @@
on the Engine loaded
</item>
<item>an Erlang map is constructed with the Engine reference, the key reference and possibly a key passphrase if
- needed by the Engine. See the <seealso marker="crypto:crypto#engine_key_ref_type">Reference Manual</seealso> for
+ needed by the Engine. See the <seealso marker="crypto:crypto#type-engine_key_ref">Reference Manual</seealso> for
details of the map.
</item>
</list>
diff --git a/lib/crypto/doc/src/engine_load.xml b/lib/crypto/doc/src/engine_load.xml
index e5c3f5d561..5f7ccc784b 100644
--- a/lib/crypto/doc/src/engine_load.xml
+++ b/lib/crypto/doc/src/engine_load.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2017</year><year>2017</year>
+ <year>2017</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,6 +42,9 @@
operations. The hardware implementation usually offers improved performance over its
software-based counterpart, which is known as cryptographic acceleration.
</p>
+ <note>
+ <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
+ </note>
</section>
<section>
@@ -54,9 +57,6 @@
<code>
1> {ok, Engine} = crypto:engine_load(&lt;&lt;"otp_test_engine">>, [], []).
{ok, #Ref}</code>
- <note>
- <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
- </note>
</section>
<section>
@@ -72,9 +72,6 @@
&lt;&lt;"LOAD">>],
[]).
{ok, #Ref}</code>
- <note>
- <p>The dynamic engine is not supported in LibreSSL from version 2.2.1</p>
- </note>
</section>
<section>
@@ -100,6 +97,28 @@ engine_method_pkey_meths, engine_method_pkey_asn1_meths].
</section>
<section>
+ <title>Load with the ensure loaded function</title>
+ <p>
+ This function makes sure the engine is loaded just once and the ID is added to the internal
+ engine list of OpenSSL. The following calls to the function will check if the ID is loaded
+ and then just get a new reference to the engine.
+ </p>
+ <code>
+ 5> {ok, Engine} = crypto:ensure_engine_loaded(&lt;&lt;"MD5">>,
+ &lt;&lt;"/some/path/otp_test_engine.so">>).
+ {ok, #Ref}</code>
+ <p>
+ To unload it use crypto:ensure_engine_unloaded/1 which removes the ID from the internal list
+ before unloading the engine.
+ </p>
+ <code>
+ 6> crypto:ensure_engine_unloaded(&lt;&lt;"MD5">>).
+ ok</code>
+ </section>
+
+
+
+ <section>
<title>List all engines currently loaded</title>
<code>
5> crypto:engine_list().
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 2e48b48d67..195c9d029d 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -31,6 +31,249 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 4.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed build link error on Windows. Unresolved symbol
+ 'bcmp'.</p>
+ <p>
+ Own Id: OTP-15750 Aux Id: ERL-905 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixes a bug that caused <c>crypto:sign</c> and
+ <c>crypto:verify</c> to return the error message
+ <c>badarg</c> instead of <c>notsup</c> in one case. That
+ case was when signing or verifying with eddsa keys (that
+ is, ed15519 or ed448), but only when FIPS was supported
+ and enabled.</p>
+ <p>
+ Own Id: OTP-15634</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added a crypto benchmark test suite.</p>
+ <p>
+ Own Id: OTP-15447</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Updated the RSA options part in the crypto application's
+ C-code, documentation and tests.</p>
+ <p>
+ Own Id: OTP-15302</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added ed25519 and ed448 sign/verify.</p>
+ <p>
+ Requires OpenSSL 1.1.1 or higher as cryptolib under the
+ OTP application <c>crypto</c>.</p>
+ <p>
+ Own Id: OTP-15419 Aux Id: OTP-15094 </p>
+ </item>
+ <item>
+ <p>
+ Fixed valgrind warnings.</p>
+ <p>
+ Own Id: OTP-15467</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.3.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The RSA options <c>rsa_mgf1_md</c>, <c>rsa_oaep_md</c>,
+ and <c>rsa_oaep_label</c> were always disabled. They will
+ now be enabled when a suitable cryptolib is used.</p>
+ <p>
+ They are still experimental and may change without prior
+ notice.</p>
+ <p>
+ Own Id: OTP-15212 Aux Id: ERL-675, PR1899, PR838 </p>
+ </item>
+ <item>
+ <p>
+ The ciphers <c>aes_ige256</c> and <c>blowfish_cbc</c> had
+ naming issues in <c>crypto:next_iv/2</c>.</p>
+ <p>
+ Own Id: OTP-15283</p>
+ </item>
+ <item>
+ <p>
+ the <c>RSA_SSLV23_PADDING</c> is disabled if LibreSSL is
+ used as cryptlib. This is due to compilation problems.</p>
+ <p>
+ This will be investigated further in the future.</p>
+ <p>
+ Own Id: OTP-15303</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The supported named elliptic curves are now reported in
+ <c>crypto:supports/0</c> in a new entry tagged by
+ <c>'curves'</c>.</p>
+ <p>
+ The function <c>crypto:ec_curves/0</c> is kept for
+ compatibility.</p>
+ <p>
+ Own Id: OTP-14717 Aux Id: OTP-15244 </p>
+ </item>
+ <item>
+ <p>
+ The typing in the CRYPTO and PUBLIC_KEY applications are
+ reworked and a few mistakes are corrected.</p>
+ <p>
+ The documentation is now generated from the typing and
+ some clarifications are made.</p>
+ <p>
+ A new chapter on Algorithm Details such as key sizes and
+ availability is added to the CRYPTO User's Guide.</p>
+ <p>
+ Own Id: OTP-15134</p>
+ </item>
+ <item>
+ <p>
+ Support for SHA3 both as a separate hash and in HMAC is
+ now available if OpenSSL 1.1.1 or higher is used as
+ cryptolib.</p>
+ <p>
+ Available lengths are reported in the <c>'hashs'</c>
+ entry in <c>crypto:supports/0</c> as <c>sha3_*</c>.</p>
+ <p>
+ Own Id: OTP-15153</p>
+ </item>
+ <item>
+ <p>
+ The mac algorithm <c>poly1305</c> and the cipher
+ algorithm <c>chacha20</c> are now supported if OpenSSL
+ 1.1.1 or higher is used as cryptolib.</p>
+ <p>
+ Own Id: OTP-15164 Aux Id: OTP-15209 </p>
+ </item>
+ <item>
+ <p>
+ The key exchange Edward curves <c>x25519</c> and
+ <c>x448</c> are now supported if OpenSSL 1.1.1 or higher
+ is used as cryptolib.</p>
+ <p>
+ Own Id: OTP-15240 Aux Id: OTP-15133 </p>
+ </item>
+ <item>
+ <p>
+ The supported RSA options for sign/verify and
+ encrypt/decrypt are now reported in
+ <c>crypto:supports/0</c> in a new entry tagged by
+ '<c>rsa_opts</c>'.</p>
+ <p>
+ The exakt set is still experimental and may change
+ without prior notice.</p>
+ <p>
+ Own Id: OTP-15260</p>
+ </item>
+ <item>
+ <p>
+ The cipher <c>aes_ccm</c> is added.</p>
+ <p>
+ Own Id: OTP-15286</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Update the crypto engine functions to handle multiple
+ loads of an engine. </p> <p><c>engine_load/3/4</c> is
+ updated so it doesn't add the engine ID to OpenSSLs
+ internal list of engines which makes it possible to run
+ the engine_load more than once if it doesn't contain
+ global data.</p> <p>Added <c>ensure_engine_loaded/2/3</c>
+ which guarantees that the engine just is loaded once and
+ the following calls just returns a reference to it. This
+ is done by add the ID to the internal OpenSSL list and
+ check if it is already registered when the function is
+ called.</p> <p>Added <c>ensure_engine_unloaded/1/2</c> to
+ unload engines loaded with ensure_engine_loaded.</p>
+ <p>Then some more utility functions are added.</p>
+ <p><c>engine_add/1</c>, adds the engine to OpenSSL
+ internal list</p> <p><c>engine_remove/1</c>, remove the
+ engine from OpenSSL internal list</p>
+ <p><c>engine_get_id/1</c>, fetch the engines id</p>
+ <p><c>engine_get_name/1</c>, fetch the engine name</p>
+ <p>
+ Own Id: OTP-15233</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a node crash in <c>crypto:compute_key(ecdh,
+ ...)</c> when passing a wrongly typed Others
+ argument.</p>
+ <p>
+ Own Id: OTP-15194 Aux Id: ERL-673 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -78,6 +321,22 @@
</section>
+<section><title>Crypto 4.2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a node crash in <c>crypto:compute_key(ecdh,
+ ...)</c> when passing a wrongly typed Others
+ argument.</p>
+ <p>
+ Own Id: OTP-15194 Aux Id: ERL-673 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/doc/src/specs.xml b/lib/crypto/doc/src/specs.xml
new file mode 100644
index 0000000000..66c79a906b
--- /dev/null
+++ b/lib/crypto/doc/src/specs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_crypto.xml"/>
+</specs>
diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml
index 0124121433..2dfc966609 100644
--- a/lib/crypto/doc/src/usersguide.xml
+++ b/lib/crypto/doc/src/usersguide.xml
@@ -50,4 +50,5 @@
<xi:include href="fips.xml"/>
<xi:include href="engine_load.xml"/>
<xi:include href="engine_keys.xml"/>
+ <xi:include href="algorithm_details.xml"/>
</part>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 714cba58b9..bc8b124b10 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -29,6 +29,7 @@
-export([generate_key/2, generate_key/3, compute_key/4]).
-export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([cmac/3, cmac/4]).
+-export([poly1305/2]).
-export([exor/2, strong_rand_bytes/1, mod_pow/3]).
-export([rand_seed/0, rand_seed_alg/1]).
-export([rand_seed_s/0, rand_seed_alg_s/1]).
@@ -51,17 +52,45 @@
engine_load/3,
engine_load/4,
engine_unload/1,
+ engine_by_id/1,
engine_list/0,
engine_ctrl_cmd_string/3,
- engine_ctrl_cmd_string/4
+ engine_ctrl_cmd_string/4,
+ engine_add/1,
+ engine_remove/1,
+ engine_get_id/1,
+ engine_get_name/1,
+ ensure_engine_loaded/2,
+ ensure_engine_loaded/3,
+ ensure_engine_unloaded/1,
+ ensure_engine_unloaded/2
]).
+-export_type([ %% A minimum exported: only what public_key needs.
+ dh_private/0,
+ dh_public/0,
+ dss_digest_type/0,
+ ec_named_curve/0,
+ ecdsa_digest_type/0,
+ pk_encrypt_decrypt_opts/0,
+ pk_sign_verify_opts/0,
+ rsa_digest_type/0,
+ sha1/0,
+ sha2/0
+ ]).
+
-export_type([engine_ref/0,
key_id/0,
password/0
]).
-
+%%% Opaque types must be exported :(
+-export_type([
+ stream_state/0,
+ hmac_state/0,
+ hash_state/0
+ ]).
+
%% Private. For tests.
-export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2, get_test_engine/0]).
@@ -73,16 +102,192 @@
%% Used by strong_rand_float/0
-define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53)
-%%-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'.
+
+%%% ===== BEGIN NEW TYPING ====
+
+%%% Basic
+-type key_integer() :: integer() | binary(). % Always binary() when used as return value
+
+%%% Keys
+-type rsa_public() :: [key_integer()] . % [E, N]
+-type rsa_private() :: [key_integer()] . % [E, N, D] | [E, N, D, P1, P2, E1, E2, C]
+-type rsa_params() :: {ModulusSizeInBits::integer(), PublicExponent::key_integer()} .
+
+-type dss_public() :: [key_integer()] . % [P, Q, G, Y]
+-type dss_private() :: [key_integer()] . % [P, Q, G, X]
+
+-type ecdsa_public() :: key_integer() .
+-type ecdsa_private() :: key_integer() .
+-type ecdsa_params() :: ec_named_curve() | ec_explicit_curve() .
+
+-type eddsa_public() :: key_integer() .
+-type eddsa_private() :: key_integer() .
+-type eddsa_params() :: edwards_curve_ed() .
+
+-type srp_public() :: key_integer() .
+-type srp_private() :: key_integer() .
+-type srp_gen_params() :: {user,srp_user_gen_params()} | {host,srp_host_gen_params()}.
+-type srp_comp_params() :: {user,srp_user_comp_params()} | {host,srp_host_comp_params()}.
+-type srp_user_gen_params() :: list(binary() | atom() | list()) .
+-type srp_host_gen_params() :: list(binary() | atom() | list()) .
+-type srp_user_comp_params() :: list(binary() | atom()) .
+-type srp_host_comp_params() :: list(binary() | atom()) .
+
+-type dh_public() :: key_integer() .
+-type dh_private() :: key_integer() .
+-type dh_params() :: [key_integer()] . % [P, G] | [P, G, PrivateKeyBitLength]
+
+-type ecdh_public() :: key_integer() .
+-type ecdh_private() :: key_integer() .
+-type ecdh_params() :: ec_named_curve() | edwards_curve_dh() | ec_explicit_curve() .
+
+
+%%% Curves
+
+-type ec_explicit_curve() :: {Field :: ec_field(),
+ Curve :: ec_curve(),
+ BasePoint :: binary(),
+ Order :: binary(),
+ CoFactor :: none | % FIXME: Really?
+ binary()
+ } .
+
+-type ec_curve() :: {A :: binary(),
+ B :: binary(),
+ Seed :: none | binary()
+ } .
+
+-type ec_field() :: ec_prime_field() | ec_characteristic_two_field() .
+
+-type ec_prime_field() :: {prime_field, Prime :: integer()} .
+-type ec_characteristic_two_field() :: {characteristic_two_field, M :: integer(), Basis :: ec_basis()} .
+
+-type ec_basis() :: {tpbasis, K :: non_neg_integer()}
+ | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()}
+ | onbasis .
+
+-type ec_named_curve() :: brainpoolP160r1
+ | brainpoolP160t1
+ | brainpoolP192r1
+ | brainpoolP192t1
+ | brainpoolP224r1
+ | brainpoolP224t1
+ | brainpoolP256r1
+ | brainpoolP256t1
+ | brainpoolP320r1
+ | brainpoolP320t1
+ | brainpoolP384r1
+ | brainpoolP384t1
+ | brainpoolP512r1
+ | brainpoolP512t1
+ | c2pnb163v1
+ | c2pnb163v2
+ | c2pnb163v3
+ | c2pnb176v1
+ | c2pnb208w1
+ | c2pnb272w1
+ | c2pnb304w1
+ | c2pnb368w1
+ | c2tnb191v1
+ | c2tnb191v2
+ | c2tnb191v3
+ | c2tnb239v1
+ | c2tnb239v2
+ | c2tnb239v3
+ | c2tnb359v1
+ | c2tnb431r1
+ | ipsec3
+ | ipsec4
+ | prime192v1
+ | prime192v2
+ | prime192v3
+ | prime239v1
+ | prime239v2
+ | prime239v3
+ | prime256v1
+ | secp112r1
+ | secp112r2
+ | secp128r1
+ | secp128r2
+ | secp160k1
+ | secp160r1
+ | secp160r2
+ | secp192k1
+ | secp192r1
+ | secp224k1
+ | secp224r1
+ | secp256k1
+ | secp256r1
+ | secp384r1
+ | secp521r1
+ | sect113r1
+ | sect113r2
+ | sect131r1
+ | sect131r2
+ | sect163k1
+ | sect163r1
+ | sect163r2
+ | sect193r1
+ | sect193r2
+ | sect233k1
+ | sect233r1
+ | sect239k1
+ | sect283k1
+ | sect283r1
+ | sect409k1
+ | sect409r1
+ | sect571k1
+ | sect571r1
+ | wtls1
+ | wtls10
+ | wtls11
+ | wtls12
+ | wtls3
+ | wtls4
+ | wtls5
+ | wtls6
+ | wtls7
+ | wtls8
+ | wtls9
+ .
+
+-type edwards_curve_dh() :: x25519 | x448 .
+
+-type edwards_curve_ed() :: ed25519 | ed448 .
+
+%%%
+-type block_cipher_with_iv() :: cbc_cipher()
+ | cfb_cipher()
+ | aes_cbc128
+ | aes_cbc256
+ | aes_ige256
+ | blowfish_ofb64
+ | des3_cbf % cfb misspelled
+ | des_ede3
+ | rc2_cbc .
+
+-type cbc_cipher() :: des_cbc | des3_cbc | aes_cbc | blowfish_cbc .
+-type aead_cipher() :: aes_gcm | aes_ccm | chacha20_poly1305 .
+-type cfb_cipher() :: aes_cfb128 | aes_cfb8 | blowfish_cfb64 | des3_cfb | des_cfb .
+
+-type block_cipher_without_iv() :: ecb_cipher() .
+-type ecb_cipher() :: des_ecb | blowfish_ecb | aes_ecb .
+
+-type key() :: iodata().
+-type des3_key() :: [key()].
+
+%%%
+-type rsa_digest_type() :: sha1() | sha2() | md5 | ripemd160 .
+-type dss_digest_type() :: sha1() | sha2() .
+-type ecdsa_digest_type() :: sha1() | sha2() .
+
+-type sha1() :: sha .
+-type sha2() :: sha224 | sha256 | sha384 | sha512 .
+-type sha3() :: sha3_224 | sha3_256 | sha3_384 | sha3_512 .
+
+-type compatibility_only_hash() :: md5 | md4 .
+
-type crypto_integer() :: binary() | integer().
-%%-type ec_named_curve() :: atom().
-%%-type ec_point() :: crypto_integer().
-%%-type ec_basis() :: {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis.
-%%-type ec_field() :: {prime_field, Prime :: integer()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}.
-%%-type ec_prime() :: {A :: crypto_integer(), B :: crypto_integer(), Seed :: binary() | none}.
-%%-type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: crypto_integer(), Order :: integer(), CoFactor :: none | integer()}.
-%%-type ec_curve() :: ec_named_curve() | ec_curve_spec().
-%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}.
-compile(no_native).
-on_load(on_load/0).
@@ -98,150 +303,240 @@ nif_stub_error(Line) ->
%% Crypto app version history:
%% (no version): Driver implementation
%% 2.0 : NIF implementation, requires OTP R14
+
+%% When generating documentation from crypto.erl, the macro ?CRYPTO_VSN is not defined.
+%% That causes the doc generation to stop...
+-ifndef(CRYPTO_VSN).
+-define(CRYPTO_VSN, "??").
+-endif.
version() -> ?CRYPTO_VSN.
+-spec start() -> ok | {error, Reason::term()}.
start() ->
application:start(crypto).
+-spec stop() -> ok | {error, Reason::term()}.
stop() ->
application:stop(crypto).
+-spec supports() -> [Support]
+ when Support :: {hashs, Hashs}
+ | {ciphers, Ciphers}
+ | {public_keys, PKs}
+ | {macs, Macs}
+ | {curves, Curves}
+ | {rsa_opts, RSAopts},
+ Hashs :: [sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash()],
+ Ciphers :: [stream_cipher()
+ | block_cipher_with_iv() | block_cipher_without_iv()
+ | aead_cipher()
+ ],
+ PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m],
+ Macs :: [hmac | cmac | poly1305],
+ Curves :: [ec_named_curve() | edwards_curve_dh() | edwards_curve_ed()],
+ RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] .
supports()->
- {Hashs, PubKeys, Ciphers, Macs, Curves} = algorithms(),
-
+ {Hashs, PubKeys, Ciphers, Macs, Curves, RsaOpts} = algorithms(),
[{hashs, Hashs},
{ciphers, Ciphers},
{public_keys, PubKeys},
- {macs, Macs}
- | case Curves of
- [] -> [];
- _ -> [{curves, Curves}] % Only show this experimental feature
- % if OpenSSL 1.1.1 beta4 or higher (where
- % eddsa and eddh is enabled)
- end
+ {macs, Macs},
+ {curves, Curves},
+ {rsa_opts, RsaOpts}
].
+-spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(),
+ VerNum :: integer(),
+ VerStr :: binary() .
info_lib() -> ?nif_stub.
-spec info_fips() -> not_supported | not_enabled | enabled.
info_fips() -> ?nif_stub.
--spec enable_fips_mode(boolean()) -> boolean().
-
+-spec enable_fips_mode(Enable) -> Result when Enable :: boolean(),
+ Result :: boolean().
enable_fips_mode(_) -> ?nif_stub.
--spec hash(_, iodata()) -> binary().
+%%%================================================================
+%%%
+%%% Hashing
+%%%
+%%%================================================================
-hash(Hash, Data0) ->
- Data = iolist_to_binary(Data0),
- MaxBytes = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
+-define(HASH_HASH_ALGORITHM, sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash() ).
--spec hash_init('md5'|'md4'|'ripemd160'|
- 'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
+-spec hash(Type, Data) -> Digest when Type :: ?HASH_HASH_ALGORITHM,
+ Data :: iodata(),
+ Digest :: binary().
+hash(Type, Data) ->
+ Data1 = iolist_to_binary(Data),
+ MaxBytes = max_bytes(),
+ hash(Type, Data1, erlang:byte_size(Data1), MaxBytes).
-hash_init(Hash) ->
- notsup_to_error(hash_init_nif(Hash)).
+-opaque hash_state() :: reference().
--spec hash_update(_, iodata()) -> any().
+-spec hash_init(Type) -> State when Type :: ?HASH_HASH_ALGORITHM,
+ State :: hash_state().
+hash_init(Type) ->
+ notsup_to_error(hash_init_nif(Type)).
-hash_update(State, Data0) ->
- Data = iolist_to_binary(Data0),
+-spec hash_update(State, Data) -> NewState when State :: hash_state(),
+ NewState :: hash_state(),
+ Data :: iodata() .
+hash_update(Context, Data) ->
+ Data1 = iolist_to_binary(Data),
MaxBytes = max_bytes(),
- hash_update(State, Data, erlang:byte_size(Data), MaxBytes).
+ hash_update(Context, Data1, erlang:byte_size(Data1), MaxBytes).
--spec hash_final(_) -> binary().
+-spec hash_final(State) -> Digest when State :: hash_state(),
+ Digest :: binary().
+hash_final(Context) ->
+ notsup_to_error(hash_final_nif(Context)).
-hash_final(State) ->
- notsup_to_error(hash_final_nif(State)).
+%%%================================================================
+%%%
+%%% MACs (Message Authentication Codes)
+%%%
+%%%================================================================
+%%%---- HMAC
--spec hmac(_, iodata(), iodata()) -> binary().
--spec hmac(_, iodata(), iodata(), integer()) -> binary().
--spec hmac_init(atom(), iodata()) -> binary().
--spec hmac_update(binary(), iodata()) -> binary().
--spec hmac_final(binary()) -> binary().
--spec hmac_final_n(binary(), integer()) -> binary().
+-define(HMAC_HASH_ALGORITHM, sha1() | sha2() | sha3() | compatibility_only_hash()).
-hmac(Type, Key, Data0) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()).
-hmac(Type, Key, Data0, MacSize) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac/3,4
+
+-spec hmac(Type, Key, Data) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary() .
+hmac(Type, Key, Data) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, undefined, erlang:byte_size(Data1), max_bytes()).
+
+-spec hmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary() .
+
+hmac(Type, Key, Data, MacLength) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, MacLength, erlang:byte_size(Data1), max_bytes()).
+%%%---- hmac_init, hamc_update, hmac_final
+
+-opaque hmac_state() :: binary().
+
+-spec hmac_init(Type, Key) ->
+ State when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ State :: hmac_state() .
hmac_init(Type, Key) ->
notsup_to_error(hmac_init_nif(Type, Key)).
+%%%---- hmac_update
+
+-spec hmac_update(State, Data) -> NewState when Data :: iodata(),
+ State :: hmac_state(),
+ NewState :: hmac_state().
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac_final
+
+-spec hmac_final(State) -> Mac when State :: hmac_state(),
+ Mac :: binary().
hmac_final(Context) ->
notsup_to_error(hmac_final_nif(Context)).
+
+-spec hmac_final_n(State, HashLen) -> Mac when State :: hmac_state(),
+ HashLen :: integer(),
+ Mac :: binary().
hmac_final_n(Context, HashLen) ->
notsup_to_error(hmac_final_nif(Context, HashLen)).
--spec cmac(_, iodata(), iodata()) -> binary().
--spec cmac(_, iodata(), iodata(), integer()) -> binary().
+%%%---- CMAC
+
+-define(CMAC_CIPHER_ALGORITHM, cbc_cipher() | cfb_cipher() | blowfish_cbc | des_ede3 | rc2_cbc ).
+-spec cmac(Type, Key, Data) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary().
cmac(Type, Key, Data) ->
notsup_to_error(cmac_nif(Type, Key, Data)).
-cmac(Type, Key, Data, MacSize) ->
- erlang:binary_part(cmac(Type, Key, Data), 0, MacSize).
-
-%% Ecrypt/decrypt %%%
-
--spec block_encrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()};
- (aes_gcm, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), TagLength::1..16}) -> {binary(), binary()}.
-
-block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
- Type =:= des_cfb;
- Type =:= blowfish_cbc;
- Type =:= blowfish_cfb64;
- Type =:= blowfish_ofb64;
- Type =:= aes_cbc128;
- Type =:= aes_cfb8;
- Type =:= aes_cfb128;
- Type =:= aes_cbc256;
- Type =:= aes_cbc;
- Type =:= rc2_cbc ->
- block_crypt_nif(Type, Key, Ivec, Data, true);
-block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
- Type =:= des_ede3 ->
+
+-spec cmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary().
+cmac(Type, Key, Data, MacLength) ->
+ erlang:binary_part(cmac(Type, Key, Data), 0, MacLength).
+
+%%%---- POLY1305
+
+-spec poly1305(iodata(), iodata()) -> Mac when Mac :: binary().
+
+poly1305(Key, Data) ->
+ poly1305_nif(Key, Data).
+
+%%%================================================================
+%%%
+%%% Encrypt/decrypt
+%%%
+%%%================================================================
+
+%%%---- Block ciphers
+
+-spec block_encrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata()}) ->
+ {binary(), binary()};
+ (aes_gcm | aes_ccm, Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata(), TagLength::1..16}) ->
+ {binary(), binary()}.
+
+block_encrypt(Type, Key, Ivec, PlainText) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= aes_cbc;
+ Type =:= rc2_cbc ->
+ notsup_to_error(block_crypt_nif(Type, Key, Ivec, PlainText, true));
+block_encrypt(Type, Key0, Ivec, PlainText) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true);
-block_encrypt(des3_cbf, Key0, Ivec, Data) ->
+ notsup_to_error(block_crypt_nif(des_ede3_cbc, Key, Ivec, PlainText, true));
+block_encrypt(des3_cbf, Key0, Ivec, PlainText) -> % cfb misspelled
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true);
-block_encrypt(des3_cfb, Key0, Ivec, Data) ->
+ notsup_to_error(block_crypt_nif(des_ede3_cbf, Key, Ivec, PlainText, true));
+block_encrypt(des3_cfb, Key0, Ivec, PlainText) ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, true);
-block_encrypt(aes_ige256, Key, Ivec, Data) ->
- notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, true));
-block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) ->
- aes_gcm_encrypt(Key, Ivec, AAD, Data);
-block_encrypt(aes_gcm, Key, Ivec, {AAD, Data, TagLength}) ->
- aes_gcm_encrypt(Key, Ivec, AAD, Data, TagLength);
-block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) ->
- chacha20_poly1305_encrypt(Key, Ivec, AAD, Data).
-
--spec block_decrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(),
+ notsup_to_error(block_crypt_nif(des_ede3_cfb, Key, Ivec, PlainText, true));
+block_encrypt(aes_ige256, Key, Ivec, PlainText) ->
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, PlainText, true));
+block_encrypt(Type, Key, Ivec, {AAD, PlainText}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText);
+block_encrypt(Type, Key, Ivec, {AAD, PlainText, TagLength}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText, TagLength);
+block_encrypt(chacha20_poly1305=Type, Key, Ivec, {AAD, PlainText}) ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText, 16).
+
+
+-spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(),
{AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error.
block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
Type =:= des_cfb;
@@ -254,36 +549,40 @@ block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
Type =:= aes_cfb128;
Type =:= aes_cbc256;
Type =:= rc2_cbc ->
- block_crypt_nif(Type, Key, Ivec, Data, false);
+ notsup_to_error(block_crypt_nif(Type, Key, Ivec, Data, false));
block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
Type =:= des_ede3 ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false);
-block_decrypt(des3_cbf, Key0, Ivec, Data) ->
+ notsup_to_error(block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false));
+block_decrypt(des3_cbf, Key0, Ivec, Data) -> % cfb misspelled
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false);
+ notsup_to_error(block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false));
block_decrypt(des3_cfb, Key0, Ivec, Data) ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, false);
+ notsup_to_error(block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, false));
block_decrypt(aes_ige256, Key, Ivec, Data) ->
notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
-block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) ->
- aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag);
-block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) ->
- chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag).
+block_decrypt(Type, Key, Ivec, {AAD, Data, Tag}) when Type =:= aes_gcm;
+ Type =:= aes_ccm;
+ Type =:= chacha20_poly1305 ->
+ aead_decrypt(Type, Key, Ivec, AAD, Data, Tag).
--spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
-block_encrypt(Type, Key, Data) ->
- block_crypt_nif(Type, Key, Data, true).
+-spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) -> binary().
--spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
+block_encrypt(Type, Key, PlainText) ->
+ notsup_to_error(block_crypt_nif(Type, Key, PlainText, true)).
+
+
+-spec block_decrypt(Type::block_cipher_without_iv(), Key::key(), Data::iodata()) -> binary().
block_decrypt(Type, Key, Data) ->
- block_crypt_nif(Type, Key, Data, false).
+ notsup_to_error(block_crypt_nif(Type, Key, Data, false)).
--spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary().
+-spec next_iv(Type:: cbc_cipher(), Data) -> NextIVec when % Type :: cbc_cipher(), %des_cbc | des3_cbc | aes_cbc | aes_ige,
+ Data :: iodata(),
+ NextIVec :: binary().
next_iv(Type, Data) when is_binary(Data) ->
IVecSize = case Type of
des_cbc -> 8;
@@ -296,7 +595,9 @@ next_iv(Type, Data) when is_binary(Data) ->
next_iv(Type, Data) when is_list(Data) ->
next_iv(Type, list_to_binary(Data)).
--spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
+-spec next_iv(des_cfb, Data, IVec) -> NextIVec when Data :: iodata(),
+ IVec :: binary(),
+ NextIVec :: binary().
next_iv(des_cfb, Data, IVec) ->
IVecAndData = list_to_binary([IVec, Data]),
@@ -305,38 +606,57 @@ next_iv(des_cfb, Data, IVec) ->
next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
+%%%---- Stream ciphers
+
+-opaque stream_state() :: {stream_cipher(), reference()}.
+
+-type stream_cipher() :: rc4 | aes_ctr | chacha20 .
+
+-spec stream_init(Type, Key, IVec) -> State when Type :: aes_ctr | chacha20,
+ Key :: iodata(),
+ IVec :: binary(),
+ State :: stream_state() .
stream_init(aes_ctr, Key, Ivec) ->
- {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
+ {aes_ctr, aes_ctr_stream_init(Key, Ivec)};
+stream_init(chacha20, Key, Ivec) ->
+ {chacha20, chacha20_stream_init(Key,Ivec)}.
+
+-spec stream_init(Type, Key) -> State when Type :: rc4,
+ Key :: iodata(),
+ State :: stream_state() .
stream_init(rc4, Key) ->
{rc4, notsup_to_error(rc4_set_key(Key))}.
+-spec stream_encrypt(State, PlainText) -> {NewState, CipherText}
+ when State :: stream_state(),
+ PlainText :: iodata(),
+ NewState :: stream_state(),
+ CipherText :: iodata() .
stream_encrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_encrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+-spec stream_decrypt(State, CipherText) -> {NewState, PlainText}
+ when State :: stream_state(),
+ CipherText :: iodata(),
+ NewState :: stream_state(),
+ PlainText :: iodata() .
stream_decrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
-%%
-%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
-%%
+
+%%%================================================================
+%%%
+%%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
+%%%
+%%%================================================================
-type rand_cache_seed() ::
nonempty_improper_list(non_neg_integer(), binary()).
--spec strong_rand_bytes(non_neg_integer()) -> binary().
--spec rand_seed() -> rand:state().
--spec rand_seed_s() -> rand:state().
--spec rand_seed_alg(Alg :: atom()) ->
- {rand:alg_handler(),
- atom() | rand_cache_seed()}.
--spec rand_seed_alg_s(Alg :: atom()) ->
- {rand:alg_handler(),
- atom() | rand_cache_seed()}.
--spec rand_uniform(crypto_integer(), crypto_integer()) ->
- crypto_integer().
+-spec strong_rand_bytes(N::non_neg_integer()) -> binary().
strong_rand_bytes(Bytes) ->
case strong_rand_bytes_nif(Bytes) of
false -> erlang:error(low_entropy);
@@ -345,16 +665,24 @@ strong_rand_bytes(Bytes) ->
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+-spec rand_seed() -> rand:state().
rand_seed() ->
rand:seed(rand_seed_s()).
+-spec rand_seed_s() -> rand:state().
rand_seed_s() ->
rand_seed_alg_s(?MODULE).
+-spec rand_seed_alg(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
rand_seed_alg(Alg) ->
rand:seed(rand_seed_alg_s(Alg)).
-define(CRYPTO_CACHE_BITS, 56).
+-spec rand_seed_alg_s(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
rand_seed_alg_s(?MODULE) ->
{#{ type => ?MODULE,
bits => 64,
@@ -412,7 +740,9 @@ strong_rand_float() ->
WholeRange = strong_rand_range(1 bsl 53),
?HALF_DBL_EPSILON * bytes_to_integer(WholeRange).
-rand_uniform(From,To) when is_binary(From), is_binary(To) ->
+-spec rand_uniform(crypto_integer(), crypto_integer()) ->
+ crypto_integer().
+rand_uniform(From, To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
<<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
<<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
@@ -447,116 +777,233 @@ rand_seed(Seed) when is_binary(Seed) ->
rand_seed_nif(_Seed) -> ?nif_stub.
--spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
-mod_pow(Base, Exponent, Prime) ->
- case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
- <<0>> -> error;
- R -> R
- end.
+%%%================================================================
+%%%
+%%% Sign/verify
+%%%
+%%%================================================================
+-type pk_sign_verify_algs() :: rsa | dss | ecdsa | eddsa .
-verify(Algorithm, Type, Data, Signature, Key) ->
- verify(Algorithm, Type, Data, Signature, Key, []).
+-type pk_sign_verify_opts() :: [ rsa_sign_verify_opt() ] .
-%% Backwards compatible
-verify(Algorithm = dss, none, Digest, Signature, Key, Options) ->
- verify(Algorithm, sha, {digest, Digest}, Signature, Key, Options);
-verify(Algorithm, Type, Data, Signature, Key, Options) ->
- case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
- notsup -> erlang:error(notsup);
- Boolean -> Boolean
- end.
+-type rsa_sign_verify_opt() :: {rsa_padding, rsa_sign_verify_padding()}
+ | {rsa_pss_saltlen, integer()} .
+-type rsa_sign_verify_padding() :: rsa_pkcs1_padding | rsa_pkcs1_pss_padding
+ | rsa_x931_padding | rsa_no_padding
+ .
+
+
+%%%----------------------------------------------------------------
+%%% Sign
+
+-spec sign(Algorithm, DigestType, Msg, Key)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | [eddsa_private() | eddsa_params()]
+ | engine_key_ref(),
+ Signature :: binary() .
sign(Algorithm, Type, Data, Key) ->
sign(Algorithm, Type, Data, Key, []).
-%% Backwards compatible
-sign(Algorithm = dss, none, Digest, Key, Options) ->
- sign(Algorithm, sha, {digest, Digest}, Key, Options);
-sign(Algorithm, Type, Data, Key, Options) ->
+
+-spec sign(Algorithm, DigestType, Msg, Key, Options)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type()
+ | none,
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | [eddsa_private() | eddsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Signature :: binary() .
+
+sign(Algorithm0, Type0, Data, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of
error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]);
notsup -> erlang:error(notsup);
Signature -> Signature
end.
+pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
+%%%----------------------------------------------------------------
+%%% Verify
+
+-spec verify(Algorithm, DigestType, Msg, Signature, Key)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type()
+ | none,
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_public()
+ | dss_public()
+ | [ecdsa_public() | ecdsa_params()]
+ | [eddsa_public() | eddsa_params()]
+ | engine_key_ref(),
+ Result :: boolean().
--type key_id() :: string() | binary() .
--type password() :: string() | binary() .
-
--type engine_key_ref() :: #{engine := engine_ref(),
- key_id := key_id(),
- password => password(),
- term() => term()
- }.
-
--type pk_algs() :: rsa | ecdsa | dss .
--type pk_key() :: engine_key_ref() | [integer() | binary()] .
--type pk_opt() :: list() | rsa_padding() .
-
--spec public_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec public_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec private_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec private_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
+verify(Algorithm, Type, Data, Signature, Key) ->
+ verify(Algorithm, Type, Data, Signature, Key, []).
-public_encrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, true) of
- error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]);
+-spec verify(Algorithm, DigestType, Msg, Signature, Key, Options)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_public()
+ | dss_public()
+ | [ecdsa_public() | ecdsa_params()]
+ | [eddsa_public() | eddsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Result :: boolean().
+
+verify(Algorithm0, Type0, Data, Signature, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
+ case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-public_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- public_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+ Boolean -> Boolean
+ end.
-private_decrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, false) of
- error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]);
- notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-private_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- private_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
-private_encrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, true) of
- error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]);
- notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-private_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- private_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+%% Backwards compatible:
+sign_verify_compatibility(dss, none, Digest) ->
+ {sha, {digest, Digest}};
+sign_verify_compatibility(Algorithm0, Type0, _Digest) ->
+ {Algorithm0, Type0}.
-public_decrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, false) of
- error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]);
+%%%================================================================
+%%%
+%%% Public/private encrypt/decrypt
+%%%
+%%% Only rsa works so far (although ecdsa | dss should do it)
+%%%================================================================
+-type pk_encrypt_decrypt_algs() :: rsa .
+
+-type pk_encrypt_decrypt_opts() :: [rsa_opt()] | rsa_compat_opts().
+
+-type rsa_compat_opts() :: [{rsa_pad, rsa_padding()}]
+ | rsa_padding() .
+
+-type rsa_padding() :: rsa_pkcs1_padding
+ | rsa_pkcs1_oaep_padding
+ | rsa_sslv23_padding
+ | rsa_x931_padding
+ | rsa_no_padding.
+
+-type rsa_opt() :: {rsa_padding, rsa_padding()}
+ | {signature_md, atom()}
+ | {rsa_mgf1_md, sha}
+ | {rsa_oaep_label, binary()}
+ | {rsa_oaep_md, sha} .
+
+%%%---- Encrypt with public key
+
+-spec public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PublicKey, Options, false, true).
+
+%%%---- Decrypt with private key
+
+-spec private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PrivateKey, Options, true, false).
+
+%%%---- Encrypt with private key
+
+-spec private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PrivateKey, Options, true, true).
+
+%%%---- Decrypt with public key
+
+-spec public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PublicKey, Options, false, false).
+
+%%%---- Call the nif, but fix a compatibility issue first
+
+%% Backwards compatible (rsa_pad -> rsa_padding is handled by the pkey_crypt_nif):
+pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) ->
+ pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec);
+
+pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) ->
+ case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of
+ error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]);
+ error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, Key, Options]);
notsup -> erlang:error(notsup);
Out -> Out
- end;
-%% Backwards compatible
-public_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- public_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
-
-
-%%
-%% XOR - xor to iolists and return a binary
-%% NB doesn't check that they are the same size, just concatenates
-%% them and sends them to the driver
-%%
--spec exor(iodata(), iodata()) -> binary().
+ end.
-exor(Bin1, Bin2) ->
- Data1 = iolist_to_binary(Bin1),
- Data2 = iolist_to_binary(Bin2),
- MaxBytes = max_bytes(),
- exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
+%%%================================================================
+%%%
+%%%
+%%%
+%%%================================================================
+
+-spec generate_key(Type, Params)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_gen_params()
+ .
generate_key(Type, Params) ->
generate_key(Type, Params, undefined).
+-spec generate_key(Type, Params, PrivKeyIn)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_comp_params()
+ .
+
generate_key(dh, DHParameters0, PrivateKey) ->
{DHParameters, Len} =
case DHParameters0 of
@@ -603,6 +1050,14 @@ generate_key(ecdh, Curve, PrivKey) ->
evp_generate_key_nif(_Curve) -> ?nif_stub.
+-spec compute_key(Type, OthersPublicKey, MyPrivateKey, Params)
+ -> SharedSecret
+ when Type :: dh | ecdh | srp,
+ SharedSecret :: binary(),
+ OthersPublicKey :: dh_public() | ecdh_public() | srp_public(),
+ MyPrivateKey :: dh_private() | ecdh_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | srp_comp_params()
+ .
compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
@@ -655,71 +1110,125 @@ compute_key(ecdh, Others, My, Curve) ->
evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
-%%======================================================================
-%% Engine functions
-%%======================================================================
+
+%%%================================================================
+%%%
+%%% XOR - xor to iolists and return a binary
+%%% NB doesn't check that they are the same size, just concatenates
+%%% them and sends them to the driver
+%%%
+%%%================================================================
+
+-spec exor(iodata(), iodata()) -> binary().
+
+exor(Bin1, Bin2) ->
+ Data1 = iolist_to_binary(Bin1),
+ Data2 = iolist_to_binary(Bin2),
+ MaxBytes = max_bytes(),
+ exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+
+
+%%%================================================================
+%%%
+%%% Exponentiation modulo
+%%%
+%%%================================================================
+
+-spec mod_pow(N, P, M) -> Result when N :: binary() | integer(),
+ P :: binary() | integer(),
+ M :: binary() | integer(),
+ Result :: binary() | error .
+mod_pow(Base, Exponent, Prime) ->
+ case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
+ <<0>> -> error;
+ R -> R
+ end.
+
+%%%======================================================================
+%%%
+%%% Engine functions
+%%%
+%%%======================================================================
+
+%%%---- Refering to keys stored in an engine:
+-type key_id() :: string() | binary() .
+-type password() :: string() | binary() .
+
+-type engine_key_ref() :: #{engine := engine_ref(),
+ key_id := key_id(),
+ password => password(),
+ term() => term()
+ }.
+
+%%%---- Commands:
+-type engine_cmnd() :: {unicode:chardata(), unicode:chardata()}.
+
%%----------------------------------------------------------------------
%% Function: engine_get_all_methods/0
%%----------------------------------------------------------------------
-type engine_method_type() :: engine_method_rsa | engine_method_dsa | engine_method_dh |
engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
engine_method_ciphers | engine_method_digests | engine_method_store |
- engine_method_pkey_meths | engine_method_pkey_asn1_meths |
+ engine_method_pkey_meths | engine_method_pkey_asn1_meths |
engine_method_ec.
-type engine_ref() :: term().
--spec engine_get_all_methods() ->
- [engine_method_type()].
+-spec engine_get_all_methods() -> Result when Result :: [engine_method_type()].
engine_get_all_methods() ->
notsup_to_error(engine_get_all_methods_nif()).
%%----------------------------------------------------------------------
%% Function: engine_load/3
%%----------------------------------------------------------------------
--spec engine_load(EngineId::unicode:chardata(),
- PreCmds::[{unicode:chardata(), unicode:chardata()}],
- PostCmds::[{unicode:chardata(), unicode:chardata()}]) ->
- {ok, Engine::engine_ref()} | {error, Reason::term()}.
-engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), is_list(PostCmds) ->
+-spec engine_load(EngineId, PreCmds, PostCmds) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds),
+ is_list(PostCmds) ->
engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()).
%%----------------------------------------------------------------------
%% Function: engine_load/4
%%----------------------------------------------------------------------
--spec engine_load(EngineId::unicode:chardata(),
- PreCmds::[{unicode:chardata(), unicode:chardata()}],
- PostCmds::[{unicode:chardata(), unicode:chardata()}],
- EngineMethods::[engine_method_type()]) ->
- {ok, Engine::term()} | {error, Reason::term()}.
+-spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ EngineMethods::[engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
is_list(PostCmds) ->
try
ok = notsup_to_error(engine_load_dynamic_nif()),
case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of
{ok, Engine} ->
- ok = engine_load_1(Engine, PreCmds, PostCmds, EngineMethods),
- {ok, Engine};
+ engine_load_1(Engine, PreCmds, PostCmds, EngineMethods);
{error, Error1} ->
{error, Error1}
end
catch
- throw:Error2 ->
- Error2
+ throw:Error2 ->
+ Error2
end.
engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
try
ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
- ok = engine_nif_wrapper(engine_add_nif(Engine)),
ok = engine_nif_wrapper(engine_init_nif(Engine)),
engine_load_2(Engine, PostCmds, EngineMethods),
- ok
+ {ok, Engine}
catch
- throw:Error ->
- %% The engine couldn't initialise, release the structural reference
- ok = engine_free_nif(Engine),
- throw(Error)
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error);
+ error:badarg ->
+ %% For example bad argument list, release the structural reference
+ ok = engine_free_nif(Engine),
+ error(badarg)
end.
engine_load_2(Engine, PostCmds, EngineMethods) ->
@@ -738,18 +1247,18 @@ engine_load_2(Engine, PostCmds, EngineMethods) ->
%%----------------------------------------------------------------------
%% Function: engine_unload/1
%%----------------------------------------------------------------------
--spec engine_unload(Engine::term()) ->
- ok | {error, Reason::term()}.
+-spec engine_unload(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()}.
engine_unload(Engine) ->
engine_unload(Engine, engine_get_all_methods()).
--spec engine_unload(Engine::term(), EngineMethods::[engine_method_type()]) ->
- ok | {error, Reason::term()}.
+-spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
engine_unload(Engine, EngineMethods) ->
try
[ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
Method <- EngineMethods],
- ok = engine_nif_wrapper(engine_remove_nif(Engine)),
%% Release the functional reference from engine_init_nif
ok = engine_nif_wrapper(engine_finish_nif(Engine)),
%% Release the structural reference from engine_by_id_nif
@@ -760,19 +1269,63 @@ engine_unload(Engine, EngineMethods) ->
end.
%%----------------------------------------------------------------------
+%% Function: engine_by_id/1
+%%----------------------------------------------------------------------
+-spec engine_by_id(EngineId) -> Result when EngineId :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()} .
+engine_by_id(EngineId) ->
+ try
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)))
+ catch
+ throw:Error ->
+ Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_add/1
+%%----------------------------------------------------------------------
+-spec engine_add(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
+engine_add(Engine) ->
+ notsup_to_error(engine_add_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_remove/1
+%%----------------------------------------------------------------------
+-spec engine_remove(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
+engine_remove(Engine) ->
+ notsup_to_error(engine_remove_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_id/1
+%%----------------------------------------------------------------------
+-spec engine_get_id(Engine) -> EngineId when Engine :: engine_ref(),
+ EngineId :: unicode:chardata().
+engine_get_id(Engine) ->
+ notsup_to_error(engine_get_id_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_name/1
+%%----------------------------------------------------------------------
+-spec engine_get_name(Engine) -> EngineName when Engine :: engine_ref(),
+ EngineName :: unicode:chardata().
+engine_get_name(Engine) ->
+ notsup_to_error(engine_get_name_nif(Engine)).
+
+%%----------------------------------------------------------------------
%% Function: engine_list/0
%%----------------------------------------------------------------------
--spec engine_list() ->
- [EngineId::binary()].
+-spec engine_list() -> Result when Result :: [EngineId::unicode:chardata()].
engine_list() ->
case notsup_to_error(engine_get_first_nif()) of
{ok, <<>>} ->
[];
{ok, Engine} ->
case notsup_to_error(engine_get_id_nif(Engine)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine, []);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine, [EngineId])
end
end.
@@ -783,9 +1336,9 @@ engine_list(Engine0, IdList) ->
lists:reverse(IdList);
{ok, Engine1} ->
case notsup_to_error(engine_get_id_nif(Engine1)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine1, IdList);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine1, [EngineId |IdList])
end
end.
@@ -793,24 +1346,26 @@ engine_list(Engine0, IdList) ->
%%----------------------------------------------------------------------
%% Function: engine_ctrl_cmd_string/3
%%----------------------------------------------------------------------
--spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
- CmdArg::unicode:chardata()) ->
- ok | {error, Reason::term()}.
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Result :: ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
engine_ctrl_cmd_string(Engine, CmdName, CmdArg, false).
%%----------------------------------------------------------------------
%% Function: engine_ctrl_cmd_string/4
%%----------------------------------------------------------------------
--spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
- CmdArg::unicode:chardata(),
- Optional::boolean()) ->
- ok | {error, Reason::term()}.
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Optional::boolean(),
+ Result :: ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
- case engine_ctrl_cmd_strings_nif(Engine,
- ensure_bin_cmds([{CmdName, CmdArg}]),
+ case engine_ctrl_cmd_strings_nif(Engine,
+ ensure_bin_cmds([{CmdName, CmdArg}]),
bool_to_int(Optional)) of
ok ->
ok;
@@ -820,6 +1375,97 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
{error, Error}
end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/2
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+ensure_engine_loaded(EngineId, LibPath) ->
+ ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/3
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ EngineMethods :: [engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ try
+ List = crypto:engine_list(),
+ case lists:member(EngineId, List) of
+ true ->
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)));
+ false ->
+ ok = notsup_to_error(engine_load_dynamic_nif()),
+ case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(<<"dynamic">>))) of
+ {ok, Engine} ->
+ PreCommands = [{<<"SO_PATH">>, ensure_bin_chardata(LibPath)},
+ {<<"ID">>, ensure_bin_chardata(EngineId)},
+ <<"LOAD">>],
+ ensure_engine_loaded_1(Engine, PreCommands, EngineMethods);
+ {error, Error1} ->
+ {error, Error1}
+ end
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+ensure_engine_loaded_1(Engine, PreCmds, Methods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
+ ok = engine_nif_wrapper(engine_add_nif(Engine)),
+ ok = engine_nif_wrapper(engine_init_nif(Engine)),
+ ensure_engine_loaded_2(Engine, Methods),
+ {ok, Engine}
+ catch
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
+ end.
+
+ensure_engine_loaded_2(Engine, Methods) ->
+ try
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- Methods],
+ ok
+ catch
+ throw:Error ->
+ %% The engine registration failed, release the functional reference
+ ok = engine_finish_nif(Engine),
+ throw(Error)
+ end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/1
+%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()}.
+ensure_engine_unloaded(Engine) ->
+ ensure_engine_unloaded(Engine, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/2
+%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine, EngineMethods) ->
+ Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
+ensure_engine_unloaded(Engine, EngineMethods) ->
+ case engine_remove(Engine) of
+ ok ->
+ engine_unload(Engine, EngineMethods);
+ {error, E} ->
+ {error, E}
+ end.
+
%%--------------------------------------------------------------------
%%% On load
%%--------------------------------------------------------------------
@@ -886,13 +1532,17 @@ path2bin(Path) when is_list(Path) ->
Bin
end.
-%%--------------------------------------------------------------------
+%%%================================================================
+%%%================================================================
+%%%
%%% Internal functions
-%%--------------------------------------------------------------------
+%%%
+%%%================================================================
+
max_bytes() ->
?MAX_BYTES_TO_NIF.
-notsup_to_error(notsup) ->
+notsup_to_error(notsup) ->
erlang:error(notsup);
notsup_to_error(Other) ->
Other.
@@ -948,9 +1598,12 @@ hmac_final_nif(_Context) -> ?nif_stub.
hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%% CMAC
-
cmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+%% POLY1305
+poly1305_nif(_Key, _Data) -> ?nif_stub.
+
+
%% CIPHERS --------------------------------------------------------------------
block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
@@ -970,16 +1623,11 @@ check_des3_key(Key) ->
%% AES - in Galois/Counter Mode (GCM)
%%
%% The default tag length is EVP_GCM_TLS_TAG_LEN(16),
-aes_gcm_encrypt(Key, Ivec, AAD, In) ->
- aes_gcm_encrypt(Key, Ivec, AAD, In, 16).
-aes_gcm_encrypt(_Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
-aes_gcm_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_encrypt(Type=aes_ccm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 12);
+aead_encrypt(Type=aes_gcm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 16).
-%%
-%% Chacha20/Ppoly1305
-%%
-chacha20_poly1305_encrypt(_Key, _Ivec, _AAD, _In) -> ?nif_stub.
-chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_encrypt(_Type, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
+aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
@@ -1005,27 +1653,25 @@ do_stream_encrypt({aes_ctr, State0}, Data) ->
{{aes_ctr, State}, Cipher};
do_stream_encrypt({rc4, State0}, Data) ->
{State, Cipher} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Cipher}.
+ {{rc4, State}, Cipher};
+do_stream_encrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_encrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
do_stream_decrypt({aes_ctr, State0}, Data) ->
{State, Text} = aes_ctr_stream_decrypt(State0, Data),
{{aes_ctr, State}, Text};
do_stream_decrypt({rc4, State0}, Data) ->
{State, Text} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Text}.
+ {{rc4, State}, Text};
+do_stream_decrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_decrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
%%
%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
--type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary().
-
--spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state().
--spec aes_ctr_stream_encrypt(ctr_state(), binary()) ->
- { ctr_state(), binary() }.
--spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
- { ctr_state(), binary() }.
-
aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub.
aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub.
aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
@@ -1036,6 +1682,13 @@ aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+%%
+%% CHACHA20 - stream cipher
+%%
+chacha20_stream_init(_Key, _IVec) -> ?nif_stub.
+chacha20_stream_encrypt(_State, _Data) -> ?nif_stub.
+chacha20_stream_decrypt(_State, _Data) -> ?nif_stub.
+
%% Secure remote password -------------------------------------------------------------------
user_srp_gen_key(Private, Generator, Prime) ->
@@ -1102,11 +1755,6 @@ srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?
srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
-%% Digital signatures --------------------------------------------------------------------
-
-pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
-pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
-
%% Public Keys --------------------------------------------------------------------
%% RSA Rivest-Shamir-Adleman functions
%%
@@ -1128,13 +1776,22 @@ ec_key_generate(_Curve, _Key) -> ?nif_stub.
ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
+-spec ec_curves() -> [EllipticCurve] when EllipticCurve :: ec_named_curve()
+ | edwards_curve_dh()
+ | edwards_curve_ed() .
+
ec_curves() ->
crypto_ec_curves:curves().
+-spec ec_curve(CurveName) -> ExplicitCurve when CurveName :: ec_named_curve(),
+ ExplicitCurve :: ec_explicit_curve() .
ec_curve(X) ->
crypto_ec_curves:curve(X).
+-spec privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey when Type :: rsa | dss,
+ EnginePrivateKeyRef :: engine_key_ref(),
+ PublicKey :: rsa_public() | dss_public() .
privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap))
of
@@ -1148,7 +1805,7 @@ privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
error:notsup ->
{error, notsup}
end.
-
+
privkey_to_pubkey_nif(_Alg, _EngineMap) -> ?nif_stub.
@@ -1160,10 +1817,16 @@ term_to_nif_prime({prime_field, Prime}) ->
{prime_field, ensure_int_as_bin(Prime)};
term_to_nif_prime(PrimeField) ->
PrimeField.
+
term_to_nif_curve({A, B, Seed}) ->
{ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}.
+
nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) ->
- {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), ensure_int_as_bin(Order), ensure_int_as_bin(CoFactor)};
+ {term_to_nif_prime(PrimeField),
+ term_to_nif_curve(Curve),
+ ensure_int_as_bin(BasePoint),
+ ensure_int_as_bin(Order),
+ ensure_int_as_bin(CoFactor)};
nif_curve_params(Curve) when is_atom(Curve) ->
%% named curve
case Curve of
@@ -1203,6 +1866,7 @@ int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
int_to_bin_neg(X,Ds) ->
int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
+-spec bytes_to_integer(binary()) -> integer() .
bytes_to_integer(Bin) ->
bin_to_int(Bin).
@@ -1250,9 +1914,6 @@ format_pwd(M) -> M.
%%--------------------------------------------------------------------
%%
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
-
-pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
%% large integer in a binary with 32bit length
%% MP representaion (SSH2)
@@ -1314,6 +1975,7 @@ engine_unregister_nif(_Engine, _EngineMethod) -> ?nif_stub.
engine_get_first_nif() -> ?nif_stub.
engine_get_next_nif(_Engine) -> ?nif_stub.
engine_get_id_nif(_Engine) -> ?nif_stub.
+engine_get_name_nif(_Engine) -> ?nif_stub.
engine_get_all_methods_nif() -> ?nif_stub.
%%--------------------------------------------------------------------
@@ -1371,7 +2033,7 @@ get_test_engine() ->
Type = erlang:system_info(system_architecture),
LibDir = filename:join([code:priv_dir(crypto), "lib"]),
ArchDir = filename:join([LibDir, Type]),
- case filelib:is_dir(ArchDir) of
+ case filelib:is_dir(ArchDir) of
true -> check_otp_test_engine(ArchDir);
false -> check_otp_test_engine(LibDir)
end.
@@ -1380,7 +2042,7 @@ check_otp_test_engine(LibDir) ->
case filelib:wildcard("otp_test_engine*", LibDir) of
[] ->
{error, notexist};
- [LibName] ->
+ [LibName|_] -> % In case of Valgrind there could be more than one
LibPath = filename:join(LibDir,LibName),
case filelib:is_file(LibPath) of
true ->
@@ -1389,4 +2051,3 @@ check_otp_test_engine(LibDir) ->
{error, notexist}
end
end.
-
diff --git a/lib/crypto/src/crypto_ec_curves.erl b/lib/crypto/src/crypto_ec_curves.erl
index 9602a7e24b..a0a2f99601 100644
--- a/lib/crypto/src/crypto_ec_curves.erl
+++ b/lib/crypto/src/crypto_ec_curves.erl
@@ -3,41 +3,7 @@
-export([curve/1, curves/0]).
curves() ->
- CryptoSupport = crypto:supports(),
- PubKeys = proplists:get_value(public_keys, CryptoSupport),
- HasEC = proplists:get_bool(ecdh, PubKeys),
- HasGF2m = proplists:get_bool(ec_gf2m, PubKeys),
- FIPSMode = crypto:info_fips() == enabled,
- prime_curves(HasEC, FIPSMode) ++ characteristic_two_curves(HasGF2m, FIPSMode).
-
-
-prime_curves(true, true) ->
- [secp160k1,secp160r1,secp160r2,
- secp192r1,secp192k1,secp224k1,secp224r1,secp256k1,secp256r1,secp384r1,
- secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,
- prime256v1,wtls7,wtls9,wtls12,
- brainpoolP160r1,brainpoolP160t1,brainpoolP192r1,brainpoolP192t1,
- brainpoolP224r1,brainpoolP224t1,brainpoolP256r1,brainpoolP256t1,
- brainpoolP320r1,brainpoolP320t1,brainpoolP384r1,brainpoolP384t1,
- brainpoolP512r1,brainpoolP512t1];
-prime_curves(true, false) ->
- [secp112r1,secp112r2,secp128r1,secp128r2,wtls6,wtls8]
- ++ prime_curves(true, true);
-prime_curves(_, _) ->
- [].
-
-characteristic_two_curves(true, true) ->
- [sect163k1,sect163r1,
- sect163r2,sect193r1,sect193r2,sect233k1,sect233r1,sect239k1,sect283k1,
- sect283r1,sect409k1,sect409r1,sect571k1,sect571r1,c2pnb163v1,c2pnb163v2,
- c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,
- c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359v1,c2pnb368w1,c2tnb431r1,
- wtls3,wtls5,wtls10,wtls11];
-characteristic_two_curves(true, _) ->
- [sect113r1,sect113r2,sect131r1,sect131r2,wtls1,wtls4,ipsec3,ipsec4]
- ++ characteristic_two_curves(true, true);
-characteristic_two_curves(_, _) ->
- [].
+ proplists:get_value(curves, crypto:supports()) -- [x25519,x448].
curve(secp112r1) ->
{
diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile
index e046a25338..988d95a8bc 100644
--- a/lib/crypto/test/Makefile
+++ b/lib/crypto/test/Makefile
@@ -6,7 +6,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# ----------------------------------------------------
MODULES = \
- blowfish_SUITE \
+ crypto_bench_SUITE \
crypto_SUITE \
engine_SUITE
@@ -77,7 +77,7 @@ release_spec:
release_tests_spec: $(TEST_TARGET)
$(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) crypto.spec crypto.cover $(RELTEST_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) crypto.spec crypto_bench.spec crypto.cover $(RELTEST_FILES) "$(RELSYSDIR)"
@tar cfh - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
chmod -R u+w "$(RELSYSDIR)"
diff --git a/lib/crypto/test/blowfish_SUITE.erl b/lib/crypto/test/blowfish_SUITE.erl
deleted file mode 100644
index a931ebb47e..0000000000
--- a/lib/crypto/test/blowfish_SUITE.erl
+++ /dev/null
@@ -1,300 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(blowfish_SUITE).
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(TIMEOUT, 120000). % 2 min
-
--define(KEY, to_bin("0123456789ABCDEFF0E1D2C3B4A59687")).
--define(IVEC, to_bin("FEDCBA9876543210")).
-%% "7654321 Now is the time for " (includes trailing '\0')
--define(DATA, to_bin("37363534333231204E6F77206973207468652074696D6520666F722000")).
--define(DATA_PADDED, to_bin("37363534333231204E6F77206973207468652074696D6520666F722000000000")).
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initialization before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- case catch crypto:start() of
- ok ->
- catch ct:comment("~s",[element(3,hd(crypto:info_lib()))]),
- catch ct:log("crypto:info_lib() -> ~p~n"
- "crypto:supports() -> ~p~n"
- "crypto:version() -> ~p~n"
- ,[crypto:info_lib(), crypto:supports(), crypto:version()]),
- Config;
- _Else ->
- {skip,"Could not start crypto!"}
- end.
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
- crypto:stop().
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initialization before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initialization before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(_TestCase, Config0) ->
- Config = lists:keydelete(watchdog, 1, Config0),
- Dog = test_server:timetrap(?TIMEOUT),
- [{watchdog, Dog} | Config].
-
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(_TestCase, Config) ->
- Dog = ?config(watchdog, Config),
- case Dog of
- undefined ->
- ok;
- _ ->
- test_server:timetrap_cancel(Dog)
- end.
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
-[{group, fips},
- {group, non_fips}].
-
-groups() ->
- [{fips, [], [no_ecb, no_cbc, no_cfb64, no_ofb64]},
- {non_fips, [], [ecb, cbc, cfb64, ofb64]}].
-
-init_per_group(fips, Config) ->
- case crypto:info_fips() of
- enabled ->
- Config;
- not_enabled ->
- case crypto:enable_fips_mode(true) of
- true ->
- enabled = crypto:info_fips(),
- Config;
- false ->
- {skip, "Failed to enable FIPS mode"}
- end;
- not_supported ->
- {skip, "FIPS mode not supported"}
- end;
-init_per_group(non_fips, Config) ->
- case crypto:info_fips() of
- enabled ->
- true = crypto:enable_fips_mode(false),
- not_enabled = crypto:info_fips(),
- Config;
- _NotEnabled ->
- Config
- end;
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases start here.
-%%--------------------------------------------------------------------
-
-ecb_test(KeyBytes, ClearBytes, CipherBytes) ->
- {Key, Clear, Cipher} =
- {to_bin(KeyBytes), to_bin(ClearBytes), to_bin(CipherBytes)},
- ?line m(crypto:block_encrypt(blowfish_ecb, Key, Clear), Cipher),
- true.
-
-ecb(doc) ->
- "Test that ECB mode is OK";
-ecb(suite) ->
- [];
-ecb(Config) when is_list(Config) ->
- true = ecb_test("0000000000000000", "0000000000000000", "4EF997456198DD78"),
- true = ecb_test("FFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFF", "51866FD5B85ECB8A"),
- true = ecb_test("3000000000000000", "1000000000000001", "7D856F9A613063F2"),
- true = ecb_test("1111111111111111", "1111111111111111", "2466DD878B963C9D"),
- true = ecb_test("0123456789ABCDEF", "1111111111111111", "61F9C3802281B096"),
- true = ecb_test("1111111111111111", "0123456789ABCDEF", "7D0CC630AFDA1EC7"),
- true = ecb_test("0000000000000000", "0000000000000000", "4EF997456198DD78"),
- true = ecb_test("FEDCBA9876543210", "0123456789ABCDEF", "0ACEAB0FC6A0A28D"),
- true = ecb_test("7CA110454A1A6E57", "01A1D6D039776742", "59C68245EB05282B"),
- true = ecb_test("0131D9619DC1376E", "5CD54CA83DEF57DA", "B1B8CC0B250F09A0"),
- true = ecb_test("07A1133E4A0B2686", "0248D43806F67172", "1730E5778BEA1DA4"),
- true = ecb_test("3849674C2602319E", "51454B582DDF440A", "A25E7856CF2651EB"),
- true = ecb_test("04B915BA43FEB5B6", "42FD443059577FA2", "353882B109CE8F1A"),
- true = ecb_test("0113B970FD34F2CE", "059B5E0851CF143A", "48F4D0884C379918"),
- true = ecb_test("0170F175468FB5E6", "0756D8E0774761D2", "432193B78951FC98"),
- true = ecb_test("43297FAD38E373FE", "762514B829BF486A", "13F04154D69D1AE5"),
- true = ecb_test("07A7137045DA2A16", "3BDD119049372802", "2EEDDA93FFD39C79"),
- true = ecb_test("04689104C2FD3B2F", "26955F6835AF609A", "D887E0393C2DA6E3"),
- true = ecb_test("37D06BB516CB7546", "164D5E404F275232", "5F99D04F5B163969"),
- true = ecb_test("1F08260D1AC2465E", "6B056E18759F5CCA", "4A057A3B24D3977B"),
- true = ecb_test("584023641ABA6176", "004BD6EF09176062", "452031C1E4FADA8E"),
- true = ecb_test("025816164629B007", "480D39006EE762F2", "7555AE39F59B87BD"),
- true = ecb_test("49793EBC79B3258F", "437540C8698F3CFA", "53C55F9CB49FC019"),
- true = ecb_test("4FB05E1515AB73A7", "072D43A077075292", "7A8E7BFA937E89A3"),
- true = ecb_test("49E95D6D4CA229BF", "02FE55778117F12A", "CF9C5D7A4986ADB5"),
- true = ecb_test("018310DC409B26D6", "1D9D5C5018F728C2", "D1ABB290658BC778"),
- true = ecb_test("1C587F1C13924FEF", "305532286D6F295A", "55CB3774D13EF201"),
- true = ecb_test("0101010101010101", "0123456789ABCDEF", "FA34EC4847B268B2"),
- true = ecb_test("1F1F1F1F0E0E0E0E", "0123456789ABCDEF", "A790795108EA3CAE"),
- true = ecb_test("E0FEE0FEF1FEF1FE", "0123456789ABCDEF", "C39E072D9FAC631D"),
- true = ecb_test("0000000000000000", "FFFFFFFFFFFFFFFF", "014933E0CDAFF6E4"),
- true = ecb_test("FFFFFFFFFFFFFFFF", "0000000000000000", "F21E9A77B71C49BC"),
- true = ecb_test("0123456789ABCDEF", "0000000000000000", "245946885754369A"),
- true = ecb_test("FEDCBA9876543210", "FFFFFFFFFFFFFFFF", "6B5C5A9C5D9E0A5A"),
- ok.
-
-cbc(doc) ->
- "Test that CBC mode is OK";
-cbc(suite) ->
- [];
-cbc(Config) when is_list(Config) ->
- true = crypto:block_encrypt(blowfish_cbc, ?KEY, ?IVEC, ?DATA_PADDED) =:=
- to_bin("6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC"),
- ok.
-
-cfb64(doc) ->
- "Test that CFB64 mode is OK";
-cfb64(suite) ->
- [];
-cfb64(Config) when is_list(Config) ->
- true = crypto:block_encrypt(blowfish_cfb64, ?KEY, ?IVEC, ?DATA) =:=
- to_bin("E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3"),
- ok.
-
-ofb64(doc) ->
- "Test that OFB64 mode is OK";
-ofb64(suite) ->
- [];
-ofb64(Config) when is_list(Config) ->
- true = crypto:block_encrypt(blowfish_ofb64, ?KEY, ?IVEC, ?DATA) =:=
- to_bin("E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA"),
- ok.
-
-no_ecb(doc) ->
- "Test that ECB mode is disabled";
-no_ecb(suite) ->
- [];
-no_ecb(Config) when is_list(Config) ->
- notsup(fun crypto:block_encrypt/3,
- [blowfish_ecb,
- to_bin("0000000000000000"),
- to_bin("FFFFFFFFFFFFFFFF")]).
-
-no_cbc(doc) ->
- "Test that CBC mode is disabled";
-no_cbc(suite) ->
- [];
-no_cbc(Config) when is_list(Config) ->
- notsup(fun crypto:block_encrypt/4,
- [blowfish_cbc, ?KEY, ?IVEC, ?DATA_PADDED]).
-
-no_cfb64(doc) ->
- "Test that CFB64 mode is disabled";
-no_cfb64(suite) ->
- [];
-no_cfb64(Config) when is_list(Config) ->
- notsup(fun crypto:block_encrypt/4,
- [blowfish_cfb64, ?KEY, ?IVEC, ?DATA]),
- ok.
-
-no_ofb64(doc) ->
- "Test that OFB64 mode is disabled";
-no_ofb64(suite) ->
- [];
-no_ofb64(Config) when is_list(Config) ->
- notsup(fun crypto:block_encrypt/4,
- [blowfish_ofb64, ?KEY, ?IVEC, ?DATA]).
-
-%% Helper functions
-
-%% Assert function fails with notsup error
-notsup(Fun, Args) ->
- ok = try
- {error, {return, apply(Fun, Args)}}
- catch
- error:notsup ->
- ok;
- Class:Error ->
- {error, {Class, Error}}
- end.
-
-
-%% Convert a hexadecimal string to a binary.
--spec(to_bin(L::string()) -> binary()).
-to_bin(L) ->
- to_bin(L, []).
-
-%% @spec dehex(char()) -> integer()
-%% @doc Convert a hex digit to its integer value.
--spec(dehex(char()) -> integer()).
-dehex(C) when C >= $0, C =< $9 ->
- C - $0;
-dehex(C) when C >= $a, C =< $f ->
- C - $a + 10;
-dehex(C) when C >= $A, C =< $F ->
- C - $A + 10.
-
--spec(to_bin(L::string(), list()) -> binary()).
-to_bin([], Acc) ->
- iolist_to_binary(lists:reverse(Acc));
-to_bin([C1, C2 | Rest], Acc) ->
- to_bin(Rest, [(dehex(C1) bsl 4) bor dehex(C2) | Acc]).
-
-m(X,X) -> ok.
diff --git a/lib/crypto/test/crypto.spec b/lib/crypto/test/crypto.spec
index cc09970cb3..4a95275687 100644
--- a/lib/crypto/test/crypto.spec
+++ b/lib/crypto/test/crypto.spec
@@ -1 +1,6 @@
{suites,"../crypto_test",all}.
+
+{skip_suites, "../crypto_test", [crypto_bench_SUITE
+ ],
+ "Benchmarks run separately"}.
+
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index ebb55c4a34..cbfa96cc16 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1,4 +1,4 @@
-%%
+%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
@@ -31,12 +31,14 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app,
+ {group, api_errors},
appup,
{group, fips},
{group, non_fips},
mod_pow,
exor,
rand_uniform,
+ rand_threads,
rand_plugin,
rand_plugin_s
].
@@ -50,9 +52,15 @@ groups() ->
{group, sha256},
{group, sha384},
{group, sha512},
+ {group, sha3_224},
+ {group, sha3_256},
+ {group, sha3_384},
+ {group, sha3_512},
{group, rsa},
{group, dss},
{group, ecdsa},
+ {group, ed25519},
+ {group, ed448},
{group, dh},
{group, ecdh},
{group, srp},
@@ -74,8 +82,11 @@ groups() ->
{group, rc2_cbc},
{group, rc4},
{group, aes_ctr},
+ {group, aes_ccm},
{group, aes_gcm},
{group, chacha20_poly1305},
+ {group, chacha20},
+ {group, poly1305},
{group, aes_cbc}]},
{fips, [], [{group, no_md4},
{group, no_md5},
@@ -88,6 +99,8 @@ groups() ->
{group, rsa},
{group, dss},
{group, ecdsa},
+ {group, no_ed25519},
+ {group, no_ed448},
{group, dh},
{group, ecdh},
{group, no_srp},
@@ -102,15 +115,17 @@ groups() ->
{group, no_blowfish_cfb64},
{group, no_blowfish_ofb64},
{group, aes_cbc128},
- {group, aes_cfb8},
- {group, aes_cfb128},
+ {group, no_aes_cfb8},
+ {group, no_aes_cfb128},
{group, aes_cbc256},
{group, no_aes_ige256},
{group, no_rc2_cbc},
{group, no_rc4},
{group, aes_ctr},
+ {group, aes_ccm},
{group, aes_gcm},
{group, no_chacha20_poly1305},
+ {group, no_chacha20},
{group, aes_cbc}]},
{md4, [], [hash]},
{md5, [], [hash, hmac]},
@@ -120,6 +135,10 @@ groups() ->
{sha256, [], [hash, hmac]},
{sha384, [], [hash, hmac]},
{sha512, [], [hash, hmac]},
+ {sha3_224, [], [hash, hmac]},
+ {sha3_256, [], [hash, hmac]},
+ {sha3_384, [], [hash, hmac]},
+ {sha3_512, [], [hash, hmac]},
{rsa, [], [sign_verify,
public_encrypt,
private_encrypt,
@@ -131,9 +150,15 @@ groups() ->
{ecdsa, [], [sign_verify
%% Does not work yet: ,public_encrypt, private_encrypt
]},
+ {ed25519, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {ed448, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
{dh, [], [generate_compute,
compute_bug]},
- {ecdh, [], [compute, generate]},
+ {ecdh, [], [use_all_elliptic_curves, compute, generate]},
{srp, [], [generate_compute]},
{des_cbc, [], [block]},
{des_cfb, [], [block]},
@@ -154,11 +179,22 @@ groups() ->
{blowfish_ofb64,[], [block]},
{rc4, [], [stream]},
{aes_ctr, [], [stream]},
+ {aes_ccm, [], [aead]},
{aes_gcm, [], [aead]},
{chacha20_poly1305, [], [aead]},
+ {chacha20, [], [stream]},
+ {poly1305, [], [poly1305]},
{aes_cbc, [], [block]},
+ {no_aes_cfb8,[], [no_support, no_block]},
+ {no_aes_cfb128,[], [no_support, no_block]},
{no_md4, [], [no_support, no_hash]},
{no_md5, [], [no_support, no_hash, no_hmac]},
+ {no_ed25519, [], [no_support, no_sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {no_ed448, [], [no_support, no_sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
{no_ripemd160, [], [no_support, no_hash]},
{no_srp, [], [no_support, no_generate_compute]},
{no_des_cbc, [], [no_support, no_block]},
@@ -169,8 +205,10 @@ groups() ->
{no_blowfish_ofb64, [], [no_support, no_block]},
{no_aes_ige256, [], [no_support, no_block]},
{no_chacha20_poly1305, [], [no_support, no_aead]},
+ {no_chacha20, [], [no_support, no_stream_ivec]},
{no_rc2_cbc, [], [no_support, no_block]},
- {no_rc4, [], [no_support, no_stream]}
+ {no_rc4, [], [no_support, no_stream]},
+ {api_errors, [], [api_errors_ecdh]}
].
%%-------------------------------------------------------------------
@@ -205,7 +243,7 @@ init_per_suite(Config) ->
Config
end
catch _:_ ->
- {skip, "Crypto did not start"}
+ {fail, "Crypto did not start"}
end.
end_per_suite(_Config) ->
@@ -223,7 +261,7 @@ init_per_group(fips, Config) ->
enabled = crypto:info_fips(),
FIPSConfig;
false ->
- {skip, "Failed to enable FIPS mode"}
+ {fail, "Failed to enable FIPS mode"}
end;
not_supported ->
{skip, "FIPS mode not supported"}
@@ -238,6 +276,8 @@ init_per_group(non_fips, Config) ->
_NotEnabled ->
NonFIPSConfig
end;
+init_per_group(api_errors, Config) ->
+ Config;
init_per_group(GroupName, Config) ->
case atom_to_list(GroupName) of
"no_" ++ TypeStr ->
@@ -352,22 +392,25 @@ cmac(Config) when is_list(Config) ->
lists:foreach(fun cmac_check/1, Pairs),
lists:foreach(fun cmac_check/1, cmac_iolistify(Pairs)).
%%--------------------------------------------------------------------
+poly1305() ->
+ [{doc, "Test poly1305 function"}].
+poly1305(Config) ->
+ lists:foreach(
+ fun({Key, Txt, Expect}) ->
+ case crypto:poly1305(Key,Txt) of
+ Expect ->
+ ok;
+ Other ->
+ ct:fail({{crypto, poly1305, [Key, Txt]}, {expected, Expect}, {got, Other}})
+ end
+ end, proplists:get_value(poly1305, Config)).
+
+%%--------------------------------------------------------------------
block() ->
[{doc, "Test block ciphers"}].
block(Config) when is_list(Config) ->
Fips = proplists:get_bool(fips, Config),
Type = ?config(type, Config),
- %% See comment about EVP_CIPHER_CTX_set_key_length in
- %% block_crypt_nif in crypto.c.
- case {Fips, Type} of
- {true, aes_cfb8} ->
- throw({skip, "Cannot test aes_cfb8 in FIPS mode because of key length issue"});
- {true, aes_cfb128} ->
- throw({skip, "Cannot test aes_cfb128 in FIPS mode because of key length issue"});
- _ ->
- ok
- end,
-
Blocks = lazy_eval(proplists:get_value(block, Config)),
lists:foreach(fun block_cipher/1, Blocks),
lists:foreach(fun block_cipher/1, block_iolistify(Blocks)),
@@ -393,12 +436,18 @@ no_block(Config) when is_list(Config) ->
no_aead() ->
[{doc, "Test disabled aead ciphers"}].
no_aead(Config) when is_list(Config) ->
- [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag} | _] =
- lazy_eval(proplists:get_value(aead, Config)),
- EncryptArgs = [Type, Key, Nonce, {AAD, PlainText}],
+ EncArg4 =
+ case lazy_eval(proplists:get_value(aead, Config)) of
+ [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, TagLen, _Info} | _] ->
+ {AAD, PlainText, TagLen};
+ [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, _Info} | _] ->
+ {AAD, PlainText}
+ end,
+ EncryptArgs = [Type, Key, Nonce, EncArg4],
DecryptArgs = [Type, Key, Nonce, {AAD, CipherText, CipherTag}],
notsup(fun crypto:block_encrypt/4, EncryptArgs),
notsup(fun crypto:block_decrypt/4, DecryptArgs).
+
%%--------------------------------------------------------------------
stream() ->
[{doc, "Test stream ciphers"}].
@@ -416,6 +465,13 @@ no_stream(Config) when is_list(Config) ->
notsup(fun crypto:stream_init/2, [Type, <<"Key">>]).
%%--------------------------------------------------------------------
+no_stream_ivec() ->
+ [{doc, "Test disabled stream ciphers that uses ivec"}].
+no_stream_ivec(Config) when is_list(Config) ->
+ Type = ?config(type, Config),
+ notsup(fun crypto:stream_init/3, [Type, <<"Key">>, <<"Ivec">>]).
+
+%%--------------------------------------------------------------------
aead() ->
[{doc, "Test AEAD ciphers"}].
aead(Config) when is_list(Config) ->
@@ -443,18 +499,25 @@ sign_verify(Config) when is_list(Config) ->
SignVerify = proplists:get_value(sign_verify, Config),
lists:foreach(fun do_sign_verify/1, SignVerify).
+%%--------------------------------------------------------------------
+no_sign_verify() ->
+ [{doc, "Test disabled sign/verify digital signatures"}].
+no_sign_verify(Config) when is_list(Config) ->
+ [SignVerifyHd|_] = proplists:get_value(sign_verify, Config),
+ notsup(fun do_sign_verify/1, [SignVerifyHd]).
+
%%--------------------------------------------------------------------
public_encrypt() ->
[{doc, "Test public_encrypt/decrypt "}].
public_encrypt(Config) when is_list(Config) ->
- Params = proplists:get_value(pub_priv_encrypt, Config),
+ Params = proplists:get_value(pub_pub_encrypt, Config, []),
lists:foreach(fun do_public_encrypt/1, Params).
%%--------------------------------------------------------------------
private_encrypt() ->
[{doc, "Test private_encrypt/decrypt functions. "}].
private_encrypt(Config) when is_list(Config) ->
- Params = proplists:get_value(pub_priv_encrypt, Config),
+ Params = proplists:get_value(pub_priv_encrypt, Config, []),
lists:foreach(fun do_private_encrypt/1, Params).
%%--------------------------------------------------------------------
@@ -466,7 +529,7 @@ generate_compute(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
compute_bug() ->
[{doc, "Test that it works even if the Secret is smaller than expected"}].
-compute_bug(Config) ->
+compute_bug(_Config) ->
ExpectedSecret = <<118,89,171,16,156,18,156,103,189,134,130,49,28,144,111,241,247,82,79,32,228,11,209,141,119,176,251,80,105,143,235,251,203,121,223,211,129,3,233,133,45,2,31,157,24,111,5,75,153,66,135,185,128,115,229,178,216,39,73,52,80,151,8,241,34,52,226,71,137,167,53,48,59,224,175,154,89,110,76,83,24,117,149,21,72,6,186,78,149,74,188,56,98,244,30,77,108,248,88,194,195,237,23,51,20,242,254,123,21,12,209,74,217,168,230,65,7,60,211,139,128,239,234,153,22,229,180,59,159,121,41,156,121,200,177,130,163,162,54,224,93,1,94,11,177,254,118,28,156,26,116,10,207,145,219,166,214,189,214,230,221,170,228,15,69,88,31,68,94,255,113,58,49,82,86,192,248,176,131,133,39,186,194,172,206,84,184,16,66,68,153,128,178,227,27,118,52,130,122,92,24,222,102,195,221,207,255,13,152,175,65,32,167,84,54,244,243,109,244,18,234,16,159,224,188,2,106,123,27,17,131,171,226,34,111,251,62,119,155,124,221,124,254,62,97,167,1,105,116,98,98,19,197,30,72,180,79,221,100,134,120,117,124,85,73,132,224,223,222,41,155,137,218,130,238,237,157,161,134,150,69,206,91,141,17,89,120,218,235,229,37,150,76,197,7,157,56,144,42,203,137,100,200,72,141,194,239,1,67,236,238,183,48,214,75,76,108,235,3,237,67,40,137,45,182,236,246,37,116,103,144,237,142,211,88,233,11,24,21,218,41,245,250,51,130,250,104,74,189,17,69,145,70,50,50,215,253,155,10,128,41,114,185,211,82,164,72,92,17,145,104,66,6,140,226,80,43,62,1,166,216,153,118,96,15,147,126,137,118,191,192,75,149,241,206,18,92,17,154,215,219,18,6,139,190,103,210,156,184,29,224,213,157,60,112,189,104,220,125,40,186,50,119,17,143,136,149,38,74,107,21,192,59,61,59,42,231,144,59,175,3,176,87,23,16,122,54,31,82,34,230,211,44,81,41,47,86,37,228,175,130,148,88,136,131,254,241,202,99,199,175,1,141,215,124,155,120,43,141,89,11,140,120,141,29,35,82,219,155,204,75,12,66,241,253,33,250,84,24,85,68,13,80,85,142,227,34,139,26,146,24>>,
OthersPublicKey = 635619632099733175381667940709387641100492974601603060984753028943194386334921787463327680809776598322996634648015962954045728174069768874873236397421720142610982770302060309928552098274817978606093380781524199673890631795310930242601197479471368910519338301177304682162189801040921618559902948819107531088646753320486728060005223263561551402855338732899079439899705951063999951507319258050864346087428042978411873495523439615429804957374639092580169417598963105885529553632847023899713490485619763926900318508906706745060947269748612049634207985438016935262521715769812475329234748426647554362991758104620357149045960316987533503707855364806010494793980069245562784050236811004893018183726397041999426883788660276453352521120006817370050691205529335316794439089316232980047277245051173281601960196573681285904611182521967067911862467395705665888521948321299521549941618586026714676885890192323289343756440666276226084448279082483536164085883288884231665240707495770544705648564889889198060417915693315346959170105413290799314390963124178046425737828369059171472978294050322371452255088799865552038756937873388385970088906560408959959429398326288750834357514847891423941047433478384621074116184703014798814515161475596555032391555842,
MyPrivateKey = 387759582879975726965038486537011291913744975764132199838375902680222019267527675651273586836110220500657652661706223760165097275862806031329642160439090779625708664007910974206651834216043397115514725827856461492311499129200688538220719685637154290305617686974719521885238198226075381217068175824097878445476010193039590876624464274744156624589136789060427283492343902761765833713520850870233407503430180028104167029073459918756981323130062648615262139444306321256382009848217866984408901761817655567071716275177768316006340055589170095799943481591033461616307776069027985761229636731465482676467627154100912586936231051371168178564599296638350391246393336702334311781595616786107810962134407697848002331639021101685320844880636050048769216986088652236979636019052557155807310341483407890060105599892252118584570558049301477535792498672552850760356632076013402382600669875697284264329434950712239302528367835155163504374877787288116104285944993818319105835423479332617802010952731990182088670508346704423006877514817882782443833997288652405892920173712497948376815825396272381214976859009518623799156300136570204539240675245115597412280078940442452936425561984312708387584800789375684525365060589104566195610526570099527133097201479,
@@ -506,6 +569,45 @@ compute(Config) when is_list(Config) ->
Gen = proplists:get_value(compute, Config),
lists:foreach(fun do_compute/1, Gen).
%%--------------------------------------------------------------------
+use_all_elliptic_curves() ->
+ [{doc, " Test that all curves from crypto:ec_curves/0"}].
+use_all_elliptic_curves(_Config) ->
+ Msg = <<"hello world!">>,
+ Sups = crypto:supports(),
+ Curves = proplists:get_value(curves, Sups),
+ Hashs = proplists:get_value(hashs, Sups),
+ ct:log("Lib: ~p~nFIPS: ~p~nCurves:~n~p~nHashs: ~p", [crypto:info_lib(),
+ crypto:info_fips(),
+ Curves,
+ Hashs]),
+ Results =
+ [{{Curve,Hash},
+ try
+ {Pub,Priv} = crypto:generate_key(ecdh, Curve),
+ true = is_binary(Pub),
+ true = is_binary(Priv),
+ Sig = crypto:sign(ecdsa, Hash, Msg, [Priv, Curve]),
+ crypto:verify(ecdsa, Hash, Msg, Sig, [Pub, Curve])
+ catch
+ C:E ->
+ {C,E}
+ end}
+ || Curve <- Curves -- [ed25519, ed448, x25519, x448, ipsec3, ipsec4],
+ Hash <- Hashs -- [md4, md5, ripemd160, sha3_224, sha3_256, sha3_384, sha3_512]
+ ],
+ Fails =
+ lists:filter(fun({_,true}) -> false;
+ (_) -> true
+ end, Results),
+ case Fails of
+ [] ->
+ ok;
+ _ ->
+ ct:log("Fails:~n~p",[Fails]),
+ ct:fail("Bad curve(s)",[])
+ end.
+
+%%--------------------------------------------------------------------
generate() ->
[{doc, " Test crypto:generate_key"}].
generate(Config) when is_list(Config) ->
@@ -530,6 +632,25 @@ rand_uniform(Config) when is_list(Config) ->
10 = byte_size(crypto:strong_rand_bytes(10)).
%%--------------------------------------------------------------------
+rand_threads() ->
+ [{doc, "strong_rand_bytes in parallel threads"}].
+rand_threads(Config) when is_list(Config) ->
+ %% This will crash the emulator on at least one version of libcrypto
+ %% with buggy multithreading in RAND_bytes().
+ %% The test needs to run at least a few minutes...
+ NofThreads = 4,
+ Fun = fun F() -> crypto:strong_rand_bytes(16), F() end,
+ PidRefs = [spawn_monitor(Fun) || _ <- lists:seq(1, NofThreads)],
+%%% The test case takes too much time to run.
+%%% Keep it around for reference by setting it down to just 10 seconds.
+%%% receive after 10 * 60 * 1000 -> ok end, % 10 minutes
+ receive after 10 * 1000 -> ok end, % 10 seconds
+ spawn_link(fun () -> receive after 5000 -> exit(timeout) end end),
+ [exit(Pid, stop) || {Pid,_Ref} <- PidRefs],
+ [receive {'DOWN',Ref,_,_,stop} -> ok end || {_Pid,Ref} <- PidRefs],
+ ok.
+
+%%--------------------------------------------------------------------
rand_plugin() ->
[{doc, "crypto rand plugin testing (implicit state / process dictionary)"}].
rand_plugin(Config) when is_list(Config) ->
@@ -571,31 +692,29 @@ hash_increment(State0, [Increment | Rest]) ->
hmac(_, [],[],[]) ->
ok;
hmac(sha = Type, [Key | Keys], [ <<"Test With Truncation">> = Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data, 20) of
- Expected ->
- ok;
- Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
+ call_crypto_hmac([Type, Key, Data, 20], Type, Expected),
hmac(Type, Keys, Rest, Expects);
-
hmac(Type, [Key | Keys], [ <<"Test With Truncation">> = Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data, 16) of
- Expected ->
- ok;
- Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
+ call_crypto_hmac([Type, Key, Data, 16], Type, Expected),
hmac(Type, Keys, Rest, Expects);
-
hmac(Type, [Key | Keys], [Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data) of
+ call_crypto_hmac([Type, Key, Data], Type, Expected),
+ hmac(Type, Keys, Rest, Expects).
+
+call_crypto_hmac(Args, Type, Expected) ->
+ try apply(crypto, hmac, Args)
+ of
Expected ->
ok;
Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
- hmac(Type, Keys, Rest, Expects).
+ ct:fail({{crypto,hmac,Args}, {expected,Expected}, {got,Other}})
+ catch
+ error:notsup ->
+ ct:fail("HMAC ~p not supported", [Type]);
+ Class:Cause ->
+ ct:fail({{crypto,hmac,Args}, {expected,Expected}, {got,{Class,Cause}}})
+ end.
+
hmac_increment(Type) ->
Key = hmac_key(Type),
@@ -726,16 +845,33 @@ stream_cipher({Type, Key, IV, PlainText}) ->
ok;
Other ->
ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other}})
+ end;
+stream_cipher({Type, Key, IV, PlainText, CipherText}) ->
+ Plain = iolist_to_binary(PlainText),
+ State = crypto:stream_init(Type, Key, IV),
+ case crypto:stream_encrypt(State, PlainText) of
+ {_, CipherText} ->
+ ok;
+ {_, Other0} ->
+ ct:fail({{crypto, stream_encrypt, [State, Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}})
+ end,
+ case crypto:stream_decrypt(State, CipherText) of
+ {_, Plain} ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other1}})
end.
stream_cipher_incment({Type, Key, PlainTexts}) ->
State = crypto:stream_init(Type, Key),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
stream_cipher_incment({Type, Key, IV, PlainTexts}) ->
State = crypto:stream_init(Type, Key, IV),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts)).
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+stream_cipher_incment({Type, Key, IV, PlainTexts, _CipherText}) ->
+ stream_cipher_incment({Type, Key, IV, PlainTexts}).
-stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
+stream_cipher_incment_loop(_State, OrigState, [], Acc, Plain) ->
CipherText = iolist_to_binary(lists:reverse(Acc)),
case crypto:stream_decrypt(OrigState, CipherText) of
{_, Plain} ->
@@ -743,40 +879,80 @@ stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
Other ->
ct:fail({{crypto, stream_decrypt, [OrigState, CipherText]}, {expected, Plain}, {got, Other}})
end;
-stream_cipher_incment(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
+stream_cipher_incment_loop(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
{State, CipherText} = crypto:stream_encrypt(State0, PlainText),
- stream_cipher_incment(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
+ stream_cipher_incment_loop(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
-aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag}) ->
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, Info}) ->
Plain = iolist_to_binary(PlainText),
case crypto:block_encrypt(Type, Key, IV, {AAD, Plain}) of
{CipherText, CipherTag} ->
ok;
Other0 ->
- ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, CipherTag}}, {got, Other0}})
+ ct:fail({{crypto,
+ block_encrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}]},
+ {expected, {CipherText, CipherTag}},
+ {got, Other0}})
end,
case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, CipherTag}) of
Plain ->
ok;
Other1 ->
- ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ ct:fail({{crypto,
+ block_decrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}]},
+ {expected, Plain},
+ {got, Other1}})
end;
-aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen}) ->
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}) ->
<<TruncatedCipherTag:TagLen/binary, _/binary>> = CipherTag,
Plain = iolist_to_binary(PlainText),
case crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of
{CipherText, TruncatedCipherTag} ->
ok;
Other0 ->
- ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, TruncatedCipherTag}}, {got, Other0}})
+ ct:fail({{crypto,
+ block_encrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}, {taglen,TagLen}]},
+ {expected, {CipherText, TruncatedCipherTag}},
+ {got, Other0}})
end,
case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, TruncatedCipherTag}) of
Plain ->
ok;
Other1 ->
- ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ ct:fail({{crypto,
+ block_decrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag},
+ {truncated,TruncatedCipherTag}]},
+ {expected, Plain},
+ {got, Other1}})
end.
+do_sign_verify({Type, undefined=Hash, Private, Public, Msg, Signature}) ->
+ case crypto:sign(eddsa, Hash, Msg, [Private,Type]) of
+ Signature ->
+ ct:log("OK crypto:sign(eddsa, ~p, Msg, [Private,~p])", [Hash,Type]),
+ case crypto:verify(eddsa, Hash, Msg, Signature, [Public,Type]) of
+ true ->
+ ct:log("OK crypto:verify(eddsa, ~p, Msg, Signature, [Public,~p])", [Hash,Type]),
+ negative_verify(eddsa, Hash, Msg, <<10,20>>, [Public,Type]);
+ false ->
+ ct:log("ERROR crypto:verify(eddsa, ~p, Msg= ~p, Signature= ~p, [Public= ~p,~p])",
+ [Hash,Msg,Signature,Public,Type]),
+ ct:fail({{crypto, verify, [eddsa, Hash, Msg, Signature, [Public,Type]]}})
+ end;
+ ErrorSig ->
+ ct:log("ERROR crypto:sign(~p, ~p, ..., [Private= ~p,~p])", [eddsa,Hash,Private,Type]),
+ ct:log("ERROR crypto:verify(eddsa, ~p, Msg= ~p, [Public= ~p,~p])~n"
+ "ErrorSig = ~p~n"
+ "CorrectSig = ~p~n"
+ ,
+ [Hash,Msg,Public,Type,ErrorSig,Signature]),
+ ct:fail({{crypto, sign, [Type, Hash, Msg, ErrorSig, [Private]]}})
+ end;
+
do_sign_verify({Type, Hash, Public, Private, Msg}) ->
Signature = crypto:sign(Type, Hash, Msg, Private),
case crypto:verify(Type, Hash, Msg, Signature, Public) of
@@ -837,25 +1013,48 @@ negative_verify(Type, Hash, Msg, Signature, Public, Options) ->
end.
do_public_encrypt({Type, Public, Private, Msg, Padding}) ->
- PublicEcn = (catch crypto:public_encrypt(Type, Msg, Public, Padding)),
- case crypto:private_decrypt(Type, PublicEcn, Private, Padding) of
- Msg ->
- ok;
- Other ->
- ct:fail({{crypto, private_decrypt, [Type, PublicEcn, Private, Padding]}, {expected, Msg}, {got, Other}})
+ try
+ crypto:public_encrypt(Type, Msg, Public, Padding)
+ of
+ PublicEcn ->
+ try
+ crypto:private_decrypt(Type, PublicEcn, Private, Padding)
+ of
+ Msg ->
+ ok;
+ Other ->
+ ct:fail({{crypto, private_decrypt, [Type, PublicEcn, Private, Padding]}, {expected, Msg}, {got, Other}})
+ catch
+ CC:EE ->
+ ct:fail({{crypto, private_decrypt, [Type, PublicEcn, Private, Padding]}, {expected, Msg}, {got, {CC,EE}}})
+ end
+ catch
+ CC:EE ->
+ ct:fail({{crypto, public_encrypt, [Type, Msg, Public, Padding]}, {got, {CC,EE}}})
end.
-do_private_encrypt({_Type, _Public, _Private, _Msg, rsa_pkcs1_oaep_padding}) ->
- ok; %% Not supported by openssl
+
do_private_encrypt({Type, Public, Private, Msg, Padding}) ->
- PrivEcn = (catch crypto:private_encrypt(Type, Msg, Private, Padding)),
- case crypto:public_decrypt(Type, PrivEcn, Public, Padding) of
- Msg ->
- ok;
- Other ->
- ct:fail({{crypto, public_decrypt, [Type, PrivEcn, Public, Padding]}, {expected, Msg}, {got, Other}})
+ try
+ crypto:private_encrypt(Type, Msg, Private, Padding)
+ of
+ PrivEcn ->
+ try
+ crypto:public_decrypt(Type, PrivEcn, Public, Padding)
+ of
+ Msg ->
+ ok;
+ Other ->
+ ct:fail({{crypto, public_decrypt, [Type, PrivEcn, Public, Padding]}, {expected, Msg}, {got, Other}})
+ catch
+ CC:EE ->
+ ct:fail({{crypto, public_decrypt, [Type, PrivEcn, Public, Padding]}, {expected, Msg}, {got, {CC,EE}}})
+ end
+ catch
+ CC:EE ->
+ ct:fail({{crypto, private_encrypt, [Type, Msg, Private, Padding]}, {got, {CC,EE}}})
end.
-
+
do_generate_compute({srp = Type, UserPrivate, UserGenParams, UserComParams,
HostPublic, HostPrivate, HostGenParams, HostComParam, SessionKey}) ->
{UserPublic, UserPrivate} = crypto:generate_key(Type, UserGenParams, UserPrivate),
@@ -924,6 +1123,8 @@ hexstr2bin(S) when is_binary(S) ->
hexstr2bin(S) ->
list_to_binary(hexstr2list(S)).
+hexstr2list([$ |T]) ->
+ hexstr2list(T);
hexstr2list([X,Y|T]) ->
[mkint(X)*16 + mkint(Y) | hexstr2list(T)];
hexstr2list([]) ->
@@ -935,6 +1136,14 @@ mkint(C) when $A =< C, C =< $F ->
mkint(C) when $a =< C, C =< $f ->
C - $a + 10.
+bin2hexstr(B) when is_binary(B) ->
+ io_lib:format("~.16b",[crypto:bytes_to_integer(B)]).
+
+decstr2int(S) when is_binary(S) ->
+ list_to_integer(binary:bin_to_list(S));
+decstr2int(S) ->
+ list_to_integer(S).
+
is_supported(Group) ->
lists:member(Group, lists:append([Algo || {_, Algo} <- crypto:supports()])).
@@ -953,7 +1162,9 @@ do_cmac_iolistify({Type, Key, Text, Size, CMac}) ->
do_stream_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
do_stream_iolistify({Type, Key, IV, PlainText}) ->
- {Type, iolistify(Key), IV, iolistify(PlainText)}.
+ {Type, iolistify(Key), IV, iolistify(PlainText)};
+do_stream_iolistify({Type, Key, IV, PlainText, CipherText}) ->
+ {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
do_block_iolistify({des_cbc = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
@@ -1199,7 +1410,7 @@ group_config(sha224 = Type, Config) ->
Keys = rfc_4231_keys(),
Data = rfc_4231_msgs(),
Hmac = rfc4231_hmac_sha224(),
- [{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
+ [{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha256 = Type, Config) ->
Msgs = [rfc_4634_test1(), rfc_4634_test2_1(), long_msg()],
Digests = rfc_4634_sha256_digests() ++ [long_sha256_digest()],
@@ -1221,31 +1432,54 @@ group_config(sha512 = Type, Config) ->
Data = rfc_4231_msgs() ++ [long_msg()],
Hmac = rfc4231_hmac_sha512() ++ [long_hmac(sha512)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
-group_config(rsa = Type, Config) ->
+group_config(sha3_224 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_256 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_384 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_512 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(rsa, Config) ->
Msg = rsa_plain(),
Public = rsa_public(),
Private = rsa_private(),
PublicS = rsa_public_stronger(),
PrivateS = rsa_private_stronger(),
- SignVerify =
- case ?config(fips, Config) of
- true ->
- %% Use only the strong keys in FIPS mode
- sign_verify_tests(Type, Msg,
- PublicS, PrivateS,
- PublicS, PrivateS);
- false ->
- sign_verify_tests(Type, Msg,
- Public, Private,
- PublicS, PrivateS)
- end,
MsgPubEnc = <<"7896345786348 Asldi">>,
- PubPrivEnc = [{rsa, PublicS, PrivateS, MsgPubEnc, rsa_pkcs1_padding},
- rsa_oaep(),
- no_padding()
+ SignVerify_OptsToTry = [[{rsa_padding, rsa_x931_padding}],
+ [{rsa_padding, rsa_pkcs1_padding}],
+ [{rsa_padding, rsa_pkcs1_pss_padding}],
+ [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_pss_saltlen, -2}],
+ [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_pss_saltlen, 5}],
+ [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_mgf1_md,sha}],
+ [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_mgf1_md,sha}, {rsa_pss_saltlen, 5}]
+ ],
+ PrivEnc_OptsToTry = [rsa_pkcs1_padding, % Compatibility
+ [{rsa_pad, rsa_pkcs1_padding}], % Compatibility
+ [{rsa_padding, rsa_pkcs1_padding}],
+ [{rsa_padding,rsa_x931_padding}]
+ ],
+ PubEnc_OptsToTry = [rsa_pkcs1_padding, % Compatibility
+ [{rsa_pad, rsa_pkcs1_padding}], % Compatibility
+ [{rsa_padding, rsa_pkcs1_padding}],
+ [{rsa_padding,rsa_pkcs1_oaep_padding}],
+ [{rsa_padding,rsa_pkcs1_oaep_padding}, {rsa_oaep_label, <<"Hej hopp">>}],
+ [{rsa_padding,rsa_pkcs1_oaep_padding}, {rsa_oaep_md,sha}],
+ [{rsa_padding,rsa_pkcs1_oaep_padding}, {rsa_oaep_md,sha}, {rsa_oaep_label, <<"Hej hopp">>}],
+ [{rsa_padding,rsa_pkcs1_oaep_padding}, {rsa_mgf1_md,sha}],
+ [{rsa_padding,rsa_pkcs1_oaep_padding}, {rsa_mgf1_md,sha}, {rsa_oaep_label, <<"Hej hopp">>}],
+ [{rsa_padding,rsa_pkcs1_oaep_padding}, {rsa_mgf1_md,sha}, {rsa_oaep_md,sha}, {rsa_oaep_label, <<"Hej hopp">>}]
],
- Generate = [{rsa, 1024, 3}, {rsa, 2048, 17}, {rsa, 3072, 65537}],
- [{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc}, {generate, Generate} | Config];
+ [{sign_verify, rsa_sign_verify_tests(Config, Msg, Public, Private, PublicS, PrivateS, SignVerify_OptsToTry)},
+ {pub_priv_encrypt, gen_rsa_pub_priv_tests(PublicS, PrivateS, MsgPubEnc, PrivEnc_OptsToTry)},
+ {pub_pub_encrypt, gen_rsa_pub_priv_tests(PublicS, PrivateS, MsgPubEnc, PubEnc_OptsToTry)},
+ {generate, [{rsa, 1024, 3}, {rsa, 2048, 17}, {rsa, 3072, 65537}]}
+ | Config];
group_config(dss = Type, Config) ->
Msg = dss_plain(),
Public = dss_params() ++ [dss_public()],
@@ -1278,6 +1512,12 @@ group_config(ecdsa = Type, Config) ->
MsgPubEnc = <<"7896345786348 Asldi">>,
PubPrivEnc = [{ecdsa, Public, Private, MsgPubEnc, []}],
[{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config];
+
+group_config(Type, Config) when Type == ed25519 ; Type == ed448 ->
+ TestVectors = eddsa(Type),
+ [{sign_verify,TestVectors} | Config];
+
+
group_config(srp, Config) ->
GenerateCompute = [srp3(), srp6(), srp6a(), srp6a_smaller_prime()],
[{generate_compute, GenerateCompute} | Config];
@@ -1347,52 +1587,101 @@ group_config(rc4, Config) ->
group_config(aes_ctr, Config) ->
Stream = aes_ctr(),
[{stream, Stream} | Config];
+group_config(aes_ccm, Config) ->
+ AEAD = fun() -> aes_ccm(Config) end,
+ [{aead, AEAD} | Config];
group_config(aes_gcm, Config) ->
AEAD = fun() -> aes_gcm(Config) end,
[{aead, AEAD} | Config];
group_config(chacha20_poly1305, Config) ->
AEAD = chacha20_poly1305(),
[{aead, AEAD} | Config];
+group_config(chacha20, Config) ->
+ Stream = chacha20(),
+ [{stream, Stream} | Config];
+group_config(poly1305, Config) ->
+ V = [%% {Key, Txt, Expect}
+ {%% RFC7539 2.5.2
+ crypto_SUITE:hexstr2bin("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b"),
+ <<"Cryptographic Forum Research Group">>,
+ crypto_SUITE:hexstr2bin("a8061dc1305136c6c22b8baf0c0127a9")
+ }
+ ],
+ [{poly1305,V} | Config];
group_config(aes_cbc, Config) ->
Block = aes_cbc(Config),
[{block, Block} | Config];
group_config(_, Config) ->
Config.
-sign_verify_tests(Type, Msg, Public, Private, PublicS, PrivateS) ->
- gen_sign_verify_tests(Type, [md5, ripemd160, sha, sha224, sha256], Msg, Public, Private,
- [undefined,
- [{rsa_padding, rsa_pkcs1_pss_padding}],
- [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_pss_saltlen, 0}],
- [{rsa_padding, rsa_x931_padding}]
- ]) ++
- gen_sign_verify_tests(Type, [sha384, sha512], Msg, PublicS, PrivateS,
- [undefined,
- [{rsa_padding, rsa_pkcs1_pss_padding}],
- [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_pss_saltlen, 0}],
- [{rsa_padding, rsa_x931_padding}]
- ]).
-
-gen_sign_verify_tests(Type, Hashs, Msg, Public, Private, Opts) ->
+rsa_sign_verify_tests(Config, Msg, Public, Private, PublicS, PrivateS, OptsToTry) ->
+ case ?config(fips, Config) of
+ true ->
+ %% Use only the strong keys in FIPS mode
+ rsa_sign_verify_tests(Msg,
+ PublicS, PrivateS,
+ PublicS, PrivateS,
+ OptsToTry);
+ false ->
+ rsa_sign_verify_tests(Msg,
+ Public, Private,
+ PublicS, PrivateS,
+ OptsToTry)
+ end.
+
+rsa_sign_verify_tests(Msg, Public, Private, PublicS, PrivateS, OptsToTry) ->
+ gen_rsa_sign_verify_tests([md5, ripemd160, sha, sha224, sha256], Msg, Public, Private,
+ [undefined | OptsToTry]) ++
+ gen_rsa_sign_verify_tests([sha384, sha512], Msg, PublicS, PrivateS,
+ [undefined | OptsToTry]).
+
+gen_rsa_sign_verify_tests(Hashs, Msg, Public, Private, Opts) ->
+ SupOpts = proplists:get_value(rsa_opts, crypto:supports(), []),
lists:foldr(fun(Hash, Acc0) ->
case is_supported(Hash) of
true ->
lists:foldr(fun
(undefined, Acc1) ->
- [{Type, Hash, Public, Private, Msg} | Acc1];
+ [{rsa, Hash, Public, Private, Msg} | Acc1];
([{rsa_padding, rsa_x931_padding} | _], Acc1)
when Hash =:= md5
orelse Hash =:= ripemd160
orelse Hash =:= sha224 ->
Acc1;
(Opt, Acc1) ->
- [{Type, Hash, Public, Private, Msg, Opt} | Acc1]
+ case rsa_opt_is_supported(Opt, SupOpts) of
+ true ->
+ [{rsa, Hash, Public, Private, Msg, Opt} | Acc1];
+ false ->
+ Acc1
+ end
end, Acc0, Opts);
false ->
Acc0
end
end, [], Hashs).
+
+gen_rsa_pub_priv_tests(Public, Private, Msg, OptsToTry) ->
+ SupOpts = proplists:get_value(rsa_opts, crypto:supports(), []),
+ lists:foldr(fun(Opt, Acc) ->
+ case rsa_opt_is_supported(Opt, SupOpts) of
+ true ->
+ [{rsa, Public, Private, Msg, Opt} | Acc];
+ false ->
+ Acc
+ end
+ end, [], OptsToTry).
+
+
+rsa_opt_is_supported([_|_]=Opt, Sup) ->
+ lists:all(fun(O) -> rsa_opt_is_supported(O,Sup) end, Opt);
+rsa_opt_is_supported({A,B}, Sup) ->
+ rsa_opt_is_supported(A,Sup) orelse rsa_opt_is_supported(B,Sup);
+rsa_opt_is_supported(Opt, Sup) ->
+ lists:member(Opt, Sup).
+
+
rfc_1321_msgs() ->
[<<"">>,
<<"a">>,
@@ -1421,6 +1710,160 @@ rfc_1321_md5_digests() ->
hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f"),
hexstr2bin("57edf4a22be3c955ac49da2e2107b67a")].
+%%% https://www.di-mgt.com.au/sha_testvectors.html
+sha3_msgs() ->
+ ["abc",
+ "",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", % length 448 bits
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", % length 896 bits
+ lists:duplicate(1000000,$a)
+ ].
+
+sha3_test_vectors(sha3_224) ->
+ {sha3_msgs(),
+ [hexstr2bin("e642824c3f8cf24a d09234ee7d3c766f c9a3a5168d0c94ad 73b46fdf"),
+ hexstr2bin("6b4e03423667dbb7 3b6e15454f0eb1ab d4597f9a1b078e3f 5b5a6bc7"),
+ hexstr2bin("8a24108b154ada21 c9fd5574494479ba 5c7e7ab76ef264ea d0fcce33"),
+ hexstr2bin("543e6868e1666c1a 643630df77367ae5 a62a85070a51c14c bf665cbc"),
+ hexstr2bin("d69335b93325192e 516a912e6d19a15c b51c6ed5c15243e7 a7fd653c")
+ ]
+ };
+sha3_test_vectors(sha3_256) ->
+ {sha3_msgs(),
+ [hexstr2bin("3a985da74fe225b2 045c172d6bd390bd 855f086e3e9d525b 46bfe24511431532"),
+ hexstr2bin("a7ffc6f8bf1ed766 51c14756a061d662 f580ff4de43b49fa 82d80a4b80f8434a"),
+ hexstr2bin("41c0dba2a9d62408 49100376a8235e2c 82e1b9998a999e21 db32dd97496d3376"),
+ hexstr2bin("916f6061fe879741 ca6469b43971dfdb 28b1a32dc36cb325 4e812be27aad1d18"),
+ hexstr2bin("5c8875ae474a3634 ba4fd55ec85bffd6 61f32aca75c6d699 d0cdcb6c115891c1")
+ ]
+ };
+sha3_test_vectors(sha3_384) ->
+ {sha3_msgs(),
+ [hexstr2bin("ec01498288516fc9 26459f58e2c6ad8d f9b473cb0fc08c25 96da7cf0e49be4b2 98d88cea927ac7f5 39f1edf228376d25"),
+ hexstr2bin("0c63a75b845e4f7d 01107d852e4c2485 c51a50aaaa94fc61 995e71bbee983a2a c3713831264adb47 fb6bd1e058d5f004"),
+ hexstr2bin("991c665755eb3a4b 6bbdfb75c78a492e 8c56a22c5c4d7e42 9bfdbc32b9d4ad5a a04a1f076e62fea1 9eef51acd0657c22"),
+ hexstr2bin("79407d3b5916b59c 3e30b09822974791 c313fb9ecc849e40 6f23592d04f625dc 8c709b98b43b3852 b337216179aa7fc7"),
+ hexstr2bin("eee9e24d78c18553 37983451df97c8ad 9eedf256c6334f8e 948d252d5e0e7684 7aa0774ddb90a842 190d2c558b4b8340")
+ ]
+ };
+sha3_test_vectors(sha3_512) ->
+ {sha3_msgs(),
+ [hexstr2bin("b751850b1a57168a 5693cd924b6b096e 08f621827444f70d 884f5d0240d2712e 10e116e9192af3c9 1a7ec57647e39340 57340b4cf408d5a5 6592f8274eec53f0"),
+ hexstr2bin("a69f73cca23a9ac5 c8b567dc185a756e 97c982164fe25859 e0d1dcc1475c80a6 15b2123af1f5f94c 11e3e9402c3ac558 f500199d95b6d3e3 01758586281dcd26"),
+ hexstr2bin("04a371e84ecfb5b8 b77cb48610fca818 2dd457ce6f326a0f d3d7ec2f1e91636d ee691fbe0c985302 ba1b0d8dc78c0863 46b533b49c030d99 a27daf1139d6e75e"),
+ hexstr2bin("afebb2ef542e6579 c50cad06d2e578f9 f8dd6881d7dc824d 26360feebf18a4fa 73e3261122948efc fd492e74e82e2189 ed0fb440d187f382 270cb455f21dd185"),
+ hexstr2bin("3c3a876da14034ab 60627c077bb98f7e 120a2a5370212dff b3385a18d4f38859 ed311d0a9d5141ce 9cc5c66ee689b266 a8aa18ace8282a0e 0db596c90b0a7b87")
+ ]
+ }.
+
+
+
+%%% http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html
+
+hmac_sha3(Type) ->
+ N = case Type of
+ sha3_224 -> 1;
+ sha3_256 -> 2;
+ sha3_384 -> 3;
+ sha3_512 -> 4
+ end,
+ {Keys, Datas, Hmacs} =
+ lists:unzip3(
+ [{hexstr2bin(Key), hexstr2bin(Data), hexstr2bin(element(N,Hmacs))}
+ || {Key,Data,Hmacs} <- hmac_sha3_data()]),
+ {Type, Keys, Datas, Hmacs}.
+
+
+hmac_sha3_data() ->
+ [
+ {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 0b0b0b0b",
+ "4869205468657265",
+ {"3b16546bbc7be2706a031dcafd56373d 9884367641d8c59af3c860f7",
+ "ba85192310dffa96e2a3a40e69774351 140bb7185e1202cdcc917589f95e16bb",
+ "68d2dcf7fd4ddd0a2240c8a437305f61 fb7334cfb5d0226e1bc27dc10a2e723a 20d370b47743130e26ac7e3d532886bd",
+ "eb3fbd4b2eaab8f5c504bd3a41465aac ec15770a7cabac531e482f860b5ec7ba 47ccb2c6f2afce8f88d22b6dc61380f2 3a668fd3888bb80537c0a0b86407689e"
+ }},
+
+ {"4a656665",
+ "7768617420646f2079612077616e7420 666f72206e6f7468696e673f",
+ {"7fdb8dd88bd2f60d1b798634ad386811 c2cfc85bfaf5d52bbace5e66",
+ "c7d4072e788877ae3596bbb0da73b887 c9171f93095b294ae857fbe2645e1ba5",
+ "f1101f8cbf9766fd6764d2ed61903f21 ca9b18f57cf3e1a23ca13508a93243ce 48c045dc007f26a21b3f5e0e9df4c20a",
+ "5a4bfeab6166427c7a3647b747292b83 84537cdb89afb3bf5665e4c5e709350b 287baec921fd7ca0ee7a0c31d022a95e 1fc92ba9d77df883960275beb4e62024"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd dddddddddddddddddddddddddddddddd dddddddddddddddddddddddddddddddd dddd",
+ {"676cfc7d16153638780390692be142d2 df7ce924b909c0c08dbfdc1a",
+ "84ec79124a27107865cedd8bd82da996 5e5ed8c37b0ac98005a7f39ed58a4207",
+ "275cd0e661bb8b151c64d288f1f782fb 91a8abd56858d72babb2d476f0458373 b41b6ab5bf174bec422e53fc3135ac6e",
+ "309e99f9ec075ec6c6d475eda1180687 fcf1531195802a99b5677449a8625182 851cb332afb6a89c411325fbcbcd42af cb7b6e5aab7ea42c660f97fd8584bf03"
+ }},
+
+ {"0102030405060708090a0b0c0d0e0f10 111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcd",
+ {"a9d7685a19c4e0dbd9df2556cc8a7d2a 7733b67625ce594c78270eeb",
+ "57366a45e2305321a4bc5aa5fe2ef8a9 21f6af8273d7fe7be6cfedb3f0aea6d7",
+ "3a5d7a879702c086bc96d1dd8aa15d9c 46446b95521311c606fdc4e308f4b984 da2d0f9449b3ba8425ec7fb8c31bc136",
+ "b27eab1d6e8d87461c29f7f5739dd58e 98aa35f8e823ad38c5492a2088fa0281 993bbfff9a0e9c6bf121ae9ec9bb09d8 4a5ebac817182ea974673fb133ca0d1d"
+ }},
+
+ %% {"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c 0c0c0c0c",
+ %% "546573742057697468205472756e6361 74696f6e",
+ %% {"49fdd3abd005ebb8ae63fea946d1883c",
+ %% "6e02c64537fb118057abb7fb66a23b3c",
+ %% "47c51ace1ffacffd7494724682615783",
+ %% "0fa7475948f43f48ca0516671e18978c"
+ %% }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54657374205573696e67204c61726765 72205468616e20426c6f636b2d53697a 65204b6579202d2048617368204b6579 204669727374",
+ {"b4a1f04c00287a9b7f6075b313d279b8 33bc8f75124352d05fb9995f",
+ "ed73a374b96c005235f948032f09674a 58c0ce555cfc1f223b02356560312c3b",
+ "0fc19513bf6bd878037016706a0e57bc 528139836b9a42c3d419e498e0e1fb96 16fd669138d33a1105e07c72b6953bcc",
+ "00f751a9e50695b090ed6911a4b65524 951cdc15a73a5d58bb55215ea2cd839a c79d2b44a39bafab27e83fde9e11f634 0b11d991b1b91bf2eee7fc872426c3a4"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54657374205573696e67204c61726765 72205468616e20426c6f636b2d53697a 65204b6579202d2048617368204b6579 204669727374",
+ {
+ "b96d730c148c2daad8649d83defaa371 9738d34775397b7571c38515",
+ "a6072f86de52b38bb349fe84cd6d97fb 6a37c4c0f62aae93981193a7229d3467",
+ "713dff0302c85086ec5ad0768dd65a13 ddd79068d8d4c6212b712e4164944911 1480230044185a99103ed82004ddbfcc",
+ "b14835c819a290efb010ace6d8568dc6 b84de60bc49b004c3b13eda763589451 e5dd74292884d1bdce64e6b919dd61dc 9c56a282a81c0bd14f1f365b49b83a5b"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e",
+ {
+ "05d8cd6d00faea8d1eb68ade28730bbd 3cbab6929f0a086b29cd62a0",
+ "65c5b06d4c3de32a7aef8763261e49ad b6e2293ec8e7c61e8de61701fc63e123",
+ "026fdf6b50741e373899c9f7d5406d4e b09fc6665636fc1a530029ddf5cf3ca5 a900edce01f5f61e2f408cdf2fd3e7e8",
+ "38a456a004bd10d32c9ab83366841128 62c3db61adcca31829355eaf46fd5c73 d06a1f0d13fec9a652fb3811b577b1b1 d1b9789f97ae5b83c6f44dfcf1d67eba"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e",
+ {
+ "c79c9b093424e588a9878bbcb089e018 270096e9b4b1a9e8220c866a",
+ "e6a36d9b915f86a093cac7d110e9e04c f1d6100d30475509c2475f571b758b5a",
+ "cad18a8ff6c4cc3ad487b95f9769e9b6 1c062aefd6952569e6e6421897054cfc 70b5fdc6605c18457112fc6aaad45585",
+ "dc030ee7887034f32cf402df34622f31 1f3e6cf04860c6bbd7fa488674782b46 59fdbdf3fd877852885cfe6e22185fe7 b2ee952043629bc9d5f3298a41d02c66"
+ }}
+ %%,
+
+ %% {"4a656665",
+ %% "'11001' or LSB 13 or MSB c8",
+ %% {
+ %% "5f8c0ea7fafecd0c3463aad09742cece b142fe0ab6f4539438c59de8",
+ %% "ec8222773fac68b3d3dcb182aec8b050 7ace4448d20a1147e682118da4e3f44c",
+ %% "21fbd3bf3ebba3cfc9ef64c0591c92c5 acb265e92d8761d1f91a52a103a6c796 94cfd67a9a2ac1324f02fea63b81effc",
+ %% "27f9388c1567ef4ef200602a6cf871d6 8a6fb048d4737ac4418a2f021289d13d 1fd1120fecb9cf964c5b117ab5b11c61 4b2da39dadd51f2f5e22aaccec7d576e"
+ %% }}
+ ].
+
+
+
rfc_4634_test1() ->
<<"abc">>.
rfc_4634_test2_1() ->
@@ -1990,6 +2433,13 @@ aes_gcm(Config) ->
"gcmEncryptExtIV192.rsp",
"gcmEncryptExtIV256.rsp"]).
+aes_ccm(Config) ->
+ read_rsp(Config, aes_ccm,
+ ["VADT128.rsp", "VADT192.rsp", "VADT256.rsp",
+ "VNT128.rsp", "VNT192.rsp", "VNT256.rsp",
+ "VPT128.rsp", "VPT192.rsp", "VPT256.rsp"
+ ]).
+
%% https://tools.ietf.org/html/rfc7539#appendix-A.5
chacha20_poly1305() ->
[
@@ -2032,9 +2482,108 @@ chacha20_poly1305() ->
"49e617d91d361094fa68f0ff77987130"
"305beaba2eda04df997b714d6c6f2c29"
"a6ad5cb4022b02709b"),
- hexstr2bin("eead9d67890cbb22392336fea1851f38")} %% CipherTag
+ hexstr2bin("eead9d67890cbb22392336fea1851f38"), %% CipherTag
+ no_info
+ }
].
+
+chacha20() ->
+%%% chacha20 (no mode) test vectors from RFC 7539 A.2
+ [
+ %% Test Vector #1:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000000"), %% Key
+ hexstr2bin("00000000" % Initial counter = 0, little-endian
+ "000000000000000000000000"), %% IV
+ hexstr2bin("00000000000000000000000000000000" %% PlainText
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"),
+ hexstr2bin("76b8e0ada0f13d90405d6ae55386bd28" %% CipherText
+ "bdd219b8a08ded1aa836efcc8b770dc7"
+ "da41597c5157488d7724e03fb8d84a37"
+ "6a43b8f41518a11cc387b669b2ee6586")},
+ %% Test Vector #2:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000001"), %% Key
+ hexstr2bin("01000000" % Initial counter = 1, little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("416e79207375626d697373696f6e2074" %% PlainText
+ "6f20746865204945544620696e74656e"
+ "6465642062792074686520436f6e7472"
+ "696275746f7220666f72207075626c69"
+ "636174696f6e20617320616c6c206f72"
+ "2070617274206f6620616e2049455446"
+ "20496e7465726e65742d447261667420"
+ "6f722052464320616e6420616e792073"
+ "746174656d656e74206d616465207769"
+ "7468696e2074686520636f6e74657874"
+ "206f6620616e20494554462061637469"
+ "7669747920697320636f6e7369646572"
+ "656420616e20224945544620436f6e74"
+ "7269627574696f6e222e205375636820"
+ "73746174656d656e747320696e636c75"
+ "6465206f72616c2073746174656d656e"
+ "747320696e2049455446207365737369"
+ "6f6e732c2061732077656c6c20617320"
+ "7772697474656e20616e6420656c6563"
+ "74726f6e696320636f6d6d756e696361"
+ "74696f6e73206d61646520617420616e"
+ "792074696d65206f7220706c6163652c"
+ "20776869636820617265206164647265"
+ "7373656420746f"),
+ hexstr2bin("a3fbf07df3fa2fde4f376ca23e827370" %% CipherText
+ "41605d9f4f4f57bd8cff2c1d4b7955ec"
+ "2a97948bd3722915c8f3d337f7d37005"
+ "0e9e96d647b7c39f56e031ca5eb6250d"
+ "4042e02785ececfa4b4bb5e8ead0440e"
+ "20b6e8db09d881a7c6132f420e527950"
+ "42bdfa7773d8a9051447b3291ce1411c"
+ "680465552aa6c405b7764d5e87bea85a"
+ "d00f8449ed8f72d0d662ab052691ca66"
+ "424bc86d2df80ea41f43abf937d3259d"
+ "c4b2d0dfb48a6c9139ddd7f76966e928"
+ "e635553ba76c5c879d7b35d49eb2e62b"
+ "0871cdac638939e25e8a1e0ef9d5280f"
+ "a8ca328b351c3c765989cbcf3daa8b6c"
+ "cc3aaf9f3979c92b3720fc88dc95ed84"
+ "a1be059c6499b9fda236e7e818b04b0b"
+ "c39c1e876b193bfe5569753f88128cc0"
+ "8aaa9b63d1a16f80ef2554d7189c411f"
+ "5869ca52c5b83fa36ff216b9c1d30062"
+ "bebcfd2dc5bce0911934fda79a86f6e6"
+ "98ced759c3ff9b6477338f3da4f9cd85"
+ "14ea9982ccafb341b2384dd902f3d1ab"
+ "7ac61dd29c6f21ba5b862f3730e37cfd"
+ "c4fd806c22f221")},
+ %%Test Vector #3:
+ {chacha20,
+ hexstr2bin("1c9240a5eb55d38af333888604f6b5f0"
+ "473917c1402b80099dca5cbc207075c0"), %% Key
+ hexstr2bin("2a000000" % Initial counter = 42 (decimal), little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("2754776173206272696c6c69672c2061" %% PlainText
+ "6e642074686520736c6974687920746f"
+ "7665730a446964206779726520616e64"
+ "2067696d626c6520696e207468652077"
+ "6162653a0a416c6c206d696d73792077"
+ "6572652074686520626f726f676f7665"
+ "732c0a416e6420746865206d6f6d6520"
+ "7261746873206f757467726162652e"),
+ hexstr2bin("62e6347f95ed87a45ffae7426f27a1df" %% CipherText
+ "5fb69110044c0d73118effa95b01e5cf"
+ "166d3df2d721caf9b21e5fb14c616871"
+ "fd84c54f9d65b283196c7fe4f60553eb"
+ "f39c6402c42234e32a356b3e764312a6"
+ "1a5532055716ead6962568f87d3f3f77"
+ "04c6a8d1bcd1bf4d50d6154b6da731b1"
+ "87b58dfd728afa36757a797ac188d1")}
+ ].
+
+
rsa_plain() ->
<<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
"09812312908312378623487263487623412039812 huagasd">>.
@@ -2228,9 +2777,397 @@ srp(ClientPrivate, Generator, Prime, Version, Verifier, ServerPublic, ServerPriv
ServerPublic, ServerPrivate, {host, [Verifier, Generator, Prime, Version]},
{host, [Verifier, Prime, Version, Scrambler]},
SessionKey}.
+
+eddsa(ed25519) ->
+ %% https://tools.ietf.org/html/rfc8032#section-7.1
+ %% {ALGORITHM, (SHA)}, SECRET KEY, PUBLIC KEY, MESSAGE, SIGNATURE}
+ [
+ %% TEST 1
+ {ed25519, undefined,
+ hexstr2bin("9d61b19deffd5a60ba844af492ec2cc4"
+ "4449c5697b326919703bac031cae7f60"),
+ hexstr2bin("d75a980182b10ab7d54bfed3c964073a"
+ "0ee172f3daa62325af021a68f707511a"),
+ hexstr2bin(""),
+ hexstr2bin("e5564300c360ac729086e2cc806e828a"
+ "84877f1eb8e5d974d873e06522490155"
+ "5fb8821590a33bacc61e39701cf9b46b"
+ "d25bf5f0595bbe24655141438e7a100b")},
+ %% TEST 2
+ {ed25519, undefined,
+ hexstr2bin("4ccd089b28ff96da9db6c346ec114e0f"
+ "5b8a319f35aba624da8cf6ed4fb8a6fb"),
+ hexstr2bin("3d4017c3e843895a92b70aa74d1b7ebc"
+ "9c982ccf2ec4968cc0cd55f12af4660c"),
+ hexstr2bin("72"),
+ hexstr2bin("92a009a9f0d4cab8720e820b5f642540"
+ "a2b27b5416503f8fb3762223ebdb69da"
+ "085ac1e43e15996e458f3613d0f11d8c"
+ "387b2eaeb4302aeeb00d291612bb0c00")},
+ %% TEST 3
+ {ed25519, undefined,
+ hexstr2bin("c5aa8df43f9f837bedb7442f31dcb7b1"
+ "66d38535076f094b85ce3a2e0b4458f7"),
+ hexstr2bin("fc51cd8e6218a1a38da47ed00230f058"
+ "0816ed13ba3303ac5deb911548908025"),
+ hexstr2bin("af82"),
+ hexstr2bin("6291d657deec24024827e69c3abe01a3"
+ "0ce548a284743a445e3680d7db5ac3ac"
+ "18ff9b538d16f290ae67f760984dc659"
+ "4a7c15e9716ed28dc027beceea1ec40a")},
+ %% TEST 1024
+ {ed25519, undefined,
+ hexstr2bin("f5e5767cf153319517630f226876b86c"
+ "8160cc583bc013744c6bf255f5cc0ee5"),
+ hexstr2bin("278117fc144c72340f67d0f2316e8386"
+ "ceffbf2b2428c9c51fef7c597f1d426e"),
+ hexstr2bin("08b8b2b733424243760fe426a4b54908"
+ "632110a66c2f6591eabd3345e3e4eb98"
+ "fa6e264bf09efe12ee50f8f54e9f77b1"
+ "e355f6c50544e23fb1433ddf73be84d8"
+ "79de7c0046dc4996d9e773f4bc9efe57"
+ "38829adb26c81b37c93a1b270b20329d"
+ "658675fc6ea534e0810a4432826bf58c"
+ "941efb65d57a338bbd2e26640f89ffbc"
+ "1a858efcb8550ee3a5e1998bd177e93a"
+ "7363c344fe6b199ee5d02e82d522c4fe"
+ "ba15452f80288a821a579116ec6dad2b"
+ "3b310da903401aa62100ab5d1a36553e"
+ "06203b33890cc9b832f79ef80560ccb9"
+ "a39ce767967ed628c6ad573cb116dbef"
+ "efd75499da96bd68a8a97b928a8bbc10"
+ "3b6621fcde2beca1231d206be6cd9ec7"
+ "aff6f6c94fcd7204ed3455c68c83f4a4"
+ "1da4af2b74ef5c53f1d8ac70bdcb7ed1"
+ "85ce81bd84359d44254d95629e9855a9"
+ "4a7c1958d1f8ada5d0532ed8a5aa3fb2"
+ "d17ba70eb6248e594e1a2297acbbb39d"
+ "502f1a8c6eb6f1ce22b3de1a1f40cc24"
+ "554119a831a9aad6079cad88425de6bd"
+ "e1a9187ebb6092cf67bf2b13fd65f270"
+ "88d78b7e883c8759d2c4f5c65adb7553"
+ "878ad575f9fad878e80a0c9ba63bcbcc"
+ "2732e69485bbc9c90bfbd62481d9089b"
+ "eccf80cfe2df16a2cf65bd92dd597b07"
+ "07e0917af48bbb75fed413d238f5555a"
+ "7a569d80c3414a8d0859dc65a46128ba"
+ "b27af87a71314f318c782b23ebfe808b"
+ "82b0ce26401d2e22f04d83d1255dc51a"
+ "ddd3b75a2b1ae0784504df543af8969b"
+ "e3ea7082ff7fc9888c144da2af58429e"
+ "c96031dbcad3dad9af0dcbaaaf268cb8"
+ "fcffead94f3c7ca495e056a9b47acdb7"
+ "51fb73e666c6c655ade8297297d07ad1"
+ "ba5e43f1bca32301651339e22904cc8c"
+ "42f58c30c04aafdb038dda0847dd988d"
+ "cda6f3bfd15c4b4c4525004aa06eeff8"
+ "ca61783aacec57fb3d1f92b0fe2fd1a8"
+ "5f6724517b65e614ad6808d6f6ee34df"
+ "f7310fdc82aebfd904b01e1dc54b2927"
+ "094b2db68d6f903b68401adebf5a7e08"
+ "d78ff4ef5d63653a65040cf9bfd4aca7"
+ "984a74d37145986780fc0b16ac451649"
+ "de6188a7dbdf191f64b5fc5e2ab47b57"
+ "f7f7276cd419c17a3ca8e1b939ae49e4"
+ "88acba6b965610b5480109c8b17b80e1"
+ "b7b750dfc7598d5d5011fd2dcc5600a3"
+ "2ef5b52a1ecc820e308aa342721aac09"
+ "43bf6686b64b2579376504ccc493d97e"
+ "6aed3fb0f9cd71a43dd497f01f17c0e2"
+ "cb3797aa2a2f256656168e6c496afc5f"
+ "b93246f6b1116398a346f1a641f3b041"
+ "e989f7914f90cc2c7fff357876e506b5"
+ "0d334ba77c225bc307ba537152f3f161"
+ "0e4eafe595f6d9d90d11faa933a15ef1"
+ "369546868a7f3a45a96768d40fd9d034"
+ "12c091c6315cf4fde7cb68606937380d"
+ "b2eaaa707b4c4185c32eddcdd306705e"
+ "4dc1ffc872eeee475a64dfac86aba41c"
+ "0618983f8741c5ef68d3a101e8a3b8ca"
+ "c60c905c15fc910840b94c00a0b9d0"),
+ hexstr2bin("0aab4c900501b3e24d7cdf4663326a3a"
+ "87df5e4843b2cbdb67cbf6e460fec350"
+ "aa5371b1508f9f4528ecea23c436d94b"
+ "5e8fcd4f681e30a6ac00a9704a188a03")},
+ %% TEST SHA(abc)
+ {ed25519, undefined,
+ hexstr2bin("833fe62409237b9d62ec77587520911e"
+ "9a759cec1d19755b7da901b96dca3d42"),
+ hexstr2bin("ec172b93ad5e563bf4932c70e1245034"
+ "c35467ef2efd4d64ebf819683467e2bf"),
+ hexstr2bin("ddaf35a193617abacc417349ae204131"
+ "12e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd"
+ "454d4423643ce80e2a9ac94fa54ca49f"),
+ hexstr2bin("dc2a4459e7369633a52b1bf277839a00"
+ "201009a3efbf3ecb69bea2186c26b589"
+ "09351fc9ac90b3ecfdfbc7c66431e030"
+ "3dca179c138ac17ad9bef1177331a704")}
+ ];
+
+eddsa(ed448) ->
+ %% https://tools.ietf.org/html/rfc8032#section-7.4
+ [{ed448, undefined,
+ hexstr2bin("6c82a562cb808d10d632be89c8513ebf"
+ "6c929f34ddfa8c9f63c9960ef6e348a3"
+ "528c8a3fcc2f044e39a3fc5b94492f8f"
+ "032e7549a20098f95b"),
+ hexstr2bin("5fd7449b59b461fd2ce787ec616ad46a"
+ "1da1342485a70e1f8a0ea75d80e96778"
+ "edf124769b46c7061bd6783df1e50f6c"
+ "d1fa1abeafe8256180"),
+ hexstr2bin(""),
+ hexstr2bin("533a37f6bbe457251f023c0d88f976ae"
+ "2dfb504a843e34d2074fd823d41a591f"
+ "2b233f034f628281f2fd7a22ddd47d78"
+ "28c59bd0a21bfd3980ff0d2028d4b18a"
+ "9df63e006c5d1c2d345b925d8dc00b41"
+ "04852db99ac5c7cdda8530a113a0f4db"
+ "b61149f05a7363268c71d95808ff2e65"
+ "2600")},
+ %% 1 octet
+ {ed448, undefined,
+ hexstr2bin("c4eab05d357007c632f3dbb48489924d"
+ "552b08fe0c353a0d4a1f00acda2c463a"
+ "fbea67c5e8d2877c5e3bc397a659949e"
+ "f8021e954e0a12274e"),
+ hexstr2bin("43ba28f430cdff456ae531545f7ecd0a"
+ "c834a55d9358c0372bfa0c6c6798c086"
+ "6aea01eb00742802b8438ea4cb82169c"
+ "235160627b4c3a9480"),
+ hexstr2bin("03"),
+ hexstr2bin("26b8f91727bd62897af15e41eb43c377"
+ "efb9c610d48f2335cb0bd0087810f435"
+ "2541b143c4b981b7e18f62de8ccdf633"
+ "fc1bf037ab7cd779805e0dbcc0aae1cb"
+ "cee1afb2e027df36bc04dcecbf154336"
+ "c19f0af7e0a6472905e799f1953d2a0f"
+ "f3348ab21aa4adafd1d234441cf807c0"
+ "3a00")},
+
+ %% %% 1 octet (with context)
+ %% {ed448, undefined,
+ %% hexstr2bin("c4eab05d357007c632f3dbb48489924d"
+ %% "552b08fe0c353a0d4a1f00acda2c463a"
+ %% "fbea67c5e8d2877c5e3bc397a659949e"
+ %% "f8021e954e0a12274e"),
+ %% hexstr2bin("43ba28f430cdff456ae531545f7ecd0a"
+ %% "c834a55d9358c0372bfa0c6c6798c086"
+ %% "6aea01eb00742802b8438ea4cb82169c"
+ %% "235160627b4c3a9480"),
+ %% hexstr2bin("03"),
+ %% hexstr2bin("666f6f"), % Context
+ %% hexstr2bin("d4f8f6131770dd46f40867d6fd5d5055"
+ %% "de43541f8c5e35abbcd001b32a89f7d2"
+ %% "151f7647f11d8ca2ae279fb842d60721"
+ %% "7fce6e042f6815ea000c85741de5c8da"
+ %% "1144a6a1aba7f96de42505d7a7298524"
+ %% "fda538fccbbb754f578c1cad10d54d0d"
+ %% "5428407e85dcbc98a49155c13764e66c"
+ %% "3c00")},
+
+ %% 11 octets
+ {ed448, undefined,
+ hexstr2bin("cd23d24f714274e744343237b93290f5"
+ "11f6425f98e64459ff203e8985083ffd"
+ "f60500553abc0e05cd02184bdb89c4cc"
+ "d67e187951267eb328"),
+ hexstr2bin("dcea9e78f35a1bf3499a831b10b86c90"
+ "aac01cd84b67a0109b55a36e9328b1e3"
+ "65fce161d71ce7131a543ea4cb5f7e9f"
+ "1d8b00696447001400"),
+ hexstr2bin("0c3e544074ec63b0265e0c"),
+ hexstr2bin("1f0a8888ce25e8d458a21130879b840a"
+ "9089d999aaba039eaf3e3afa090a09d3"
+ "89dba82c4ff2ae8ac5cdfb7c55e94d5d"
+ "961a29fe0109941e00b8dbdeea6d3b05"
+ "1068df7254c0cdc129cbe62db2dc957d"
+ "bb47b51fd3f213fb8698f064774250a5"
+ "028961c9bf8ffd973fe5d5c206492b14"
+ "0e00")},
+ %% 12 octets
+ {ed448, undefined,
+ hexstr2bin("258cdd4ada32ed9c9ff54e63756ae582"
+ "fb8fab2ac721f2c8e676a72768513d93"
+ "9f63dddb55609133f29adf86ec9929dc"
+ "cb52c1c5fd2ff7e21b"),
+ hexstr2bin("3ba16da0c6f2cc1f30187740756f5e79"
+ "8d6bc5fc015d7c63cc9510ee3fd44adc"
+ "24d8e968b6e46e6f94d19b945361726b"
+ "d75e149ef09817f580"),
+ hexstr2bin("64a65f3cdedcdd66811e2915"),
+ hexstr2bin("7eeeab7c4e50fb799b418ee5e3197ff6"
+ "bf15d43a14c34389b59dd1a7b1b85b4a"
+ "e90438aca634bea45e3a2695f1270f07"
+ "fdcdf7c62b8efeaf00b45c2c96ba457e"
+ "b1a8bf075a3db28e5c24f6b923ed4ad7"
+ "47c3c9e03c7079efb87cb110d3a99861"
+ "e72003cbae6d6b8b827e4e6c143064ff"
+ "3c00")},
+ %% 13 octets
+ {ed448, undefined,
+ hexstr2bin("7ef4e84544236752fbb56b8f31a23a10"
+ "e42814f5f55ca037cdcc11c64c9a3b29"
+ "49c1bb60700314611732a6c2fea98eeb"
+ "c0266a11a93970100e"),
+ hexstr2bin("b3da079b0aa493a5772029f0467baebe"
+ "e5a8112d9d3a22532361da294f7bb381"
+ "5c5dc59e176b4d9f381ca0938e13c6c0"
+ "7b174be65dfa578e80"),
+ hexstr2bin("64a65f3cdedcdd66811e2915e7"),
+ hexstr2bin("6a12066f55331b6c22acd5d5bfc5d712"
+ "28fbda80ae8dec26bdd306743c5027cb"
+ "4890810c162c027468675ecf645a8317"
+ "6c0d7323a2ccde2d80efe5a1268e8aca"
+ "1d6fbc194d3f77c44986eb4ab4177919"
+ "ad8bec33eb47bbb5fc6e28196fd1caf5"
+ "6b4e7e0ba5519234d047155ac727a105"
+ "3100")},
+ %% 64 octets
+ {ed448, undefined,
+ hexstr2bin("d65df341ad13e008567688baedda8e9d"
+ "cdc17dc024974ea5b4227b6530e339bf"
+ "f21f99e68ca6968f3cca6dfe0fb9f4fa"
+ "b4fa135d5542ea3f01"),
+ hexstr2bin("df9705f58edbab802c7f8363cfe5560a"
+ "b1c6132c20a9f1dd163483a26f8ac53a"
+ "39d6808bf4a1dfbd261b099bb03b3fb5"
+ "0906cb28bd8a081f00"),
+ hexstr2bin("bd0f6a3747cd561bdddf4640a332461a"
+ "4a30a12a434cd0bf40d766d9c6d458e5"
+ "512204a30c17d1f50b5079631f64eb31"
+ "12182da3005835461113718d1a5ef944"),
+ hexstr2bin("554bc2480860b49eab8532d2a533b7d5"
+ "78ef473eeb58c98bb2d0e1ce488a98b1"
+ "8dfde9b9b90775e67f47d4a1c3482058"
+ "efc9f40d2ca033a0801b63d45b3b722e"
+ "f552bad3b4ccb667da350192b61c508c"
+ "f7b6b5adadc2c8d9a446ef003fb05cba"
+ "5f30e88e36ec2703b349ca229c267083"
+ "3900")},
+ %% 256 octets
+ {ed448, undefined,
+ hexstr2bin("2ec5fe3c17045abdb136a5e6a913e32a"
+ "b75ae68b53d2fc149b77e504132d3756"
+ "9b7e766ba74a19bd6162343a21c8590a"
+ "a9cebca9014c636df5"),
+ hexstr2bin("79756f014dcfe2079f5dd9e718be4171"
+ "e2ef2486a08f25186f6bff43a9936b9b"
+ "fe12402b08ae65798a3d81e22e9ec80e"
+ "7690862ef3d4ed3a00"),
+ hexstr2bin("15777532b0bdd0d1389f636c5f6b9ba7"
+ "34c90af572877e2d272dd078aa1e567c"
+ "fa80e12928bb542330e8409f31745041"
+ "07ecd5efac61ae7504dabe2a602ede89"
+ "e5cca6257a7c77e27a702b3ae39fc769"
+ "fc54f2395ae6a1178cab4738e543072f"
+ "c1c177fe71e92e25bf03e4ecb72f47b6"
+ "4d0465aaea4c7fad372536c8ba516a60"
+ "39c3c2a39f0e4d832be432dfa9a706a6"
+ "e5c7e19f397964ca4258002f7c0541b5"
+ "90316dbc5622b6b2a6fe7a4abffd9610"
+ "5eca76ea7b98816af0748c10df048ce0"
+ "12d901015a51f189f3888145c03650aa"
+ "23ce894c3bd889e030d565071c59f409"
+ "a9981b51878fd6fc110624dcbcde0bf7"
+ "a69ccce38fabdf86f3bef6044819de11"),
+ hexstr2bin("c650ddbb0601c19ca11439e1640dd931"
+ "f43c518ea5bea70d3dcde5f4191fe53f"
+ "00cf966546b72bcc7d58be2b9badef28"
+ "743954e3a44a23f880e8d4f1cfce2d7a"
+ "61452d26da05896f0a50da66a239a8a1"
+ "88b6d825b3305ad77b73fbac0836ecc6"
+ "0987fd08527c1a8e80d5823e65cafe2a"
+ "3d00")},
+ %% 1023 octets
+ {ed448, undefined,
+ hexstr2bin("872d093780f5d3730df7c212664b37b8"
+ "a0f24f56810daa8382cd4fa3f77634ec"
+ "44dc54f1c2ed9bea86fafb7632d8be19"
+ "9ea165f5ad55dd9ce8"),
+ hexstr2bin("a81b2e8a70a5ac94ffdbcc9badfc3feb"
+ "0801f258578bb114ad44ece1ec0e799d"
+ "a08effb81c5d685c0c56f64eecaef8cd"
+ "f11cc38737838cf400"),
+ hexstr2bin("6ddf802e1aae4986935f7f981ba3f035"
+ "1d6273c0a0c22c9c0e8339168e675412"
+ "a3debfaf435ed651558007db4384b650"
+ "fcc07e3b586a27a4f7a00ac8a6fec2cd"
+ "86ae4bf1570c41e6a40c931db27b2faa"
+ "15a8cedd52cff7362c4e6e23daec0fbc"
+ "3a79b6806e316efcc7b68119bf46bc76"
+ "a26067a53f296dafdbdc11c77f7777e9"
+ "72660cf4b6a9b369a6665f02e0cc9b6e"
+ "dfad136b4fabe723d2813db3136cfde9"
+ "b6d044322fee2947952e031b73ab5c60"
+ "3349b307bdc27bc6cb8b8bbd7bd32321"
+ "9b8033a581b59eadebb09b3c4f3d2277"
+ "d4f0343624acc817804728b25ab79717"
+ "2b4c5c21a22f9c7839d64300232eb66e"
+ "53f31c723fa37fe387c7d3e50bdf9813"
+ "a30e5bb12cf4cd930c40cfb4e1fc6225"
+ "92a49588794494d56d24ea4b40c89fc0"
+ "596cc9ebb961c8cb10adde976a5d602b"
+ "1c3f85b9b9a001ed3c6a4d3b1437f520"
+ "96cd1956d042a597d561a596ecd3d173"
+ "5a8d570ea0ec27225a2c4aaff26306d1"
+ "526c1af3ca6d9cf5a2c98f47e1c46db9"
+ "a33234cfd4d81f2c98538a09ebe76998"
+ "d0d8fd25997c7d255c6d66ece6fa56f1"
+ "1144950f027795e653008f4bd7ca2dee"
+ "85d8e90f3dc315130ce2a00375a318c7"
+ "c3d97be2c8ce5b6db41a6254ff264fa6"
+ "155baee3b0773c0f497c573f19bb4f42"
+ "40281f0b1f4f7be857a4e59d416c06b4"
+ "c50fa09e1810ddc6b1467baeac5a3668"
+ "d11b6ecaa901440016f389f80acc4db9"
+ "77025e7f5924388c7e340a732e554440"
+ "e76570f8dd71b7d640b3450d1fd5f041"
+ "0a18f9a3494f707c717b79b4bf75c984"
+ "00b096b21653b5d217cf3565c9597456"
+ "f70703497a078763829bc01bb1cbc8fa"
+ "04eadc9a6e3f6699587a9e75c94e5bab"
+ "0036e0b2e711392cff0047d0d6b05bd2"
+ "a588bc109718954259f1d86678a579a3"
+ "120f19cfb2963f177aeb70f2d4844826"
+ "262e51b80271272068ef5b3856fa8535"
+ "aa2a88b2d41f2a0e2fda7624c2850272"
+ "ac4a2f561f8f2f7a318bfd5caf969614"
+ "9e4ac824ad3460538fdc25421beec2cc"
+ "6818162d06bbed0c40a387192349db67"
+ "a118bada6cd5ab0140ee273204f628aa"
+ "d1c135f770279a651e24d8c14d75a605"
+ "9d76b96a6fd857def5e0b354b27ab937"
+ "a5815d16b5fae407ff18222c6d1ed263"
+ "be68c95f32d908bd895cd76207ae7264"
+ "87567f9a67dad79abec316f683b17f2d"
+ "02bf07e0ac8b5bc6162cf94697b3c27c"
+ "d1fea49b27f23ba2901871962506520c"
+ "392da8b6ad0d99f7013fbc06c2c17a56"
+ "9500c8a7696481c1cd33e9b14e40b82e"
+ "79a5f5db82571ba97bae3ad3e0479515"
+ "bb0e2b0f3bfcd1fd33034efc6245eddd"
+ "7ee2086ddae2600d8ca73e214e8c2b0b"
+ "db2b047c6a464a562ed77b73d2d841c4"
+ "b34973551257713b753632efba348169"
+ "abc90a68f42611a40126d7cb21b58695"
+ "568186f7e569d2ff0f9e745d0487dd2e"
+ "b997cafc5abf9dd102e62ff66cba87"),
+ hexstr2bin("e301345a41a39a4d72fff8df69c98075"
+ "a0cc082b802fc9b2b6bc503f926b65bd"
+ "df7f4c8f1cb49f6396afc8a70abe6d8a"
+ "ef0db478d4c6b2970076c6a0484fe76d"
+ "76b3a97625d79f1ce240e7c576750d29"
+ "5528286f719b413de9ada3e8eb78ed57"
+ "3603ce30d8bb761785dc30dbc320869e"
+ "1a00")}
+ ].
+
ecdh() ->
%% http://csrc.nist.gov/groups/STM/cavp/
- Curves = crypto:ec_curves(),
+ Curves = crypto:ec_curves() ++
+ [X || X <- proplists:get_value(curves, crypto:supports(), []),
+ lists:member(X, [x25519,x448])],
TestCases =
[{ecdh, hexstr2point("42ea6dd9969dd2a61fea1aac7f8e98edcc896c6e55857cc0", "dfbe5d7c61fac88b11811bde328e8a0d12bf01a9d204b523"),
hexstr2bin("f17d3fea367b74d340851ca4270dcb24c271f445bed9d527"),
@@ -2313,7 +3250,32 @@ ecdh() ->
"2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194512B71876285FA"),
hexstr2bin("16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD87BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764CAD57665422"),
brainpoolP512r1,
- hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")}],
+ hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")},
+
+ %% RFC 7748, 6.1
+ {ecdh,
+ 16#8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a,
+ 16#5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+ {ecdh,
+ 16#de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f,
+ 16#77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+
+ %% RFC 7748, 6.2
+ {ecdh,
+ 16#9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0,
+ 16#1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")},
+ {ecdh,
+ 16#3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609,
+ 16#9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")}
+ ],
lists:filter(fun ({_Type, _Pub, _Priv, Curve, _SharedSecret}) ->
lists:member(Curve, Curves)
end,
@@ -2322,6 +3284,8 @@ ecdh() ->
dh() ->
{dh, 90970053988169282502023478715631717259407236400413906591937635666709823903223997309250405131675572047545403771567755831138144089197560332757755059848492919215391041119286178688014693040542889497092308638580104031455627238700168892909539193174537248629499995652186913900511641708112112482297874449292467498403, 2}.
+
+
rsa_oaep() ->
%% ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt
Public = [hexstr2bin("010001"),
@@ -2334,7 +3298,32 @@ rsa_oaep() ->
hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
%%Msg = hexstr2bin("6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34"),
Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
- {rsa, Public, Private, Msg, rsa_pkcs1_oaep_padding}.
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}]}.
+
+rsa_oaep_label() ->
+ Public = [hexstr2bin("010001"),
+ hexstr2bin("a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb")],
+ Private = Public ++ [hexstr2bin("53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"),
+ hexstr2bin("d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d"),
+ hexstr2bin("cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77"),
+ hexstr2bin("0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c1"),
+ hexstr2bin("95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d71583"),
+ hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
+ Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
+ Lbl = hexstr2bin("1332a67ca7088f75c9b8fb5e3d072882"),
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}, {rsa_oaep_label, Lbl}]}.
+
+rsa_oaep256() ->
+ Public = [hexstr2bin("010001"),
+ hexstr2bin("a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb")],
+ Private = Public ++ [hexstr2bin("53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"),
+ hexstr2bin("d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d"),
+ hexstr2bin("cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77"),
+ hexstr2bin("0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c1"),
+ hexstr2bin("95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d71583"),
+ hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
+ Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}, {rsa_oaep_md, sha256}]}.
ecc() ->
%% http://point-at-infinity.org/ecc/nisttv
@@ -2371,13 +3360,6 @@ cmac_nist(Config, aes_cbc256 = Type) ->
read_rsp(Config, Type,
["CMACGenAES256.rsp", "CMACVerAES256.rsp"]).
-no_padding() ->
- Public = [_, Mod] = rsa_public_stronger(),
- Private = rsa_private_stronger(),
- MsgLen = erlang:byte_size(int_to_bin(Mod)),
- Msg = list_to_binary(lists:duplicate(MsgLen, $X)),
- {rsa, Public, Private, Msg, rsa_no_padding}.
-
int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []);
int_to_bin(X) -> int_to_bin_pos(X, []).
@@ -2419,29 +3401,36 @@ read_rsp(Config, Type, Files) ->
Tests =
lists:foldl(
fun(FileName, Acc) ->
- read_rsp_file(filename:join(datadir(Config), FileName),
- Type, Acc)
+ NewAcc = read_rsp_file(filename:join(datadir(Config), FileName),
+ Type, Acc),
+ ct:log("~p: ~p tests read.~n",[FileName,length(NewAcc)-length(Acc)]),
+ NewAcc
end, [], Files),
log_rsp_size(Type, Tests),
Tests.
read_rsp_file(FileName, Type, Acc) ->
- {ok, Raw} = file:read_file(FileName),
- Split = binary:split(Raw, [<<"\r">>, <<"\n">>], [global, trim_all]),
- parse_rsp(Type, Split, Acc).
+ case file:read_file(FileName) of
+ {ok, Raw} ->
+ Split = binary:split(Raw, [<<"\r">>, <<"\n">>], [global, trim_all]),
+ parse_rsp(Type, Split, #{file => FileName}, Acc);
+ Other ->
+ ct:fail("~p ~p",[FileName, Other])
+ end.
-parse_rsp(_Type, [], Acc) ->
+parse_rsp(_Type, [], _State, Acc) ->
Acc;
-parse_rsp(_Type, [<<"DECRYPT">>|_], Acc) ->
+parse_rsp(_Type, [<<"DECRYPT">>|_], _State, Acc) ->
Acc;
%% AES format
parse_rsp(Type, [<<"COUNT = ", _/binary>>,
<<"KEY = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"PLAINTEXT = ", PlainText/binary>>,
- <<"CIPHERTEXT = ", CipherText/binary>>|Next], Acc) ->
- parse_rsp(Type, Next, [{Type, hexstr2bin(Key), hexstr2bin(IV),
- hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]);
+ <<"CIPHERTEXT = ", CipherText/binary>>|Next], State, Acc) ->
+ parse_rsp(Type, Next, State,
+ [{Type, hexstr2bin(Key), hexstr2bin(IV),
+ hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]);
%% CMAC format
parse_rsp(Type, [<<"Count = ", _/binary>>,
<<"Klen = ", _/binary>>,
@@ -2449,23 +3438,23 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
<<"Tlen = ", Tlen/binary>>,
<<"Key = ", Key/binary>>,
<<"Msg = ", Msg/binary>>,
- <<"Mac = ", MAC/binary>>|Rest], Acc) ->
+ <<"Mac = ", MAC/binary>>|Rest], State, Acc) ->
case Rest of
[<<"Result = P">>|Next] ->
- parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Next, Acc);
+ parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Next, State, Acc);
[<<"Result = ", _/binary>>|Next] ->
- parse_rsp(Type, Next, Acc);
+ parse_rsp(Type, Next, State, Acc);
_ ->
- parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Rest, Acc)
+ parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Rest, State, Acc)
end;
%% GCM format decode format
-parse_rsp(Type, [<<"Count = ", _/binary>>,
+parse_rsp(Type, [<<"Count = ", Count/binary>>,
<<"Key = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"CT = ", CipherText/binary>>,
<<"AAD = ", AAD/binary>>,
<<"Tag = ", CipherTag0/binary>>,
- <<"PT = ", PlainText/binary>>|Next], Acc) ->
+ <<"PT = ", PlainText/binary>>|Next], #{file:=File}=State, Acc) ->
CipherTag = hexstr2bin(CipherTag0),
TestCase = {Type,
hexstr2bin(Key),
@@ -2474,16 +3463,17 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
hexstr2bin(AAD),
hexstr2bin(CipherText),
CipherTag,
- size(CipherTag)},
- parse_rsp(Type, Next, [TestCase|Acc]);
+ size(CipherTag),
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
%% GCM format encode format
-parse_rsp(Type, [<<"Count = ", _/binary>>,
+parse_rsp(Type, [<<"Count = ", Count/binary>>,
<<"Key = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"PT = ", PlainText/binary>>,
<<"AAD = ", AAD/binary>>,
<<"CT = ", CipherText/binary>>,
- <<"Tag = ", CipherTag0/binary>>|Next], Acc) ->
+ <<"Tag = ", CipherTag0/binary>>|Next], #{file:=File}=State, Acc) ->
CipherTag = hexstr2bin(CipherTag0),
TestCase = {Type,
hexstr2bin(Key),
@@ -2492,13 +3482,88 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
hexstr2bin(AAD),
hexstr2bin(CipherText),
CipherTag,
- size(CipherTag)},
- parse_rsp(Type, Next, [TestCase|Acc]);
+ size(CipherTag),
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
+%% CCM-VADT format
+parse_rsp(Type, [<<"[Alen = ", AlenB0/binary>>|Next], State0, Acc) ->
+ AlenSize = size(AlenB0) - 1, % remove closing ']'
+ Alen = decstr2int(<<AlenB0:AlenSize/binary>>),
+ State = State0#{alen => Alen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Nlen = ", NlenB0/binary>>|Next], State0, Acc) ->
+ NlenSize = size(NlenB0) - 1, % remove closing ']'
+ Nlen = decstr2int(<<NlenB0:NlenSize/binary>>),
+ State = State0#{nlen => Nlen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Plen = ", PlenB0/binary>>|Next], State0, Acc) ->
+ PlenSize = size(PlenB0) - 1, % remove closing ']'
+ Plen = decstr2int(<<PlenB0:PlenSize/binary>>),
+ State = State0#{plen => Plen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Tlen = ", TlenB0/binary>>|Next], State0, Acc) ->
+ TlenSize = size(TlenB0) - 1, % remove closing ']'
+ Tlen = decstr2int(<<TlenB0:TlenSize/binary>>),
+ State = State0#{tlen => Tlen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Alen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{alen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Plen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{plen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Count = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{count => B},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Nlen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{nlen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Tlen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{tlen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Key = ",Key/binary>>|Next], State0, Acc) ->
+ State = State0#{key => hexstr2bin(Key)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Nonce = ",Nonce/binary>>|Next], State0, Acc) ->
+ State = State0#{nonce => hexstr2bin(Nonce)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Adata = ",Adata/binary>>|Next], State0, Acc) ->
+ State = State0#{adata => hexstr2bin(Adata)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Payload = ",Payload/binary>>|Next], State0, Acc) ->
+ State = State0#{payload => hexstr2bin(Payload)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type,
+ [<<"CT = ", CT/binary>>|Next],
+ #{count := Count,
+ file := File,
+ alen := Alen,
+ plen := Plen,
+ nlen := _Nlen,
+ tlen := Tlen,
+ key := Key,
+ nonce := IV,
+ adata := Adata,
+ payload := Payload
+ } = State, Acc) ->
+ AAD = <<Adata:Alen/binary>>,
+ PlainText = <<Payload:Plen/binary>>,
+ <<CipherText:Plen/binary, CipherTag:Tlen/binary>> = hexstr2bin(CT),
+ TestCase = {Type,
+ Key,
+ PlainText,
+ IV,
+ AAD,
+ CipherText,
+ CipherTag,
+ Tlen,
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
+parse_rsp(Type, [_|Next], State, Acc) ->
+ parse_rsp(Type, Next, State, Acc).
-parse_rsp(Type, [_|Next], Acc) ->
- parse_rsp(Type, Next, Acc).
-parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, Acc) ->
+parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, State, Acc) ->
Key = hexstr2bin(Key0),
Mlen = binary_to_integer(Mlen0),
<<Msg:Mlen/bytes, _/binary>> = hexstr2bin(Msg0),
@@ -2506,7 +3571,18 @@ parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, Acc) ->
case binary_to_integer(Tlen) of
0 ->
- parse_rsp(Type, Next, [{Type, Key, Msg, MAC}|Acc]);
+ parse_rsp(Type, Next, State, [{Type, Key, Msg, MAC}|Acc]);
I ->
- parse_rsp(Type, Next, [{Type, Key, Msg, I, MAC}|Acc])
+ parse_rsp(Type, Next, State, [{Type, Key, Msg, I, MAC}|Acc])
end.
+
+api_errors_ecdh(Config) when is_list(Config) ->
+ %% Check that we don't segfault when fed garbage.
+ Test = fun(Others, Curve) ->
+ {_Pub, Priv} = crypto:generate_key(ecdh, Curve),
+ crypto:compute_key(ecdh, Others, Priv, Curve)
+ end,
+ Others = [gurka, 0, <<0>>],
+ Curves = [gaffel, 0, sect571r1],
+ [_= (catch Test(O, C)) || O <- Others, C <- Curves],
+ ok.
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT128.rsp b/lib/crypto/test/crypto_SUITE_data/VADT128.rsp
new file mode 100644
index 0000000000..a4fe9130a0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT128.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = d24a3d3dde8c84830280cb87abad0bb3
+Nonce = f1100035bb24a8d26004e0e24b
+
+Count = 0
+Adata = 00
+Payload = 7c86135ed9c2a515aaae0e9a208133897269220f30870006
+CT = 1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab1123301219c70599b7c373ad4b3ad67b
+
+Count = 1
+Adata = 00
+Payload = 48df73208cdc63d716752df7794807b1b2a80794a2433455
+CT = 2bf7d09079bc0b904c711a0b0e4a70ca8ea892d9566f03f8b77a140819f39ef045103e785e1df8c2
+
+Count = 2
+Adata = 00
+Payload = b99de8168e8c13ea4aef66bdb93133dff5d57e9837ff6ccb
+CT = dab54ba67bec7bad10eb5141ce3344a4c9d5ebd5c3d35b664b01098842a618390619b86e00850b2e
+
+Count = 3
+Adata = 00
+Payload = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce
+CT = 6ad4821cbf7f2b9973662b5084aff39b69c6276d8636c0638bd518724ab84fb814fe7b5570769f7f
+
+Count = 4
+Adata = 00
+Payload = cb43320d7488dfd6eed9efd88f440ea3f6f77a0df09d0727
+CT = a86b91bd81e8b791b4ddd824f84679d8caf7ef4004b1308a7229cbcecef221570cee8345b38cd6ec
+
+Count = 5
+Adata = 00
+Payload = a350ed58c04473e113b9088b1fb9dad92807f6b63b0d690c
+CT = c0784ee835241ba649bd3f7768bbada2140763fbcf215ea1fee47fec27d7764e5e2819c850088bac
+
+Count = 6
+Adata = 00
+Payload = 0709e691faf41383fab5d1848a8eee77101d1c99e526a264
+CT = 642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d610bc1ab4bc9a8a28c7306f7c539e
+
+Count = 7
+Adata = 00
+Payload = e7b913c2f0630562eb1c16b3b1ed84090c011a15c09e5471
+CT = 8491b07205036d25b118214fc6eff37230018f5834b263dc2e31657ecc51f5ec8590482fc053230d
+
+Count = 8
+Adata = 00
+Payload = 6b909697074900d41ce8c7d559b229af11fb3cec334784d4
+CT = 08b83527f229689346ecf0292eb05ed42dfba9a1c76bb379d500827f2081b00397102f90fc9ccd88
+
+Count = 9
+Adata = 00
+Payload = 495ff03335bcb39a317b9ea3f8bb6306fa771f3c55adebce
+CT = 2a775383c0dcdbdd6b7fa95f8fb9147dc6778a71a181dc63e2e7997803029476598c0e8d4fc63857
+
+[Alen = 1]
+
+Key = 08b0da255d2083808a1b4d367090bacc
+Nonce = 777828b13679a9e2ca89568233
+
+Count = 10
+Adata = dd
+Payload = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0
+CT = e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6282283e16602331bcca9d51ce76
+
+Count = 11
+Adata = c5
+Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
+CT = f0828917020651c085e42459c544ec52e99372005362baf308ebeed45f67ef8733737c9c6f82daad
+
+Count = 12
+Adata = 68
+Payload = 9c4cd65b92070bc382fd18146611defb4204acddfdf6b276
+CT = 6fe1b1d12ffd9676197322ab732e80b1183032b65be00628f9b477e3a23bfdfdb619c7bc531fbcce
+
+Count = 13
+Adata = be
+Payload = 2ff93ef2fc5fe2c297ace05f3f7585aed75ef90ade3acf89
+CT = dc54597841a57f770c22dae02a4adbe48d6a6761782c7bd7aa82130f5a86c0cd0433585e5c208cf7
+
+Count = 14
+Adata = 7a
+Payload = 62766e9acd41285eeed9b4007340dbb611699624274ad117
+CT = 91db091070bbb5eb75578ebf667f85fc4b5d084f815c65499d60012a2f25463e036ceecea57b3c97
+
+Count = 15
+Adata = 13
+Payload = ea689c268a04912d0527b16d9d9406df38302fb11cb64a99
+CT = 19c5fbac37fe0c989ea98bd288ab58956204b1dabaa0fec7e337897c90eb260729a729aed1c8a244
+
+Count = 16
+Adata = e5
+Payload = f31e35953beb211efcce487ba8c0cd1a8446343d5851b9fd
+CT = 00b3521f8611bcab674072c4bdff9350de72aa56fe470da373dc2911c75b37cd995481d42b04524a
+
+Count = 17
+Adata = e3
+Payload = c4ac3c645387584c2a95b1f16b8317730592924dd831a388
+CT = 37015beeee7dc5f9b11b8b4e7ebc49395fa60c267e2717d684f76ecf3dc5f3307ce982f185321248
+
+Count = 18
+Adata = d5
+Payload = 81af394c2ea3a85e1ea954596e3772f01635d007794c0b19
+CT = 72025ec6935935eb85276ee67b082cba4c014e6cdf5abf472c38d0fe4e4eba054c1420c39a3dcc61
+
+Count = 19
+Adata = ed
+Payload = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304
+CT = 13bec5676842f61e167bf32b183552cc1e4c5fc6e470375a7cfa6c9945f5aee3c799eee37b0605db
+
+[Alen = 2]
+
+Key = 1538cc03b60880bf3e7d388e29f27739
+Nonce = 9e734de325026b5d7128193973
+
+Count = 20
+Adata = c93c
+Payload = e7b819a853ffe79baaa72097ff0d04f02640ae62bcfd3da5
+CT = 1d8f42f9730424fa27240bd6277f4882604f440324b11b003ca01d874439b4e1f79a26d8c6dc433a
+
+Count = 21
+Adata = 4cf9
+Payload = dc6cf325ed6d968efba9f57e48a58f4578cc3540fe121ba2
+CT = 265ba874cd9655ef762ade3f90d7c3373ec3df21665e3d07b40653cd23afc7cc7a31fa13ba8f4e49
+
+Count = 22
+Adata = b469
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = d89c315c8f6ef204502b4f8d3699345c6153e166b2a1f421c8c10aaf90b1116be216f912c82ca96a
+
+Count = 23
+Adata = cf6b
+Payload = a35f62a431fee63468dc02fdf7bef78d3a5937de56151939
+CT = 596839f511052555e55f29bc2fccbbff7c56ddbfce593f9c2f568ef41324189fb3644edcd76dc19c
+
+Count = 24
+Adata = af7c
+Payload = 548840cb0400824af809fb68447500b77e977128200d3b81
+CT = aebf1b9a24fb412b758ad0299c074cc538989b49b8411d242548c244a875d3681d715db3da19962f
+
+Count = 25
+Adata = 61dc
+Payload = 440b6095c77495e73fff54c785b7ceb5eb358731c213ffcd
+CT = be3c3bc4e78f5686b27c7f865dc582c7ad3a6d505a5fd968b599bc8927ad8d43067807f4b858f854
+
+Count = 26
+Adata = b97e
+Payload = 50c59ca54eb64575b82b13c6dac96488af369e9f5f86cdf2
+CT = aaf2c7f46e4d861435a8388702bb28fae93974fec7caeb577454774ee78f76e555cf743df340381e
+
+Count = 27
+Adata = 57ab
+Payload = 21b8eb1f0bda26ca36167ce7bc2e796818bf11fc8c192885
+CT = db8fb04e2b21e5abbb9557a6645c351a5eb0fb9d14550e20e0a22a5ee031978271c7dd2a0d4e7018
+
+Count = 28
+Adata = 5f9c
+Payload = b4d84fb1e81e18c89391a7a59fc05fedaf160e0d0d027a7c
+CT = 4eef14e0c8e5dba91e128ce447b2139fe919e46c954e5cd99a242ebae5c6da57ee38e5c227c46b32
+
+Count = 29
+Adata = e0c4
+Payload = 54dc5a0e1b67577cda4e7dbd48b769c120c1d13dd567cfad
+CT = aeeb015f3b9c941d57cd56fc90c525b366ce3b5c4d2be908a5f8a92f4201c4658289307167cee810
+
+[Alen = 3]
+
+Key = f149e41d848f59276cfddd743bafa9a9
+Nonce = 14b756d66fc51134e203d1c6f9
+
+Count = 30
+Adata = f5827e
+Payload = 9759e6f21f5a588010f57e6d6eae178d8b20ab59cda66f42
+CT = f634bf00f1f9f1f93f41049d7f3797b05e805f0b14850f4e78e2a23411147a6187da6818506232ee
+
+Count = 31
+Adata = e9699b
+Payload = 1555bc87d6c688fd221a2c75cd1e4dd1c1693207ac421d24
+CT = 7438e575386521840dae5685dc87cdec14c9c65575617d28f10835db9897b7528e3204fe3a81424f
+
+Count = 32
+Adata = 972896
+Payload = b72b2a080d92f3f3bb7d96222982de82a28c9eebaddba247
+CT = d64673fae3315a8a94c9ecd2381b5ebf772c6ab974f8c24b3efa05ba4a73ec2234461d459f54acd2
+
+Count = 33
+Adata = 3053f3
+Payload = b5417ed6933ffe2b57ea601d77e97eb12fa1fb8fdc06c86f
+CT = d42c27247d9c5752785e1aed6670fe8cfa010fdd0525a863b557537c6525e827750917a1ed49602f
+
+Count = 34
+Adata = 24db75
+Payload = 4e7f42666035a00e62783283c54b027603917685d27326bc
+CT = 2f121b948e9609774dcc4873d4d2824bd63182d70b5046b0dfd06b037e9094f120eb3d8649d48918
+
+Count = 35
+Adata = ff27a4
+Payload = 7bf180699c294421ad9565cacc27227a4b3a7cf9637290c6
+CT = 1a9cd99b728aed5882211f3addbea2479e9a88abba51f0cabfa8cfabbd79b3e3210482e6f3822fee
+
+Count = 36
+Adata = 77ec24
+Payload = 3d47071c13f994cb42fb2887e5c6e53a542be7ddad9779e0
+CT = 5c2a5eeefd5a3db26d4f5277f45f6507818b138f74b419ec3b9575e347051e98d0c8646ad46318e6
+
+Count = 37
+Adata = 6d7748
+Payload = 317d5da0a2ec12c3b96c83dd61cc955242a9c1c640e2b92f
+CT = 501004524c4fbbba96d8f92d7055156f9709359499c1d92378e7af65eb0388ae7a52f58f6ba32109
+
+Count = 38
+Adata = 029674
+Payload = c9bb21306ee1b4a6c4fa5443af2e181716993cbb374e177c
+CT = a8d678c280421ddfeb4e2eb3beb7982ac339c8e9ee6d77708019fa97ff70d4d21c0bd83caa434b3a
+
+Count = 39
+Adata = 60dfe8
+Payload = 44eb7edd6bee501ad97873aa7ecbf7ed8b613760d7c95e15
+CT = 2586272f854df963f6cc095a6f5277d05ec1c3320eea3e191814ed48a21d97ea02e86d7e6e8834cb
+
+[Alen = 4]
+
+Key = 9a57a22c7f26feff8ca6cceff214e4c2
+Nonce = 88f30fd2b04fb8ddbce8fc26e6
+
+Count = 40
+Adata = a95bdff6
+Payload = 035c516776c706a7dd5f181fa6aa891b04dd423042ea0667
+CT = b92f7ec2ebecebdbd2977b3874e61bf496a382153b2529fc9b6443a35f329b2068916fb6ab8227eb
+
+Count = 41
+Adata = d2672cbb
+Payload = 3ba306bcec94615c347f990b62841a16df7b321f113f1714
+CT = 81d0291971bf8c203bb7fa2cb0c888f94d05f23a68f0388f19e2aa492ce9ddfb6de0ab7a447f5351
+
+Count = 42
+Adata = 737f4d00
+Payload = 68313a29ace3efe521c3ca1e5bac8e98d6b4434c80a7dc74
+CT = d242158c31c802992e0ba93989e01c7744ca8369f968f3ef2bf683b1209f104e82ba39f7c62cd666
+
+Count = 43
+Adata = 3610b1ae
+Payload = 963bfe556138317bebe3936b18a2c1dd100dc73be6fde556
+CT = 2c48d1f0fc13dc07e42bf04ccaee53328273071e9f32cacd4fc7d5cac043f182edbe5c2658f73092
+
+Count = 44
+Adata = f1aa7f72
+Payload = 52d5c53ee4f23cb050a95db54112b44033c34ac31de96be8
+CT = e8a6ea9b79d9d1cc5f613e92935e26afa1bd8ae664264473b8234f3fbaca3dc2c497418219151b05
+
+Count = 45
+Adata = 6b1013aa
+Payload = a302aebc0f8fd61badc8371991beacf5933de46effacb8ce
+CT = 1971811992a43b67a200543e43f23e1a0143244b866397558fa5f9539e0500f139016e4a4337d86b
+
+Count = 46
+Adata = 33028129
+Payload = f7d653c23254875625b20e1ef60ae92847046d84bb4ce857
+CT = 4da57c67af7f6a2a2a7a6d3924467bc7d57aada1c283c7ccfa2379fde155e64b5b84e336056445c3
+
+Count = 47
+Adata = 2cab4a09
+Payload = 872a3f7230e626abff519e5aeecc93897249405daeaffc98
+CT = 3d5910d7adcdcbd7f099fd7d3c800166e0378078d760d30358208335cb81e4fb10923fca4ddb9ff9
+
+Count = 48
+Adata = 73142ba7
+Payload = 766f94e7d9b1ce74bbaf2c99d215350f060122767fc1953f
+CT = cc1cbb42449a2308b4674fbe0059a7e0947fe253060ebaa42d6ecfb49ac8983415503efef1e21950
+
+Count = 49
+Adata = bc9f967e
+Payload = 5f089ed9267363bc23c6c7b8f73208a36f61fa8ea8084ff7
+CT = e57bb17cbb588ec02c0ea49f257e9a4cfd1f3aabd1c7606c1978a62d15430fc20b87940292b49641
+
+[Alen = 5]
+
+Key = 54caf96ef6d448734700aadab50faf7a
+Nonce = a3803e752ae849c910d8da36af
+
+Count = 50
+Adata = 5f476348dd
+Payload = c69f7c5a50f3e72123371bbfd6bdf532b99ef78500508dfe
+CT = 20c43ad83610880249f1632dd418ec9a5ed333b50e996d1a4e5a32fbe7961b832b722bc07a18595b
+
+Count = 51
+Adata = 07db8aada5
+Payload = 9cf8b638f2b295b85cf782fabab11153dc091b4afcd761a9
+CT = 7aa3f0ba9451fa9b3631fa68b81408fb3b44df7af21e814d401a2222443696021b5faa520129b563
+
+Count = 52
+Adata = 31ef6561ff
+Payload = 62b8263dc015ef873cd16272e4da89799b910f2b04204420
+CT = 84e360bfa6f680a456171ae0e67f90d17cdccb1b0ae9a4c4f842681d2e90da5718234ed893197662
+
+Count = 53
+Adata = e97dfcbafb
+Payload = 810bed3a2bc0f9d75389155b7a39d9d014c08646814f9718
+CT = 6750abb84d2396f4394f6dc9789cc078f38d42768f8677fc33a08eb30ee154f71279682ab02eff27
+
+Count = 54
+Adata = 4981c51fcc
+Payload = 063d23fc3ec344c1ba3486802e01e55617455d5cfbfb5279
+CT = e066657e58202be2d0f2fe122ca4fcfef008996cf532b29d8d3071c79f0cf86fe4148cb5e8ace0ce
+
+Count = 55
+Adata = c8437dba76
+Payload = 41db5b245ea0fab985b93e7fc0a00cd3cca5bdbb642b7ebf
+CT = a7801da63843959aef7f46edc205157b2be8798b6ae29e5b842700619dc1599603f3f3f6cfdf5e0b
+
+Count = 56
+Adata = 6f65a24344
+Payload = b0e36734b2ba871d59df0b029c7f32af68e003a689ac4911
+CT = 56b821b6d459e83e331973909eda2b078fadc7968765a9f539a0cd8d8bbf211b907f34411f868c79
+
+Count = 57
+Adata = cd62d6d203
+Payload = 747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2
+CT = 922515644109d2c3a7b1af1f1972391642553c92f9a7b746c4a90e5fc11266bab77eea1d24fbdbb9
+
+Count = 58
+Adata = 9663b3c8e6
+Payload = c70c92ec4c518802662fa4c41a6a33a22599f79f8f7264b3
+CT = 2157d46e2ab2e7210ce9dc5618cf2a0ac2d433af81bb8457b3c1246f7dd6462ce757db82db45f36e
+
+Count = 59
+Adata = 35c4720d3c
+Payload = a26835605b66fc08abdbb5dc77e39783d60b8e8f2314e95f
+CT = 443373e23d85932bc11dcd4e75468e2b31464abf2ddd09bbd472c06a5f4c04f97d06ec401d3e7fd9
+
+[Alen = 6]
+
+Key = cc0c084d7de011e2f031616a302e7a31
+Nonce = f0b4522847f6f8336fe534a4e7
+
+Count = 60
+Adata = da853a27aee2
+Payload = 15b369889699b6de1fa3ee73e5fe19814e46f129074c965b
+CT = f39755d160a64611368a8eccf6fcbc45ef7f1f56240eb19a2e3ca4ec3c776ab58843f617d605fd72
+
+Count = 61
+Adata = d4ed4584678e
+Payload = a18c0460b56a5bcd5bf6842cec6ed44d90b2bfa968a6a7e7
+CT = 47a838394355ab0272dfe493ff6c7189318b51d64be48026327804c44c8f17a4446a3d5ba85f9c7f
+
+Count = 62
+Adata = 590a27721a36
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = a7eadcb559a39501de6924b5e07bf12be89c6b08be689c0bbcd00e9cb726d75e4283820ee81d933a
+
+Count = 63
+Adata = 58830fb0b1f3
+Payload = dce983e4e3734a9bd8848dba0d744d07bbeba602f4006025
+CT = 3acdbfbd154cba54f1aded051e76e8c31ad2487dd74247e4d5d71a1f0f1b6518c35f0632a30931fd
+
+Count = 64
+Adata = eedd0d767a25
+Payload = 4653b3e879ab18b65c5c3706a5139698262cb830a22d943b
+CT = a0778fb18f94e879757557b9b611335c8715564f816fb3fa3ad112899e9ba442660eb5dfe33b2f96
+
+Count = 65
+Adata = 618bcf2e3e79
+Payload = 8586383281925363ac15fb19c26d64c639c75920c792dc2c
+CT = 63a2046b77ada3ac853c9ba6d16fc10298feb75fe4d0fbed54fba446028919342b2fe86ee67efcc7
+
+Count = 66
+Adata = 549c9b84c7f7
+Payload = 95c25ae4445cd8c4d267df82687484667e309992fcf1e737
+CT = 73e666bdb263280bfb4ebf3d7b7621a2df0977eddfb3c0f69fc23013142f62881ccfa3037067e1ef
+
+Count = 67
+Adata = 92d7fa6a8135
+Payload = e58034bbb0e6f5e724e32ee56896dadae25c2a3efb8c6f2f
+CT = 03a408e246d905280dca4e5a7b947f1e4365c441d8ce48ee8263568d56fae8bf35b2f2cdecbffe0a
+
+Count = 68
+Adata = f43e126c0f83
+Payload = d98f0dddfe9cb3cae1336970d5efb55316a65e2c51e316f4
+CT = 3fab318408a34305c81a09cfc6ed1097b79fb05372a13135de2c2fbfdddc7dd6672714af174c5121
+
+Count = 69
+Adata = f02074812dde
+Payload = 548747b1669c6383b793054d93957f9e99d605761c6c23b5
+CT = b2a37be890a3934c9eba65f28097da5a38efeb093f2e04743704560ff23ce0000fba8812c45940ad
+
+[Alen = 7]
+
+Key = d7572ed0e37261efa02f8c83e695efdc
+Nonce = f4f96d7b4384a3930b3d830f82
+
+Count = 70
+Adata = 922340ec94861f
+Payload = 1edef80c57d17f969f8bde10ab38a1a8811a124de72c526e
+CT = de14558cc686e1836f1f121ea1b941a9ebd4f0fb916dc870fd541b988a801cb5751c7faaf5b0c164
+
+Count = 71
+Adata = 4eb379f21b1531
+Payload = ddd5282a207c1dcb03c1c3bbc9eb12a7bd28534118db2735
+CT = 1d1f85aab12b83def3550fb5c36af2a6d7e6b1f76e9abd2bc068bd1b1c309dfbd52d9a24be07c630
+
+Count = 72
+Adata = 7fa89e9d6e3fec
+Payload = c5b7c462eb166f48bb59c8102ee7b3dc67a28e5de7570c51
+CT = 057d69e27a41f15d4bcd041e246653dd0d6c6ceb9116964f2d114d6ab082738d05d60acca8e8ccfb
+
+Count = 73
+Adata = fda8665f87c618
+Payload = af793815e147e3180f5146aa6a582e343dc479f26b4226b2
+CT = 6fb3959570107d0dffc58aa460d9ce35570a9b441d03bcac1cc84bd77fe00e1a13433f2c10e3b799
+
+Count = 74
+Adata = 46bde207491ebd
+Payload = 47c76a0bbd5b1616b278089d41a050c509c7a1c280574bf7
+CT = 870dc78b2c0c880342ecc4934b21b0c463094374f616d1e9990c81f1bae32c953bf02ddbde047632
+
+Count = 75
+Adata = a799f5f895fd7a
+Payload = d554806ffc3900a0952a3c094c745808950697a6e5d62c1d
+CT = 159e2def6d6e9eb565bef00746f5b809ffc875109397b6031af19f1f080dd1dd2da799059755e49f
+
+Count = 76
+Adata = 20225831a9ee06
+Payload = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b
+CT = 7a8f4c050fad7d7754decd18abcfa88ac9a738da00820b2523d3b9a0060834ac4860dae0eac570ef
+
+Count = 77
+Adata = 785360916464eb
+Payload = 57bc338946ff78cf76adf5021e2e44e34e687fb68ad703f3
+CT = 97769e09d7a8e6da8639390c14afa4e224a69d00fc9699edff96e7cf841a66c50bbb6fb2bac7ef51
+
+Count = 78
+Adata = 57b946369226db
+Payload = 9ac5be9929c4fe5a9992749a38dc69874866db3d4747da97
+CT = 5a0f1319b893604f6906b894325d898622a8398b3106408986e1c33a45f9d52755c374650635bef6
+
+Count = 79
+Adata = 73e4da8973c1e3
+Payload = 5a05410aa3a71f5f1a253b8576eba269c06a4c30591144cc
+CT = 9acfec8a32f0814aeab1f78b7c6a4268aaa4ae862f50ded2d78592c2d89c15edc5bb7486aa93f896
+
+[Alen = 8]
+
+Key = 98a42d7a0c5917deaf3b4de3f0cbe0a1
+Nonce = 03d33ab0c2df7bfce88b5ee4c4
+
+Count = 80
+Adata = 2d5438b728b950d9
+Payload = 9aa9c8358117564371366beeec923051ef433252197aaad5
+CT = 9ff942baa60f440c17a78e9581216b9a947a67f04d54911feecfff971fdfaa856310b014aa59c978
+
+Count = 81
+Adata = 6e430b497a16e7f5
+Payload = 5758a500978c71a9b90f6e5beae9d96ef05a41486b10ea2e
+CT = 52082f8fb09463e6df9e8b20875a82a58b6314ea3f3ed1e46a4d7b4b4df6c831ee32116ee4dad98c
+
+Count = 82
+Adata = e12f98507d6514c3
+Payload = 49efe18c76a8355127d914a3a830c1c6ff2a163d728526e1
+CT = 4cbf6b0351b0271e4148f1d8c5839a0d8413439f26ab1d2b3243fc75cd1624e152f451678edcac87
+
+Count = 83
+Adata = eecf8d641ee0bee9
+Payload = 49ae2309fbe6ce4e9421516b8f79ae64b1316cb849eaf638
+CT = 4cfea986dcfedc01f2b0b410e2caf5afca08391a1dc4cdf2dd6d8ca57da1880e1baff43736b3da34
+
+Count = 84
+Adata = 9066367c784de0a4
+Payload = b1bda5fa4242aa6aad0f5a5b1d31d86b8d4a97588b3e315d
+CT = b4ed2f75655ab825cb9ebf20708283a0f673c2fadf100a97f05439a661001513a96b896de46b7081
+
+Count = 85
+Adata = edf848b2510f7803
+Payload = eaa8608f6763d968576a7e89056b9828a1686c8441b06377
+CT = eff8ea00407bcb2731fb9bf268d8c3e3da513926159e58bdcf20709b2dc2ff9946094190b5ea09d1
+
+Count = 86
+Adata = 0f49cae81c8628d2
+Payload = f32029cf51609f0df9832ad1b283ea94a5356f70112c1328
+CT = f670a34076788d429f12cfaadf30b15fde0c3ad2450228e2a5bb6b4f87b9b198665203e4fdf9e7f7
+
+Count = 87
+Adata = b0c47e9cce46a276
+Payload = 7a550ef9254a8da6e4fee290a76ea838ffb61d3533d4d31f
+CT = 7f05847602529fe9826f07ebcaddf3f3848f489767fae8d529f416f89f1a34bbbf2ce40d943c6d8b
+
+Count = 88
+Adata = a6fe7c9ce2d49f85
+Payload = e67c486dd7ba9a9061844b9354f55890321ae626efaa28cc
+CT = e32cc2e2f0a288df0715aee83946035b4923b384bb8413067eb95550b91b955d5c2d72d5c189b704
+
+Count = 89
+Adata = eb1d11cc4876f58f
+Payload = 35f2c810091e930a52e4a3f28c9c8184967f1554c2675eb5
+CT = 30a2429f2e06814534754689e12fda4fed4640f69649657f0e8e8a5a7e0ea6860bab4a4320f03ae5
+
+[Alen = 9]
+
+Key = 2a68e3fe746f593c1b97cb637079c3e5
+Nonce = cd62d0f27b7f4864dc7c343acd
+
+Count = 90
+Adata = abe4f1d3812bfe3ccf
+Payload = 13b4a874888db0e5d8fd814b5e7e04f7fdfbc1601ccc02bc
+CT = 032835a3dbf688d09cf2a32a92b101959d33ff47500f92f4fd49840440f866d1a22b0854996111d8
+
+Count = 91
+Adata = 2e21f466814d3d6340
+Payload = 08b5c773364cded74d7b308984313c17ff90eed496a27a2b
+CT = 18295aa46537e6e2097412e848fe39759f58d0f3da61ea63de2f5c335df537fbbc6ae59cd562732f
+
+Count = 92
+Adata = dba22aabcea0e694fc
+Payload = bbac1790abb7aafe272ec472c897e6363e335b3c4126c762
+CT = ab308a47f8cc92cb6321e6130458e3545efb651b0de5572acc5ed6e4a907ff4742ab6c835a427f92
+
+Count = 93
+Adata = 97e9d16bd757395ec1
+Payload = 7249612dc09809bbca9dd311e720f7da2cb54ce33e3eb9c3
+CT = 62d5fcfa93e3318e8e92f1702beff2b84c7d72c472fd298b1714b5a3df454f3bc35869da75adc882
+
+Count = 94
+Adata = 866cf710470cac74d3
+Payload = 060ae0ab9857324a3b2ac79f3b6e6f90f5de884ce9c7b930
+CT = 16967d7ccb2c0a7f7f25e5fef7a16af29516b66ba5042978aa33dffe2596832f98a9c8413bd898b9
+
+Count = 95
+Adata = 2dd7a7f832b29ccce2
+Payload = f77a9fd5363836deefd34e1bea0882484a7ab746b4495d59
+CT = e7e6020265430eebabdc6c7a26c7872a2ab28961f88acd11dd5049f7c53d6a7fe5d7f959689ee960
+
+Count = 96
+Adata = 502349a60e897356b5
+Payload = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34
+CT = 868d1068b64f0cedead7a50869faee6eeb9077fbed0b8c7ced9c3a0d0de8788471c5f6c2f9638b7c
+
+Count = 97
+Adata = debed45c9acf129268
+Payload = df5a47d3eb5c0b6cabb6711a45400602d205b82ecae9e849
+CT = cfc6da04b8273359efb9537b898f0360b2cd8609862a7801d49b4b9bead1b7de2021cff280d6f93b
+
+Count = 98
+Adata = 2726702dd62a6e5344
+Payload = 5a7649cb001fbb6f653cbca17756c5c1a078c2e240d92085
+CT = 4aead41c5364835a21339ec0bb99c0a3c0b0fcc50c1ab0cd69df31aba209d87ee22bd6a1dcadb168
+
+Count = 99
+Adata = e8006cfb0536696ac7
+Payload = 95186d41f927cdbef42157f21d966e88061b6558b5ec932f
+CT = 8584f096aa5cf58bb02e7593d1596bea66d35b7ff92f03677cc5b60c881fe834a789d28447d8fb54
+
+[Alen = 10]
+
+Key = 46b067cf9b1a28cf187002e90b14e130
+Nonce = bad8c03292bf01cfd8d34f860c
+
+Count = 100
+Adata = 8d65880eddb9fd96d276
+Payload = cc0915194218d4536e467433cd6d79ff1d9eb9ff160ab684
+CT = bd56edc015692c6ab9bec493a9893863598414a3d11a6a0f27ecdcb257d0d30491e5bf1aa8f90958
+
+Count = 101
+Adata = 8a65cde13149d9d54a5b
+Payload = 28257133b1d8b0b2be4faecd6e819ac783707a5c5f50c302
+CT = 597a89eae6a9488b69b71e6d0a65db5bc76ad70098401f89b10f9fc201e4128696dcd899dd2e24ea
+
+Count = 102
+Adata = e999ec3e1bfb25b5877c
+Payload = 96ab0cfc204bafc4f5851d6c682d631d0c5ad03ac925a943
+CT = e7f4f425773a57fd227dadcc0cc9228148407d660e3575c8c522e5ba5adbc6a639cbd06f103ebc9e
+
+Count = 103
+Adata = a8554441e073d6065dce
+Payload = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+CT = 21cda08aff3bcbc6eed9e44483d3ae5dc9d564d38a42e922e1a4e0f7ebc3cff3915d27971cce7e91
+
+Count = 104
+Adata = 838f0be8d04d28d77549
+Payload = d0700658d5f4010ff21091f3d119c99645e339198029c3a9
+CT = a12ffe818285f93625e82153b5fd880a01f9944547391f22c215c88d80bffc881aff10ba40f11976
+
+Count = 105
+Adata = 20f014d928d5b25fbaf4
+Payload = 4bdf28748a0c281dd49c7294ae8e55fe7a52d45ff6384db3
+CT = 3a80d0addd7dd0240364c234ca6a14623e487903312891382cc9391bc06aa6ca9d486a4e2a218c54
+
+Count = 106
+Adata = 56c026b8a71974ff7ecd
+Payload = f75db057f0276fff85014f54ecdec8f90b96a2a982db14cb
+CT = 8602488ea75697c652f9fff4883a89654f8c0ff545cbc840778b05c6c582a0bb7d1d9dcf6a46b9f6
+
+Count = 107
+Adata = 75c3b9e52648a4f9aca9
+Payload = c15c554169dbb9b08494afaa44819a10dc9ddad54199ab54
+CT = b003ad983eaa4189536c1f0a2065db8c98877789868977dff47d9ebbd3cff14623b10cecc94b53d6
+
+Count = 108
+Adata = 1c76c3014a14b7fa1ca8
+Payload = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032
+CT = 68b10e2ecf8d9031bd55ac7a099d37518bfc15f3b3495cb9d2b74b84dc170c00dce85b56e346a976
+
+Count = 109
+Adata = a4eb60d4eb7ead1bd0e6
+Payload = e06e5dba5ac35cfd07949e5cc12ad70507d4a86a952ecca3
+CT = 9131a5630db2a4c4d06c2efca5ce969943ce0536523e1028d92e19fd8b5c1fcbff36adaa5e47ae84
+
+[Alen = 11]
+
+Key = e94dac9c90984790a7c0c867536615ff
+Nonce = c19f06f91e645d4199365f18c0
+
+Count = 110
+Adata = 537038b5357e358a930bd6
+Payload = 4d64461c55eb16bf7b9120f22be349598f2f394da8460dc6
+CT = e9fc5004c2359724e1e4411ae6f834ef6bea046d549753c88790c1648f461a31c84e62ea8592a074
+
+Count = 111
+Adata = 7e3d7b3eada988668f3784
+Payload = eab7d5dbd91d4cbbac8d79fadd70b5dcb3baadac5cb713a3
+CT = 4e2fc3c34ec3cd2036f81812106bc86a577f908ca0664dadacb1d1c9231d2c22ecfeed622792dfd0
+
+Count = 112
+Adata = 78b107b29c4878ff18f749
+Payload = 3c6ae2e2578875a1f5611582528e058aece2ddc33a4dde3d
+CT = 98f2f4fac056f43a6f14746a9f95783c0827e0e3c69c8033fffe60299768f048e7098033cde046b0
+
+Count = 113
+Adata = d293908bb516c5f3a411b9
+Payload = d7a46e726ed43f1580eb52141a93390982cc809dc833e3f0
+CT = 733c786af90abe8e1a9e33fcd78844bf6609bdbd34e2bdfe4ee6ebc0d90a0de05b428495c93e1801
+
+Count = 114
+Adata = 33ef208faad4d2948c9e67
+Payload = b1fe5d9d34157193fc0608cd8ecb872e17720f5f6814a466
+CT = 15664b85a3cbf0086673692543d0fa98f3b7327f94c5fa687e7e64cc0fcd6a92c79ceb6ce2abd8ee
+
+Count = 115
+Adata = b7f7ed9ccac3c2b4fbfee0
+Payload = de6bb539fb7a9c87414f62a7cf25a4cfca176509e991af41
+CT = 7af3a3216ca41d1cdb3a034f023ed9792ed258291540f14fb02b53bc779e0976b634b0d1b88fc0a9
+
+Count = 116
+Adata = a6e287383927f76e4927af
+Payload = 8719d20c20c8959068b8adcd65e6f6bc7b3693828f0735a0
+CT = 2381c414b716140bf2cdcc25a8fd8b0a9ff3aea273d66bae3c37fa936243b393f07fcccb0fc13e41
+
+Count = 117
+Adata = 70828be6dd93954f4e7b6b
+Payload = 30b39426831f61c8ba5f2ef5b71f0c4b2f916e3b5a578110
+CT = 942b823e14c1e053202a4f1d7a0471fdcb54531ba686df1e0d7534a489e6d242966ebea4455f8f79
+
+Count = 118
+Adata = 506015fc2831df293f4da0
+Payload = 818d5d810f678629f078723f5c6c3657271077533bfb7c29
+CT = 25154b9998b907b26a0d13d791774be1c3d54a73c72a2227ccbf64f04e95b180d09e843847d22104
+
+Count = 119
+Adata = e9394b0245b379e68e3dea
+Payload = f0613205a7a0822849df9e8a3cf6caf281f3adfa966c5507
+CT = 54f9241d307e03b3d3aaff62f1edb744653690da6abd0b0927b546ef8cd717073832584fb25a0645
+
+[Alen = 12]
+
+Key = f6bb5d59b0fa9de0828b115303bf94aa
+Nonce = 05358f33e1fc6a53ab5a5c98ce
+
+Count = 120
+Adata = 040b25771239cc2a39446e3c
+Payload = 011fc50329bfd63a85ebd4f7693363602f1a4147371270b7
+CT = 4432d7eb42980734d34f19c50cf8abf71ac1b19ed75a727854e5d050a405f755047d09cb0f49546a
+
+Count = 121
+Adata = 50a1d37fa2f3462bd304631b
+Payload = c90e40540d372ab1eb00ea5d5b8de5bf7c94ce4e376d6949
+CT = 8c2352bc6610fbbfbda4276f3e462d28494f3e97d7256b862abee8547ee3f24cfa677468ecc1d121
+
+Count = 122
+Adata = ac3bb872a41df35e415d2b0c
+Payload = 9e7be78c0ab9e6a4c6c257e77c63681bea35d951f168b0c5
+CT = db56f564619e37aa90669ad519a8a08cdfee29881120b20a61cef865ce4080e7c7abfc43f62c03a3
+
+Count = 123
+Adata = e3106ae6456153dd922640a1
+Payload = 00df0c5a5d3eceb2bd293066529799544f846672a9a1d31b
+CT = 45f21eb236191fbceb8dfd54375c51c37a5f96ab49e9d1d4e1d19c321a1e0852adba939b447220ab
+
+Count = 124
+Adata = 297b4498bf5427e6341aa927
+Payload = 14967a0476dbaea03b07fa8d40d344eabaf479be2443243a
+CT = 51bb68ec1dfc7fae6da337bf25188c7d8f2f8967c40b26f579ea5fb65018abdcde1a39f6859ecb56
+
+Count = 125
+Adata = 5de60dc0e3b5bda0b33a9520
+Payload = 2da3716d76d10b6766a1f9cbf9f420316fd5f396e7b9a2ba
+CT = 688e63851df6da69300534f99c3fe8a65a0e034f07f1a075c2629ff871ee15745fd8c1ddbdae4c29
+
+Count = 126
+Adata = 1c9b8541943ad50b4243c179
+Payload = 8c1b3ba18d1f5cff74a457aadd6b3e7d093d06ad2622e6a0
+CT = c9362949e6388df122009a98b8a0f6ea3ce6f674c66ae46f04e198ad16ad1106d3ba6172f4a13a8f
+
+Count = 127
+Adata = 51e926d2542ac8faef61465a
+Payload = 88936e97db070c0ec2aa58d1c6f5b34df3d32ddf7db34a8b
+CT = cdbe7c7fb020dd00940e95e3a33e7bdac608dd069dfb484475981131e3934ec6d41e00d502729799
+
+Count = 128
+Adata = ebefbac97b363e6f32526aac
+Payload = c20742e4b410c5b661da373a905fb0ed55b20e0e879eff5c
+CT = 872a500cdf3714b8377efa08f594787a6069fed767d6fd93e2c005b5bebe07ff578b1b4bc51971cd
+
+Count = 129
+Adata = 1ef059ac7d648e9e32d9b1f2
+Payload = 65c55ca21a89a8325365bf2be861d700559de2eabb41b37f
+CT = 20e84e4a71ae793c05c172198daa1f97604612335b09b1b021a25f15b5b4229a872a9199972c85b3
+
+[Alen = 13]
+
+Key = d1da2e961e78063af8de41865b226873
+Nonce = 03739f5474857006340cce554d
+
+Count = 130
+Adata = e3afd091d2b588465872a6300f
+Payload = 8e5fa1a6662a8378cda15697e926841594f2f394fa5a34ab
+CT = ca0d95e3ff186ad6b88d45fc4079e6b7b4a615e7e8dd5f4742d522cc9dc19c47a4fa0b1528069cf8
+
+Count = 131
+Adata = ce3186bb737753b59ee76b748c
+Payload = 311ebc5ff2f625944562ea699b2690df3e6e64a17c62bd3a
+CT = 754c881a6bc4cc3a304ef9023279f27d1e3a82d26ee5d6d659b26510b8f25610799e011d7c850ecd
+
+Count = 132
+Adata = bfd636989dfbcb0edc9f014cc8
+Payload = c96cee5ba7b799f16254a17b1870cdb85fe0ef3f42110c13
+CT = 8d3eda1e3e85705f1778b210b12faf1a7fb4094c509667ff52942aa0d39649f3d9ed535bebc2b603
+
+Count = 133
+Adata = 4812b092aa59d57451bfd812c3
+Payload = 13b1b4404dc5735655139414fcbd02c5327ae9fb148bd324
+CT = 57e38005d4f79af8203f877f55e26067122e0f88060cb8c8c1e61efb9c1d84ddac2d24f43531f569
+
+Count = 134
+Adata = f6ef9ac4f4c9ce1e4309c64fa8
+Payload = 6c5b59319e2710f5d63407f85b424d1860425ef8ce0cfe53
+CT = 28096d740715f95ba3181493f21d2fba4016b88bdc8b95bf13350de0ef34df12fb945b0ae0a0d9bd
+
+Count = 135
+Adata = 9bf12168bb3d79ebd25262f2b4
+Payload = 968e1d78008da78611e82985c4028e86770858cfe61c3723
+CT = d2dc293d99bf4e2864c43aee6d5dec24575cbebcf49b5ccfa0734563638598d8c4bf1fcd94009925
+
+Count = 136
+Adata = 7d870d7e52d3053c65eefad477
+Payload = 6a1306d911434cc7400d2f9a95e36aedceddca2b3d583f51
+CT = 2e41329c8871a56935213cf13cbc084fee892c582fdf54bda1f5fc53b08aca82bccfba6fbcb27e69
+
+Count = 137
+Adata = e95099f04371e445e5eaa1d80e
+Payload = b9197eb50c8168d16b8a12bd261d553ffcc521d979b26fee
+CT = fd4b4af095b3817f1ea601d68f42379ddc91c7aa6b3504027d1a922953facbd630d7fea6b63594ec
+
+Count = 138
+Adata = 3e80eb03db6545204ef4241ad6
+Payload = 95f59e36eac8eb3b51709d635b07fa2da0976ea20e25807f
+CT = d1a7aa7373fa0295245c8e08f258988f80c388d11ca2eb9383fa000d10078256b71249d9d1f1846c
+
+Count = 139
+Adata = 9748798c0f3cc766795c8ce0e4
+Payload = a48db9add9ecdeb49e51d3ab7bb2075202ed2aa50c0195b1
+CT = e0df8de840de371aeb7dc0c0d2ed65f022b9ccd61e86fe5d2773c2f55b752477c489facee812c614
+
+[Alen = 14]
+
+Key = 1eee667267ef10b03624cf9c341e3f75
+Nonce = 0630a3eae27e505c61c56e6560
+
+Count = 140
+Adata = d24651ef0561282d3e20e834960c
+Payload = 798e31cce0a83702a95171fb1162a17b9ce00ec3592ce262
+CT = f3c3e52f1a1ff528a8d3783ee4e75f114e3e6416334815d2d9236d5c5c9319092078411b72c51ba8
+
+Count = 141
+Adata = c527d309ab29ee91c5fc53117e71
+Payload = d79cd4c8891ec4ce2c51136712d23b32266b2b73768aeb1e
+CT = 5dd1002b73a906e42dd31aa2e757c558f4b541a61cee1caed8ad2a48cb734e3f93e602c15c7c775e
+
+Count = 142
+Adata = a93dfc3944514ddfc5acdd89fab7
+Payload = d7fa81c949f1f2af29dbd56529b307e3b348e996d0936455
+CT = 5db7552ab34630852859dca0dc36f98961968343baf793e5f34b297f3f106a9cdae255f7634fbd0f
+
+Count = 143
+Adata = e502abe21c7b22120693a08ef3e6
+Payload = 6330caaeddf0473d564d175b9408c6f12e6d3cd4ee2c423f
+CT = e97d1e4d2747851757cf1e9e618d389bfcb356018448b58f4f5d9c3dbfe3e2fe03a002e55039ebe6
+
+Count = 144
+Adata = a49b34dfad43333fb2ffd701a2d6
+Payload = 45671482c390e65f75de15ca91b93596e9bf3d6fc9178bcb
+CT = cf2ac06139272475745c1c0f643ccbfc3b6157baa3737c7b6f7bb0749c99d75740f2d193fef36c60
+
+Count = 145
+Adata = 9e4d8aa3dbdc4d4b4b8d72734f52
+Payload = c8f34bea8bdc403a48d8ed9268429141cd03c29558050ef4
+CT = 42be9f09716b8210495ae4579dc76f2b1fdda8403261f944ceec82fc674da9efa6926e8641729ed8
+
+Count = 146
+Adata = 052327ad59cc791259817fd0ed96
+Payload = d8d1c57b16c23894b66023c29f8648ce4a6074647e1f5f69
+CT = 529c1198ec75fabeb7e22a076a03b6a498be1eb1147ba8d92ff19e93f60c8f3a511300fddc38ee59
+
+Count = 147
+Adata = 14bc3c44c001ccb261a2a0526523
+Payload = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b78
+CT = fb8c9e93cbb4ff9b5a7c2a72aa6863c55a58b7c4534efcc87fa00fb244eda0d77cf6c05c8fd590af
+
+Count = 148
+Adata = 3477384c396a9e9efb3e169722cb
+Payload = afa795f836763a1210bb36fef167864f73ba3b6abc593537
+CT = 25ea411bccc1f83811393f3b04e27825a16451bfd63dc287bae19612657c87d3bb73cfb8cee7c8a8
+
+Count = 149
+Adata = 0c3b9a6924ad506038cb2d6590c9
+Payload = ca4a186f116a179579e3d327aec3f5be358bc7094f853bc3
+CT = 4007cc8cebddd5bf7861dae25b460bd4e755addc25e1cc733d9713d2e916c23ac3039de34c295fc4
+
+[Alen = 15]
+
+Key = dbbd26f5d9e970e4e384b2273961be5a
+Nonce = 0b1eabe504ef4822542e397fec
+
+Count = 150
+Adata = 477937301c83ba02d50760b603e0ea
+Payload = 553714e17a208a2eceb847a4a2d95088388b1ac8d8ca43e0
+CT = 1c80213268bad5402c4dc9b5d836ab7499810d0d8a974716df9a0e986ab2890736423bb3772cec3e
+
+Count = 151
+Adata = c91eb5a07ff19c044023e5cf339203
+Payload = c94d0b9e728413c58202cb3f6b82dba7aa9e3ca0a72c40c7
+CT = 80fa3e4d601e4cab60f7452e116d205b0b942b65f571443139f907a92cb01215e3cda84ae13af48b
+
+Count = 152
+Adata = 38c71a8e9b279c605c7f0418a0afc1
+Payload = b4e8c4fd5ad98a1be8b5a11677c57ca1c1694e3528092aa9
+CT = fd5ff12e4843d5750a402f070d2a875d606359f07a542e5f3dbd8dbf7485106cdf9ea0e7088a5650
+
+Count = 153
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe8
+Payload = 578ce26cdb5ba2e8798e23588e5cd04ef782820b80e49a42
+CT = 1e3bd7bfc9c1fd869b7bad49f4b32bb2568895ced2b99eb4853fde6f4dca88ff11bbce20ed9e5012
+
+Count = 154
+Adata = 36004342dd74e7966692a848b2c11e
+Payload = 78733c635d4d4e8b0729732f1e174dfcec4e020a7ac3870d
+CT = 31c409b04fd711e5e5dcfd3e64f8b6004d4415cf289e83fbd94e979108fcecbd32f6bdf72f0ccb4d
+
+Count = 155
+Adata = db92bc3fe5d4141aeb39baea6f114c
+Payload = c7aafe7760945e45703c1e19f1032dfd56ddc216c3b03826
+CT = 8e1dcba4720e012b92c990088becd601f7d7d5d391ed3cd0229c8f9d4e39fc16cbdb44236ef125c7
+
+Count = 156
+Adata = 34ec2d5b6f0d950509b47a0637d74c
+Payload = 2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3
+CT = 6af2d6b9712454163d6068187d28765c4584762254d8a5051c9ab7cb0a779c3fa78c9ee12603802b
+
+Count = 157
+Adata = 6ab658d177c2dd87c9b8787cd70182
+Payload = b0725f735543eb0c0ec88ae69b140f5787d28ef4a2e36d57
+CT = f9c56aa047d9b462ec3d04f7e1fbf4ab26d89931f0be69a1648c6307ec5ea304045a7cdc93f36b9d
+
+Count = 158
+Adata = 483f135c61250fa610b4d14b99ecf0
+Payload = 315a947bf5291278d446d332ee5ca0def7655d5c957a8fb4
+CT = 78eda1a8e7b34d1636b35d2394b35b22566f4a99c7278b42364ff3b1ad915347b1c7f062b10d3da4
+
+Count = 159
+Adata = bb022aed60819ef84ae83ce27db9d0
+Payload = f78d00755bcb45e6822121fe7cb03c8e627c9f548ccd7e7c
+CT = be3a35a649511a8860d4afef065fc772c3768891de907a8a7569808dab58d42181543b2e2d05992c
+
+[Alen = 16]
+
+Key = 10a7720f2e18f739c26924925af6b670
+Nonce = 8c4e7813ab9bce9dafee01c628
+
+Count = 160
+Adata = a209941fab710fda38d11c68b13d930f
+Payload = e59782a9aea45f467b90e51a0fdf166baba05663def2d8b6
+CT = e357b1ccdaca6f3506dc45279c2e4c59f5307a5fd6a99cd72341ea8c0785569973f90ee9ee645acc
+
+Count = 161
+Adata = 2e2f6f9755a492ee54df77b2ecab9808
+Payload = 042a072f6ebf11f79fcb4f5a64f7946dc837d9d2355785ea
+CT = 02ea344a1ad12184e287ef67f706ce5f96a7f5ee3d0cc18b703eb81224cdb1fd2e1cfb2fbfe1e402
+
+Count = 162
+Adata = 99e98c9983c85d1f49ae43ebad67a652
+Payload = 5db6bda27910e7b8b61ac476c6532570b71b3932bd6a698c
+CT = 5b768ec70d7ed7cbcb56644b55a27f42e98b150eb5312ded64c4aea7f17f18f068897557c93ffaaa
+
+Count = 163
+Adata = 37a837d73fa15793f6f823fb99c2ea74
+Payload = 8cac261a461c3ddd2642b8e4e5c3389e491fcb2ff8356412
+CT = 8a6c157f32720dae5b0e18d9763262ac178fe713f06e20736f3b2e70e6e2dc7acc74a823a7f49722
+
+Count = 164
+Adata = 11119a4e779cfb64c736d425e4ff554d
+Payload = 3429f9b088b501d7944c462694d0799568282e7ce07d3e61
+CT = 32e9cad5fcdb31a4e900e61b072123a736b80240e8267a000dc3b57096f0df1d4eb5328c416921bc
+
+Count = 165
+Adata = 962d7d4305f23d1692747b504960c0a4
+Payload = a46ae4c71d4c9eb72fabfa76b8074aa02e07653eca10eef5
+CT = a2aad7a26922aec452e75a4b2bf6109270974902c24baa94f62ed804e9f2ac0f7001d0f35ea9f3c1
+
+Count = 166
+Adata = bbb1fdfefcf3657ba6cd93ff341a04e1
+Payload = 92f5e3083f57c77ac9553a2024a66489698bd2261f05d415
+CT = 9435d06d4b39f709b4199a1db7573ebb371bfe1a175e9074907dcd7ac1e0bb248d46c3036c39fb02
+
+Count = 167
+Adata = 74be126f7c596642dafa8fe3da904e69
+Payload = 41ecc3aae5cfebfad7921a47a0684601ffe73816380f8716
+CT = 472cf0cf91a1db89aadeba7a33991c33a177142a3054c37787cbb80fd21127feca7e76fd6947d5b7
+
+Count = 168
+Adata = d72cc521c90a468522af8966c24799f3
+Payload = 8850bdda4bd0271e333db344a47b837183eb48269c3dc0b6
+CT = 8e908ebf3fbe176d4e711379378ad943dd7b641a946684d7cdb5d1243b6e73b8e380d8ca041647db
+
+Count = 169
+Adata = 28f427fba8d0bb0380bbe5072ccfa519
+Payload = fdd3ca2f193f93f5a349b50357d26748b767cde6ab5cbfe7
+CT = fb13f94a6d51a386de05153ec4233d7ae9f7e1daa307fb864a0ae8604b103f882f17db893ed5c576
+
+[Alen = 17]
+
+Key = 6bffab1f4f4c1ff66b4a669b515b2f8d
+Nonce = ddb34d5e0140fb96d690e1a2b7
+
+Count = 170
+Adata = 5cbba9ea778e01af00afb2a934f28c7211
+Payload = d91b12e8655dd92b1332fc1d71c391c96a17111562d90ba3
+CT = d302e5b2d5d90433186b804cd7717e2db2f22cdc34fb2942ab30780a2c4f12af8f35350d65284c59
+
+Count = 171
+Adata = 1583138aa307401dddc40804ac0f414d33
+Payload = eeafb08d4a4819f5682a01d44371e34cc5729079e74e73a6
+CT = e4b647d7faccc4ed63737d85e5c30ca81d97adb0b16c514746577901b7f6feb88b8e2b8562f9cb5f
+
+Count = 172
+Adata = 23931c258c84086500c6a3b6eda457e6b5
+Payload = b8737d5bbfc976c2d8d9786148dea664dd83cee98df537b5
+CT = b26a8a010f4dabdad3800430ee6c49800566f320dbd715548735a59390ba7a892741694f3a89b0bf
+
+Count = 173
+Adata = e12f98507d6514c3b551d240595346bc9e
+Payload = eb021b63c61c0b194bd44870608d7ef0b932b6104412d7a9
+CT = e11bec397698d601408d3421c63f911461d78bd91230f548f4f81ed18cc1820375a7bec2318cde1e
+
+Count = 174
+Adata = e14b87d49d231c0199eec627fd7f1b5332
+Payload = 93b42584c4956078359d77e80aef52281b9228a1f66aa36b
+CT = 99add2de7411bd603ec40bb9ac5dbdccc3771568a048818a187b430caa60d98dc3e2aeefe6249b44
+
+Count = 175
+Adata = ca095aec96a8b093e62b10f0950ce35ce7
+Payload = 6a788d8238c7b313b8eba27b210a71c36819d719115b9b76
+CT = 60617ad888436e0bb3b2de2a87b89e27b0fcead04779b9970a77372b727408e1bf5a70790b9eba3a
+
+Count = 176
+Adata = d1cac02b34ad33c0e77a5bda2c3baf5e5d
+Payload = 3bc1ee54d0094603dfc68eee118e547d031fb36e464e776d
+CT = 31d8190e608d9b1bd49ff2bfb73cbb99dbfa8ea7106c558cdc1f5cb4d4fa2204e82eedcb3784443d
+
+Count = 177
+Adata = 065c06b49a49898e20bb679e35edbb1f76
+Payload = 8a12adb8b746216baa8a418725e608e4377f13816a036a10
+CT = 800b5ae207c2fc73a1d33dd68354e700ef9a2e483c2148f12413f9496592a75a1d6e42ee3a258607
+
+Count = 178
+Adata = 98a42d7a0c5917deaf3b4de3f0cbe0a191
+Payload = 30a226c07401d0ae24c73d682e3a6e7e377ec1613bafba17
+CT = 3abbd19ac4850db62f9e41398888819aef9bfca86d8d98f6b571a3150887df1ac5f813676b2eb24f
+
+Count = 179
+Adata = e245a7528931841b52a5f59d861d98d7b7
+Payload = 3d17bcdf30445ebd8a9b6aa2fe11d443c1161bb1ee69ced0
+CT = 370e4b8580c083a581c216f358a33ba719f32678b84bec3131aa5e4657c92e31c69ab18d447d3578
+
+[Alen = 18]
+
+Key = ae6136df9ab43631ef143515dacedbe7
+Nonce = c5c445792208a50c8e93d64aa3
+
+Count = 180
+Adata = e04006b68c83a5dd4ceac3cde238e48895ae
+Payload = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731
+CT = c7584c0203c2535c5702c6ae93b7cbfb066f4a055c627a180d6d676d11fce907b5c93fa1ed7bff2b
+
+Count = 181
+Adata = 5da64e368f45153ea5b7ddca966b6c5b699a
+Payload = 15e0c672c6764f3699d9d3e7120f8ce5daab166f08fdd074
+CT = b8f1b62e36c280a68fdacefb6a8ea6fb67012bca0351ad5d2cd45f211b1a1364c91ad07959bf0ee5
+
+Count = 182
+Adata = 1b315d024bb5d1e03d7510e61f37d8adb10a
+Payload = de907d58cd8f5a72acaa1d329b937dfbbfed65a4e45eb029
+CT = 73810d043d3b95e2baa9002ee31257e502475801eff2cd0018f021a98b2edfb0b7500363099c2a1a
+
+Count = 183
+Adata = 8691ba4f9232ca86f919fe72ddb39c91d707
+Payload = c7fa314d27be79f9d3e2d1e188c1785b0c970f91b8ed4290
+CT = 6aeb4111d70ab669c5e1ccfdf0405245b13d3234b3413fb92ac9aeb018c48f3902276ac759710b6d
+
+Count = 184
+Adata = ff0baf1cbb5884a9290ea7b5ee49915efb4b
+Payload = 33b05b20f3c849fac091a5028cbfa0bc9a1c32514136fee3
+CT = 9ea12b7c037c866ad692b81ef43e8aa227b60ff44a9a83ca7dac49f606dadb9f7034e0a1860d519b
+
+Count = 185
+Adata = 2d118cda20700bc2748ea1753fbca6f74933
+Payload = f43832e420e2eccd5d80502bea2ba1804e17d4433318fc86
+CT = 592942b8d056235d4b834d3792aa8b9ef3bde9e638b481af623ccbab19c1442806e21c5a820945da
+
+Count = 186
+Adata = 0c7a5fd2010c999a8a0efa81f89ff5bfefe0
+Payload = ceb203c842a962183f22e602644fc66e4290b3d5be445fb4
+CT = 63a37394b21dad882921fb1e1cceec70ff3a8e70b5e8229ddbcd18947ac1800856c9c92eb0388c70
+
+Count = 187
+Adata = 73fdddb9e0a64f5671fd70c4ea8443507789
+Payload = d6015b6bd5f5eabb2a649129f8f727c06a3ad59499f21caf
+CT = 7b102b372541252b3c678c3580760dded790e831925e618639c29ea73b0c5aa130d8b14f7b9926a9
+
+Count = 188
+Adata = 82c4484e3a6e18b6bbfd78b69b00c40b30c5
+Payload = c288b810fb533441bd549d02c0b28d5b834293683eaacda2
+CT = 6f99c84c0be7fbd1ab57801eb833a7453ee8aecd3506b08bf0a0f148ae138c2ea02538c8fd7ac76c
+
+Count = 189
+Adata = 267d8385b14721eded743cffd69e4d595f7e
+Payload = 667cc47d13c34923be2441300066a6c150b24d66c947ca7b
+CT = cb6db421e37786b3a8275c2c78e78cdfed1870c3c2ebb75285eb537e7583f04e040a0ddc41106213
+
+[Alen = 19]
+
+Key = f1908328edf2996ebfc9655472ca5ad0
+Nonce = 4c693364546930b6c5250e2699
+
+Count = 190
+Adata = 4a3634e5028df97fbe00eb016e8ea4f1918faa
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 90c850790b0b380f5aeb2488fdf43c9d5ef1759861e86f6e52570e769629dcc2e568737ba53a1195
+
+Count = 191
+Adata = 041b93e3fc059fa44aa755e88df277b9b6e499
+Payload = e61ca7310172eec16745a73e34516f65844eecd0dbc5566a
+CT = 980af6f885e3e6f2e2ba4a2bb3e020d1a87976ba1bf63feff1d82ec19a2e3ec43bbdb34e10999d90
+
+Count = 192
+Adata = d1be393376cb5d23cf8139da0fd92f3d520ae9
+Payload = ea887edee68ad5fa6bae928aa480dda898037f820700ec52
+CT = 949e2f17621bddc9ee517f9f2331921cb434e5e8c73385d7f2abb0ce4de9eeb5e8af9cdf3391d3cc
+
+Count = 193
+Adata = f3e551b34d2db1286a9f41085e4dda95ec3f75
+Payload = 71fe1ba5d299495d2a56039c64032ec6263d437f55e3f5be
+CT = 0fe84a6c5608416eafa9ee89e3b261720a0ad91595d09c3b239c73b01ba49a8498b5ff4833851069
+
+Count = 194
+Adata = a69ddc66e63a3415f21009d53adcf26bc1a9a5
+Payload = bd04d854216740a6ceb9827cbddd83761d19feb2a21d78ef
+CT = c312899da5f648954b466f693a6cccc2312e64d8622e116a2248dacd3903c26a2dc5ae649566ad67
+
+Count = 195
+Adata = 5735d6f5882d8f27155eb4cc285a65138ad64a
+Payload = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda
+CT = 4da219ba2330ed8378449366c0d371fb8dfb435d3e81065fd4156cf7d97b2e744351b6960a807cf8
+
+Count = 196
+Adata = 5d94ed976ab2063512690ae704c3b115519742
+Payload = d3909d577a4e89642227cc6fc146b61bc18392175e342898
+CT = ad86cc9efedf8157a7d8217a46f7f9afedb4087d9e07411d5a50086b6711ac72533c3c5717f6892c
+
+Count = 197
+Adata = db20b384620ab8691aed2fed14a745188d94c0
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c56699029
+CT = c41147fcdb6eb0dc1182c7006ce978ee33c69226965af9ac54fb74ecb9a5163b01b9dbf97ff2f999
+
+Count = 198
+Adata = 94897cdd04e0c8480b2ef7b5201dda37558ba9
+Payload = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9cc
+CT = 215d1e5e323b409e36cc81509d1d78cbf27d452d494cb049d2a81702f665ff5c54f586defd268c94
+
+Count = 199
+Adata = 95c44e1e5ad256b3ce1cc1d87137a1e09f1fd4
+Payload = 598e91d39c414496fd5e69f2cf80826b4e7d59ba28e0a0d8
+CT = 2798c01a18d04ca578a184e74831cddf624ac3d0e8d3c95dfa641889723e163825ab65727e8a5343
+
+[Alen = 20]
+
+Key = 61cb8eb792e95d099a1455fb789d8d16
+Nonce = 1f37b3e59137f2a60dc09d16ac
+
+Count = 200
+Adata = 09db3efac9473f713da630ae92c2c8604c61c51e
+Payload = 6ad541695a37c32d73ff6d5f870abd5b0f362a8968c4fce0
+CT = e65fcc975865c1499b088b58ba163283085d8ca68dc3b235d89756e5d78753ef22c012ae34b39a20
+
+Count = 201
+Adata = b6d07035aed9c141c713cc3bce60f7ba8ac2545f
+Payload = 9cce4c82fe9d38ef64ac8abdf0619f201a25ce6903675627
+CT = 1044c17cfccf3a8b8c5b6cbacd7d10f81d4e6846e66018f2fc78ebae9c143a7283b0641e1f83f5a0
+
+Count = 202
+Adata = 80a5ab693378af29cd5a33555cb3579f9ae540aa
+Payload = 7295a7aed3e987baef19ad68c33ba5a5dcbff27875ff5236
+CT = fe1f2a50d1bb85de07ee4b6ffe272a7ddbd4545790f81ce35a7e44348d2b3085348f787128a4e96a
+
+Count = 203
+Adata = 220817144a15a0a654fc1beaabce60270aa72df8
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 67ab73defe1d9021c3d1f8ab3067ffd9681fcf803af0ed2024dfc096cd8a09d2d81f6146fb54082a
+
+Count = 204
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01
+Payload = 23bf80f51dfd83f63986910e69d54a315c2bfb43f432b7de
+CT = af350d0b1faf8192d171770954c9c5e95b405d6c1135f90b5da82204f4dd8f535cb2fec2f133d882
+
+Count = 205
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe88436fdc216
+Payload = fc3a50cc8a68778327923ea697f5388da4c814381e29c5e4
+CT = 70b0dd32883a75e7cf65d8a1aae9b755a3a3b217fb2e8b31108630135498ba409f4b6c8caee8a85b
+
+Count = 206
+Adata = b40c8c1d2cee490653105ca2443356cdb63e4fd0
+Payload = 465e41c69928d08c33e063ea119595a04d0de6bffd17bba5
+CT = cad4cc389b7ad2e8db1785ed2c891a784a6640901810f570f89c515837d129ba41f9c24b0229ddcf
+
+Count = 207
+Adata = 6ebfa1e8f80b3cdb1bedf2e3c7e74f30f55c38e1
+Payload = 3f98ee3922f8f1086e3135ae66c5465426b13c8794954880
+CT = b31263c720aaf36c86c6d3a95bd9c98c21da9aa871920655a352fa6b9c4e40733ddcd3fcdaf9ae63
+
+Count = 208
+Adata = 6d0159861031c1a5f01aab35927fe2ab28154d19
+Payload = 5b43067a5ab3a9f9e633fdc084c44ffa7f11edd12ea5873d
+CT = d7c98b8458e1ab9d0ec41bc7b9d8c022787a4bfecba2c9e82c1aa13f062c0f1f5008e27ff2191942
+
+Count = 209
+Adata = 15e5ade017b30ab41878a2747e93aa91c61c2908
+Payload = e40b7e9e46e339e64891526e730b3bf6562fa37acefce307
+CT = 6881f36044b13b82a066b4694e17b42e514405552bfbadd2e149dd02bc7face0c4dfe4e501c2ac2a
+
+[Alen = 21]
+
+Key = be1ed49e2cb0caf6b6a0940c58453b93
+Nonce = b78ad129457681fa7346435b97
+
+Count = 210
+Adata = 161d92c7df1ebb0924719e066e08b95eb4914a5eda
+Payload = a9eec383f63892521e4616fcbadc5485942ffaf4669c43a7
+CT = 949be340720c4fdc4adc05cb777dd81a2549628d33fba07e62d2b338a7b34ebd9d85c244c952d681
+
+Count = 211
+Adata = 6b1d94bc0c6e45fc905c509ea667853e4b2c5a8848
+Payload = 7b44a093162bfc8b4d65f1031d890a6b08a3705b142c0c26
+CT = 46318050921f210519ffe234d02886f4b9c5e822414befff8a4defafeb3d61dad8c007b68d8fb9b3
+
+Count = 212
+Adata = 868dd3e241f60f097a7a2fe571307ee5eb961218ca
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447cad9d5
+CT = 15b1f61dba183895d001006a515cbc1b41858d2d12ad3a0c57cbab553b511d68a4f41db211d0a2fc
+
+Count = 213
+Adata = 3776f37fbf8803bdfd246ffaff2e59658a6c3f0ebb
+Payload = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+CT = 2ba665a3ee05875c14f0a8fc8e6c0034582e8802f3b699ab0290fd7dbf0afa3e597274e3c9fe170b
+
+Count = 214
+Adata = d0f2769eba9b8e618f00eed6b34c261c59322a253b
+Payload = fcbbcdd9599a86e7c8ccb9347065789a9728ca1220fa51ca
+CT = c1ceed1addae5b699c56aa03bdc4f405264e526b759db2139c7dec3960e6aba3174d793b4e08f449
+
+Count = 215
+Adata = 2be180892faed0bb75887668d187807666d3c66c68
+Payload = 8d145b1f792cc31a2e5b86216609bb018e7aea3012ff70a5
+CT = b0617bdcfd181e947ac19516aba8379e3f1c72494798937c7057b9e2d844e86ee5c3ecfb3270804e
+
+Count = 216
+Adata = 52859849a5b7c1d432c3bfb35271cd8141db2ec774
+Payload = 741db990b43ef34993c33d1c4953b67b128b9299dfe86d74
+CT = 49689953300a2ec7c7592e2b84f23ae4a3ed0ae08a8f8ead1150fa899152eef7a30ae0f20986818e
+
+Count = 217
+Adata = aa192759625f4e42d1d1fa73dc0f62199142155615
+Payload = 51dca5c0f8e5d49596f32d3eb87437bcae866640310ce1e3
+CT = 6ca985037cd1091bc2693e0975d5bb231fe0fe39646b023aba7ff9203608089558698ec29472dda7
+
+Count = 218
+Adata = 6de564226884188ec7bea3894535a875cff2a42fdb
+Payload = dfaa7aa8b28626210d5c24e2ddfe516189be05aabe26f3b2
+CT = e2df5a6b36b2fbaf59c637d5105fddfe38d89dd3eb41106b85bd0a5074ef852575baf5f12c22663e
+
+Count = 219
+Adata = f245f2ee23755df863dee55d7ef0c3c09a0b6f0b0c
+Payload = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc57
+CT = d3aa206931d9325331d3c04919e2d47ead3e145da4263f8e9eb617436bae012331daf020fce24e47
+
+[Alen = 22]
+
+Key = 34ab6fd7f54a2e0276fcb7cf1e203aba
+Nonce = 6091afb62c1a8eed4da5624dd7
+
+Count = 220
+Adata = 1ab5cc3d7b01dc74e6cf838bb565fea3187d33d552a2
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 0d30ab07153b5153637969e6bd3539448c541e42b3d432fd7ef14622a9b621d1721b944c60f7fd67
+
+Count = 221
+Adata = 1f1ac4674b272bc7a4ee9f4eae33e969b16fa90a69ba
+Payload = 14e99a2ef0de650adbd785c692342cdb765e6d20d5fca09a
+CT = 94cf7e706b44755193be855740cdcde455605601adf35bb6dfa4ec2c92671c64ee07946527be67f0
+
+Count = 222
+Adata = 43ee77f12ea42e82a02275a68aa95cbd1bb440442bcf
+Payload = 383242c709fe5f2ce782bf8c83b645d171f2bd238abc655d
+CT = b814a69992644f77afebbf1d514fa4ee52cc8602f2b39e71173572fbf3d9495760aae4347397b110
+
+Count = 223
+Adata = ae2ff288199be25bf640811541394ad7e1dd0dc0d24d
+Payload = 9c16a5b638c35c97c5c981c1b8dbcba11aec30e72e45a936
+CT = 1c3041e8a3594ccc8da081506a222a9e39d20bc6564a521a4d2327956e030b9df753e063b5b71201
+
+Count = 224
+Adata = 4ccfb4281852b5ca7e787723d689384a68ff9437db31
+Payload = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878
+CT = 6cbb6a8169cc55094068b67903b3cefc92ade051adea1354e4dac0c9130f5641afd035dd884b6271
+
+Count = 225
+Adata = d3a2fffc798fd9cc2f409471faf18caa2ff3dcf4e652
+Payload = 0db33eda4188a9165147e24e40f79fee1985eb68d5162728
+CT = 8d95da84da12b94d192ee2df920e7ed13abbd049ad19dc0448807dd50a9cf41651083c49c7493ceb
+
+Count = 226
+Adata = 7b5121aa4d1e314f209ffe3e92cd26ee4f74d91e27f2
+Payload = e0d3ea4308376423c4322503f56e427a64e2e6d8b4f5e668
+CT = 60f50e1d93ad74788c5b25922797a34547dcddf9ccfa1d448ea0da53046733f522ded40a09c6d7a6
+
+Count = 227
+Adata = 6e12c112720ef346bbbe7d1c19483721b1c52c438dad
+Payload = 491f2bca585d6b5fdf38d18890e4d1bc923fe26930b3d2f1
+CT = c939cf94c3c77b049751d119421d3083b101d94848bc29dd345cb5a968f39654b994686699d532c2
+
+Count = 228
+Adata = 20433402a2d869c95ac4a070c7a3da838c928a385f89
+Payload = f45908d691ddaf89c0bc129ffada94c3ceda5f47d63ef76a
+CT = 747fec880a47bfd288d5120e282375fcede46466ae310c46cce85eb55339b886b7121b306fccc0b2
+
+Count = 229
+Adata = 42f944c21cc221beaacb288115ac628346b8a1d94bd5
+Payload = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b
+CT = 63261824c00c9038caaa5a64603b09dd40bc4e3a210ef667a37ca5ce12aa6f0659467642deb8bfcd
+
+[Alen = 23]
+
+Key = ea96f90fbae12a857f5c97e0cba57943
+Nonce = 21cc46d9ced1539b0ad946e600
+
+Count = 230
+Adata = 105258d2f25f62675aee975cfdb668aff833f05b61eb2a
+Payload = 49db80f22bc267a70e5636dfbc8a21c83d9691fe4b9c3051
+CT = d2fcc8b7809b5fc07e44083e437d8180157f1782a9ce9f65c7fa9ee2e7cdc1b755258f2212a8a8f4
+
+Count = 231
+Adata = 0f5938540651fa4ca03867e67518eb2b73f60dd8750fa0
+Payload = 26618e21099a79d6c517335389551323065ad89c8848ea12
+CT = bd46c664a2c341b1b5050db276a2b36b2eb35ee06a1a4526bfdb9bfcd3b969fb2e41221eb92b0147
+
+Count = 232
+Adata = d6b228960fcbcf07c7bede616139db62b3808718a5b511
+Payload = 4de1d6d57144896ddea1c30f49afecd27bdf4840ed9928b5
+CT = d6c69e90da1db10aaeb3fdeeb6584c9a5336ce3c0fcb8781f8beea22cba93203c912209c78c03aa1
+
+Count = 233
+Adata = 75f8f071e229355e286882917ce5dd4f1db591fee51b6c
+Payload = 785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8
+CT = e37411f4772c72796b7fb9d042da3134cb00937ba241bfdc69a2e3ea4a40f7c491912c1a0778ebde
+
+Count = 234
+Adata = 4afb62aa8648ac7474dd16fcc376f8909c69e1ce36e6d1
+Payload = ab627aac1496d011ed2edcb2fc6b2afbcc394654f56124f6
+CT = 304532e9bfcfe8769d3ce253039c8ab3e4d0c02817338bc2a75c7ba2a769c27903e99b72639b0841
+
+Count = 235
+Adata = 736fdf94db820a2efe89e7fc9dcfe7c23d5754ac2bcc7c
+Payload = 40722cffb37f1455c2618408e777ed0f4b1bd039952730cc
+CT = db5564ba18262c32b273bae918804d4763f2564577759ff8f84f4ca4a69fde75d7207e50494819b6
+
+Count = 236
+Adata = 8a9a0367137c28db4c4e78d9cd9a68cde0d1b4583532ae
+Payload = dcaabf7a061502618541c09ea59dbbbd52b2692fd0064747
+CT = 478df73fad4c3a06f553fe7f5a6a1bf57a5bef533254e873a0c34a24d3ee0946034c71fba4dbb333
+
+Count = 237
+Adata = 34dbbff560ef04ea731b8979aef2ae50972f4db3efe14a
+Payload = dd641a893b16e0e173ea2eda20638bb01849ac11e64e8ddb
+CT = 464352cc904fd88603f8103bdf942bf830a02a6d041c22ef0f5e24a435a39a716c39f43dabdc4281
+
+Count = 238
+Adata = f3d1fcd912252431db9d8ccfc3e203d5b34d537468b4c6
+Payload = 9aa3e8ad92777dfeb121a646ce2e918d1e12b30754bc0947
+CT = 0184a0e8392e4599c13398a731d931c536fb357bb6eea673f623d59f66764d859a772bb50ec91fc3
+
+Count = 239
+Adata = 513b4cdc551c203ed5f1e659813584862023911590b672
+Payload = c8f44ae4b02fffdbce0df773c24075f877945fc7a86be460
+CT = 53d302a11b76c7bcbe1fc9923db7d5b05f7dd9bb4a394b543b6549eb16fba96318afb3df51f4675f
+
+[Alen = 24]
+
+Key = 35b403a15212097085d6e2b77ec3d4f2
+Nonce = daa423bf9256c3fcc347a293aa
+
+Count = 240
+Adata = d3c0ed74e5f25e4c1e479e1a51182bb018698ec267269149
+Payload = 7dd7396db6613eb80909a3b8c0029b624912aabedda0659b
+CT = 5b00cf8a66baa7fe22502ed6f4861af71fa64b550d643f95eee82c19ecba34280604b58d92dacd3f
+
+Count = 241
+Adata = 62f4fe53e99a9b0c51e9561d910d7e2ffe19a5176c9dec06
+Payload = 897f0dfd90213f64a9277a0eda4f134f303fa89f56ca54fb
+CT = afa8fb1a40faa622827ef760eecb92da668b4974860e0ef5ab4999e9689d52b8afeb87923efa3b48
+
+Count = 242
+Adata = 191c4dfa653c20292657f7694c6b6a4a410c49a879abd217
+Payload = 2b7cf9e6e2d6abcd7775f8a6eb6294e822041c4c45f09c3c
+CT = 0dab0f01320d328b5c2c75c8dfe6157d74b0fda79534c632cdc71e556c34fd4e1b5ebc50d38da8b3
+
+Count = 243
+Adata = ba34741f8edb51470eb20f891869aabeab562d92571ac943
+Payload = dccb9a4625512496b372a2b8b768f75741d8c2e30e57d638
+CT = fa1c6ca1f58abdd0982b2fd683ec76c2176c2308de938c3646223d381090661c2ee2370d29a572a9
+
+Count = 244
+Adata = 8b922aca6125722ec490b134a45864397f4e2c281d6e2089
+Payload = e0e452c990665465160b02cad6367ca89723613488d8efbf
+CT = c633a42e40bdcd233d528fa4e2b2fd3dc19780df581cb5b1f78af50466646b7c7e652f787afe5357
+
+Count = 245
+Adata = afb9fd78e3f8eaf4e8c91da62b2da534508e54f7dfa214fc
+Payload = b536fdb8839f87080ae65ec35da347e792622ffe18a61d46
+CT = 93e10b5f53441e4e21bfd3ad6927c672c4d6ce15c8624748cc9d9a1270f78648a6b66cb8c0f2471b
+
+Count = 246
+Adata = ecf942ccee7396cb3ee177eadd4d96a4af1d90afdce97376
+Payload = c81233826e5125e1f31fe275184ccba8f1a743e58e146e4d
+CT = eec5c565be8abca7d8466f1b2cc84a3da713a20e5ed03443b17d3d6f1fc4f530841b749d9f3a0a7a
+
+Count = 247
+Adata = 16fea92ffcaad563792aa924bffe7ef690edc90ea4e29cc0
+Payload = 24ab253b5b06552665c3c810254c0ed15e68a783180d7eee
+CT = 027cd3dc8bddcc604e9a457e11c88f4408dc4668c8c924e05852ed48cf88d9ab2326aa46b6541b60
+
+Count = 248
+Adata = 76f110eecd369d79e21fb208058359d3a2f37581d1f7f691
+Payload = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4a
+CT = 598e9d2078ce4845c6c6e0aa1c328fe7f8192a7852088444c62dff6bcade5ac2edb8ec9797ce433e
+
+Count = 249
+Adata = 8834c776a3237f060ae0ab9857324a3b2ac79f3b6e6f90f5
+Payload = 11cbfb3d348c7abef99f562607e289de34a2bb379a5dfe50
+CT = 371c0ddae457e3f8d2c6db483366084b62165adc4a99a45eb936ac4764575f85352c24ab23209d42
+
+[Alen = 25]
+
+Key = 7a459aadb48f1a528edae71fcf698b84
+Nonce = fa4616b715ea898772b0e89dd4
+
+Count = 250
+Adata = 0c0b4a45df5c3919c1e1669c5af5d398d9545e44307d95c481
+Payload = 0b3d947de8632dc8ff752f619ba7c84716fac7a23e101641
+CT = 7db9f3f7dc26fc2adf58d4525d26d5601e977de5a7c33911a1138cff7b624f9908b5b4d7e90a824a
+
+Count = 251
+Adata = aa27a28a36b5a2cee57ffeca0233feb4bdd4eacb2cae28e98f
+Payload = e6dedce2c278c44e5678d13e7d5b5d3501d61bb0bb6b5558
+CT = 905abb68f63d15ac76552a0dbbda401209bba1f722b87a08e23f92b598f7a248a894e6b8f5691bee
+
+Count = 252
+Adata = 66220aa9b40a1772caba7749a544bff938e804dbc6e556498f
+Payload = a276b0922fbd5094bf89b9329d07341e039d6204397b81c0
+CT = d4f2d7181bf881769fa442015b8629390bf0d843a0a8ae90e94043c0d80fd651469232fe9d47a81f
+
+Count = 253
+Adata = 3d765d20e03a4cebfda50316c4b7d8b6c55078d5b3e9cbc567
+Payload = b99afbc2dbb377350cc58d4bfe8e954cef25d7b27b82fad4
+CT = cf1e9c48eff6a6d72ce87678380f886be7486df5e251d58425088b522fc0731097e729448236b317
+
+Count = 254
+Adata = e91b6265879153e1692b00a112b4205111c8eb1a7b7f2c6898
+Payload = 56114cc783b80ca2dd2881387b6d92a59a237dfc8e976d8b
+CT = 20952b4db7fddd40fd057a0bbdec8f82924ec7bb174442db2208cf07574cc4f3f83ed6301b904404
+
+Count = 255
+Adata = 340b16f352817babb4fb70e9e6e18784b3e67bdd449872158c
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 9da599aac80a43a70b0be59fcbfa6d266719d3e846248ca514b0a900068e55cd24c92bbb78c521ad
+
+Count = 256
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01445be684dc
+Payload = b15083a73607c9d7e197a8cc884ad3be98ac343f6493df67
+CT = c7d4e42d02421835c1ba53ff4ecbce9990c18e78fd40f0373f8ba66d74321c80c057f010078d2f28
+
+Count = 257
+Adata = 5fe8bb27a59a5f4e370adbba96484c2365fc0d8c6e58d7d3e6
+Payload = 07542d18e8f2d3e199fca0f90cabb78b169525fdce81666a
+CT = 71d04a92dcb70203b9d15bcaca2aaaac1ef89fba5752493a0a189319e4f06d53c1405d37b06cc8eb
+
+Count = 258
+Adata = 23e5422e8d7560a9e65642b5e723a47536c16791f3a0cf918d
+Payload = cd574ed56bdfd1408f7831e0b24b4345ee979ac906a7aa22
+CT = bbd3295f5f9a00a2af55cad374ca5e62e6fa208e9f748572dd72f48ae03670249d74f8460b63b1ae
+
+Count = 259
+Adata = fcc9422ba5023a9997baa9c4ee6cb196ffe96e08eb9c2b8a75
+Payload = 8c9abe94beed4c9bd46adb1d04fbfe7016dd50d324525abb
+CT = fa1ed91e8aa89d79f447202ec27ae3571eb0ea94bd8175eb1717c00c93d36a77141b723d573c8c65
+
+[Alen = 26]
+
+Key = ca748225057f735f712ecc64791367f0
+Nonce = 1341a6998eb1f50d4b710a13ac
+
+Count = 260
+Adata = 5fb96b045f494808c02014f06074bd45b8a8ad12b4cb448ec162
+Payload = e92cd0cb97afe4fb00c4f12e9b9abe1d08db98f49a27f461
+CT = 82b666694232e86e82295beae66ae67d56aceb5d6b1484ceb4a6843ec16078038c10afedc41f5362
+
+Count = 261
+Adata = 87db0d9d69bc0cf69cabeb92570e482bbc8ff3e1ba72f12f3225
+Payload = a6dbad96ad23ff61479df39b99f0673a09f2a7eaebbd34b9
+CT = cd411b3478bef3f4c570595fe4003f5a5785d4431a8e4416a7c6566d0b8ff97f946d7c7773a845f2
+
+Count = 262
+Adata = a061a09024f1e03b223695d4703ee202e90e07156b95859a22e3
+Payload = b1dd81cc3b2b0efe540a3194d6fe304cd2de53db7929ebe1
+CT = da47376eeeb6026bd6e79b50ab0e682c8ca92072881a9b4ee1d66a4728b67b42602e23c8500b0115
+
+Count = 263
+Adata = 0dd513c5d8d62b723ab8b0a3aaa477e843d9149dc8a2f878e585
+Payload = fb30c2e98f3d7e4ed7431da285711d3d287884db13a474e7
+CT = 90aa744b5aa072db55aeb766f881455d760ff772e297044803c51e8c59ed13b3e5d9b489d4ea2ccf
+
+Count = 264
+Adata = 3ff59c40bd796048e586eccc23a82e4d09fc5e779f38eb4afbed
+Payload = 886f9f91a6566ceb99c39462ab675a3ae3be98f68787626f
+CT = e3f5293373cb607e1b2e3ea6d697025abdc9eb5f76b412c0f1ec270b43fc5a9811b56ccf033789c6
+
+Count = 265
+Adata = 0df7ef91f7124da867e992bcbc6fb38232ff6d5205f38768da72
+Payload = ed370d1c2d6dc03e4fae4deb9343a7d4339562cffd427587
+CT = 86adbbbef8f0ccabcd43e72feeb3ffb46de211660c710528bb4ed25940d58cba64271fe1d2e8013d
+
+Count = 266
+Adata = 6777de159c34d005b94f67c33ae4a35ebab09d9cb9c56b4c9c81
+Payload = 2f77c2eb07db14bd713c5af10c0760ea3a6ca5ff8d046d36
+CT = 44ed7449d2461828f3d1f03571f7388a641bd6567c371d99392636a5e373c1354ea9b969abb4932a
+
+Count = 267
+Adata = 75559898f4ba03c55afc25ea91aa61a93c2f8270a5fa51b6f6dc
+Payload = 360fb89429dc9b48358097d930c8561b2bd18dc0a470d1d6
+CT = 5d950e36fc4197ddb76d3d1d4d380e7b75a6fe695543a17959a7e8bc0570f19159f91fc14ac6532a
+
+Count = 268
+Adata = 5e03fc430473c5de96d68907fa506f9da353ae48a965445e1f24
+Payload = f2d8d67b9f291c3edc264893922622b2693f3e7231137eba
+CT = 994260d94ab410ab5ecbe257efd67ad237484ddbc0200e1507e559568c27a30b5676f98cc66f57d6
+
+Count = 269
+Adata = 7eee4869e77f6db12c91d1f647cad2340d33a3defaeb362d311d
+Payload = 7fd6fb81c36e44b150af10e04683b1ec9b5dda87c71ff939
+CT = 144c4d2316f34824d242ba243b73e98cc52aa92e362c89964910615920f6f3c3421a9c2bec1bec7e
+
+[Alen = 27]
+
+Key = fdf2b2c7fcb3789b4e90abe607dca2af
+Nonce = a69ddc66e63a3415f21009d53a
+
+Count = 270
+Adata = c76846da496ed87b9c0f65c6266c9a822224acde9775efb186a4a5
+Payload = d7aa4efa5d75195a400018bd38f7d8cd53fdffe88df1837f
+CT = 150d9a8b78d9c04239d66207a1f95021bbb1b7c70d7c354825d05e5a2e76a90f6fe489fd74cab2a3
+
+Count = 271
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d
+Payload = 5f94a2e48d348a1d56c55a659306e319c3d2ad78b9fe43a7
+CT = 9d337695a89853052f1320df0a086bf52b9ee5573973f590be6af49ce97d5e0e77c7fd5d9cc6d932
+
+Count = 272
+Adata = 7631cf7822a545daefa16a5ec43c877d475a82d5aa2d51cec7fbb4
+Payload = a44b010fc1c659eac9241a58b11a73d7ce33156ddfc54c3c
+CT = 66ecd57ee46a80f2b0f260e22814fb3b267f5d425f48fa0b924b268cab915f999aea3e1cc3a88ccd
+
+Count = 273
+Adata = e4da34663edc44370bfd8aa8315945471a893a1cc069628a071ee0
+Payload = 28d157f5741f1be057d5219711414c0638b47d165a905a6a
+CT = ea76838451b3c2f82e035b2d884fc4ead0f83539da1dec5dc368f5af8e311e67209e02dfa2613377
+
+Count = 274
+Adata = 077509eae1dc367540f87832c5780f6c5b29e180bc6c1fee38e826
+Payload = ba7432a8e34bfaa91b35c8dfd822d86850be39e63150257f
+CT = 78d3e6d9c6e723b162e3b265412c5084b8f271c9b1dd9348ad175fcad35d29396380b79a28784cff
+
+Count = 275
+Adata = a513d750ca1e8bf6cb7b8cea5204e064c15c2dc40d742b31cf5459
+Payload = 3f5830b0ce8849a660af7d58a60c19a9824a3033bb5fed43
+CT = fdffe4c1eb2490be197907e23f0291456a06781c3bd25b7493b4b3e33d325359c9c651290ce73bed
+
+Count = 276
+Adata = e439db829c1291df49fc42c2fa1a92118c2665f11e13f28dc6f11a
+Payload = e69b2a243340df5dc70b2cb05be12e5992ee36f7d9f4ca84
+CT = 243cfe5516ec0645bedd560ac2efa6b57aa27ed859797cb371f88ca5857c6d801e726a01c621a0c3
+
+Count = 277
+Adata = a12c690568114fd7a677f49d74e84fc1a6b7f7d2a08693266c0a91
+Payload = 9de35b840a69a84701ffae1b1d2bf13c34b42a57d14c524d
+CT = 5f448ff52fc5715f7829d4a1842579d0dcf8627851c1e47a0592d360fc6a46aa18c4ce5d74fa4532
+
+Count = 278
+Adata = 1813bf176a1127f4d508d7663ae750f9c4bcb84a6e26811ac60d46
+Payload = 9e2fa20bf76768a5a1467d90a048bb503a2c33bbbaa71653
+CT = 5c88767ad2cbb1bdd890072a394633bcd2607b943a2aa0648b772cef893495cf0a94e8ebf06e920b
+
+Count = 279
+Adata = cc6e9cc2699d3ba0e624e715599480d6b7dbc6eeea0d12a9236444
+Payload = 6681b1cbeceea57a828324831407280b00f4917ed52a10df
+CT = a42665bac9427c62fb555e398d09a0e7e8b8d95155a7a6e8b1851d571a1ef8aed565b784dcaaac4e
+
+[Alen = 28]
+
+Key = 7d870d7e52d3053c65eefad47764cfeb
+Nonce = 37d888f4aa452d7bf217f5a529
+
+Count = 280
+Adata = 9610949f6d23d5b1f3989b2f4e524fab4f297a5bec8ddad4f16cb616
+Payload = 109317556c21c969eda65a94176d7a11462c9ae18a865b6d
+CT = 4e6b967b1571c6d7b9e118b112b7ac949a4a175650316a242dd579cb0d201d22c86bbc7fbe47bd0d
+
+Count = 281
+Adata = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34626ac9b9
+Payload = 3e6c914a196e175079315b1c92b2b8a844deb472e249e3d3
+CT = 60941064603e18ee2d76193997686e2d98b839c538fed29af0dd7aef4a609f3587652173446ebd82
+
+Count = 282
+Adata = 21fc96f73975298207f818909088295d6d6861677130ca258c2174f6
+Payload = e0014147d5771b4380dc0192d45f36f7d60776d1ba47374d
+CT = bef9c069ac2714fdd49b43b7d185e0720a61fb6660f0060463e4405d45caf4836467edbf35089d87
+
+Count = 283
+Adata = 72a5151abcb55933ff7c9314f3235eba2a400121454144c2670e8359
+Payload = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a
+CT = 51e4ecd194f980c441d8dee31dfa69374576555d7eac44537441c813e90fac775eddb7290df059d9
+
+Count = 284
+Adata = dbbf192914b1ad73666e9f5e9c22c08ca398f7524af62b1046a863bd
+Payload = c1ddd14e380cc91324cf2a381df1da1ccffd90ae436a373a
+CT = 9f255060415cc6ad7088681d182b0c99139b1d1999dd067334d9316f1f1c3142c1c9b26e5c220a32
+
+Count = 285
+Adata = 28e4b88fbf04e9897057ff5bfde7eb04fa480256817a50fa281030b4
+Payload = d4dae9c4cae92afb80f9a5c99383ff16e23a2ec942eed4d2
+CT = 8a2268eab3b92545d4bee7ec965929933e5ca37e9859e59bc0b188e33bfab29b237d6c6920ce3418
+
+Count = 286
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d7
+Payload = 8a188d40a6e6fbb06a9f06304349a7a808b092cc2fc10b9e
+CT = d4e00c6edfb6f40e3ed844154693712dd4d61f7bf5763ad7fdde04d21b876468bd9184101b5f32d0
+
+Count = 287
+Adata = 34ad69f192ae4dcab771aeeacf01bbd32609bcbbea8ff9df31ded719
+Payload = 590c1aac30ab166b1caff748452fc146765c372e226ffc26
+CT = 07f49b8249fb19d548e8b56d40f517c3aa3aba99f8d8cd6f068c65e9d0e5f1b81c86393900e64c19
+
+Count = 288
+Adata = f5e50ce1f99ed5e9f2baa54b96ae7039234b1131e734ec190695d28d
+Payload = 16d0522b2e691e42bd80ce95e00c8a7a1fc738169e904bdb
+CT = 4828d305573911fce9c78cb0e5d65cffc3a1b5a144277a9206ab3b72c56c8df4a12dba89a2f21276
+
+Count = 289
+Adata = 9b1e7e52ea1a12444d884866e11dcf367b70b816460936fdaebba36d
+Payload = 0bddf342121b82f906368b0d7b04df1c682ecd4c2b2b43df
+CT = 5525726c6b4b8d475271c9287ede0999b44840fbf19c72960170ca7b16d23537eeb3034105334699
+
+[Alen = 29]
+
+Key = 8fcac40527c0e7ca8eaff265ca12c053
+Nonce = ae9f012fd9af60a400e20b1690
+
+Count = 290
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154
+Payload = 78d1e96af8cebdcc7e7e2a4ddcfa34f6cf9a24fb85672ad7
+CT = 9adb9a95a9379ad795d8d3ffd4e37a045160d6d727f974a6cb3b5151f327e65447e52c7525562c91
+
+Count = 291
+Adata = e7c78ef4c4b959ee00cb1a09d71221a43892ef8ad705edd27ed85d03a3
+Payload = bc59f18c8473941abc681a92741ab5ee13679829f542b8f4
+CT = 5e538273d58ab30157cee3207c03fb1c8d9d6a0557dce68534e5b08e27d8f5eeef0f064ff620652a
+
+Count = 292
+Adata = f1bce6f2a4bdd3a07ebf5f8d47f931d27e7e63389d70e1059f701216be
+Payload = 5575d950312c14c89ac609dfb0b2fd1af732bb6aae5e8651
+CT = b77faaaf60d533d37160f06db8abb3e869c849460cc0d82044c0a96baae318f4714f0206812516b5
+
+Count = 293
+Adata = 3da3bb091016e54477dae88af1c84c1a51b59c1bb49a05deb6f32064e6
+Payload = df5947d8c6094ccc25816639ec42214b28731bfd7b8312dc
+CT = 3d53342797f06bd7ce279f8be45b6fb9b689e9d1d91d4cad4e7bdce2dc6aae24178aab6984f31028
+
+Count = 294
+Adata = c4cd183071c37a8157c6930a7d4d530cf4b7eb021682327810bd48209e
+Payload = 2fbb6dc235761875411ef59ae06110df8f15f66b721b0fd6
+CT = cdb11e3d648f3f6eaab80c28e8785e2d11ef0447d08551a7f18ece8260bd56ecdee768022d0dd8d1
+
+Count = 295
+Adata = 0e0fece7b6b659b642668e8ba3dca330523e70279155f485f3f6f8041e
+Payload = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e
+CT = 2f1eeee88a5ecb4bebad75e198c85a9be155443c87ae413f6f0fb3b7440b84ddc3cc53819c2e93be
+
+Count = 296
+Adata = a35c6f70f637a9a5e6f215c694fdf65b6fd85f794ed3eaa1bc19abe592
+Payload = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa00
+CT = e109e352e48bd5a6c1ccbde6f5716d9e4f2e977be1b6f47129ca778c51f9320f121dd803ece8d5da
+
+Count = 297
+Adata = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f904398afbec
+Payload = f2d9cf953c8d3a051d9b3eae4307a3cb4fffaa2435b49586
+CT = 10d3bc6a6d741d1ef63dc71c4b1eed39d1055808972acbf79c223a5ad65120bfca4a5992e5ebc6fc
+
+Count = 298
+Adata = c023763a285ea934bc5bc7ddfc2aefe2b3f9eafe7b87c61383dcc07990
+Payload = 4b92e8d2ffaa4af8f3e0ac037a900bd18e195f490a3d71e1
+CT = a9989b2dae536de3184655b17289452310e3ad65a8a32f905c3bc4f618ffb3a159f4e2d0622cea6e
+
+Count = 299
+Adata = 0a39ec0163c7aeb1b4fbe7cb4fa5b0592fade70f430e23730a23ed4160
+Payload = 7c0e6a0d35f8ac854c7245ebc73693731bbbc3e6fab64446
+CT = 9e0419f264018b9ea7d4bc59cf2fdd81854131ca58281a376f099dce6e18435fba4d26c1e93bda0c
+
+[Alen = 30]
+
+Key = ddf9f150cc3f1c15e8e773663c5b061c
+Nonce = 98c5036b7d54da9a1177105600
+
+Count = 300
+Adata = 20c5ab290e6d97f53c74121951f39ba865b3acc465fa3f0fb8a591622277
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d00d29396ffa9e691290d746527777bf96a851f306d4da0b1816df1e0e82bb7bc8105930ad6a2232
+
+Count = 301
+Adata = 0e205a4dc5d5ead0d9ff7f182dc140fc49511c01b0fdbc7e6d6cb5fdf027
+Payload = 88b2572fbe7cf2b46df04db476ffedb41778ae2eb3c3aae4
+CT = 2167fa0c69b415af3383c4e8ae35d41e00b8232e3dbc3cd2df823c8ccd466807f2bd1c4032f0cfeb
+
+Count = 302
+Adata = 48043560d60381e83c11d4bc9d997d3ee2add6b0524b779c62dfaa73ce0a
+Payload = d44bf28b010e076b45db1b053af03db718b60748da51db1f
+CT = 7d9e5fa8d6c6e0701ba89259e23a041d0f768a48542e4d2931f5be8c9965345c760c72cc1b7908d1
+
+Count = 303
+Adata = f0729a8a2fd073699ab87b521cbe0420b43529556a505f5f87874d1a053c
+Payload = eab8cffb512eabe267cd64353552513defe97c2d10f35503
+CT = 436d62d886e64cf939beed69ed986897f829f12d9e8cc335381d94a828a95872ebdfda8a4c6a196b
+
+Count = 304
+Adata = fc2cd69bb61223f713e33a5071d09bf2783640c307c22d836dd94952dd37
+Payload = 001056926546c261fbbdf92b94498e038c2bcfd0b6345497
+CT = a9c5fbb1b28e257aa5ce70774c83b7a99beb42d0384bc2a163931808533f4f70d7a78242ced110eb
+
+Count = 305
+Adata = 8f653c5c003c807d16d17f833eebb97c9c2f0e5aae3780a52ce53a6c33f7
+Payload = 29ffaef9415fd300127ffd26ef324083a9d90e0f60e2ab4f
+CT = 802a03da9697341b4c0c747a37f87929be19830fee9d3d79f34553198f8e40fde6473f9cf04f1de6
+
+Count = 306
+Adata = 8d05e7d3077151c6d9378cb08e049e4d7c28a908f7f7c079c46ff92cd01b
+Payload = 9874dc5ca1b541f7b21c7b3860fa6b0c3ab1b712ab0fca98
+CT = 31a1717f767da6ecec6ff264b83052a62d713a1225705cae0fac20e8d45d2b0771d140b5e4a47c87
+
+Count = 307
+Adata = d4feb3ea76ac2945651f557406f3f38a2d7e9232ed55ff4eaf1201dd8255
+Payload = 1e01c7128c821fb9c971a27fc7c6f9bb902fa735de583b8a
+CT = b7d46a315b4af8a297022b231f0cc01187ef2a355027adbcd3cacfe4281e52d79e60eeb38319bc3a
+
+Count = 308
+Adata = 7cbb4ae995a3367a256cafd11cd6c6cab5bf3252fa97f27a8a1434ca9a27
+Payload = 51cd306fac7d20e3c7043eae3a6dfec046c5c24a666a0723
+CT = f8189d4c7bb5c7f89977b7f2e2a7c76a51054f4ae81591158f0d7646a799b14288bb2f354b5d8847
+
+Count = 309
+Adata = bd40b06a4beded2be3d176266b10772c7fa2949f0a9b20d613af90c2daf5
+Payload = fc5b26befc633a3e8ace011aa7a42bd0258a9f3dc14fc1c8
+CT = 558e8b9d2babdd25d4bd88467f6e127a324a123d4f3057fefd7f95e1d331e700aa9ef83f09b689fd
+
+[Alen = 31]
+
+Key = b1dc81d116d94f5eced526b37c004b95
+Nonce = 97c8f69fb91b17299461fd8d63
+
+Count = 310
+Adata = f8b08aa83bed09ca342249b2cf9e2b45a89dcfb8711a120395e455921af481
+Payload = 54390715b6e7c7bd51a234db059a51ba030cf22ee00b7277
+CT = cb629994c3418a662a8cde1b5f4d99aa7df66e24c53dc6df11297930fd44c63675b7cca70671ef4d
+
+Count = 311
+Adata = 0351c969dd38eeaa4b9b0000e346eeb1a2cd462033c59d9e6e3331822045cd
+Payload = 65b5e856a8cf35dffd42c5ba105cba4c434aa1c2a0390352
+CT = faee76d7dd697804866c2f7a4a8b725c3db03dc8850fb7fa7e77f5566ca2fd9293835bceb461dbaa
+
+Count = 312
+Adata = 5db8b6bc16740680f78fba917733a6899cdba5e4c10a8058963d1265681eaa
+Payload = 9a7685e3daac43ccf22cad0df900ba8acddc5d420846118d
+CT = 052d1b62af0a0e17890247cda3d7729ab326c1482d70a525ec2cf9f5d35521c1c000685e49d2ed42
+
+Count = 313
+Adata = e7d6024611210da0cfb90a9955195aa0a0539280a3a7c792a1540930daae2d
+Payload = c18d9e7971e2ae5fc128777086338fbe194443324e2d2cd1
+CT = 5ed600f80444e384ba069db0dce447ae67bedf386b1b987966f33dfb44ae413283b238616c6b99fb
+
+Count = 314
+Adata = 77a878c9c76f3e6a4ddd330d1d8828949d08e0fedffe0d8e2e557b29e7c78c
+Payload = fcf8982f7342f1b953658453cd5ea413700eff00f1ee7d6f
+CT = 63a306ae06e4bc62284b6e9397896c030ef4630ad4d8c9c731df6fc6b4cf0b6332936ed7cfe9455e
+
+Count = 315
+Adata = aa540554ee80dbffa475f702d862d6b60e0a4090792420a26d02926517723e
+Payload = 0d5690d2a7083ad6daf22b308314b8f5363aca77ca72835e
+CT = 920d0e53d2ae770da1dcc1f0d9c370e548c0567def4437f67c8162a815f2809601ad02595e2e0ff4
+
+Count = 316
+Adata = fae86f95dd06fb7fbae63a646615555aec8153dc328bdf79da5d4cc9677ed6
+Payload = f6e313cc35e8f8812b10a44f8ad00b6893f8084d942effe0
+CT = 69b88d4d404eb55a503e4e8fd007c378ed029447b1184b487fcaa11bdeab86f60f9cd0a2b45cee1a
+
+Count = 317
+Adata = fd525302d2fb246a47cf4e3a27808bda89d8488cf450f1a1c7df6eedd810ee
+Payload = 91e961ea2eb750577c5137c609602dbfcc4c07955ba429ec
+CT = 0eb2ff6b5b111d8c077fdd0653b7e5afb2b69b9f7e929d440a86a810881bd969744ad80f579400f1
+
+Count = 318
+Adata = 767b1bdf9793a512d3a84e99ef77b43011a3bcb8de4cd375dfe47a79293e01
+Payload = 98438c4411bead6f30c89ead762a12bf39391d3652b78b7a
+CT = 071812c56418e0b44be6746d2cfddaaf47c3813c77813fd2250ca00d3231819ecdf501ad39c864f3
+
+Count = 319
+Adata = aac7014f606df6feec415a75e29015891007f07518c955875fbf5619262ff2
+Payload = 540cb00c0eface3d1b2d632d80a642f53c78ff672a1ff6ff
+CT = cb572e8d7b5c83e6600389edda718ae54282636d0f2942571224d1d0294d46981d7dc39114a693d2
+
+[Alen = 32]
+
+Key = 5a33980e71e7d67fd6cf171454dc96e5
+Nonce = 33ae68ebb8010c6b3da6b9cb29
+
+Count = 320
+Adata = eca622a37570df619e10ebb18bebadb2f2b49c4d2b2ff715873bb672e30fc0ff
+Payload = a34dfa24847c365291ce1b54bcf8d9a75d861e5133cc3a74
+CT = 7a60fa7ee8859e283cce378fb6b95522ab8b70efcdb0265f7c4b4fa597666b86dd1353e400f28864
+
+Count = 321
+Adata = 55a62968c222a8501d1ae56a9a815667f8a9554607b7c56e6753f8fa92a4d054
+Payload = 764dbefb42644d18d23e5e4568685d14dbacfa418d36c4ef
+CT = af60bea12e9de5627f3e729e6229d1912da194ff734ad8c4423862a715dda2f63a4197f894515803
+
+Count = 322
+Adata = f8436e35b7a1c810ac6aabe8e2d48a3678d19e1e96337dada514ee5fc075fce4
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 17e3f2110e9ec22c8ebef633023a178021ef45ff5f31cefec200f190bd700f6108f9959f6d12f0f0
+
+Count = 323
+Adata = 548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f
+Payload = 53c164a4990c6e0637267ff2556c1542712fc584f6ff7458
+CT = 8aec64fef5f5c67c9a2653295f2d99c78722ab3a088368733a66ebc4e0777a6fc140a51e04a10f86
+
+Count = 324
+Adata = d100f1d08ef1e3eda4aef22cd970c2b785c4ff9b523c401b4064324aecf7f2d9
+Payload = 15681d2121ac56a63b9d0a38b9c4eccf84fdb746d32c14b4
+CT = cc451d7b4d55fedc969d26e3b385604a72f0d9f82d50089fb810cdc08db0a9966dffeb43ba26446e
+
+Count = 325
+Adata = eece934a807c9f21487cd810f15fd55d7bb4421882333ff2c43b0353de7fc5a6
+Payload = 412a8ef924ca156de860f147575e5731825f0a3759688928
+CT = 98078ea34833bd174560dd9c5d1fdbb474526489a7149503cfc5b397578f8d02a0b936ffac29b99a
+
+Count = 326
+Adata = 86311ff444d9be90459b6ee3652e1705ed0b5cdac3d27293ddea3378fb686ee5
+Payload = 54ba8a020d0876fa369dc32e8627f565ba3dda862ea0bcfe
+CT = 8d978a5861f1de809b9deff58c6679e04c30b438d0dca0d52c3fcd6d618c260d51724126f257534a
+
+Count = 327
+Adata = ab6efbc44a8906d5c067eaed71af467e130aaf170827a58beb03c55069674125
+Payload = 7a15506fd1dae444d77b2a3ae7b57a8d5b4f10e25a9f78e2
+CT = a3385035bd234c3e7a7b06e1edf4f608ad427e5ca4e364c9bf8b2821920640b992b00cd1c9618025
+
+Count = 328
+Adata = ddb640923d083725587aced81ae1d7409983d1f1e3ccc8dcf94376dc1bbcae8b
+Payload = b18a61a89cd698f32e059b7a2a9f62a46be2c248790a9915
+CT = 68a761f2f02f30898305b7a120deee219defacf68776853e4cd52d41a968284af8907ccbb4588cc0
+
+Count = 329
+Adata = d95ec4a6f594be1ba39fa1aa933dc0a5dafff5ce44509577ebb3a3e8084c4401
+Payload = 16ee3bc9ec8b4448e292b8973618e02a99da1c348539d5c7
+CT = cfc33b938072ec324f92944c3c596caf6fd7728a7b45c9ec47449a5cb4943ff2846c589b7c98ef49
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT192.rsp b/lib/crypto/test/crypto_SUITE_data/VADT192.rsp
new file mode 100644
index 0000000000..1a7a5875fe
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT192.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+Nonce = 15b369889699b6de1fa3ee73e5
+
+Count = 0
+Adata = 00
+Payload = 39f08a2af1d8da6212550639b91fb2573e39a8eb5d801de8
+CT = 6342b8700edec97a960eb16e7cb1eb4412fb4e263ddd2206b090155d34a76c8324e5550c3ef426ed
+
+Count = 1
+Adata = 00
+Payload = 296fbda0017351491c2187273fbde2c3a427170e430a703c
+CT = 73dd8ffafe754251987a3070fa13bbd088e5f1c323574fd2167ee33e75d05023a7d63c770cfef2ea
+
+Count = 2
+Adata = 00
+Payload = eb61c284fe009921039ef6a9ce50e702823e44b35357923f
+CT = b1d3f0de01068a3987c541fe0bfebe11aefca27e330aadd170647420f79c0d91cbbd69b806fe96a5
+
+Count = 3
+Adata = 00
+Payload = ffeccc6460d23fdcc387c697e75dbb959b78013a8282eaa4
+CT = a55efe3e9fd42cc447dc71c022f3e286b7bae7f7e2dfd54a8a3ef2324754539ac774872282534386
+
+Count = 4
+Adata = 00
+Payload = 90958d7f458d98c48cbb464c74bf495a49846dd468c514e9
+CT = ca27bf25ba8b8bdc08e0f11bb111104965468b1908982b07e292cd0e32535a848e327bc53cdae94c
+
+Count = 5
+Adata = 00
+Payload = a4fad5205d38206e25097075687ca86032b95b3fe7e82a07
+CT = fe48e77aa23e3376a152c722add2f1731e7bbdf287b515e9bb21701af36936be5f62d02b84df87c3
+
+Count = 6
+Adata = 00
+Payload = b37114c65372b052cbeecf83d05a5da44f7b5bbff7d986b5
+CT = e9c3269cac74a34a4fb578d415f404b763b9bd729784b95b7da7f975367be24341e4af51b8bb156a
+
+Count = 7
+Adata = 00
+Payload = 9c0f0426f171ff18b2a4392f61fb4ee4a44c476fe03dc930
+CT = c6bd367c0e77ec0036ff8e78a45517f7888ea1a28060f6de360c6d50a96f316eda0b216cbb6380ef
+
+Count = 8
+Adata = 00
+Payload = 7b6e0a480a40585545b0e940e8d97c9ec987bd3c0e9c16a8
+CT = 21dc3812f5464b4dc1eb5e172d77258de5455bf16ec1294634cd1bd98e8137b578a174e39efe09b8
+
+Count = 9
+Adata = 00
+Payload = 34dac6dbc28be62332a6935efc122e37b26ee100eb4033f8
+CT = 6e68f4813d8df53bb6fd240939bc77249eac07cd8b1d0c16909a895a3b08b63d7a2a1e75d25e7861
+
+[Alen = 1]
+
+Key = 9748798c0f3cc766795c8ce0e4c979c1930dfe7faefea84a
+Nonce = cdf4ba655acfe8e2134fa0542f
+
+Count = 10
+Adata = 67
+Payload = 100fa71462277d76ca81f2cfdb3d39d3894b0ca28074a0f0
+CT = 36e2415b4f888a6072f260d7e786d803be16f8b9cbee112d7ff74e3b05b7d7c13284573bd3e7e481
+
+Count = 11
+Adata = 17
+Payload = 0217eb6778691f8dfe2d0e5241f05fcbcf97b9171f4de3f0
+CT = 24fa0d2855c6e89b465e9c4a7d4bbe1bf8ca4d0c54d7522d3ee7ce845f85dfc770d96dee9ca54ccd
+
+Count = 12
+Adata = dc
+Payload = a78b7bc6c1a7250c5fc236f2a8343725a9a7bd3ca81b53e4
+CT = 81669d89ec08d21ae7b1a4ea948fd6f59efa4927e381e239dc14ddd8ae0aa5d810040a8d1d4da1e9
+
+Count = 13
+Adata = 0c
+Payload = 390c808d998582793bb10ee60568eb8d975c51d68b4e4da9
+CT = 1fe166c2b42a756f83c29cfe39d30a5da001a5cdc0d4fc746b40dec7e647720f1f5e8474bf570c2f
+
+Count = 14
+Adata = 3e
+Payload = bcd9747fb54184b61b2e9e049caa75e22006e250f3722c0e
+CT = 9a34923098ee73a0a35d0c1ca0119432175b164bb8e89dd3c10c4aac45d90119cce490cc8681a49f
+
+Count = 15
+Adata = 7e
+Payload = d0342e3cd2c1142b642da7297ee3b9978cec405e6810f12f
+CT = f6d9c873ff6ee33ddc5e353142585847bbb1b445238a40f2f9a95091d2cab7d3d9fa3e10d3e67ac9
+
+Count = 16
+Adata = e3
+Payload = 7fab91d1aa072947d22f0dc322355a022fe7f0747f4a184b
+CT = 5946779e87a8de516a5c9fdb1e8ebbd218ba046f34d0a996180f7818c373e89f7ff3003f53260060
+
+Count = 17
+Adata = 3e
+Payload = e487143dc4d98dcc6a2dfe6ee0f85d565d1f46bb0fafe62a
+CT = c26af272e9767adad25e6c76dc43bc866a42b2a0443557f71905f581585e59e3c8c038b5bf966559
+
+Count = 18
+Adata = 3b
+Payload = 976b489244ed6789a34251500057d1d4a3229367a42b9066
+CT = b186aedd6942909f1b31c3483cec3004947f677cefb121bbea56569c34f8d9eea23e85fec18cfc51
+
+Count = 19
+Adata = a5
+Payload = 71efa75961dfd60ad533082a8cfe111214eb02573adc4591
+CT = 570241164c70211c6d409a32b045f0c223b6f64c7146f44c212da23548f2ca4e9a8a07962be6422c
+
+[Alen = 2]
+
+Key = 393dcac5a28d77297946d7ab471ae03bd303ba3499e2ce26
+Nonce = fe7329f343f6e726a90b11ae37
+
+Count = 20
+Adata = 1c8b
+Payload = 262f4ac988812500cb437f52f0c182148e85a0bec67a2736
+CT = e6d43f822ad168aa9c2e29c07f4592d7bbeb0203f418f3020ecdbc200be353112faf20e2be711908
+
+Count = 21
+Adata = 9db5
+Payload = d5982c462ad40458660cd7b120ce07fce9afe812caedcebd
+CT = 1563590d888449f231618123af4a173fdcc14aaff88f1a89015e5cd97b7dd3d981321ae0b2d99e1a
+
+Count = 22
+Adata = 69cf
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = da6e85202048347568befac0731db702e687d5ef51d50402bf3e75863c7acd2699caba3cc301f4b2
+
+Count = 23
+Adata = 6c6e
+Payload = 373c157e59b934a1afb57d4c5dd9ca7fb736b206a6210bef
+CT = f7c76035fbe9790bf8d82bded25ddabc825810bb9443dfdb5d6a8f7a9f52a8038aa9dc1bdc9ed876
+
+Count = 24
+Adata = dafa
+Payload = 26e10a2ed8cc883a6552aee162c5542ff8bb8e758a1975f8
+CT = e61a7f657a9cc590323ff873ed4144eccdd52cc8b87ba1cc8a15603f10cbfdb041f8b2b12cc8f037
+
+Count = 25
+Adata = c8b1
+Payload = dd235b05c15479dfe0326ba206ac784eca50038bbeb35d32
+CT = 1dd82e4e63043475b75f3d308928688dff3ea1368cd189061278bf62ba6a4819513d49fdcdb45480
+
+Count = 26
+Adata = af48
+Payload = a0818342a5cae4a90ef281d3d1289d83f273f418a545fcbf
+CT = 607af609079aa903599fd7415eac8d40c71d56a59727288b8b4d00309b50f9ea72f8105c94475b52
+
+Count = 27
+Adata = b1cd
+Payload = 33c0d06b6583bb4d15b4a07364c4be70ac6e72795c3dae0f
+CT = f33ba520c7d3f6e742d9f6e1eb40aeb39900d0c46e5f7a3b220ba58e97936612c4183ba86705b2f9
+
+Count = 28
+Adata = 649a
+Payload = 3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863bde9
+CT = fb5a67c9744faec46fa7e127d646ed5f8be555566a0169dd87d602dc85bb260fb3df1221e2fbd10c
+
+Count = 29
+Adata = 593c
+Payload = a97faefcae36732fcfe47736c2334ea7d411bf7638b0c019
+CT = 6984dbb70c663e85988921a44db75e64e17f1dcb0ad2142deb3835b7eecad6dac9785ad1d370ede4
+
+[Alen = 3]
+
+Key = a74abc4347e4be0acb0a73bb8f7d25c35bae13b77f80233a
+Nonce = 6a850e94940da8781159ba97ef
+
+Count = 30
+Adata = a4490e
+Payload = 6372824bf416cd072a7ad0ae5f9f596c6127520c1b688ab4
+CT = b14a07bdc119d87611342c4c6935c5786ff1f9ae2eb49e6191c88a3cb4fbafcb8a4a157d587d7e39
+
+Count = 31
+Adata = 5cad2e
+Payload = 295f4f3417a77fcf0bbda17b0fd629ad57a6086573c87eb1
+CT = fb67cac222a86abe30f35d99397cb5b95970a3c746146a64235c34d1390bba5b008c3fb29c2df958
+
+Count = 32
+Adata = ebdf4c
+Payload = 86f354a505de941d34cd98e3af3706d56a938ab9a2797182
+CT = 54cbd15330d1816c0f836401999d9ac16445211b97a565575a733bba0a6992d0664dc77d2b5d194c
+
+Count = 33
+Adata = 7c0d70
+Payload = 88c3bfb546abe2f6bfc92a7c56c627e24ab92a8a87a6b43c
+CT = 5afb3a4373a4f7878487d69e606cbbf6446f8128b27aa0e90902a31b15eed99c2dc4ed1bf11cad96
+
+Count = 34
+Adata = 8fa501
+Payload = 75d4216bad77943bfe82be216157843b0da0fd16eeee8471
+CT = a7eca49d9878814ac5cc42c357fd182f037656b4db3290a42f25595ae00103d4eb20288158132e7d
+
+Count = 35
+Adata = b7aca7
+Payload = bf1401e8dcf6f681ed6dd74c7e23b7e54b384608b0e5ec52
+CT = 6d2c841ee9f9e3f0d6232bae48892bf145eeedaa8539f88760e67693b509ea4795b7da32c5c5d17f
+
+Count = 36
+Adata = 1f283f
+Payload = 7e623e7ef7d0a678b5d22a8402d89220f4f1bf759e3084dd
+CT = ac5abb88c2dfb3098e9cd66634720e34fa2714d7abec900880ef8ea380a1a0a38b2c20288e637a9f
+
+Count = 37
+Adata = e93f31
+Payload = 14f80e7a6298d85d31fb80376a394a8f88b0ae47f00450c7
+CT = c6c08b8c5797cd2c0ab57cd55c93d69b866605e5c5d84412d553aafe8536385d34c412c14d3a1563
+
+Count = 38
+Adata = 27e9a5
+Payload = 3330df12249639961f562a74b34f60b0a8bc7c783f6572fd
+CT = e1085ae411992ce72418d69685e5fca4a66ad7da0ab96628f594d366c8fc826ce58309e9053c27f7
+
+Count = 39
+Adata = 72d566
+Payload = 1a1860ac8c11c5d262f8141738cae8ff91ca05906dc98bb4
+CT = c820e55ab91ed0a359b6e8f50e6074eb9f1cae3258159f61cdd6ac6c42cd3d11e0344a9c1001e253
+
+[Alen = 4]
+
+Key = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb0
+Nonce = ba356d392c3f700f4f2706a4ca
+
+Count = 40
+Adata = 8ffc0e3d
+Payload = e8c1a89228d8212f75c136bab7923a89f9fea18e781cb836
+CT = 66b5d782323925e1bd0a8413a9a5a881356453d5df2cbeb199b2e1e803550dcdde55fd66ecb45edd
+
+Count = 41
+Adata = 2b4f9cfc
+Payload = a12c6324e022affd61b7e0d8cccbeb23e2e6c65355c1d586
+CT = 2f581c34fac3ab33a97c5271d2fc792b2e7c3408f2f1d3019e8fbc507244ba234a0581dc69962a66
+
+Count = 42
+Adata = b4de3039
+Payload = 7cccb26f1dd227bc77458b99fd9e00f8e801adaece7bfcd1
+CT = f2b8cd7f07332372bf8e3930e3a992f0249b5ff5694bfa5628a2857099af20a4ae08e687bdb02c75
+
+Count = 43
+Adata = bc59f18c
+Payload = 692b53c1355475c71ceff0b0952a8b3541b2938270247d44
+CT = e75f2cd12fb57109d42442198b1d193d8d2861d9d7147bc3e33a6416e387d9e571a1954471ec9cc7
+
+Count = 44
+Adata = 4fd9fd39
+Payload = 7e3e755e25bbe78d4a7770f9356ab9f4ff1bbfdba46383f5
+CT = f04a0a4e3f5ae34382bcc2502b5d2bfc33814d8003538572180f9735f994c8335e593f30b331a920
+
+Count = 45
+Adata = 296cd04c
+Payload = 997b712cd9295dc43cc19b40679f218c27af3e8c638d2e5d
+CT = 170f0e3cc3c8590af40a29e979a8b384eb35ccd7c4bd28da91990fa537d2657d01f66872ba9af22f
+
+Count = 46
+Adata = 88037d3e
+Payload = 577981ccb6c893dfe6405075fcb41507de7f9bfda860791f
+CT = d90dfedcac2997112e8be2dce283870f12e569a60f507f984915cb93e84028c7aedce1a2dadbb6bb
+
+Count = 47
+Adata = fc4bb852
+Payload = 37ba9f57ec230675ce060ba3d388095adf15907aa0b0673d
+CT = b9cee047f6c202bb06cdb90acdbf9b52138f6221078061ba25baa6385af8d7b807a2d2ab19aa4999
+
+Count = 48
+Adata = f40ec14f
+Payload = 401e0cdc132a9e4a9b5ceeed3c181f67e5203ea69508deff
+CT = ce6a73cc09cb9a8453975c44222f8d6f29baccfd3238d8786adcdb44870e1105b7318d8bad0af957
+
+Count = 49
+Adata = 90e2c63b
+Payload = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+CT = 8c40a5f5a79be2a2af34beb3212d8b12c1e13ceff68c2dfa8b079fb71d45bd985bffd343c3362653
+
+[Alen = 5]
+
+Key = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+Nonce = d4ef3e9e04f1b7f20ffc5a022e
+
+Count = 50
+Adata = a468f08d07
+Payload = d3bef460223c81e4579c9d1d463ac5e0881685de1420a411
+CT = abb85db49a9b1c8724ecbc734cc8373bd20083cfa4007b1cfe4d3a3bb25f89f692884be230c6035c
+
+Count = 51
+Adata = 4497649a54
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326461ee1
+CT = f9ab96ecd34a5695258f723269aaffc4ddf5c1329666c1ecd05ae56511a230627e02d066c52a919e
+
+Count = 52
+Adata = c30ddd994e
+Payload = 84b88264afec06b370dfcebf5e1d3e2c1f005faf248b3215
+CT = fcbe2bb0174b9bd003afefd154efccf7451659be94abed188ef92fc17dca026f1ac1eaf78a05017c
+
+Count = 53
+Adata = 9573270f7e
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a040
+CT = e64a237d0d2d13c8b62849fcffa6e2dbee2911c810717f4d38eddff1e60e2d9ae74a936364b8df21
+
+Count = 54
+Adata = 40336790fc
+Payload = 260f67122dfbe03365bc9e35e9d4ac4b2eb150eddb30857d
+CT = 5e09cec6955c7d5016ccbf5be3265e9074a756fc6b105a70aa3d464ad89cae59b474d019a5a7605c
+
+Count = 55
+Adata = 0b310c8529
+Payload = 1d55e7352bd895c4ef77389a7225c664f72b38c8de778d57
+CT = 65534ee1937f08a79c0719f478d734bfad3d3ed96e57525abeab0c520e64939c6950c0fa406eafb1
+
+Count = 56
+Adata = 5756b2c681
+Payload = fbd315e1f5bd0f0e60ee6684c88f3543452c62ea0701d11d
+CT = 83d5bc354d1a926d139e47eac27dc7981f3a64fbb7210e10d22d339c382343bf39c239fd64c2a64f
+
+Count = 57
+Adata = 3b919e3665
+Payload = d68d6556c5a5b1f5a123389b3ce966d5837cb8fcf5accfff
+CT = ae8bcc827d022c96d25319f5361b940ed96abeed458c10f2fcd6b562a1b6aa10be92a81f99ed540c
+
+Count = 58
+Adata = 58749b643f
+Payload = 062cb6962fa5b3a6239b95f3a51b478a1f32b081dc538a80
+CT = 7e2a1f4297022ec550ebb49dafe9b5514524b6906c73558d4b853022237d94d253b375bf2150e699
+
+Count = 59
+Adata = a5d50c008b
+Payload = 08c62ff9bd7bcf189f530d5065f8764532d2692f69858483
+CT = 70c0862d05dc527bec232c3e6f0a849e68c46f3ed9a55b8ee7aee0d403b2cf6f8b993eebd6b93615
+
+[Alen = 6]
+
+Key = 1c476cfd7dd300d961fd3f24a6fe0e80742b00851676ca63
+Nonce = e300fc7a5b96806382c35af5b2
+
+Count = 60
+Adata = 28130f938c45
+Payload = 6f3938932b5c1280311e892280d8a822a828a0be7fdb1bcd
+CT = df48662fe134e75a85abc2cece2c3b6236c88a70fa792e9beadc9601adf9fbdf4e3e94b395b0a332
+
+Count = 61
+Adata = f600024a7bf9
+Payload = 0af7345e71f4e8886503395ade0b0296a5856e086638b06a
+CT = ba866ae2bb9c1d52d1b672b690ff91d63b6544c6e39a853c0692a40a6aba8d7c5addae21de90fea9
+
+Count = 62
+Adata = 4eef510d1f48
+Payload = 37f57772f056f45a5ce9f46d27be1858980c8935b9c839b7
+CT = 878429ce3a3e0180e85cbf81694a8b1806eca3fb3c6a0ce122f64becb581070411957e632e19bb8f
+
+Count = 63
+Adata = 4c9c76b6fad5
+Payload = 8bb10c82bcabb7fb2b169252ab443b01df217cf908b8c241
+CT = 3bc0523e76c342219fa3d9bee5b0a84141c156378d1af71708c59f83aa97d069b6d83d9387051f43
+
+Count = 64
+Adata = 5572ecfc7e53
+Payload = d1ccb4654a22b1afe32f3d3035fdccd87e9cbed83c679007
+CT = 61bdead9804a4475579a76dc7b095f98e07c9416b9c5a551f04686ee1d7b985d903f1de6cf78f8f4
+
+Count = 65
+Adata = bffdf9d20d74
+Payload = f990a8f6ba14065d48665db36eb470c49f38e2b6376a9bde
+CT = 49e1f64a707cf387fcd3165f2040e38401d8c878b2c8ae88f8118f1b9f39b51965ae9ef1bdb40111
+
+Count = 66
+Adata = 3f27e678c580
+Payload = f8c7d89639ab742a8bcfffe776e868d671e1fbdd55807a8a
+CT = 48b6862af3c381f03f7ab40b381cfb96ef01d113d0224fdca3236d02f33f49759f281315e449bfef
+
+Count = 67
+Adata = 1294cb9db5f5
+Payload = 8601cfd7d935e8a8487b9c39d55ca27096255f2eb9e009e3
+CT = 3670916b135d1d72fcced7d59ba8313008c575e03c423cb5e74770a07c242c3854ceb242dadc1976
+
+Count = 68
+Adata = cec271332b75
+Payload = 77c85b8022f58337b364142a2474fe5cfddb31cfca48af46
+CT = c7b9053ce89d76ed07d15fc66a806d1c633b1b014fea9a10d6c65f19175cfa49898655ccdddb864a
+
+Count = 69
+Adata = da06bd140502
+Payload = b0f2db802475fa70af02057373844f637a3244cda4b4f93d
+CT = 0083853cee1d0faa1bb74e9f3d70dc23e4d26e032116cc6b458822e49e69031431b3eea872a72eb7
+
+[Alen = 7]
+
+Key = 79d1e38a70df1cf239be168833dcd0570bc8f37b3aa26c37
+Nonce = 8229d6d7e9e21fdc789bff5dcf
+
+Count = 70
+Adata = 076887d2abe900
+Payload = 83c24f3a77b83b4ef45277ba90225f3ba1722312f52b1a07
+CT = 19d880f1d959a68f162de243d4a45747ace704613359b27218d1531a066de60a95d2924a6910e990
+
+Count = 71
+Adata = 7535bcc6fbd1a0
+Payload = 24f85ef683cc521387f484bc0b2ad9172f61884c09a9718c
+CT = bee2913d2d2dcfd2658b11454facd16b22f4af3fcfdbd9f96dbf58406020e6df7b312b6825127f9a
+
+Count = 72
+Adata = f4f96d7b4384a3
+Payload = 212bedfa06b5e1a2c3a2f31f6f791dd9df8ef26077821c0a
+CT = bb312231a8547c6321dd66e62bff15a5d21bd513b1f0b47f64dd755177efc87f8b1daf1fd88e51a6
+
+Count = 73
+Adata = 3b7e3d9c1a7fa2
+Payload = 8b9036914bb0f440c8dbcfde9b9547be5e5ef1f56492c75e
+CT = 118af95ae55169812aa45a27df134fc253cbd686a2e06f2b0be31cab31f1a20805d5c07dc516d707
+
+Count = 74
+Adata = a8c35fae8912d6
+Payload = 50f3f3a91bf6fd9573d5ef54b9bb5805205b2f9865d81fd7
+CT = cae93c62b517605491aa7aadfd3d50792dce08eba3aab7a2399df9a45ad153c0dfb3fec3b9d6f7c5
+
+Count = 75
+Adata = db636541f2429d
+Payload = 6fbda8d435555e735443f1e6bc09e96065092efd89edd64a
+CT = f5a7671f9bb4c3b2b63c641ff88fe11c689c098e4f9f7e3fe20b7da94eac8c7ef8478671165e0d82
+
+Count = 76
+Adata = a8de55170c6dc0
+Payload = 640ef4c246a2c6e16ddc49072a5aeef70319149ffba071ef
+CT = fe143b09e8435b208fa3dcfe6edce68b0e8c33ec3dd2d99a4979c35bdbf9538666b6fa57f0f915d8
+
+Count = 77
+Adata = f8d64ce2aa66e6
+Payload = a14e3910766f31594a28ad2c3678c31d0c3aee88484ca6d6
+CT = 3b54f6dbd88eac98a85738d572fecb6101afc9fb8e3e0ea3752824a691da2e99374ae6c031d74ffb
+
+Count = 78
+Adata = b3c340afdc53a8
+Payload = 1b8e0a09e6364020b4cac704dc19bfa79455295604cf9c9a
+CT = 8194c5c248d7dde156b552fd989fb7db99c00e25c2bd34ef04159a68706faa2e8c3376b4dbeb423a
+
+Count = 79
+Adata = 73824034001519
+Payload = 52c84a0735eea6c5c230644075ebfc5db0c3128056e7a8f4
+CT = c8d285cc9b0f3b04204ff1b9316df421bd5635f390950081e5adc7564721ead2af75cb98e61148b4
+
+[Alen = 8]
+
+Key = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+Nonce = 3820db475c7cb04a0f74d8e449
+
+Count = 80
+Adata = f427c47e10c45bb3
+Payload = 54bc7e3c227df4e83252a5848fea12dfdb2d14b9e67c1629
+CT = 91e7baff2b42af63e26c87ce6991af22422c1f82906858b1721961de5c768f4d19bd3034f44f08d2
+
+Count = 81
+Adata = ca25504f3f5559aa
+Payload = ff4493fea916f49fbb3cae2838bc84e293531092cc0904ab
+CT = 3a1f573da029af146b028c62dec7391f0a521ba9ba1d4a3342968c638ecb8a2b358e8eaefd931efb
+
+Count = 82
+Adata = 8215753d9efc5132
+Payload = af16ab8558269a93d8e8c9e38f12a8768947d8b69be0e259
+CT = 6a4d6f465119c11808d6eba96969158b1046d38dedf4acc1f8ac11752fe51e354f3f8a68815539aa
+
+Count = 83
+Adata = 9e7cdbc6202e6492
+Payload = 744a167ae31a8ca20df82290766429de9ef0b7dfe199a78d
+CT = b111d2b9ea25d729ddc600da901f942307f1bce4978de915489de8e241dcab16bdcbf1a1ff4d8d10
+
+Count = 84
+Adata = b8d511d0ab86a07f
+Payload = eeb39de1fe21b5aba654da45fe1481decb22365fa4cbe49d
+CT = 2be85922f71eee20766af80f186f3c2352233d64d2dfaa053fab212a1b6dc7b953e2bc211be194ae
+
+Count = 85
+Adata = c74a5d4265f9f3d5
+Payload = e95c20e80153bae3fde3c3d82b6b33b35fc1959fa31a5d11
+CT = 2c07e42b086ce1682ddde192cd108e4ec6c09ea4d50e138973918ab70fe048d6c5b63a01725eddfb
+
+Count = 86
+Adata = fd849d3ada03181a
+Payload = 6d00606c72cea3deaea5b51ae09e61924355e167058ef42c
+CT = a85ba4af7bf1f8557e9b975006e5dc6fda54ea5c739abab487089bc20867f474c1127aa1320f0000
+
+Count = 87
+Adata = 56825a68681f498c
+Payload = c47705d897a6c7e7aed710b96e2d8532c23b82090e21b114
+CT = 012cc11b9e999c6c7ee932f3885638cf5b3a89327835ff8c34a23b0b6ac4d297dd7832a5e2102272
+
+Count = 88
+Adata = 72e4da839913a26e
+Payload = c822a1ee581cf85b0482c821473385bd3f28528e5e5760d9
+CT = 0d79652d5123a3d0d4bcea6ba1483840a62959b528432e41dd665766c7af21ff890bd40178f1c660
+
+Count = 89
+Adata = 138457571ee8dafd
+Payload = 3ffb82a83308da66e95ac63ae92931b09ffe0e42afbb4979
+CT = faa0466b3a3781ed3964e4700f528c4d06ff0579d9af07e16a6a58bb772c79481dc26861ffbd68c6
+
+[Alen = 9]
+
+Key = 39c03a0c8634047b1635348f284d3dc1e752ab40548eb337
+Nonce = 9e2ea8eb7f56087ee506925648
+
+Count = 90
+Adata = 28d157f09a71da80dd
+Payload = 0662e63c88e963d3e0cf2c4653515ae4474a2c78ab0394c0
+CT = 01dcd4dd3b8c1369518136ce45e8bb9df565b0ad231a887b02ada34addf0aa2f4744ed2e07995491
+
+Count = 91
+Adata = c17d311362c41d442b
+Payload = d6df8b60c697093987b3d89a3667b36504b6ddddf12b0900
+CT = d161b98175f2798336fdc21220de521cb6994108793215bb38a27466b8741bffce44ef04b23af321
+
+Count = 92
+Adata = 006669ef1a11b65b1d
+Payload = 49ad29ef5e82b08752ac5a50dd982e4bcb700005454ade6c
+CT = 4e131b0eede7c03de3e240d8cb21cf32795f9cd0cd53c2d77d11372fb0dab1c99b159e5fe9f91118
+
+Count = 93
+Adata = 8eafce9ba466fd53eb
+Payload = 385f9fb139dbf88561b7a500b0c7b835fe57e2698c6d9f76
+CT = 3fe1ad508abe883fd0f9bf88a67e594c4c787ebc047483cd09e4898a4046f6ec9f40e412915007e4
+
+Count = 94
+Adata = 796e55fbe7bed46d02
+Payload = 4ebb149b01cbacba32d11168ca61928ea149dcf2ee2c1001
+CT = 4905267ab2aedc00839f0be0dcd873f71366402766350cba5d40a9902481bfac7ff33d08fb4b3d31
+
+Count = 95
+Adata = 8f958d796be0566512
+Payload = 0d974e5621caa1d86eaaee689ccbca57843373fcf20db407
+CT = 0a297cb792afd162dfe4f4e08a722b2e361cef297a14a8bcd972d09a17172161eb68a30b593b1bd6
+
+Count = 96
+Adata = cc879ff2d583a7288c
+Payload = f8e0dac6a691dfb231411b5c5f70a0daff83cc637b0c7bb3
+CT = ff5ee82715f4af08800f01d449c941a34dac50b6f3156708119cc26a80c152c253fbc36cb886e0fc
+
+Count = 97
+Adata = 4765d696d19dec58bc
+Payload = 096a36396ccfa260f28fb0919157a5076b53506c51a2a4ef
+CT = 0ed404d8dfaad2da43c1aa1987ee447ed97cccb9d9bbb8549de06cc5c3bc4ad75076c774576843fb
+
+Count = 98
+Adata = a004f283afc3309c31
+Payload = 5b943269be41e2758a4ea6a3cc621b711a8ba6002783aa72
+CT = 5c2a00880d2492cf3b00bc2bdadbfa08a8a43ad5af9ab6c9135493b44f79a5774df6b2943b0bec67
+
+Count = 99
+Adata = cdd5d8aefe49a315ad
+Payload = 5f27867109e74862ce0dbc9ba73c420b93067bdede17ae51
+CT = 5899b490ba8238d87f43a613b185a3722129e70b560eb2ea7a5da4a29a9012d78b6de6f1b3e8c9ed
+
+[Alen = 10]
+
+Key = e2a92ffbb0b5eb68cb82687f12449fae5167d375131b0b10
+Nonce = 441ad5e1382e083a95224f395d
+
+Count = 100
+Adata = 2352648299b0413cb2ce
+Payload = 048c9ba4597c3bb595bfd5048e5e9a1296f30e5c0118b177
+CT = 25247a258e4ac0a988d8def60cc174a9d4578cd5346fb5150c96e8ab8774baa421f39c64a386c418
+
+Count = 101
+Adata = ce003c836a6f5f066053
+Payload = 02ea8e7e488c863584f828df13dfeb68433294d11d9ca9d7
+CT = 23426fff9fba7d29999f232d914005d30196165828ebadb5d453036cdc6bad0c5e770a6249a52e74
+
+Count = 102
+Adata = d11be73a104ccc6346d5
+Payload = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024
+CT = 4cfd9248f0ae6ccbcc072678175fa50e889b2fa48bfea4464627ad75bbfe17f3f5ddfd3dbc1045f3
+
+Count = 103
+Adata = 6a7b80b6738ff0a23ad5
+Payload = 97a813e75d95d25c2edb1c705c4ffe4d7c08c756761fbc0b
+CT = b600f2668aa3294033bc1782ded010f63eac45df4368b869af8943f74706cc3394a170fd49f7011a
+
+Count = 104
+Adata = a391acdb3a06dae4a671
+Payload = a78981ac244307451e4d3fd7f654b70cc4e6518aa47a3c18
+CT = 8621602df375fc59032a342574cb59b78642d303910d387af22597f63074ca3533bb5e107860481f
+
+Count = 105
+Adata = 0b9f28f2d3215785f569
+Payload = 5d649d79ff0e304e164a383c74f13d7ffab145d00cb0ec2c
+CT = 7ccc7cf82838cb520b2d33cef66ed3c4b815c75939c7e84e905b5609f593c6ea9281f66cd2e646dd
+
+Count = 106
+Adata = 7928b1091cbfb2eef0fe
+Payload = 83a273687dced7b94d569f81d75508595cde668f06406183
+CT = a20a92e9aaf82ca55031947355cae6e21e7ae406333765e1428195355618ea0cf87260ad20b6d7b9
+
+Count = 107
+Adata = 3b74afb81f54a93c79d5
+Payload = b4dc3c059cf7b47dd0bb7f165a63fc80b5c6b5f3ca7eeb73
+CT = 9574dd844bc14f61cddc74e4d8fc123bf762377aff09ef1155019659f41a5f0430695b4ada9d8b8d
+
+Count = 108
+Adata = a46ae4c71d4c9eb72fab
+Payload = 7e919581c5105d98717d0613e1ca869c6516506ea482d5c2
+CT = 5f3974001226a6846c1a0de16355682727b2d2e791f5d1a01514b252f33dc870c42260e48c4fa9fd
+
+Count = 109
+Adata = a1ace61711f0a09ac17d
+Payload = 3a4558b55214f21cbd2ae2eda5a2321cfc2f102e059b744a
+CT = 1bedb93485220900a04de91f273ddca7be8b92a730ec7028c263c667d7ed58907452c092905d0b31
+
+[Alen = 11]
+
+Key = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Nonce = 8e7d8a44244daa7df2b340993e
+
+Count = 110
+Adata = 521583c25eb4a3b2e46120
+Payload = 9f580cc6c62a05ce125c6bec109a48ca527ee26a64b14b68
+CT = ff0ff95bcb0bccd5e4aadd77ac6770f5013654eb3c6386fded2c87135861b43a99f258b6938f66e3
+
+Count = 111
+Adata = 31adb39e947f8883fa4b69
+Payload = f16bba081bddda83546eabc9a55c81a439720dd8562ce964
+CT = 913c4f9516fc1398a2981d5219a1b99b6a3abb590efe24f132b87476d66a1bd405f484ef9ac8ab7e
+
+Count = 112
+Adata = f05f39eb0a3d6460076aa8
+Payload = 6baf784f63cf45a1836fa8f3609fff7870ce8cbd1e91268c
+CT = 0bf88dd26eee8cba75991e68dc62c74723863a3c4643eb19a120b455b366cb104fd8b6dc2c80471e
+
+Count = 113
+Adata = 74c7a633ff73ff507009c5
+Payload = d8176a6de1c15a14c8b8b58725c179dc84c9308268d718d5
+CT = b8409ff0ece0930f3e4e031c993c41e3d78186033005d5400c8ca09f4bf06b1c27e75abf15112e49
+
+Count = 114
+Adata = ab322a88cf44b9ca774415
+Payload = 3706e4d8ff748574f382e5f9b0a3b6258f1f360fd87001b0
+CT = 57511145f2554c6f057453620c5e8e1adc57808e80a2cc25b3159274a7de3550baf759f7fae53dbc
+
+Count = 115
+Adata = d6fe6e17221d4e06ed3ab9
+Payload = e02217394772deffe218c405e40f2a3a56ca01d55d6d3330
+CT = 8075e2a44a5317e414ee729e58f212050582b75405bffea516fba8d193e133e6f78daa39681cb262
+
+Count = 116
+Adata = 2739d2cdfcbe7d5cd7d28c
+Payload = bb713f74a884bd1a994adba87561d637853c6181290ef5e8
+CT = db26cae9a5a574016fbc6d33c99cee08d674d70071dc387d65f92db3b3d1c2de04c69c5d06b0e001
+
+Count = 117
+Adata = 5841571299cd064a6262b7
+Payload = 9641dedd50d80ac0abf7591436065fa2e23e4687abbb86e4
+CT = f6162b405df9c3db5d01ef8f8afb679db176f006f3694b716e4d20ab5ffad6f71155f6839dfdbb25
+
+Count = 118
+Adata = dc5d7fd97bb3243ba585fa
+Payload = aefda8501193edacb8abb94fff875529a537a462c4b9b69c
+CT = ceaa5dcd1cb224b74e5d0fd4437a6d16f67f12e39c6b7b090ebc3af2de52b8bee3d130fa973f716b
+
+Count = 119
+Adata = 8789e0b3e0dc13d9725b37
+Payload = 65e53f549b62aca03f21ab2a494b93805e02cfecf4f12aa4
+CT = 05b2cac9964365bbc9d71db1f5b6abbf0d4a796dac23e731b5cd5a004a0ef28e30383bdaed8f93c7
+
+[Alen = 12]
+
+Key = 44cba20b7204ed85327c9c71c6fea00b47ce7bdde9dea490
+Nonce = f3329154d8908f4e4a5b079992
+
+Count = 120
+Adata = f1e0af185180d2eb63e50e37
+Payload = 6333bde218b784ccd8370492f7c8c722f8ef143af66d71d7
+CT = b9401a4927b34dc15e9193db00212f85f0c319781ec90e3b4484d93cb422cb564acc63d3d18e169c
+
+Count = 121
+Adata = ea74231e49e667ca1c21d46d
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+CT = e67d8fbeec794d42fc64d7f36a87d2ac22aafa440021ea72c4c151d9927e6a9f19d47ff7d79ca6f6
+
+Count = 122
+Adata = 7f5871a8300471dc325f8289
+Payload = c642c9722d84d708682350dc70bdaa9a1181a415a9e72b93
+CT = 1c316ed912801e05ee85c7958754423d19ada9574143547f959eee29be1415ab03444de0fa42707d
+
+Count = 123
+Adata = ee7e6075ba52846de5d62549
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = f8f50646e284ba77f4ea3e08d69777a53aab062ec784ad70ce97c1c8aea70de04580d7b37f8c014d
+
+Count = 124
+Adata = a30f2fd445820cdf80014554
+Payload = 92577d5db20391110309d490f52acecdfc18382f368bbe42
+CT = 4824daf68d07581c85af43d902c3266af434356dde2fc1ae23b536f993381e525a14599dd5c02e80
+
+Count = 125
+Adata = 0cfec933831644b468724e80
+Payload = 6803dc3f7c06568ca78ee5aa2e9b1b354a4f1e067ff6a25b
+CT = b2707b9443029f81212872e3d972f392426313449752ddb7d6ea722fdd82ede2c7b8832dde3cbe80
+
+Count = 126
+Adata = 6bd14e3bf91dc7fd6be07647
+Payload = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adba
+CT = 8ff3c0856dae0290f7eca38aebda1485163fe5bbe0edd2565c2994b2b469ad977564d83db1ebfe38
+
+Count = 127
+Adata = 6c6ad35e97d023217018162f
+Payload = 1bd1bcc6766d251144376d91ff93ef83033d0e0ee546266f
+CT = c1a21b6d4969ec1cc291fad8087a07240b11034c0de25983ac31ebf9e255eecf3c69ddf198760556
+
+Count = 128
+Adata = 52c35db85cc34b6efed180ee
+Payload = 28f71a2fe498f89203a5d23e8f8fa64b124aea6459fe721d
+CT = f284bd84db9c319f8503457778664eec1a66e726b15a0df13424079e3de87fa59c3d10fd62380a90
+
+Count = 129
+Adata = a96e4776270683ee7d0c9b6e
+Payload = 5be078ead1926074afca81f9a97dc93dcb954c955e4343e4
+CT = 8193df41ee96a979296c16b05e94219ac3b941d7b6e73c082258e1f3fc3eb7e976c86c8a21bd6569
+
+[Alen = 13]
+
+Key = b5f43f3ae38a6165f0f990abe9ee50cd9ad7e847a0a51731
+Nonce = 13501aebda19a9bf1b5ffaa42a
+
+Count = 130
+Adata = ead4c45ff9db54f9902a6de181
+Payload = 3726c1aaf85ee8099a7ebd3268700e07d4b3f292c65bba34
+CT = fd80e88f07dad09eed5569a4f9bb65c42ef426dda40450119503d811701642143013f28ce384d912
+
+Count = 131
+Adata = e63b89e95df8338ecdcc885c3b
+Payload = 37f86aa62b1e31e9ded3e1a38a7e1a8a638d619ac109694f
+CT = fd5e4383d49a097ea9f835351bb5714999cab5d5a356836ac6d3f9c7b9f25e09ce164a11370b8b05
+
+Count = 132
+Adata = a2161536e263459e0b0a29a225
+Payload = 1749f5977197359a5d318d5fea38aba95b3603f1d7011e66
+CT = ddefdcb28e130d0d2a1a59c97bf3c06aa171d7beb55ef443e02b848b006c28803303fd97bdc35476
+
+Count = 133
+Adata = 8ac95a6ae0bce0fb07f85368ab
+Payload = 0842bfb8b38283257c2ea58b29c8350775f1dbf15f73c905
+CT = c2e4969d4c06bbb20b05711db8035ec48fb60fbe3d2c2320431de2bc45b2b726bfda92939a11f68b
+
+Count = 134
+Adata = 44cc9b2510680c4d73f1938c77
+Payload = 68d09fce5e89e4ef6d453b8ee326090cedb97b75b886c7b3
+CT = a276b6eba10ddc781a6eef1872ed62cf17feaf3adad92d96786add8c2619f0782ca12312a1d64266
+
+Count = 135
+Adata = d8a662ab8449bd037da0346a24
+Payload = 45245de4ac6a6196a0b15b77c622a21bb50627379ddb4256
+CT = 8f8274c153ee5901d79a8fe157e9c9d84f41f378ff84a873b6bd4a09f9b4aa2864d39ff1a03e0ff7
+
+Count = 136
+Adata = 8ed39da1d9179e77156eb909f3
+Payload = e928e37dbe8389a53c650edc86f83cd3589a53dc8e45adfd
+CT = 238eca584107b1324b4eda4a17335710a2dd8793ec1a47d819b6935778ffbc0953974de0a9d87a31
+
+Count = 137
+Adata = 423515f7bd592d6a7a2408661a
+Payload = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b1
+CT = 869df54479ad40017e50e6012b5bd71d829b5ed19c64329400a3da0d3ce34a272b51582a998f461e
+
+Count = 138
+Adata = 5a6bc2cd6890a473d478a582b4
+Payload = 1c5ebaeb7b926a39b8aaf65a4c484b113d6f2caafadc33ea
+CT = d6f893ce841652aecf8122ccdd8320d2c728f8e59883d9cf4ef28c338f497a40f550f2945734ad1a
+
+Count = 139
+Adata = 7bdc26b5b4df58af539d91eb2e
+Payload = be5c9fee6babf569c66e6a0d0f3c4dc314f40c0aeca493f7
+CT = 74fab6cb942fcdfeb145be9b9ef72600eeb3d8458efb79d2e07f1998e57ba9b611568632dc5cb9fe
+
+[Alen = 14]
+
+Key = 13f179aa2a23bc90a85660306394940e9bb226ce3885ec01
+Nonce = aaa52c63ca1f74a203d08c2078
+
+Count = 140
+Adata = 5cc924222692979a8e28ab1e0018
+Payload = d3b36c6289ad6ae7c5d885fe83d62a76270689ce05fa3b48
+CT = bc4fcef401c2e1d1c335734ff23ea52c3474d2e6f31648a7f58649400ac9e825b038d67f0c2a6f1c
+
+Count = 141
+Adata = 21fb9cdd9b110bbbc6832275dfa7
+Payload = a7742dd9c3e8bbad08157fbd01ebfb94e1639117c4b4eb5d
+CT = c8888f4f4b87309b0ef8890c700374cef211ca3f325898b23fa5ad4142e0b4650fa5cc8f7ef70d62
+
+Count = 142
+Adata = 9919ddb6ee6c330646cd15953d39
+Payload = 297b4498bf5427e6341aa9275c1f62e3b0c9b150a195ae72
+CT = 4687e60e373bacd032f75f962df7edb9a3bbea785779dd9dfec551d11b8647432cc4320173939600
+
+Count = 143
+Adata = f94cfd1f8c7902a57784c10b9a5a
+Payload = 2218868033e17220655f0196dab6193c58293ca105d467d9
+CT = 4de42416bb8ef91663b2f727ab5e96664b5b6789f3381436a79a075ec2cacee1482b8328b697a3b2
+
+Count = 144
+Adata = 63f3fe58c348dc6bcbb44c3c370f
+Payload = 4a9bc26fb10000a57b9e73a8a3d30f66ef9de8782201ffa8
+CT = 256760f9396f8b937d738519d23b803cfcefb350d4ed8c4739cbe17b4edd64a3dcd2b8ae3352c04a
+
+Count = 145
+Adata = dec0ce763833305aa9c9efdc2c65
+Payload = 1b61b3ff3e4847a17f55f7565826b0e2ccc1368f4de32022
+CT = 749d1169b627cc9779b801e729ce3fb8dfb36da7bb0f53cdf54665c476d0741164685b0d81caca31
+
+Count = 146
+Adata = 592ef6784ee839a049e0d96257fa
+Payload = 32e5998b37987a38800f5bfe3132979ca1447314570aaef7
+CT = 5d193b1dbff7f10e86e2ad4f40da18c6b236283ca1e6dd18500d93b11fecc8b4560320878ba53550
+
+Count = 147
+Adata = 4a47a82b999a2a739959f153a091
+Payload = 84acfb6cf10b301558e5acbf41bbbe0b145dc66dc600f4df
+CT = eb5059fa7964bb235e085a0e30533151072f9d4530ec87303c2a41443578adaf31483bbb6b9f10b0
+
+Count = 148
+Adata = 4ceba98cc0ff5de1a7d580cf23d2
+Payload = d7c73d77a286df38aad116843620911c92e11486be5fcb0c
+CT = b83b9fe12ae9540eac3ce03547c81e4681934fae48b3b8e32232a856c07999e99a4701988b486ef2
+
+Count = 149
+Adata = 15e3b3c5794fececd703ac58ccb2
+Payload = 140882c5d3534bb0861e7ba9423e67439a02ee6f0b0b00f3
+CT = 7bf420535b3cc08680f38d1833d6e8198970b547fde7731cb3a6d50a92f3183c0c5090edc3c7f822
+
+[Alen = 15]
+
+Key = c1dfc48273d406a3a7b9176f80b2dc4e9a7f68134bab66d2
+Nonce = 1ac53ba965cdaeeef7326a37e4
+
+Count = 150
+Adata = 39ba54a410a58a5d11615a2163cc3b
+Payload = 67d9728a88f1fac3af43ed6d634ba902896bd226858697d9
+CT = 360f0fc714994e3b59448b50cdd61d511b4f09e0e5fb5ac826a51fe5b9b598a17eb3da10f936813b
+
+Count = 151
+Adata = 38b0cca09d69320105d24ee3f96684
+Payload = a8365ba9fcfff060b28895f7a2d786c5991a8f7758962caa
+CT = f9e026e460974498448ff3ca0c4a32960b3e54b138ebe1bbba673a94f4280e84724f4a2510165e9a
+
+Count = 152
+Adata = 76718dfb9c68acdd82592d96def39a
+Payload = 497be597dd695cb159d8a64f44049c3b549ac927837b1b90
+CT = 18ad98da4101e849afdfc072ea992868c6be12e1e306d68118865ab37be6f015316e0d177b6c2e91
+
+Count = 153
+Adata = dd719ba1710916a546233c1494a7a7
+Payload = ca452c21383ebc3fb584f0d59a227374854983f243a3f460
+CT = 9b93516ca45608c7438396e834bfc727176d583423de39713d903f67ad0d72fb8ffea2035216b769
+
+Count = 154
+Adata = d893fa2bd7c70e21a5934dc2e99037
+Payload = 3dd118ed65453d3d7844d8de78d7a43587ac5e9305b11464
+CT = 6c0765a0f92d89c58e43bee3d64a10661588855565ccd9750b885e3e054f519d0355db1bd589bb35
+
+Count = 155
+Adata = 97c60265a3a6993b97ac1b375a79b8
+Payload = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117
+CT = f6e126eebe391bf9cebaf9e55248de2fd18ff76fc781cc064a950e4bed4137e38787839e39924821
+
+Count = 156
+Adata = acfdf302ed116ac4755069d1704423
+Payload = d39d188f28521e4fb0a0c5e48e6d6efe4383c95b2535ea8d
+CT = 824b65c2b43aaab746a7a3d920f0daadd1a7129d4548279cca94dd97fd2a5d50eb7dd6234b40c525
+
+Count = 157
+Adata = d449f97164aae9a3046624e98810bc
+Payload = 758102470e221e30d87d2807b5f8b793a7a56c83eecf32a4
+CT = 24577f0a924aaac82e7a4e3a1b6503c03581b7458eb2ffb596f11450d5d2ba55ffb4a6cf7eab847a
+
+Count = 158
+Adata = 3e6c914a196e175079315b1c92b2b8
+Payload = 1db875c4b4f9dd4926dfb5604d6c4d21aba7d905aed9d1b0
+CT = 4c6e0889289169b1d0d8d35de3f1f972398302c3cea41ca164894e9218ecacd143fb62df69a13d33
+
+Count = 159
+Adata = e2b7b00d0cfbdfcc24f1819ae1869f
+Payload = d7a75bc621addccbbe162b86d536d69c887c278384af54e7
+CT = 8671268bbdc5683348114dbb7bab62cf1a58fc45e4d299f685a7c19bc9c2f8e36ed95015ebb679ae
+
+[Alen = 16]
+
+Key = d8a662ab8449bd037da0346a24565683a3bbbbd1800e3c1c
+Nonce = 166fb8d0e110124c09013e0568
+
+Count = 160
+Adata = 1c1c082eeb5b8548283d50cc2ace1c35
+Payload = 61fdd10938557080191d13dd6c3002dd445d9af988029199
+CT = 23c05927502a4ee6e61e4e10552d49b020643eab476eeacc867601fe79a122a7817819655183283e
+
+Count = 161
+Adata = cae884fa25adedd883ef4e7c855def19
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = ce476aedad7cd761d26d59297533ece2b6703002fa0bda63160bb976ab072aec8fcea8eab3dc5aff
+
+Count = 162
+Adata = a350ed58c04473e113b9088b1fb9dad9
+Payload = 863f9a26182f131c594972398b52b3a01a9d314fd9390bf4
+CT = c402120870502d7aa64a2ff4b24ff8cd7ea4951d165570a1291b2c13a3f5e49ce35b9047ee1e8627
+
+Count = 163
+Adata = cb7090f7a465782f680fd44cbc558107
+Payload = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402
+CT = ffa941830a2cfc3b3b14a5b6574fab5b45f550e17099cf57fdd9fd1d469a9042b80e6458d25292b4
+
+Count = 164
+Adata = 914cf55a3fc739b5f87ac7518cc4171b
+Payload = c313bd213dc29c00691e25ce028884192e21a820003aece4
+CT = 812e350f55bda266961d78033b95cf744a180c72cf5697b1a8b8e82175ff30c69ea71d2cfb814ada
+
+Count = 165
+Adata = adc8b69d84ef7ae62f9ca9f371d3488e
+Payload = 85e4e053b976e06a64dfa8523130cdd802d3e7c3d6d797c2
+CT = c7d9687dd109de0c9bdcf59f082d86b566ea439119bbec9776fa36db27b2f84d1b8ab55e2fc89ab8
+
+Count = 166
+Adata = 29ed477994dd231d3a71157eb56d219d
+Payload = c77aae5fd09dc9bceee7428e0734d4b0556528396a58f909
+CT = 85472671b8e2f7da11e41f433e299fdd315c8c6ba534825c0e32058ea939036805a735198934a072
+
+Count = 167
+Adata = 494c8f931029a4919e2dcbc16512a8bf
+Payload = 1f47273103f265f963e498878361c06c01a5ffcfb630a161
+CT = 5d7aaf1f6b8d5b9f9ce7c54aba7c8b01659c5b9d795cda3437098c81475f8a1d8f3b0e63d499d387
+
+Count = 168
+Adata = 53200bc5d1f1fb0eeff02d2bc42f7d54
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = e1bfb9812822f9d1f38ee14181532085c4e58ac732b057bd9d7317973878957e8fc1fa57a025a3e9
+
+Count = 169
+Adata = 61e0e28bf344a9a1b04b15156e06498e
+Payload = a0d3a94ba6bb3bedf38220d1cba7e91273ad19f9a1c436c0
+CT = e2ee2165cec4058b0c817d1cf2baa27f1794bdab6ea84d95b0aa1befae96e71b9d221673844b1cb7
+
+[Alen = 17]
+
+Key = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5
+Nonce = 924322a3ef0c64412f460a91b2
+
+Count = 170
+Adata = 03c2d22a3bb08bbb96b2811ce4b1110a83
+Payload = 1bd3b5db392402790be16e8d0a715453928f17f3384c13a7
+CT = ad736402626df0f9393fe4491eb812725ad39d6facf20b5b2f9340b0d48a17ae1cc71d7515e61ee9
+
+Count = 171
+Adata = f390387610741d560325b5d2010d8cd4a0
+Payload = c93aaa04279e451b6880ed7b7fdb3ca9e80ab76180434937
+CT = 7f9a7bdd7cd7b79b5a5e67bf6b127a8820563dfd14fd51cb717bae4c040561bcfcf80fd842ae8dd8
+
+Count = 172
+Adata = 891d7988a56415a7b433f463b1e80eaa62
+Payload = 2611612ccb5ffefaa73195509bb52c641472bca0dfd09d49
+CT = 90b1b0f590160c7a95ef1f948f7c6a45dc2e363c4b6e85b5bc9fb15d874feccb6b5f581fa470734f
+
+Count = 173
+Adata = 831c0fed5e600dd82d7d55669262a9a17d
+Payload = 08136e946e306cde0544ddc2f3f4a529c89c7b77a5e635c1
+CT = beb3bf4d35799e5e379a5706e73de30800c0f1eb31582d3da72589ee50d23f925f7998ab3ccac37f
+
+Count = 174
+Adata = 32ca9d412d4ef0e89928496e96c9de7f2e
+Payload = 695aaac402942de7d899cc3f741c7fb2b2d8247a7676cf29
+CT = dffa7b1d59dddf67ea4746fb60d539937a84aee6e2c8d7d555c0b608f331dca47c65f5c879f2d532
+
+Count = 175
+Adata = 0746b2e6149c7f55854e9ca3e6861bf0e9
+Payload = 8f958d796be0566512f0512dcebd2e12f3160b05b72ae955
+CT = 39355ca030a9a4e5202edbe9da7468333b4a81992394f1a9b039bd916e923e2fc1f7c60eb59916fd
+
+Count = 176
+Adata = 0e4cbd1c574d656112bf6e70a8f23347f0
+Payload = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364
+CT = 80de1cc22a964beab63cbc5b3cb91bdb23ac4da247e34b98ac07f2c0847069fe5be26e623033f532
+
+Count = 177
+Adata = 1a05ff12412bf728497536534c234901ce
+Payload = a9ccee975feb10f635d548a8502f7c8b6adbd2be74117257
+CT = 1f6c3f4e04a2e276070bc26c44e63aaaa2875822e0af6aabf4e66a2b210e5a03bb10ff2926ed8a48
+
+Count = 178
+Adata = 3bd063a51c71fab5aeb47e7f8f958d796b
+Payload = 7df6220599d6235eb450989b6f0cd6c96db62b0d13afc4f4
+CT = cb56f3dcc29fd1de868e125f7bc590e8a5eaa1918711dc08ec90169d0c5c11fff8f255fedb13a99a
+
+Count = 179
+Adata = f0d334e0a27c3d00d56b15c2ee426e6347
+Payload = 6f65a24344c32debaf9f8c3fa426fe0b139e8ad1c8b1fbbb
+CT = d9c5739a1f8adf6b9d4106fbb0efb82adbc2004d5c0fe347170141cf3f207c4f0fc1b0238477cfad
+
+[Alen = 18]
+
+Key = e67f3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863
+Nonce = a727ed373886dd872859b92ccd
+
+Count = 180
+Adata = 68d199e8fced02b7aeba31aa94068a25d27a
+Payload = d7a954dae563b93385c02c82e0143b6c17ce3067d8b54120
+CT = c6cfaa1f54d041089bd81f89197e57a53b2880cefc3f9d877e30b2bcc3f1ea9ec2b8f28bf0af4ecf
+
+Count = 181
+Adata = fc4bbe329a86089ebe2a2f3320dad55a9bda
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd2
+CT = b3605f2ec11a2a70abff1c3ab717fd172ba9e9ac72d961753a6e6844102d6bb86986c030765d3393
+
+Count = 182
+Adata = d8741e540330692d83cc806a8ac1c4742be6
+Payload = 56ef76dbec6b8b46f5b7b4e311c0baaa6fcf54c69c0b9c3b
+CT = 4789881e5dd8737debaf87e8e8aad6634329e46fb881409c3f92a80b1d82f8c1dc32bfe64adca12a
+
+Count = 183
+Adata = c8b1992dfba55b4ab86b480546c861655e1a
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 364f9da4a34153d9d97696eed355ec79d464405a927d14a12fb48ad162b0c0678674d79d26a6b5ef
+
+Count = 184
+Adata = 347e12eec56e95aafcc7d25bf10fc756b4e4
+Payload = dd433eb7422c7c4dccee57a1679633ced3b5f08df763d457
+CT = cc25c072f39f8476d2f664aa9efc5f07ff534024d3e908f081c7cd81c974d985bf24b7fe9542141a
+
+Count = 185
+Adata = 45b35a04d6e2645e9a5aef206ed4e36199c9
+Payload = 70523bc397417e09d791a4976960e02636ca7144a5681cf7
+CT = 6134c50626f28632c989979c900a8cef1a2cc1ed81e2c050a7f6a5c04e59896074e1594706ab27e9
+
+Count = 186
+Adata = 378b48531fe34f55125b2f14f59715dd6ef0
+Payload = 514cb462dd4b117f26cac22062fcbeb353650c71649a7b3d
+CT = 402a4aa76cf8e94438d2f12b9b96d27a7f83bcd84010a79aa9d16c3ab79276cff345444511940a9d
+
+Count = 187
+Adata = 73ed686d6fecdc031cd97653137f269d6537
+Payload = 7f0c2b261db3f3de0ce3a733f4b8c446c374567d96d00379
+CT = 6e6ad5e3ac000be512fb94380dd2a88fef92e6d4b25adfdef92bf8aa6facbe6f9607ea02b54a1bf0
+
+Count = 188
+Adata = 5b0441107e5560be94f030a41cedbdb116d9
+Payload = ebb3e2ad7803508ba46e81e220b1cff33ea8381504110e9f
+CT = fad51c68c9b0a8b0ba76b2e9d9dba33a124e88bc209bd238e4936ee93b5c7a302913292df33c1700
+
+Count = 189
+Adata = feedcc5f8524fe7d49bcd178415b9f4c450a
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = 237022260902363567fc3cf433ad446235fc1a5a3d53ad7493426b6193afe765a76b3dec00266e69
+
+[Alen = 19]
+
+Key = e0a29a2c7840cf9b41de49780b9ee92d646a4bfc5b9da74a
+Nonce = fc9fd876b1edded09f70b18824
+
+Count = 190
+Adata = 36e15baafa0002efbb4bb26503b7e3b79f6c68
+Payload = 344dc8b6bd66a1fbbe330a95af5dd2a8783dc264d6a9267d
+CT = 43b3b96aa5a54378f3bb573ffda3e154aa7f425fc3008175b60a77b9d38740356b544b1c0f259086
+
+Count = 191
+Adata = 712b788f0276e2b5a58be80f9114a12ab2a268
+Payload = 6d0546d4e95d1cfcb37a8f88a62064f5d95791311511535b
+CT = 1afb3708f19efe7ffef2d222f4de57090b15110a00b8f4535f750bb4cd42db3038e2c1622b72cea8
+
+Count = 192
+Adata = 07f77f114d7264a122a7e9db4fc8d091334a03
+Payload = 05024ce13b9057dd2c509db7dbcbd5585e4e64a1e2e380ff
+CT = 72fc3d3d2353b55e61d8c01d8935e6a48c0ce49af74a27f761e77b59ef7eeeae35bb53bb9543b64a
+
+Count = 193
+Adata = 899b036138cee77cd28382ba27984d858a6351
+Payload = 77b8e735b13b10e45e411ab94c6fe1a9eb89f0a7af40ff1a
+CT = 004696e9a9f8f26713c947131e91d25539cb709cbae9581244a60fdb473098a11b2176d37b2c4643
+
+Count = 194
+Adata = 4b000440a8484a5201cd54aec058919769772e
+Payload = 6b21800ae599a15254bb33f0bb080788fb6e9fa054bfd8b2
+CT = 1cdff1d6fd5a43d119336e5ae9f63474292c1f9b41167fba58d4afc30a7f672ea34e05ec1843d848
+
+Count = 195
+Adata = 73a222e681ed1ca47d92a6dd90625d895fbf29
+Payload = bfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028
+CT = c857a87376dcd0352fe24172c9e201ade919d09a987317204ef270e0f3b5e3ca0b8440af65c76e85
+
+Count = 196
+Adata = 7109a3a36b286059bc1a1abb2767c92f884e3f
+Payload = c68b1bc0050e19780ab53efbea175634f70a7245d966966e
+CT = b1756a1c1dcdfbfb473d6351b8e965c82548f27ecccf3166ffb66991b38a0345fbbff5f2362f87de
+
+Count = 197
+Adata = cd15973753b94b77bb4b778de8b3b0cabbde85
+Payload = 4256f1c9b64390fe2120df9fd38e497c2903c2ca5679ab75
+CT = 35a88015ae80727d6ca8823581707a80fb4142f143d00c7dd033a087c44c2e44adbeb333aa9ded10
+
+Count = 198
+Adata = 6e5e0793855f7145e13a5872f563e5ec61cfd2
+Payload = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192e
+CT = ccfe476f53cfc28a00bb072626088022766c6cf454ecbe26ff9c8713422fe38d5bbf2dedccbffe10
+
+Count = 199
+Adata = f844684f5404e7d8eedfa20394b40b4f5d910a
+Payload = 86afa9cdd743916563ebfd3adbdd56e015ea3a4ebc61cfe2
+CT = f151d811cf8073e62e63a0908923651cc7a8ba75a9c868eae75de56eabcf8e02c1a27705adef2732
+
+[Alen = 20]
+
+Key = 26d0a3a8509d97f81379d21981fe1a02c579121ab7356ca0
+Nonce = 8015c0f07a7acd4b1cbdd21b54
+
+Count = 200
+Adata = 093ed26ada5628cfb8cfc1391526b3bcc4af97d9
+Payload = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711
+CT = a3a60b422eb070b499cf6da0a404b13a05cedda549c6b93e6ca0e07e04674f21a46df2659a5905fb
+
+Count = 201
+Adata = 7df13c9d2247aa40af7bbe2da98bd366d8b47b43
+Payload = 93925579b6367ff592ecbd59495fdeccb50f31ea4fa390bc
+CT = 079f7430e3ef9b6373c1c0cb11d884507d02a31d83cd9e93836597806f5da1d176c745d95c4fa46a
+
+Count = 202
+Adata = 7f369bbc99b6f08049eeb43566269a174829d4dd
+Payload = 8363aef9c7c34e1f8149de46c97d5ac79d38c6ed31ab1d12
+CT = 176e8fb0921aaa896064a3d491fa005b5535541afdc5133df826dda99111691993027628c70ff6ae
+
+Count = 203
+Adata = 04aa8442179f62babad0c006e36af0c21105f27a
+Payload = 17281acb525b13653000ab45d86e70106c10a93c99b18f76
+CT = 83253b820782f7f3d12dd6d780e92a8ca41d3bcb55df8159d074b018143a7ea1b5369b7f80eae20d
+
+Count = 204
+Adata = 997e646014f19a53beab8877ca6022bef23016f1
+Payload = 5d48a71557608736eded309027a80349a18e9ce5dee2bc6a
+CT = c945865c02b963a00cc04d027f2f59d569830e12128cb2455db17d3f75214c3cf39858617cfee57a
+
+Count = 205
+Adata = 60ffcb23d6b88e485b920af81d1083f6291d06ac
+Payload = 6c9d11cfb64d96bfab61c04a25d9e19294fb7330fb4847c8
+CT = f8903086e39472294a4cbdd87d5ebb0e5cf6e1c7372649e79550998376e61e11a5a69e9f8fe1c329
+
+Count = 206
+Adata = d574632658bf456dfbb11c2653602ed0f4dae777
+Payload = 7d41688c86d5e3bc53966810f2299fdd732e3471fb0a88f9
+CT = e94c49c5d30c072ab2bb1582aaaec541bb23a686376486d6a1b0d05a7ebc657c3235479893bf7e5d
+
+Count = 207
+Adata = d896ed60128f4bb0277d3af94c5138cf91697aa9
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = 1877c38a90da0d91cc43797614a9fd131a4406a7f909af1980c98c8959c158ce209aebcbd554f250
+
+Count = 208
+Adata = a350ed58c04473e113b9088b1fb9dad92807f6b6
+Payload = 49bc9d3bcf3c22daa8cf55c1b59d4bffddc2412d60518e98
+CT = ddb1bc729ae5c64c49e22853ed1a116315cfd3daac3f80b7573175f9105cd16ee384465ebb232200
+
+Count = 209
+Adata = 1db5887001204194e8b5dcee92c8af8fa5f7321f
+Payload = 25f3788e0d3dd8f5821faa4e45a9d6b3995fd881f927135c
+CT = b1fe59c758e43c636332d7dc1d2e8c2f51524a7635491d732b67e993384f2e7229d1838efd040d99
+
+[Alen = 21]
+
+Key = aac60835c309d837aacc635931af95702a4784c214283ebb
+Nonce = 0e20602d4dc38baa1ebf94ded5
+
+Count = 210
+Adata = 796e55fbe7bed46d025599c258964a99574c523f6a
+Payload = e8610756528f75607b83926597ef515f4b32a8386437e6d4
+CT = e0a3d5f43e688ce104f4ae1a4fcd85500aa6b8fdbcd1b8d3003c0c3b7369e79339433e1754c0937f
+
+Count = 211
+Adata = 5170836711fcb1a350b087907d8a17c7637aa1595b
+Payload = c61b0c1845fa9b2e0013b3fa9a8cb4f4fbbc6846f63ed180
+CT = ced9deba291d62af7f648f8542ae60fbba2878832ed88f87120a7f18d021833b167bf330c4858239
+
+Count = 212
+Adata = 2a68e3fe746f593c1b97cb637079c3e5ee352c107a
+Payload = 10c654c78a9e3c0628f004b061e28c39a3c23e7250f53615
+CT = 18048665e679c587578738cfb9c05836e2562eb788136812ca9698d9a88e892c364e57dd35c2f17a
+
+Count = 213
+Adata = bf38ca0e89b8f5ccd29387f7f193ab5a967caa715b
+Payload = fa3a959fdff853c39f76da626094a1ea6dbc78bd2f091a79
+CT = f2f8473db31faa42e001e61db8b675e52c286878f7ef447ef3839d6f7e20a2e343f4c4da9eb9be13
+
+Count = 214
+Adata = bee00f2f75a4415ce993d2d14a6d8e01d1d59a48f6
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f6d
+CT = 7e13fc9e20ba608a8a14fa757cbb4a5dd81998ba4fa1216a6630bfb7a2a2441e020efdf36274b72f
+
+Count = 215
+Adata = d5b614e4e8f72a5d8b1ec2b375da5dac64c2cc30b1
+Payload = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b634
+CT = 61fd7cd894ad5a168fc586d10191139a7ee1f78794afe833866bcee343ec5aae61f9effa19b99d3b
+
+Count = 216
+Adata = 33f11aa36d8ab0fc53486839a576b31ee915dbd769
+Payload = 56ce9a09f38127b14dbbdcaa59f363c92a3b9843ad20e2b7
+CT = 5e0c48ab9f66de3032cce0d581d1b7c66baf888675c6bcb00331b60eb252f744a06b4a95aa9f4e7c
+
+Count = 217
+Adata = f40bce1a6817b29b9e8b56f214fcca7dfde17e7ee6
+Payload = 5cd8986e974d09ede34ba68fd81d6109a64092e7fbbaf87d
+CT = 541a4accfbaaf06c9c3c9af0003fb506e7d48222235ca67a4153778a644cb2469cef3ad125e257bc
+
+Count = 218
+Adata = 53c457d8d4d4ab95ba116c28b82c16743cb09de9fe
+Payload = 9c3c610f204d98702dd91ea28e0cc14830b26bb5e2ee0349
+CT = 94feb3ad4caa61f152ae22dd562e154771267b703a085d4e7013e1c34dbc5efc7bcd4f8e52797644
+
+Count = 219
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c
+Payload = 90c5dd9db0316dac89db18f70491bdf0a06a6a7f72b77d9a
+CT = 98070f3fdcd6942df6ac2488dcb369ffe1fe7abaaa51239d66aed667c761b7dea44822e30cff671f
+
+[Alen = 22]
+
+Key = 671544bf2988056f7f9ccd526861391a27233793a23f811f
+Nonce = 0a259148a1d081e0df381ecd0c
+
+Count = 220
+Adata = 61dafc237cb52f83ab773ba8a885462b6f77d4924611
+Payload = 576b069ae2713f53d2924c1fd68f786cb2eec68892f9e1be
+CT = ce06b3d09b02921f290544032a081a7766612940048867281bb089af0245792c16e6320cf5ffa19e
+
+Count = 221
+Adata = 87e49b8164e7052becfa0c966991637b38df833fc5f7
+Payload = d7eb0d7dd737805cd3b8dbf451aeea2fa1f6a96eb58cb428
+CT = 4e86b837ae442d10282fd3e8ad298834757946a623fd32be3cec29bd5df92363d6bb75456f5cd32b
+
+Count = 222
+Adata = d302a518d7c625756d3e4c8cc2b1d973a19107c945fc
+Payload = 77d8c9e6321314524afd05b7ad599c29f4eedda9e9f0763f
+CT = eeb57cac4b60b91eb16a0dab51defe32206132617f81f0a901ca82cddb78a2fe3904d1d8bf6fe5b2
+
+Count = 223
+Adata = 6566bb616a94bb03df5c26b722bcd38d516285c5f6c1
+Payload = abbf28b3ae164051648293d0b94e11f5af8468450005c7c0
+CT = 32d29df9d765ed1d9f159bcc45c973ee7b0b878d96744156d095ad121f0f76f07b715cad996def52
+
+Count = 224
+Adata = 141be3601e38185a9fa1596d2ee406415c9673af32f5
+Payload = b67d50110f844b36a00d352123012a1123c7c3cba959dc48
+CT = 2f10e55b76f7e67a5b9a3d3ddf86480af7482c033f285ade8529ec8f477462dc2409482c3479756d
+
+Count = 225
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732b
+Payload = 2a63f7b09b43fee65738e8115bd8419b3ef3e8f86eca707f
+CT = b30e42fae23053aaacafe00da75f2380ea7c0730f8bbf6e9b14fe8dbb3c361ea61d7b44e689a1c48
+
+Count = 226
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc
+Payload = 59dad755af92c29522da4348ab9b3037fe87004f5fa1394a
+CT = c0b7621fd6e16fd9d94d4b54571c522c2a08ef87c9d0bfdc54f0659fae291f943f2f3b33688602cb
+
+Count = 227
+Adata = 5d895fb949344e603ce5de029842b20d2bb614ecbbb8
+Payload = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f
+CT = fdb508761d1cdb90977f95f3288015e5c3be88e1745a2f993af4e3a7a20390a8da264299712a34e3
+
+Count = 228
+Adata = 74cc8da150b0bacdefa8943900b4ea047611d96be70a
+Payload = 0c3c9a634a000f00be003846eac7482e303a5bef3a70fe75
+CT = 95512f293373a24c4597305a16402a35e4b5b427ac0178e3a7f79d2b5a9bde5bd453bc8a03e971d8
+
+Count = 229
+Adata = 65f6adbaaa803dbad5ba9cb6d231314d55147cc61399
+Payload = 712c788928c8a1562bc1f3f0eb1286e15c3405f6a6fa0443
+CT = e841cdc351bb0c1ad056fbec1795e4fa88bbea3e308b82d5ffccebfb8c833833db40e98a1950fb70
+
+[Alen = 23]
+
+Key = 90e2c63b6e5394b1aeec03f95a9d13a01a7d4e9d58610786
+Nonce = dada5465eb9b7229807a39e557
+
+Count = 230
+Adata = f5629ca0eea589f6cf963d875a7d2efb656983f2dd2231
+Payload = 44dd098b1f869d670a8a841900c4bef023a1946a0c278354
+CT = 6b38ca85450e05e7b9362ed7e6e291a130ff233b5a561cdef7ec84dd992fdf98514f845dac8f656e
+
+Count = 231
+Adata = d43d7753530a7280b76221906dca85d396b6cf05125018
+Payload = cea19562328bd1fea889f575db6a28a14b7d06fb9f9c98bb
+CT = e144566c6803497e1b355fbb3d4c07f05823b1aac9ed07313613ed15d527d9dc58ab6893e723db58
+
+Count = 232
+Adata = 75650ce366757618af20205b69af7e5d4e82c398c00101
+Payload = f0641f595b791edd860977fcf699688587a354e053e9c7fe
+CT = df81dc5701f1865d35b5dd3210bf47d494fde3b105985874ef8728d1bf3a2d93db3266bafadb7c26
+
+Count = 233
+Adata = c00f1b8066677c63e898fddfb8a1b482b536963da0628d
+Payload = c7486a084f8475e6f5138e8d6e9f42a1de90f05aa88a362d
+CT = e8ada906150ced6646af244388b96df0cdce470bfefba9a7a5bce94d7564d297fe87730f1a36acf4
+
+Count = 234
+Adata = 5a89ab6b26b2ca78f98a8f8409fe8008b97ba9ef185d41
+Payload = 091ef698e16dc43a11d3ea005d5a5cdb7f1bdb5665a6c81e
+CT = 26fb3596bbe55cbaa26f40cebb7c738a6c456c0733d75794cd971b07fc14c512b8df6dd964b129d0
+
+Count = 235
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d3
+Payload = 62f204394b367c4410746001e02dfd171858396568fdd43b
+CT = 4d17c73711bee4c4a3c8cacf060bd2460b068e343e8c4bb1a192b781dc94448d4a0f6a439a716339
+
+Count = 236
+Adata = 4a47a82b999a2a739959f153a091a65c4d7387646da66b
+Payload = ac1cd5ba4997af91dbd74aee7730f9ee92cf8a360ca96a8a
+CT = 83f916b4131f3711686be0209116d6bf81913d675ad8f500cade9533b272e0a3edeba68362b057b4
+
+Count = 237
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab
+Payload = d0a249a97b5f1486721a50d4c4ab3f5d674a0e29925d5bf2
+CT = ff478aa721d78c06c1a6fa1a228d100c7414b978c42cc4785d68df8ff28345be4d83541a72071059
+
+Count = 238
+Adata = 720a9dc3e33ac080775a06f67f4a6591c37d0e101944a0
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664caa7ec8892be6a18458c663665495035
+
+Count = 239
+Adata = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664862fda880e45e891a3a50da7e14344c8
+
+[Alen = 24]
+
+Key = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903e6
+Nonce = f97b532259babac5322e9d9a79
+
+Count = 240
+Adata = ad6622279832502839a82348486d42e9b38626e8f06317c4
+Payload = d7c837971b973f5f651102bf8d032e7dcd10e306739a0d6c
+CT = 4709600418f2839841e6d126359f6982bdb53acc7ff209635623d15b24184481eadc63bb8c878fc4
+
+Count = 241
+Adata = ad4833aa53218949cfd724814a43889a74a2114bbef4cf37
+Payload = 7d672bccd0fb01ce79320ed61779146aa432038daa13cb41
+CT = eda67c5fd39ebd095dc5dd4fafe55395d497da47a67bcf4e614c3e546273f0aeef207bd3f4d32fca
+
+Count = 242
+Adata = 54a723826086c7175e8fdc854b62d780de6ac1f90b57dd3a
+Payload = 0e1b73df74982f535a5fb08bc13d22515ee10969efe033bb
+CT = 9eda244c77fd93947ea8631279a165ae2e44d0a3e38837b413c6395ce9aee2e22ac0606beb140185
+
+Count = 243
+Adata = bec02d7df4cc3deefdd7e7d3ea82d381c870ad46bc06d64f
+Payload = 9a55aff269b180118ff0ea99e851c7474d19d23e641f16a9
+CT = 0a94f8616ad43cd6ab07390050cd80b83dbc0bf4687712a661e4f02150bedd86dfa49f52b214239d
+
+Count = 244
+Adata = 1b8090d712e0ec95a01bc3aeb6f5230c67c355e0ed68043a
+Payload = ff19294e8faed8353dbcab0b146e2ef928dd2680833424bd
+CT = 6fd87edd8ccb64f2194b7892acf269065878ff4a8f5c20b2f0e82b9f04bfc0cc0ba432b5135450c2
+
+Count = 245
+Adata = 5ed0b9f25d07b26717cdcb2507bef9d681ecd9389831ac15
+Payload = db1eba6ac4a79aa1d97838d263c7c4ffa7d354770e762805
+CT = 4bdfedf9c7c22666fd8feb4bdb5b8300d7768dbd021e2c0a2e64c82b60880c5c7506321a1060a481
+
+Count = 246
+Adata = 55f16fefaf2168aebc61b5e01d9e1f7bfe215eaaef118974
+Payload = 012d45168505ca9fde5aed123875639a207d473b993dc7b8
+CT = 91ec128586607658faad3e8b80e9246550d89ef19555c3b77152f64dc993b36ad9d5d12bb52b1ad5
+
+Count = 247
+Adata = 9893bf14fd3a86c418a35c5667e642d5998507e396596c50
+Payload = b205f26d6c8a8d6085ab28d595703cae046f96d82093082b
+CT = 22c4a5fe6fef31a7a15cfb4c2dec7b5174ca4f122cfb0c243e5c69256b6326ebb7ee6e677d396765
+
+Count = 248
+Adata = 244b840085bda9576c8424bb05a925a6b09cad2d0528ab8d
+Payload = 549ba26a299391538b56ce4bd71dbbfd96995836f8915ca5
+CT = c45af5f92af62d94afa11dd26f81fc02e63c81fcf4f958aa2083dac565c7a63908f0022e2867bb68
+
+Count = 249
+Adata = 9e8d492c304cf6ad59102bca0e0b23620338c15fc9ecd1e9
+Payload = 9e9dbd78a1066800ae33253be6104015158a0187e4f38116
+CT = 0e5ceaeba263d4c78ac4f6a25e8c07ea652fd84de89b851968242fe32958ea32e670ae1b3543974f
+
+[Alen = 25]
+
+Key = 90851933d4d3257137984cdb9cba2ca737322dac4dbd64bc
+Nonce = be02df3a840322df8d448c600c
+
+Count = 250
+Adata = 69a9dd9ac8be489c3a3f7f070bdaca10699171f66ab3da9351
+Payload = ba1785a149cb8b69a4e011c11a3ff06f6d7218f525ac81b5
+CT = 89ab2efefa8406336d9e2245199fbc9454f0ef650b9ed0f446c7246bd3130803bf8d703ef5bdf15c
+
+Count = 251
+Adata = 0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0
+Payload = 263dc4fb5cd8798ce0f183a816e51fafba167533dde1bf96
+CT = 15816fa4ef97f4d6298fb02c15455354839482a3f3d3eed7096a6a4422e582c5d02973952ac80e5f
+
+Count = 252
+Adata = 911d9f5c4c34c2f4b69be1e253d43fe729e2ab2622130394b1
+Payload = 7b5da2c283116713f3d80c7907114270964541e03ab80d50
+CT = 48e1099d305eea493aa63ffd04b10e8bafc7b670148a5c115965f6df4332fe7a2cdc4d1b80e28a34
+
+Count = 253
+Adata = 8a961df9c23f6d5ecdafa94c61164a22f460a1bf7415258d39
+Payload = 541a2b3ee25022c92fdc6783a6cbde90680ad3dc41868e5f
+CT = 67a68061511faf93e6a25407a56b926b5188244c6fb4df1e18bed174081b2170ffc6ab53b54c9ddb
+
+Count = 254
+Adata = cac7a248a4d4e96a9733627e247234995d6aa57e491498118a
+Payload = ebb2e893da9f32c363f98bc76fd14eda59e7cc620070f6d3
+CT = d80e43cc69d0bf99aa87b8436c71022160653bf22e42a792bac3d3a2b9ef6d4c8715f9a5c6fe8245
+
+Count = 255
+Adata = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eebd9
+Payload = 199cca0d0e1c70ec405d6816cbddc69f8ada624f2c168891
+CT = 2a206152bd53fdb689235b92c87d8a64b35895df0224d9d07f9610c82fe9a7c78e8f1980e886b446
+
+Count = 256
+Adata = 78b6ed20ed85337c969618bd41917cd85c37e7c35c3a12e25f
+Payload = ca481f557306f9ce386edd0cfde375a550cb5b574be524f7
+CT = f9f4b40ac0497494f110ee88fe43395e6949acc765d775b6aab366637ec41d0bf557f578be424a8b
+
+Count = 257
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc93e7cf
+Payload = 6f1b4ff66d3aec7b0c0d9e202acc52722e15bca0983291e0
+CT = 5ca7e4a9de756121c573ada4296c1e8917974b30b600c0a1e57a5b3ae26469d229425f887ad5a2a1
+
+Count = 258
+Adata = 7f19ac3e53a629a2df1cb56d68fde0c80a46be40a996830e2a
+Payload = 7533c88ce55c2243b64b6c5bd01aed4dd6ac8bb9fd333e06
+CT = 468f63d35613af197f355fdfd3baa1b6ef2e7c29d3016f476ce4fe492062f74bff4c3c0e9ea849a4
+
+Count = 259
+Adata = 0516a69bfd8785ad001367b51e5410b75c11b761be08b9eea5
+Payload = 19ea09a9bfd10db2a74e398859d8f4831fa5749767773acf
+CT = 2a56a2f60c9e80e86e300a0c5a78b8782627830749456b8ead47ffc17b871f530f62b9f9aec98509
+
+[Alen = 26]
+
+Key = 5c5d02c93faa74a848e5046fc52f236049e28cd8096dcac6
+Nonce = 54cbf2889437673b8875a0f567
+
+Count = 260
+Adata = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce33bb
+Payload = b4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7
+CT = d40725397229021a18f3481e3a85f70445557bb2a85e4ae8101a34c777e918e16186fda05a386572
+
+Count = 261
+Adata = 10f0c45d06a138a964fb11b2d450620a2977bcd2952afe371cad
+Payload = 7b628930d44e22907277db057395601b82b65479fbd59613
+CT = 1bbfefe258f4b63ce5c21ae0e193eb7717e5678a9556085cc1e79234882846d916dabae40b1bd055
+
+Count = 262
+Adata = 64dbb170a037b36beed28a2637c87830e2b23f8eea6cd9a7331c
+Payload = 9db30b669fc5d25f05e0dc708d597da6ddce2dacc85ae99c
+CT = fd6e6db4137f46f392551d951f5ff6ca489d1e5fa6d977d3e35499e3c09dc384eb41344ee8be3769
+
+Count = 263
+Adata = c47de6608546a02c6eebd6628c9123f6936c0154d3df52a367e5
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 02de0a6c5fdcf929f5f8fc2c53f2bc29dec98633526340ddd605189608ce40b237dde7bed6fde487
+
+Count = 264
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb7
+Payload = 5c9bc739f6b6fe4214f3c6aad307d1f208892d79de010e37
+CT = 3c46a1eb7a0c6aee8346074f41015a9e9dda1e8ab0829078c31f69c847440be20bd08cfef330002f
+
+Count = 265
+Adata = 8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df9
+Payload = 0df109298083d3896214b84ff6edb11e9cfdbd88f5702839
+CT = 6d2c6ffb0c394725f5a179aa64eb3a7209ae8e7b9bf3b676ca83622b127fa50fc9637998c0ddd44d
+
+Count = 266
+Adata = 2d52447d1244d2ebc28650e7b05654bad35b3a68eedc7f851530
+Payload = 518f651f6d82f670b63767ad8476ed8fc24df12a45110611
+CT = 315203cde13862dc2182a648167066e3571ec2d92b92985e81e738b9e4b0dc7b7a39eb7d03adc64a
+
+Count = 267
+Adata = 3cba0fd2bb16ae1d997cbe659a2dd101885c97f2322b0172b5d6
+Payload = e91a694bea2d351928b6098660d49f382c087f6777de159c
+CT = 89c70f996697a1b5bf03c863f2d21454b95b4c94195d8bd3d298c05b1d2e597f44f8621ecd11ed16
+
+Count = 268
+Adata = c7f93152016bba584dadc6002ec493a46305726068886d2340da
+Payload = 2d14792ed349a878b2b879e7fa5f438a50e36947ce827e73
+CT = 4dc91ffc5ff33cd4250db8026859c8e6c5b05ab4a001e03c5fd5221fceecbf0dc7211a1aec06793a
+
+Count = 269
+Adata = 799cac048eaccded37ca6a70dd89595e1ee04606212da5572679
+Payload = 315b8d95938d304015bbc94ea03c21f6dc25c90f991ba680
+CT = 5186eb471f37a4ec820e08ab323aaa9a4976fafcf79838cf5c25f00b862b49fcfe8447949f39787c
+
+[Alen = 27]
+
+Key = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+Nonce = 16d345606a315ad2406abbcb43
+
+Count = 270
+Adata = c37fdf7449fd7e943595d75e977089c623be0a3926e63fdbbfdf4a
+Payload = 0f960a89a7e806f8709047cb7a2e7c4211ad724692c88a05
+CT = 3907880d25f910eab12dd14e704d1b33ea7c453634d54da2a461f44dac1112ae3f9c65671a931d3e
+
+Count = 271
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb99
+Payload = ab40a4baa39b0e568bf2193fecbc36b84c76bb50523b2912
+CT = 9dd1263e218a18444a4f8fbae6df51c9b7a78c20f426eeb5ed15db6e142ee07b59eb5b0ad3a59194
+
+Count = 272
+Adata = 79ae14843b2e7ccf0fd85218184f7844fbb35e934476841b056b3a
+Payload = b74c06d9077c568762796d5be14f3563e7205a6e9bc65bcb
+CT = 81dd845d856d4095a3c4fbdeeb2c52121cf16d1e3ddb9c6c203f11f66b74366caeca8dbded2bf17a
+
+Count = 273
+Adata = 542d86fd7ff591f97e6926a090553538bc3b8a6bcd45f2e29c7d9f
+Payload = f2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12b
+CT = c486196fd424b0ca69899c4baa9ca835d334e963a0b5068ced925fb9a4cf6b6bf17f72ab044653d1
+
+Count = 274
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a4
+Payload = d1a9e4593bc3d02c407e84a1736e587c1819c72195a07d57
+CT = e73866ddb9d2c63e81c31224790d3f0de3c8f05133bdbaf0d1f677deca1bfda83c1b9223aaaedbfc
+
+Count = 275
+Adata = 966954582e78e99ba68d6ffaf794b55a82325834ec4f373b2bd227
+Payload = 15b94910853a8f23dfb8b31c0262b8461f777075cc0937e9
+CT = 2328cb94072b99311e0525990801df37e4a647056a14f04e12937871932a7ca3e1e27a90a7f73694
+
+Count = 276
+Adata = b7aca715dcc402565cb711b001f21e8e95ec54c4afab2e2dcc8a2f
+Payload = fd1681cc306518bf77766f55226afac3eb21e31ed897075c
+CT = cb870348b2740eadb6cbf9d028099db210f0d46e7e8ac0fba0464ff4ddeccbd523a5ed3b32337f7c
+
+Count = 277
+Adata = 290a36f7daeeeafca4431446b396dbec0bea0a1f6f081418811656
+Payload = 0804fa48fc76f98bb021e3501bef8875b64a3b508adf8594
+CT = 3e9578cc7e67ef99719c75d5118cef044d9b0c202cc242332f68ed5e44a71c5ba8bade07b7bf5495
+
+Count = 278
+Adata = f0739a855422310a21ed863376bce9d75dc7c687b9b535cb7a05cc
+Payload = 4f5c6d80a3955f12f4d2594e02a045c42fabb11d90817fff
+CT = 79cdef0421844900356fcfcb08c322b5d47a866d369cb8583b5dc1fbe32743e257b7c1c9d624adc8
+
+Count = 279
+Adata = ffac0edb0b62977bb5040e4128a48deaf711f5e6a84d8f677341f3
+Payload = 5c29c458212d010a0d9c5a547aba1138eb4ce94742fef01e
+CT = 6ab846dca33c1718cc21ccd170d97649109dde37e4e337b9e53b654de1976294897cae0476ac6248
+
+[Alen = 28]
+
+Key = 6351a67fd6daabd2fd49ee944dd41dd37301f958dd17fcc3
+Nonce = b8d517b033754058128d13d11a
+
+Count = 280
+Adata = 511c6924fa96db716f6b053b7a48aebdc1504145a56cd02d6be2590d
+Payload = 0c0663dd69ccbffbbd0c8c2e9473d0354451ae7a20fa3695
+CT = 19f2745df5007619c79c84d174e4521b942776478a0601d982c560fede4741e2fd3b54b3a48f3e38
+
+Count = 281
+Adata = d9ccd93317441e9d6ccc358f31e7e2ccef8c921b23d742993eff9d53
+Payload = 34a882834172924d39d2df5d637d9d273a99a9222971701c
+CT = 215c9503ddbe5baf4342d7a283ea1f09eaef711f838d4750ee82d927a2aa678e792acdeb615409f8
+
+Count = 282
+Adata = c268d65f7a7b30d3d198b2045fc8d1db7adda56604fa567d8855d1a5
+Payload = 5b7450b73d68de079e92bba56c7860f11126b8fdedd3334d
+CT = 4e804737a1a417e5e402b35a8cefe2dfc15060c0472f04017a48226389d24ed3ec3da2da1a9bdf7c
+
+Count = 283
+Adata = 4c2b6815156f0643b4573825e28b9f2a668a4976e3342884f48bc310
+Payload = 140c6933248f052e05bd4a36aec185ee86730108cc2989b6
+CT = 01f87eb3b843cccc7f2d42c94e5607c05605d93566d5befa16fe6bd83993ccbdd50e1ca061f4845f
+
+Count = 284
+Adata = f11c873354b3c0cff2c8f8010e9e364582b9c05c62efdefbdcc2e1c0
+Payload = 2a083de317380d94dd991349a7b8761c7c98013b1b0227e0
+CT = 3ffc2a638bf4c476a7091bb6472ff432aceed906b1fe10ac577c5893cb3896400012e48f5b190b73
+
+Count = 285
+Adata = d0a056754098d7f7ef2f639d61ea3d2b9cc936c48a1b2c5a9e96d169
+Payload = 02769283d5a06c363c2cc66c09b1ac954134e3ec7df773f2
+CT = 17828503496ca5d446bcce93e9262ebb91423bd1d70b44be80c80101fdfe6dc4cfce080bf921582e
+
+Count = 286
+Adata = 56de0e55653b9a04a3ded71c31f8807c3c8dd96bc82892e4acccef30
+Payload = 4890404bc5b24822b4cf7a2fe28abc52fbefb919ae0629ec
+CT = 5d6457cb597e81c0ce5f72d0021d3e7c2b99612404fa1ea0122dfc20e3088dcd33b6706a0c1fdfa8
+
+Count = 287
+Adata = 794a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b425
+Payload = 161f8501f59338f72026815c77cad6d8d581859192cd5644
+CT = 03eb9281695ff1155ab689a3975d54f605f75dac3831610828f0a78ce798448529afe26eec875aa6
+
+Count = 288
+Adata = b1eafc03ea2fa3e9e3842a09a225e83055de8a1f412badd6fc9ead12
+Payload = b3f38aedbf08dd7ead9d402c5aaa1ec9279c7e4bfd4a2967
+CT = a6079d6d23c4149cd70d48d3ba3d9ce7f7eaa67657b61e2ba48856a266c0d404474316f418f8f4e4
+
+Count = 289
+Adata = 8fec99f1be0e69267620c0b934bf984d60c1437f74c6ac19610fe188
+Payload = 5c09e2a6a055fe9c21e06e5519cf56b8e2e7fb44094e79f9
+CT = 49fdf5263c99377e5b7066aaf958d49632912379a3b24eb56412292d8015285efaa6f1154580eb57
+
+[Alen = 29]
+
+Key = 9a5a9560baed3b8e0e90b92655d4e5f33889e5d7253d9f6c
+Nonce = c0049382cdd8646756d4e6bff5
+
+Count = 290
+Adata = c95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe3
+Payload = 5bbe9c1fb2563e3e82999fe097b28da4dc6ff2e020f3b4f3
+CT = 6d5401db42b5c48b79203b6ad82806d7460ac4c82ad0809b811020480e834f6fe55900a162a4e61a
+
+Count = 291
+Adata = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193dfa755a5943
+Payload = 8a85a9b32a323c6af156a3fa2f1448b6387cc3660aa8a0f4
+CT = bc6f3477dad1c6df0aef0770608ec3c5a219f54e008b949cba9827513c7f1de970d316b6f81c109d
+
+Count = 292
+Adata = c834096e059ea73ddc90b0c982f9a3a31bfc6b1b81a03f9d41c9c741e7
+Payload = 1e02c13104937fe084b18eba1ea8951dcc5e75b692937dea
+CT = 28e85cf5f47085557f082a3051321e6e563b439e98b04982c9d79dd3255a8323f8229ac1c6d76ae4
+
+Count = 293
+Adata = 9249022bdead3d86ef5bd03acf053132d08663ba1f2426e19c126b22e9
+Payload = 3225570fb15ae13a13c71e364ae9a9fef03d1c9a7fa5dfa0
+CT = 04cfcacb41b91b8fe87ebabc0573228d6a582ab27586ebc8425dc81f93257ae8399fc2d48b4a7685
+
+Count = 294
+Adata = 3c3a92c4ece49fb9f84243d7c1bc91f595fce118305a758c83985c34b4
+Payload = fa0a458174537ddba25708b8d0c22d5517d57b122517b0c9
+CT = cce0d84584b0876e59eeac329f58a6268db04d3a2f3484a1b595003c58e69600c2a3b9ec45c0e15a
+
+Count = 295
+Adata = b49b845ccf76acf508f9db8543c73375d530d91f3b0e4ed70decfd2c2d
+Payload = b7fbdaeaa3ee1d0bbf5ec47898b069ec4ba6a140a3e83996
+CT = 8111472e530de7be44e760f2d72ae29fd1c39768a9cb0dfe0da009261c43c6640303696655e2981f
+
+Count = 296
+Adata = 3aabdf589eeb1709bb3d60b08bc71eaa3ffeba4e2903a5dbd8339aae85
+Payload = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7e
+CT = ac001b7d0b3a47f0ff578aaf4ad3c9c0a759edf04836ef16dfdcdbd4ad711c493d3176f032a02af0
+
+Count = 297
+Adata = 6a79879cd62bd1dbf9609897d2ebf2dc4dda43cc15fcb241aaa0deb4b3
+Payload = 3a861638ccd6591e51e2a525be59447e4a28bab32e36a5f3
+CT = 0c6c8bfc3c35a3abaa5b01aff1c3cf0dd04d8c9b2415919bfd59b45c05873c670f5f8bb47732d59f
+
+Count = 298
+Adata = c5b6ca474eb251817ae4d2f47c0632c381e222aae3b6f585a0dcae120a
+Payload = c7da4e9ba6e5758be726e6e227d7bddb0332228f7e3ecb6b
+CT = f130d35f56068f3e1c9f4268684d36a8995714a7741dff031572a24bc00b40a6b4b172b3648142e7
+
+Count = 299
+Adata = 64a96d191f1d5f95f5fed6259e33e7206adc07b0279e16cb453a9c6438
+Payload = 2b9347d3e195152dce22afdb92acd179eb484872285704c3
+CT = 1d79da171176ef98359b0b51dd365a0a712d7e5a227430ab828bc33396179ac39ce0027a1d62e0fe
+
+[Alen = 30]
+
+Key = 3e61094c80df0053e86d43fccf4e1d3ee2cdb862d3237b0a
+Nonce = 63f00b2488809fdc49ca5f05d5
+
+Count = 300
+Adata = a08763ca936abdeece06467bef8c3c47c3a473636a039d4db540c867d3e3
+Payload = 1fada8f4c7daea0d1c370184c169485b80a278708ed41451
+CT = 680dd22f16a1290bde42c9792dfa997aed24d5bd2265b6e095aa6b99d3f894d3790c2aa2dae1ba2c
+
+Count = 301
+Adata = 19508a6c83b992c660a1a28597e07c729ea2ed39401aadbf9d7586b5720d
+Payload = e9f1f2cf0b8d563e2d20f39f9f464a808b136dba364a6446
+CT = 9e518814daf69538ef553b6273d59ba1e695c0779afbc6f72d9d77109f4597e9c4c8cf7023dc5f3b
+
+Count = 302
+Adata = e5929c3b5d68a4c9fcf1168ea35bf8c0bf3043cb1ed54ff301578b3b7266
+Payload = 07a74c3b874849ecbf013713b80a84337c90b690cea0b837
+CT = 700736e056338aea7d74ffee5499551211161b5d62111a86b2544ecc3c7d5accd22ac075e7b44d5a
+
+Count = 303
+Adata = caa5cc5d0d87680eafc29429bac55c9e33167d485789c7c124b5c57a1ba8
+Payload = 4255f2cf90f0d15e9bead4be799165c57f7225980713d609
+CT = 35f58814418b1258599f1c439502b4e412f48855aba274b8f1a8a1db25de0fab7cabb11a18497584
+
+Count = 304
+Adata = f61cf7ae23a66777bd3fabc3d542feed2b00c6d4f46a772fda11b5214551
+Payload = 70b1e2e4cf260b108f5a52d0d8234838ffd6ffe7b4acd78d
+CT = 0711983f1e5dc8164d2f9a2d34b099199250522a181d753c5a9718ed0257a50e38de86154054fc3a
+
+Count = 305
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb993e86f4
+Payload = af4be10b3a59ea99dadc75fbe5651f6f7630852bb556aa39
+CT = d8eb9bd0eb22299f18a9bd0609f6ce4e1bb628e619e70888550d1acca34c28ba8a3b890bb0542b23
+
+Count = 306
+Adata = 296cd04c4d9ab493def7aeb6841a45309e777028868efe45166235c56b2d
+Payload = 72d5663727592f1bfc9c65be83f4d3508126fecc4e34ae72
+CT = 05751cecf622ec1d3ee9ad436f670271eca05301e2850cc3a268dc1596a7855639c63fa76ad8479b
+
+Count = 307
+Adata = f380ca0a26a94adcf2c1ce26d226d3bf520268c72412e58a71acd9a66d00
+Payload = 3e2ccce03c10ce1527ef8e002adb265edba5779fbd4fcaf6
+CT = 498cb63bed6b0d13e59a46fdc648f77fb623da5211fe6847e3416c75fc28924a21cc123e62a7894c
+
+Count = 308
+Adata = 8825532a31680cb3b5bdb027802d2d8718755e135367e0c8c88e21288311
+Payload = a18dfe7f2d7bbaf316366f67445170afcbe18e2a1de1e947
+CT = d62d84a4fc0079f5d443a79aa8c2a18ea66723e7b1504bf6ff1a47f23d08485951aab18b393584ef
+
+Count = 309
+Adata = f768375589b687fb17c56673af4263626da69eb991007d94d4f5a163fd05
+Payload = 17ca72a440c944fefd6c08ecc3a8ecb54d96b9cad9d2aa4c
+CT = 606a087f91b287f83f19c0112f3b3d9420101407756308fd7d024456bcb69a4f77008773a3f48805
+
+[Alen = 31]
+
+Key = b5664dd6ed435df006052f6ded74bb7ce9482ca9229886f7
+Nonce = 7a1649896f3e030c18f0205599
+
+Count = 310
+Adata = c5f1a26351e53e6509c8bbbed03c42c23ad81c65fccec7ffa1cb494c7f1fc4
+Payload = 0b6de49b530703affc94010c2b793ddc6de0c44d48037ff2
+CT = 56b02fea595cc24e798691ae905be3d466ca68ca744005dba260b5ea3b047020b73b5bafa17e5084
+
+Count = 311
+Adata = 89899be18b4c389afa769b11ecd22e9fad8f38fd614ea5f8eb7a066c0ed8d8
+Payload = 2f1821aa57e5278ffd33c17d46615b77363149dbc9847041
+CT = 72c5eadb5dbee66e782151dffd43857f3d1be55cf5c70a685e4bd97b9dc83134867c00c2acea0aaf
+
+Count = 312
+Adata = d43b841f174335f1347834590b0984a2cb35f7a00a0ee993157d2d4f848748
+Payload = c7da4e95cb38342c6d5bf0c381d5a192adc3bfc1cda3a1d7
+CT = 9a0785e4c163f5cde84960613af77f9aa6e91346f1e0dbfe55202ba34bb9918fe915776de65947c0
+
+Count = 313
+Adata = c1093518efd80245e3c42371f220b21f2034e6738fe02ef43e828190f01aef
+Payload = 414a70aba5a219dbd41cdc46b84812b28cc4f7399218004d
+CT = 1c97bbdaaff9d83a510e4ce4036accba87ee5bbeae5b7a642fdf807b5a6880f2d4c36d558b40eb90
+
+Count = 314
+Adata = 90f627d5b939625bc76fe1bd4643b39edc11d3dc7f4bfe16e61bc26c3d49d8
+Payload = 58b260d3f645a35bad7a3842440bc03608248bd46e725e60
+CT = 056faba2fc1e62ba2868a8e0ff291e3e030e2753523124495a9307ca4239380a45bb7f87e41c4cf7
+
+Count = 315
+Adata = 2f360a4715074e942244ab7f9b6db127b0442df9af2efa2e78db1a94312905
+Payload = 5505caa97218957e90247fde60275bdafce4b16bcb36c263
+CT = 08d801d87843549f1536ef7cdb0585d2f7ce1decf775b84af3aeadff9dd60468aef2a8e2c56dda7d
+
+Count = 316
+Adata = 7db564811f14bc5c2098d5635655c3671fbd8288ea14944af925eaec653408
+Payload = b93e40f556a786e39126b8834a6ecacd2dc9f0f528bab135
+CT = e4e38b845cfc470214342821f14c14c526e35c7214f9cb1c8335f2e31a0468b830c5009cd02dbd5f
+
+Count = 317
+Adata = 36be91854d3d02a5d62503bb9047ef4354280510f7576c4272fd757240b621
+Payload = 543a070fdb3a855dd7d83fbc5f983671ad9e905f307148e4
+CT = 09e7cc7ed16144bc52caaf1ee4bae879a6b43cd80c3232cd5d772a599e91504e022b9dbfb124b71a
+
+Count = 318
+Adata = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb8813ccc2f2dd96
+Payload = 86ef67572cb339c6706eb5909b96848aba5246a196972a1e
+CT = db32ac2626e8f827f57c253220b45a82b178ea26aad450379846cd12430f7adc910d1f0c51d80636
+
+Count = 319
+Adata = 3a64414c3588d7c26871d7d054ac6c8420d4917e3baad4a343685916265321
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 9313393a683cabb7a6ac4a4ab359450ddcc887c69d0ea8fcd9ee65ac3a8fae1b00a4f1dfe2577293
+
+[Alen = 32]
+
+Key = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+Nonce = 809343e986f6ff47f54d4cac22
+
+Count = 320
+Adata = d70aef3532bdc5293a3ebb11589ac1f801c9f93ea0d656e1d04068facf9f768b
+Payload = 718f061e8b972a3adcf465d66c5b28e8661f080127f6722f
+CT = bad3b0e6772e9c4c9c631c095e259d99692292932efb72b8966e91a19617bb748f3495aa433585bb
+
+Count = 321
+Adata = 1ee0eb409398bc252175cb460ef9a2da4c9beab2ef6d8206e4fcce74df785246
+Payload = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+CT = b9ba78455331962a0ee33b5956c2b80fbb55e0b52b1ab75dc8f70aa565a12ca3545e68110968040f
+
+Count = 322
+Adata = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698b0ed5c8cb09a8c96
+Payload = d959dd38a458039e2400d21d27b9a2faee8fe23683330cb5
+CT = 12056bc058e1b5e86497abc215c7178be1b278a48a3e0c22daf38076c810e14a7843444a02f010e0
+
+Count = 323
+Adata = f555216840a1f40b411d44128e567617e2694caf16216ea74c604a8d6ec01e72
+Payload = 337f12e8ebc0544b82fcdd3c4a0dab0e5e75c9f433a27d66
+CT = f823a4101779e23dc26ba4e378731e7f514853663aaf7df1594aebf9b8318877bdec2900a22df858
+
+Count = 324
+Adata = 2311a6fe1feeda3a1f16310d635496c0dd662024f0b0f1de79325e030cb850e5
+Payload = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb4
+CT = 8d60d302875518204538f90eccb4ec7651d51698b6ca2c231d9872d1c10a6594b5c349b84f710d64
+
+Count = 325
+Adata = b2c633e3181ae5fe7828707ed5b70e0460088a84465eadeecdbcfa0e9ff19bb1
+Payload = 23c1732959c4bf85bc707e45cc964b6227acd3a8fc73e675
+CT = e89dc5d1a57d09f3fce7079afee8fe132891493af57ee6e2a9db7c4bcaf6087e158c1a5d4eb1c2cc
+
+Count = 326
+Adata = 791f23252094b9b99fafe7fac1d8ff3ba09305c476041e75afb245ac438b4069
+Payload = 02f60f967e7fbcf957313619882407ea8a03fc943062296c
+CT = c9aab96e82c60a8f17a64fc6ba5ab29b853e6606396f29fb5e1c87d9e1c1f3b7d30fdc2f0ccac783
+
+Count = 327
+Adata = 22197f9ad14591e7a6d5f8b18c969a553de9a85309757fa5d319cc505c24f438
+Payload = 6c1aa088d1a6086d0e72636744a6840c80ab8223409c61b7
+CT = a74616702d1fbe1b4ee51ab876d8317d8f9618b1499161201514b449a741e07f9287f7e9090fa54b
+
+Count = 328
+Adata = 0bb18f7280a30767cd769cb5ffd3edd1c18914b92d1b2192e27ac88f57135616
+Payload = 57275bc3b4d63b9b01b0b0760235c9785d45761cace23f1e
+CT = 9c7bed3b486f8ded4127c9a9304b7c095278ec8ea5ef3f892c889b610157e16e9f31558c669298a7
+
+Count = 329
+Adata = 3e5f0f32e27be18ca6f84de11e6e9c25fc0c4cb0cf83633eea1f033aa1373f3c
+Payload = eba27a27f0d4604a5296a41b3fe995c50c66bcba302d0447
+CT = 20feccdf0c6dd63c1201ddc40d9720b4035b2628392004d0fbe19321dc22c748a17aa5eda29d8cf3
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT256.rsp b/lib/crypto/test/crypto_SUITE_data/VADT256.rsp
new file mode 100644
index 0000000000..af4f5c1df7
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT256.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886df3ba3e6da3a1389
+Nonce = 72a60f345a1978fb40f28a2fa4
+
+Count = 0
+Adata = 00
+Payload = 30d56ff2a25b83fee791110fcaea48e41db7c7f098a81000
+CT = 55f068c0bbba8b598013dd1841fd740fda2902322148ab5e935753e601b79db4ae730b6ae3500731
+
+Count = 1
+Adata = 00
+Payload = e44b4307234281209bd41f89dbe2cc3fbf68e14df2f7fce4
+CT = 816e44353aa38987fc56d39e50f5f0d478f6248f4b1747ba003abc6a4b020625adc8b6cd7bafbd42
+
+Count = 2
+Adata = 00
+Payload = 8db7a73856bcb4007346bb3e00096f69e75e97c0bb960f3b
+CT = e892a00a4f5dbca714c477298b1e538220c052020276b465e7cfa7a208a8b3e6b6377236045df17d
+
+Count = 3
+Adata = 00
+Payload = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e676d44
+CT = 2dd6c9e8563298008cba3be237c67ffb68f59f97c787d61a81b39a0c55822e32042b4f8981021090
+
+Count = 4
+Adata = 00
+Payload = 7cdb2c9b167b3ae811289acf7dc1814bbe241f553447699f
+CT = 19fe2ba90f9a324f76aa56d8f6d6bda079bada978da7d2c1091117e2ad77db510d902038743b5a98
+
+Count = 5
+Adata = 00
+Payload = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eeb
+CT = 24cfc842c9bb65abbc5ff4e61cb2156c19663821c6d395b5ac7379b8e51592b98e4874f4592278a8
+
+Count = 6
+Adata = 00
+Payload = bde9e3eb9f0c57302c9185b1cb912ef76d88f2f9c3b51e9a
+CT = d8cce4d986ed5f974b1349a64086121caa16373b7a55a5c4d08c1c902c4c2f078452dd6943b85028
+
+Count = 7
+Adata = 00
+Payload = 6f9ccc033c6bfbdfad4719ad033c927e2175727a9a021dc6
+CT = 0ab9cb31258af378cac5d5ba882bae95e6ebb7b823e2a69832fefb87445f1ca42811899acc0cdf68
+
+Count = 8
+Adata = 00
+Payload = cc67bc3b7afd625b2610226d3b30e111e6aa47a3254f711a
+CT = a942bb09631c6afc4192ee7ab027ddfa213482619cafca4481d605a1019c8e9778b8928b4636053e
+
+Count = 9
+Adata = 00
+Payload = a10c81725f49ab9075fbf4d96be030a2d881d8501b115d61
+CT = c429864046a8a337127938cee0f70c491f1f1d92a2f1e63f96a82e8411e5b04426dc608298c6408d
+
+[Alen = 1]
+
+Key = a4490ed6ab51dbfccd6f3702a857575dad44da3a27eaf31178abc97da60d1e4b
+Nonce = 26ceaf6e3b28190a17c4f0c378
+
+Count = 10
+Adata = 9e
+Payload = 1b5cc6b1651dec4bbbf5130343852e971c7ff1774100d9be
+CT = 789bce069a725a96c484e64a9e54dcb7a7c268c85df47815a462ff2dd8ba44a381e1f6edab12b5a9
+
+Count = 11
+Adata = 4e
+Payload = e7ab98901c0cb1d7d76e125d8ac8e86edf6f469fa937bc10
+CT = 846c9027e363070aa81fe71457191a4e64d2df20b5c31dbb6b0789c5866b7e3312ad992e228d6d20
+
+Count = 12
+Adata = cc
+Payload = 53bc7e3648d0b389b887b065e9e8f79685beb2eb36e2eb95
+CT = 307b7681b7bf0554c7f6452c343905b63e032b542a164a3e39b1b1a480fdd268c1c75b131cde798b
+
+Count = 13
+Adata = 45
+Payload = 6d7262476da95db63b322c5193ea05030923c3cbf0f8e8b1
+CT = 0eb56af092c6eb6b4443d9184e3bf723b29e5a74ec0c491a32060fea35c3e9528fd18994fae9fce8
+
+Count = 14
+Adata = 2c
+Payload = 8246bf7b81b287411777df7ecb53a1795e54b150ff3dd584
+CT = e181b7cc7edd319c68062a3716825359e5e928efe3c9742fb4e0a604ab30a764e8c98a9cafbca8d4
+
+Count = 15
+Adata = a9
+Payload = 2596ca8772bc69b50bcbf33088c6efbab614b691ed836f92
+CT = 4651c2308dd3df6874ba067955171d9a0da92f2ef177ce397ca72f1acf6dfd078b6f4eb82fa01e9b
+
+Count = 16
+Adata = 85
+Payload = 703065d701f4fcadee20d64300b3082c0c76490eb2dc4ba7
+CT = 13f76d60fe9b4a709151230add62fa0cb7cbd0b1ae28ea0c2a85c9252ee62612dc29cffa7289b2ca
+
+Count = 17
+Adata = dc
+Payload = a1aeda4b4cb8dd2943675181561bac48ba07e8de5b327837
+CT = c269d2fcb3d76bf43c16a4c88bca5e6801ba716147c6d99c9fbdac729413152c089d3939e30b8602
+
+Count = 18
+Adata = ce
+Payload = aa17341f4cead054d41c171dd34c459f7052da225c6c365d
+CT = c9d03ca8b3856689ab6de2540e9db7bfcbef439d409897f6f86266c273f8184e901b50c04845b8ab
+
+Count = 19
+Adata = a6
+Payload = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f
+CT = 274bd52b4497d536191e2f7f65f40159339a43830fbdc0b4ddd02d5c9ae2bbac47a7a076edb1d207
+
+[Alen = 2]
+
+Key = df594db94ef8eca56a417afe946085eaed444c7cc648d07d58132e6cb5bc2bc3
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+
+Count = 20
+Adata = c0c3
+Payload = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259
+CT = bea778540a90033b2c0d087e3cc447711ea25f7eea96855506ec97f23bd6ea97834f92f7263c3195
+
+Count = 21
+Adata = 34b9
+Payload = f6c043c70136585d012ae0df6f42b25584e374649d0116c5
+CT = bcb0ac1ca69079500eeb5d1a4b21c21820cb45216b0581c9f3230df0b52b5cb7ac907dcadcb662ca
+
+Count = 22
+Adata = d4ab
+Payload = dec0c896b04490816409da1783478ef2510231d0a28c5b39
+CT = 94b0274d17e2b18c6bc867d2a724febff52a00955488cc35a99c3165ce83102891ef3885088ed6eb
+
+Count = 23
+Adata = 2a3a
+Payload = cbfd94fc31785d30214271dab2264134805fee6e52aa0b5c
+CT = 818d7b2796de7c3d2e83cc1f964531792477df2ba4ae9c50c9d8078607994ae5dff0de6526fb53d1
+
+Count = 24
+Adata = 4eb1
+Payload = 134d2d9726400d09dd3521326f96fbef993ddc0c40887700
+CT = 593dc24c81e62c04d2f49cf74bf58ba23d15ed49b68ce00c7e84da7d2564533e7ad55390ec3a6ff9
+
+Count = 25
+Adata = 0a79
+Payload = 1ccdcf789d42caba80d7893feaf26d3853fbcaf7d964df0b
+CT = 56bd20a33ae4ebb78f1634face911d75f7d3fbb22f604807520849295a56191367a696999ffef8e9
+
+Count = 26
+Adata = 865f
+Payload = 4042dbe148db3e6dc542b25d57a5787af535d38e8c34c71b
+CT = 0a32343aef7d1f60ca830f9873c60837511de2cb7a305017bc4aceed1a10309b6402b9e9420b33a3
+
+Count = 27
+Adata = f4ae
+Payload = 85b6894fec36294aa934cdc3523fd95c90ad56cbd18545dd
+CT = cfc666944b900847a6f57006765ca9113485678e2781d2d176c180d2e299ccf0b8781ba6de8a72ce
+
+Count = 28
+Adata = 10bf
+Payload = 0f27f4fc8538a676a763b3e5db845a1bfb20d5fab340dee3
+CT = 45571b27229e877ba8a20e20ffe72a565f08e4bf454449ef98d91c68d94873a5d6557611a5402a0a
+
+Count = 29
+Adata = b92e
+Payload = 1b5ec0cb03810a12fc6a0a1ff565afb001405d2a45a1f18a
+CT = 512e2f10a4272b1ff3abb7dad106dffda5686c6fb3a566865321cedf1122354636e130acbd69718b
+
+[Alen = 3]
+
+Key = d98193ab2a465e3fcd85651aaeca18b8e91489b73b7c7e93b518c4b5b81fc6ac
+Nonce = 2247dc7e2674e9e0a63fe70613
+
+Count = 30
+Adata = 4dc2f4
+Payload = edba7d6312144e90ec9eaace7576045a46e553dcb8ee5a98
+CT = 44b9ea727c847336fd739ad11f4b906b292edb810462f06ef59626ad5cdac2e4d4cb07b538a1fd8f
+
+Count = 31
+Adata = 2f3bf0
+Payload = 52a9626f5279c11e17e96f5dc5e1c1f58c1e913020d8499b
+CT = fbaaf57e3ce9fcb806045f42afdc55c4e3d5196d9c54e36ded0d53402253453e494ad350994ca77a
+
+Count = 32
+Adata = 95d2cf
+Payload = 87b6447d97a74d0b315031078aa06fffc7b9f246bfa5f147
+CT = 2eb5d36cf93770ad20bd0118e09dfbcea8727a1b03295bb196dbc3bff865a1d94b164df23d708e8e
+
+Count = 33
+Adata = 0caba9
+Payload = 1852848046706f2e274ba381a2bee1422df4f61d93219af7
+CT = b151139128e0528836a6939ec8837573423f7e402fad3001791b4469fe50d45f8efb81217cd68580
+
+Count = 34
+Adata = f8d459
+Payload = 99aac82fa66a15e4f76b76cf4590150999d5cf8468df7f42
+CT = 30a95f3ec8fa2842e68646d02fad8138f61e47d9d453d5b4587106da25012f92f01cc2db8d11ac29
+
+Count = 35
+Adata = e883dd
+Payload = 4e2f0f91990b855a00d27fbb2e8db7184cd82909de361b52
+CT = e72c9880f79bb8fc113f4fa444b023292313a15462bab1a464148536847290e4fdda7966fe6d5e3b
+
+Count = 36
+Adata = e45da4
+Payload = e558be3fd246170b294d18ffa708842242681890baf8bed9
+CT = 4c5b292ebcd62aad38a028e0cd3510132da390cd0674142fcc4cb33472825363940e2b26424b7802
+
+Count = 37
+Adata = 3b6fc8
+Payload = f8b284c2d851289275973fcd807fac5d8e5e3b6a75ba2ace
+CT = 51b113d3b6c11534647a0fd2ea42386ce195b337c9368038a99dd8dbe89b3ecf663eda1b0f92be7f
+
+Count = 38
+Adata = 043d68
+Payload = 8edf1eb90f0ad33be8a7c6446899e06addc10b3badc4ea25
+CT = 27dc89a8619aee9df94af65b02a4745bb20a8366114840d3dc4894c8fa0a1e1aa760acf9360042f5
+
+Count = 39
+Adata = e89257
+Payload = 8fe9a6bd82462c97f436d382d1ff971c95406b1a6c847d81
+CT = 26ea31acecd61131e5dbe39dbbc2032dfa8be347d008d777cdad1590fd8bf2d7ea919e60d0316566
+
+[Alen = 4]
+
+Key = 45c8afd7373cb0f6b092af3a633d9fd97c4ca378e19d75f9b74d089429726c29
+Nonce = fdb1fa230ae0b172ff98fc7496
+
+Count = 40
+Adata = 270981af
+Payload = 0b92adbb251dc29a67f0bb97f8e7160862b6c4e843d07fd9
+CT = 274e2faea3271ea6fa0494c1951f115b5491a893056c3ee4c76fc350e585277e373e9119bf9595cb
+
+Count = 41
+Adata = 633f3efa
+Payload = 1f88dfd4f5c52c22b1db47f9f4fb6e2f8bcd78d593061369
+CT = 33545dc173fff01e2c2f68af9903697cbdea14aed5ba52540fa7e55dc54e80488a05ee7f1fc96e9d
+
+Count = 42
+Adata = aad86fb5
+Payload = b2b4cb5e90ebf4bd265093b7f5efd4d62dc60e29737aa496
+CT = 9e68494b16d12881bba4bce19817d3851be1625235c6e5ab18151c17d9e3f97244000a3b2d3c2f95
+
+Count = 43
+Adata = ed42941a
+Payload = f312b47d05f8eb5a29943b41347cb1983c75cb7a458a3868
+CT = dfce366883c23766b46014175984b6cb0a52a7010336795562d521c4b5c7a6f2c5ac65f2fd15b066
+
+Count = 44
+Adata = e5b085d8
+Payload = e9fb86938ea7f04cc230296859e7c96fcc352f968c9473e4
+CT = c5270486089d2c705fc4063e341fce3cfa1243edca2832d9e491a31218f688744098851672a09a64
+
+Count = 45
+Adata = 3776f37f
+Payload = 8af6b7540f997954812e38dbd99ccfaedd5c69963c353a4e
+CT = a62a354189a3a5681cda178db464c8fdeb7b05ed7a897b730ece28347d7ebf8291d7eb66b7651b4e
+
+Count = 46
+Adata = 4eb08c9e
+Payload = b90cfd9dd58e320d98510483b1d939bdb5f3b81666ecee59
+CT = 95d07f8853b4ee3105a52bd5dc213eee83d4d46d2050af64cbd25fb40480d15c039878b5d2f25afb
+
+Count = 47
+Adata = c7f93152
+Payload = 02caabc6ed0641681e7148c10cf3159fe35e44013252071e
+CT = 2e1629d36b3c9d5483856797610b12ccd579287a74ee4623fbfd98c8567b78d4b9c3a49a4641908e
+
+Count = 48
+Adata = 57957630
+Payload = 2f29882fdf1418d04f0b9d44272995a56973c4369c687a99
+CT = 03f50a3a592ec4ecd2ffb2124ad192f65f54a84ddad43ba4655c1abcb3ed1a175f12721a407c5d00
+
+Count = 49
+Adata = 19da955d
+Payload = 4e427130be9e94639320529ec135715e65da1117b5ba3c76
+CT = 629ef32538a4485f0ed47dc8accd760d53fd7d6cf3067d4b90621a5e5683df421a0dc52341485d1b
+
+[Alen = 5]
+
+Key = a2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd
+Nonce = 693cbb46bc8366086ec7cd7776
+
+Count = 50
+Adata = 3ba11282d6
+Payload = d822f84b023f12ea9e3ce16b904278e4aaab5e11c2c23f3f
+CT = 9f91fd2f6472e33b02b1eabb9d6655729d44c44dad6b3883fe0667bcc5806b225224b04ade8b21c1
+
+Count = 51
+Adata = 3f3a4718ea
+Payload = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12
+CT = e834b623d3d3c675b88d41d09d59e6595dbad43bed00b9aea6750fffa5a487540ce65770cd836e99
+
+Count = 52
+Adata = ff79ca8965
+Payload = 82b7cd168b6a82cb2d837f41ceda0c27adc5f5b28030454b
+CT = c504c872ed27731ab10e7491c3fe21b19a2a6feeef9942f7e7cfafe32bd71ea9813607c5df446c9d
+
+Count = 53
+Adata = 0021be18ed
+Payload = 1c1a0f144df76781e7c85ab178ed9b1ce8c6dc3f15c59149
+CT = 5ba90a702bba96507b45516175c9b68adf2946637a6c96f576716fe674c33ad3b9d3e54cc86bfccf
+
+Count = 54
+Adata = 9ae7996547
+Payload = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841
+CT = 9e0874c9f658dc8d867e53185d3b85088aa48de3205d3ffdab55dbee34f1bab555bbb196095fb5fd
+
+Count = 55
+Adata = fa292d1958
+Payload = fc7d028a1aa05c74b7ffe333ba6f676913b0f9f1ffa050b8
+CT = bbce07ee7cedada52b72e8e3b74b4aff245f63ad9009570476a4e9e759d5bb79c187a157099e3d12
+
+Count = 56
+Adata = 88800df7b6
+Payload = c9ea772e61742a6706da3ab3e81df14b31506ae58b063ece
+CT = 8e59724a0739dbb69a573163e539dcdd06bff0b9e4af39729f0f3699c9743ad6c9f09dc00ea10487
+
+Count = 57
+Adata = 715041afd4
+Payload = 70d2b8d64121ceccf1961444e8d33b7b7f998aeb58d3d270
+CT = 3761bdb2276c3f1d6d1b1f94e5f716ed487610b7377ad5cc560d78cba6d9f50e9c2677a710f92155
+
+Count = 58
+Adata = 14682301a9
+Payload = 1013946815001a2c08acca4196e0d6668ffbb3883cf111e7
+CT = 57a0910c734debfd9421c1919bc4fbf0b81429d45358165b95ffb6e29172a283d47e4478e2e1f7c4
+
+Count = 59
+Adata = e44c3c21c1
+Payload = f40dc834067bd163e0004d0ec5dd4b96e2a1ea31ea431c98
+CT = b3becd50603620b27c8d46dec8f96600d54e706d85ea1b24ccf233caf0bad9f68f71d78ee58512ec
+
+[Alen = 6]
+
+Key = c5a850167a5bfdf56636ce9e56e2952855504e35cc4f5d24ee5e168853be82d8
+Nonce = c45b165477e8bfa9ca3a1cd3ca
+
+Count = 60
+Adata = 4759557e9bab
+Payload = e758796d7db73bccb1697c42df691ac57974b40ca9186a43
+CT = 93ad58bd5f4f77ac4f92b0ae16c62489e4074c7f152e2ed8a88179e0d32f4928eff13b4ce2873338
+
+Count = 61
+Adata = 2ea07d393a0a
+Payload = ce60ddbe40b70bd55a9147036ad079dec1558ef4c2c625b3
+CT = ba95fc6e624f47b5a46a8befa37f47925c2676877ef06128b7d812c4d69f1f53ee9158382e56625b
+
+Count = 62
+Adata = aa6667faedc1
+Payload = 89eb3056770a6157f06921bc153834447c4b6d862d10d185
+CT = fd1e118655f22d370e92ed50dc970a08e13895f59126951e26fdbed62b228db008a1b14bd7942e12
+
+Count = 63
+Adata = 9e2127d92311
+Payload = 132f3e19e12f462a7463226b716c41a05a59c76f0e1a2f72
+CT = 67da1fc9c3d70a4a8a98ee87b8c37fecc72a3f1cb22c6be9124e1eb78de01b8af83b684baf3e43ad
+
+Count = 64
+Adata = 2f191bc9cff6
+Payload = b8611cbb9a3667b9458ca57eb636eb1dc580e7dbb5701692
+CT = cc943d6bb8ce2bd9bb7769927f99d55158f31fa809465209cb0f79736d1a810d06a776094f9fb67f
+
+Count = 65
+Adata = ad739d5f4736
+Payload = 112f89ccbdadc2433008d3ede2290f9ce81e5c736abf42a8
+CT = 65daa81c9f558e23cef31f012b8631d0756da400d6890633bfba2348f629471c232c9ff7e5f6f85a
+
+Count = 66
+Adata = 01acc909b7d3
+Payload = d47f2ff745de39a9055ad002de6334971fde480bef268b33
+CT = a08a0e27672675c9fba11cee17cc0adb82adb0785310cfa8c0f694d03ffed043787343827ea2603f
+
+Count = 67
+Adata = ce003c836a6f
+Payload = 13be365884b8a91a284ca24f70011e48794b51be275153b9
+CT = 674b1788a640e57ad6b76ea3b9ae2004e438a9cd9b671722279b553998a6fee0a86e177a448573a4
+
+Count = 68
+Adata = 6a759a4efd00
+Payload = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e
+CT = a13d5db4b781965f9dd065b0790f42dedde61cce68d673f54eeb434cca3ea719827417e94d6ed564
+
+Count = 69
+Adata = 02b84a26c773
+Payload = b7bc1580c68fd5d06c1bf75c31dad7a3e26d636d7eee20b9
+CT = c3493450e47799b092e03bb0f875e9ef7f1e9b1ec2d86422a74b5e4e2edb91fbbe722bfaf1500db4
+
+[Alen = 7]
+
+Key = ae8f93c3efe38e2af07e256961dd33028faa0716e5320a7ab319a10d2f4c5548
+Nonce = 6333bde218b784ccd8370492f7
+
+Count = 70
+Adata = 0b1fabdf2a4107
+Payload = bc9ca92a9c9919e39095d3e53fb148694620ae61227e0069
+CT = 45811b0c8f754bf03950e520cd4afc81c2e3eb8a11f4fd386d5a6e4b1fbee15d35939c721004502e
+
+Count = 71
+Adata = 2fc7f5c0ce052f
+Payload = f25a4ca20bbf4969bed6b93c1c77e3d7415f60fe3784216b
+CT = 0b47fe8418531b7a17138ff9ee8c573fc59c2515040edc3a24a68f98716190fb55f743a8bf62a085
+
+Count = 72
+Adata = 8a74412da3034b
+Payload = 3237bf953989d17c65a0fafd2bb1e32c237f98f55389e8f8
+CT = cb2a0db32a65836fcc65cc38d94a57c4a7bcdd1e600315a923afef7b4955d7d1e8f1abef9933bf9f
+
+Count = 73
+Adata = 7139f3c1d6cc36
+Payload = 55d86dc0423cfc2616ef996a3316e776707f8d25c985884a
+CT = acc5dfe651d0ae35bf2aafafc1ed539ef4bcc8cefa0f751b8e824c62632dff5cbc103d3060fbd174
+
+Count = 74
+Adata = af7a380f079aa1
+Payload = ac48398adb10292314973946f261ec39397442ca09b98dd8
+CT = 55558bacc8fc7b30bd520f83009a58d1bdb707213a33708980202d518ca871c9544f4a8c55fd8d20
+
+Count = 75
+Adata = e602abe8f72964
+Payload = 2fb78654e4395df8c37f260d74def234a3a4e3d2b1fe8614
+CT = d6aa3472f7d50feb6aba10c8862546dc2767a63982747b454b33ea6e4344033f74f513d1e41b82ae
+
+Count = 76
+Adata = 82741c5fd6e1df
+Payload = d488bdda400932de56a9f105f0e74ee79c2ed869faaadc31
+CT = 2d950ffc53e560cdff6cc7c0021cfa0f18ed9d82c920216073ccf18c7ea7dce79d0be1204c593234
+
+Count = 77
+Adata = 78f0cc22535402
+Payload = b22aba8d3e9f4b4bf006e26062de15daf94597731a600912
+CT = 4b3708ab2d73195859c3d4a59025a1327d86d29829eaf443b81b8af57b85093778690266e20e2fbb
+
+Count = 78
+Adata = 18e468139dd16f
+Payload = bd864f7b8efd6ed2b068f425482d449bf53a203ea88e1ca1
+CT = 449bfd5d9d113cc119adc2e0bad6f07371f965d59b04e1f09b94a857e7a0423ef6c9cbebde1f9c40
+
+Count = 79
+Adata = a6dab47c0fbfe1
+Payload = 47d9d18b6addc5f88986f0457b666faae59aba4fa3a02abb
+CT = bec463ad793197eb2043c680899ddb426159ffa4902ad7ea64718820065a739fbd3ba560a416895c
+
+[Alen = 8]
+
+Key = 548c2d1eb7d91e003633d4d9ff199e4a8447180edd89ac7867d25a1db288b5ce
+Nonce = 23b205bd6ff8ed0bab0c98999c
+
+Count = 80
+Adata = a6601111cd92c943
+Payload = 49fd5cbe4aff89dc3b8718f9ce545d612cbbebb289ecbf42
+CT = 3cfc6211e359ae322802fc9566f377b0dfe17d1dfe0878ebf2a9047e37cc0be1fab0006af8db8dc4
+
+Count = 81
+Adata = 96f0b7cd7439721d
+Payload = 94a95e945f660d1571b4d7d22709b000b45ff98b2129a4ae
+CT = e1a8603bf6c02afb623133be8fae9ad147056f2456cd6307106a430b04938e97f2e4cda81108ad3e
+
+Count = 82
+Adata = 2ee135dc2ddd9501
+Payload = aeed3aea01755c912213c8c276a2b75dad24f888a611efa3
+CT = dbec0445a8d37b7f31962caede059d8c5e7e6e27d1f5280ab2ab219c6c4952d52505cd9f904b0e04
+
+Count = 83
+Adata = 10c361934fd6ff77
+Payload = be1fcebea4c22a1d71e08047b028d7f4ccab0a6b8085d344
+CT = cb1ef0110d640df36265642b188ffd253ff19cc4f76114edfc1f7b2fe314faea28ab0dae349feb9c
+
+Count = 84
+Adata = 3f6c8a69917f7776
+Payload = 87680ac26fe1511e0f1f745aa4c2a5b9f6c0117dcf08feaa
+CT = f269346dc64776f01c9a90360c658f68059a87d2b8ec390308e529d64e786a29661cccddc0366f3b
+
+Count = 85
+Adata = 0f7a1426ff3b5ee1
+Payload = 9e004b072a27b085e59ca201c157c7d3c906a2c3b455c56e
+CT = eb0175a88381976bf619466d69f0ed023a5c346cc3b102c797c6510b85dfd097f3eac276aff00ba2
+
+Count = 86
+Adata = faa5bed84dcf168e
+Payload = a1bf47b15cd66e43daff420edf014a14b11994b97ada4030
+CT = d4be791ef57049adc97aa66277a660c5424302160d3e87998e522b6f13f99ecb553b6de845940907
+
+Count = 87
+Adata = 2851dae3cb3fcb1c
+Payload = 2d15734871adc63ff32d7002ab40c4a235a4d5fad223953f
+CT = 58144de7d80be1d1e0a8946e03e7ee73c6fe4355a5c752967a9ca39566189ee96c86462bfea78af5
+
+Count = 88
+Adata = 35a29c1bcbe2182f
+Payload = 5a84c4fdd47510fb7aebc0f79d7b625ccd0a96575740b8e6
+CT = 2f85fa527dd33715696e249b35dc488d3e5000f820a47f4fa613b5fbbe73a2df6c630a00ff4b1b92
+
+Count = 89
+Adata = 45820ae66c3e8e77
+Payload = 2052a94e1392dc1db0e89be19ea8f7379ee4cb607a914c89
+CT = 555397e1ba34fbf3a36d7f8d360fdde66dbe5dcf0d758b20d19feb067e9f6225376da21b4899d296
+
+[Alen = 9]
+
+Key = aab793e377a12484dbdd74c9b3a85c74c286e1cc498663fbd7c718b5633bb91a
+Nonce = 10022cddb323e88b3c08f95a0f
+
+Count = 90
+Adata = 82b8c736037ce2f2e8
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1044250f58857c69f72b5d3454d43949e5c02b3822970b280de1a3f7fc5d06cc30f06075f5504ed7
+
+Count = 91
+Adata = 8f2777ec4930f7e349
+Payload = bd845561f099500a6ff3fd09964dc3820f7ab48ba4ed04d5
+CT = d1c8f9ebee44ff231485207e684b0e65a033db29b082ac45835840df6fa96f5c972ac09d94148cbc
+
+Count = 92
+Adata = 5cab3b846870709569
+Payload = a6e09404fe60badfc63dc228057485e6f563ba82acdabd7c
+CT = caac388ee0bd15f6bd4b1f5ffb7248015a2ad520b8b515ec2f83ef84b299cfdb61d2b5039d536c3f
+
+Count = 93
+Adata = 0938f2e2ebb64f8af8
+Payload = 33404d7e0e620c1030b91020e33619c5f53d8b210fa86489
+CT = 5f0ce1f410bfa3394bcfcd571d30d4225a74e4831bc7cc19db04e655cbe22b9ea508d2a03757b97c
+
+Count = 94
+Adata = 82f78ca0e0da2b2d3a
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb9f087a50bf50
+CT = 0d34c4248f2aaaefcef5688a80188d610ef2f0aa6e3f17c04bd88dc6985f819004c2b634c5303ed8
+
+Count = 95
+Adata = 401191aa3fd34abe87
+Payload = 949cdd7c2973d7519e7bca98b2c5947e6d8e91c90e632319
+CT = f8d071f637ae7878e50d17ef4cc35999c2c7fe6b1a0c8b894ff3572e4ebf78473760d8cb4b0366b4
+
+Count = 96
+Adata = 4df4377596d8987671
+Payload = f6720a0bd8705c70e0f923338965e810b3ea939bad652327
+CT = 9a3ea681c6adf3599b8ffe44776325f71ca3fc39b90a8bb7de95ec3eee17753e60fb3c0661bdd098
+
+Count = 97
+Adata = 6593194b9970545c5a
+Payload = de9b0556661e726f3e6e34515ff7196420fe61b4f38419f2
+CT = b2d7a9dc78c3dd464518e926a1f1d4838fb70e16e7ebb162b8590ff04f967e51fbd1be84f01b4dcb
+
+Count = 98
+Adata = ab2d432058b540ac72
+Payload = 6cad7f3b9f196839bbc5a7f755c09aa8e17c83d9cb8b3954
+CT = 00e1d3b181c4c710c0b37a80abc6574f4e35ec7bdfe491c471d67b75b2da855a12ffb24ddd64a048
+
+Count = 99
+Adata = 5dc631eeeacb5a0b0b
+Payload = 70a55aec1144357377612fd0bbc2c817f33465a656219957
+CT = 1ce9f6660f999a5a0c17f2a745c405f05c7d0a04424e31c71fc798dd16c1fadef607a9297cbfbfef
+
+[Alen = 10]
+
+Key = 06ac39896073a44283611a66ccab067e2dd2faa8da82ff9a45bb29e54d2e6e77
+Nonce = 6c7942c9819cf69b817bfcdb0a
+
+Count = 100
+Adata = 215e2a6c24325340fdec
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = c5b3b50ed8a7b7b96b02ba9464b6a2ff80e90548605699a63d70e6dffb31a376a1eb7f94526dca48
+
+Count = 101
+Adata = e0a29a2c7840cf9b41de
+Payload = 7e5e5710a693ebfa36335cf7965574740880acdddd13fb1a
+CT = 89fb3efdc685924d24d5e99c3824fe2091730366a49c136fcbf516608fe20e06bbff931e84683545
+
+Count = 102
+Adata = b8026fbada6339d84802
+Payload = 08c342a50aa23362622934dfab55d9b22c22c249ad08138c
+CT = ff662b486ab44ad570cf81b4052453e6b5d16df2d487fbf9d70eb14f3fa0229906b9e0360be3d3f9
+
+Count = 103
+Adata = 65f4b3a00c1c1ef39445
+Payload = e085aba85882c75d5e41559167731496cf17d3907894352a
+CT = 1720c2453894beea4ca7e0fac9029ec256e47c2b011bdd5f4184771199a427861bf17cd8401e794e
+
+Count = 104
+Adata = 96118dbfe53434d8aed8
+Payload = 710f890be2b8da77c1eff429ede9cc931d50f059748cbcb6
+CT = 86aae0e682aea3c0d3094142439846c784a35fe20d0354c34e20b2db52fde68f88bfb886fdcb2c47
+
+Count = 105
+Adata = cdf4b485d2e04709cf8f
+Payload = cda96efee4e188ab3048bc1904ac2c36ab018f2ab7602682
+CT = 3a0c071384f7f11c22ae0972aadda66232f22091ceefcef782ee3df38ddea8e269eb47e39900345e
+
+Count = 106
+Adata = 50e57e57cf8e49e3a4e6
+Payload = 3dc596d52e520779a50bcba3049388b340dbf6d0f2eb94cf
+CT = ca60ff384e447eceb7ed7ec8aae202e7d928596b8b647cba44aaac4ed86f687cfc031f22827725f1
+
+Count = 107
+Adata = 48c670f11ff7f74e7003
+Payload = a33105c0dccf8e3b687212a870af9f710462756705fe09b3
+CT = 54946c2dbcd9f78c7a94a7c3dede15259d91dadc7c71e1c6d75255006ac037d6a4d048f1fc338012
+
+Count = 108
+Adata = 465e3be6113a2fb2ee20
+Payload = 573ac2436158eb7dd9be981e3cfbe75d3a188ea9cf2b1ee2
+CT = a09fabae014e92cacb582d75928a6d09a3eb2112b6a4f6976c1da33a80bc8157cece1acf9400b2bb
+
+Count = 109
+Adata = ee4e10574faeae85e9b6
+Payload = ca35bdb54e73eac5a5200a296b3aba5f37c87349746102d4
+CT = 3d90d4582e659372b7c6bf42c54b300bae3bdcf20deeeaa165c1cb98da4a1a920ca1ed9a7b6ec514
+
+[Alen = 11]
+
+Key = 50412c6444bcf9829506ab019e98234af1541061557412740bc120b456052763
+Nonce = 85684f94c3702c5d870310166d
+
+Count = 110
+Adata = f706a3e09df95d3e21d2e0
+Payload = 6cdbd63f6d591f59776f828533b28e2453a214d1d0dd8a39
+CT = 8c8b4ae854a5d5c265b25e3b54bded9444cc454b3e0e6a24d6c05eaf406a5ebd578e19edd5227380
+
+Count = 111
+Adata = e46b25b9a41a858e87900a
+Payload = 100132c315bfc9c4fb93023f5d3500d7208a68acb4d2c630
+CT = f051ae142c43035fe94ede813a3a636737e439365a01262d5088446e42591c0ede68e82334d97cfa
+
+Count = 112
+Adata = 28d34b29afe6586fd9bf0e
+Payload = d5460c1db0d24dedc63c4c78ce6d1f0b2d46f3b01934525c
+CT = 351690ca892e8776d4e190c6a9627cbb3a28a22af7e7b2413eaaef2823f5ac3f313f560bd774d10e
+
+Count = 113
+Adata = 2852d4fd68a3e9e47d44a7
+Payload = d2d73b62e3b1c9ab75f3544ff8616741e0adbae84b8cf9d0
+CT = 3287a7b5da4d0330672e88f19f6e04f1f7c3eb72a55f19cd62d30d99bb7dadec34e2891c156a1f5d
+
+Count = 114
+Adata = ec1c17b2ab13d7c8ac874f
+Payload = 74796d78d6ad03634ed80800af530212baa7e5093651cedf
+CT = 9429f1afef51c9f85c05d4bec85c61a2adc9b493d8822ec241c9a05ebf9ed27792bbced83b5dc582
+
+Count = 115
+Adata = 4f1ab5ddb1c199e9a5daab
+Payload = fb432488b5d08d576a90f085181ad883407a6ce9ea29950a
+CT = 1b13b85f8c2c47cc784d2c3b7f15bb3357143d7304fa75171ffc24020e86b1314724104e6b57b3ce
+
+Count = 116
+Adata = 864e0e728aea856fae6c6d
+Payload = 2b82d96ed1778412378abe4e09c633acf3359b9709ae3dcb
+CT = cbd245b9e88b4e89255762f06ec9501ce45bca0de77dddd6539bbb0af8ecf77b4508533247b3501a
+
+Count = 117
+Adata = 21ee21a5ed0d75d0380a28
+Payload = 85143071241bb65261fe7afcc102416e59b9e46ee0c90073
+CT = 6544aca61de77cc97323a642a60d22de4ed7b5f40e1ae06ef8981ec6ce7c4687b178f2103fa8c8be
+
+Count = 118
+Adata = 2b63f7b676f13f45d103dd
+Payload = 185577b48237acbdaa3590b8057fe374f875ce829b62c98f
+CT = f805eb63bbcb6626b8e84c06627080c4ef1b9f1875b1299265d9d899c6b71c0ab3049ea1dbfaf6a9
+
+Count = 119
+Adata = a33e86d813c2c4ff3bab20
+Payload = f051beb936e60fd4f3bca31964f1ad3e6fa16dd27b65a6db
+CT = 1001226e0f1ac54fe1617fa703fece8e78cf3c4895b646c6b246474c4e79822f5fd55f2fb0067a40
+
+[Alen = 12]
+
+Key = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0cb00b1abade1b5ce0ed
+Nonce = d80210b9f9776ea36dc0e0a787
+
+Count = 120
+Adata = e4296d1c8cf4ffc4b2635135
+Payload = c825952293e434ea866db558aaf486ef09a92bf366988f71
+CT = b8b3b15fdf6a4a0b5abc313afc769e4e8413bd887552583ede3ed995d1b70561c8e28a7b1a7e3dc8
+
+Count = 121
+Adata = d18bfcc1584eeb8695388ebe
+Payload = a1e0248355bfd1d881fb1a4798cda2f6f6ad513c69c5f9b4
+CT = d17600fe1931af395d2a9e25ce4fba577b17c7477a0f2efb561575f6743c5759494be59afa0c3e11
+
+Count = 122
+Adata = 14682301a99bf680805d1ffe
+Payload = ded135fcbf62219bfba2cba40c2d2cbe4815ddaac1342231
+CT = ae471181f3ec5f7a27734fc65aaf341fc5af4bd1d2fef57e34f689367228cbaf3cd76fb407109cf6
+
+Count = 123
+Adata = 8853aa2dfea9c4d370678bb6
+Payload = 12d3900c6c01968b8344762e0e883e5e219f42b052dc6215
+CT = 6245b471208fe86a5f95f24c580a26ffac25d4cb4116b55a2cacb7fc3856abcf759feb8dc0998ab1
+
+Count = 124
+Adata = c5d3b9c593c3185fe4b6d1bc
+Payload = 8c3c1193fe1a1ebad7e01a1eed1a32c08a0091b1c948e184
+CT = fcaa35eeb294605b0b319e7cbb982a6107ba07cada8236cb42a740cd3262424a2c3d77849ead6149
+
+Count = 125
+Adata = dfb9e8149b51f89b1ec00a8e
+Payload = 8219618b7728ac89237705ecf84012cc7c80293c4cf171d8
+CT = f28f45f63ba6d268ffa6818eaec20a6df13abf475f3ba69747d4dbe0f9415d40843070e1e93059eb
+
+Count = 126
+Adata = 08a4590d262e4dbcb7e23ffc
+Payload = b344b7dc239617fa51b9ea10a349e940c3163779f5284c9c
+CT = c3d293a16f18691b8d686e72f5cbf1e14eaca102e6e29bd31215b3dccba4ca5de64be7fab8a7a22c
+
+Count = 127
+Adata = 74aab7b5b96238710637c6e5
+Payload = 740d4b25ca7221d0826057701a6bfd66c50a82f010a57be8
+CT = 049b6f5886fc5f315eb1d3124ce9e5c748b0148b036faca734e09945ee44c95c7923d8b9249ade7b
+
+Count = 128
+Adata = 420aac47a3f212fffca40549
+Payload = 5d9000489186abdf4f0a2794f0222fcaa156fe6309c10f79
+CT = 2d062435dd08d53e93dba3f6a6a0376b2cec68181a0bd8360a568dd779526a0058d522af1dafde30
+
+Count = 129
+Adata = 6e80dd7f1badf3a1c9ab25c7
+Payload = ac2c44263363810bec3a309aa618b303e05099dfdbeb5c16
+CT = dcba605b7fedffea30ebb4f8f09aaba26dea0fa4c8218b59279442c88d612ed1a39ae0005f88155d
+
+[Alen = 13]
+
+Key = a4cc7e1c90f8684e6a5f95e6898ab4e3c194cb46e196d8228062b9f3fa744930
+Nonce = cdc2712e51c7f333d6bad78eee
+
+Count = 130
+Adata = 569c56b27268d3db54e728aac0
+Payload = 10d4cff95ef490923c9e0906880729d4d05412e7675cce76
+CT = be3ce3e9dc72499839a98ae52abb17415e8547687e8a3c7b8aaaac20d4c9276f2851cbba2b04d185
+
+Count = 131
+Adata = d75635b6450e43285fba966835
+Payload = c9db03e2efbab713b0b640421018d3971ffe2abd70fe8fa1
+CT = 67332ff26d3c6e19b581c3a1b2a4ed02912f7f3269287dacc121ff83891335dd1214ea6fc25f6a68
+
+Count = 132
+Adata = 70750acea6a05f8b7b425d262b
+Payload = add631ce5846ce71434aad4998f8e429aed430e7d38bdbb2
+CT = 033e1ddedac0177b467d2eaa3a44dabc20056568ca5d29bf549e71ec517cd65150f42b3cb53f936e
+
+Count = 133
+Adata = 2a567c7ec7edaa5a438ae3bb35
+Payload = a514d170422feb1d87bb7725a9e77cc6fc8afb45c2af6d90
+CT = 0bfcfd60c0a93217828cf4c60b5b4253725baecadb799f9d0e432ec394ddbb65205dc40a5a8e90a4
+
+Count = 134
+Adata = 0f8795385b805246a0a2573afc
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d730a80a3ab4a07849d4ddf9280170800fb9897c917dbe30926b0d977107a3918717f79b63f36b0a
+
+Count = 135
+Adata = 111d224c102b136159fbeb44a7
+Payload = 2edd498e54b23aab6f4fd7b3f22c4c787e3a4f1fb06c9ec7
+CT = 8035659ed634e3a16a785450509072edf0eb1a90a9ba6ccac2cd61599bb93db3dd3dabc12aa90932
+
+Count = 136
+Adata = df0821c9ea6ab329c626d11b4b
+Payload = 6e3e25db29da2c787bb37755ee770e2402fb8208da23389d
+CT = c0d609cbab5cf5727e84f4b64ccb30b18c2ad787c3f5ca90bd027ecd00cc6dc5ffd5d746d92281e9
+
+Count = 137
+Adata = aacaf4839c35338d6e2b47ac45
+Payload = d4ed4584678e982ace8664e77d0e55be356be558cead3755
+CT = 7a056994e5084120cbb1e704dfb26b2bbbbab0d7d77bc5583c01354a450eda2588be7578530e38c0
+
+Count = 138
+Adata = dc6eed3f8bd1b5563c1eeb9afa
+Payload = 4ebf00eadaf70711f630f5badf0214d8518a200afb0e5765
+CT = e0572cfa5871de1bf30776597dbe2a4ddf5b7585e2d8a5688d7a1d546e25ba026cd46556eb2c4b7e
+
+Count = 139
+Adata = fbfe7e910f242a78dd6e69a2ec
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 89c14f71907472e8c25926068883be257653a57caf213a0b0e951aee790239e7067ef37f497b4bf4
+
+[Alen = 14]
+
+Key = 347e12eec56e95aafcc7d25bf10fc756b4e42bc2e43da7f97df24331f27f1f5c
+Nonce = b8d517b033754058128d13d11a
+
+Count = 140
+Adata = 511c6924fa96db716f6b053b7a48
+Payload = ca88dddfc876a12f45f19562bc9ca250f43267ab251a7f34
+CT = eeedcfa8f5b5b48c1d7e277526eecb7294213b9f5785167ae949b93003dfe63c95c1d49edfb4de3f
+
+Count = 141
+Adata = 10c26d5939618189a9503623f55f
+Payload = de0c0d17c3950e7f8985b56d60623cbd010cd765da4df5ab
+CT = fa691f60fe561bdcd10a077afa10559f611f8b51a8d29ce585c32a90d77fed97eb0ac164ed616e1c
+
+Count = 142
+Adata = bc09c59d20e55a9e184d70af2c7c
+Payload = 2f35102d78a32fcde1cfb563ea8d310ecb83c146ab8de362
+CT = 0b50025a45603a6eb940077470ff582cab909d72d9128a2c180fdf5f63045f326057cf74fd4cee6b
+
+Count = 143
+Adata = b75887f13d6e8c4b35b27b965693
+Payload = a3fcce3420effdd6edb37271735a0d30c10c65233aee173f
+CT = 8799dc431d2ce875b53cc066e9286412a11f391748717e7134959a180fc2cf2ba99af21cc1bc8e5c
+
+Count = 144
+Adata = 603401a9b8ecde4d5c86b6107363
+Payload = 4ac918727e41b8c536484e3781c403e260c278712853508d
+CT = 6eac0a054382ad666ec7fc201bb66ac000d124455acc39c32ca2e5195dbd44f0a119538c95788510
+
+Count = 145
+Adata = 7206b06f306124ca3a302e84c5a6
+Payload = 97d770cbb2c42a552e450cc4e35e5668b2ff89cec735cc91
+CT = b3b262bc8f073ff676cabed3792c3f4ad2ecd5fab5aaa5df74a4e1198878a76291594b9826d4b563
+
+Count = 146
+Adata = b15efed90a5d1d62f545ac22af6e
+Payload = 86bb2ae50e36c72936240a74502172625cbca210cf285077
+CT = a2de389233f5d28a6eabb863ca531b403caffe24bdb73939ff5f993dcfbd048274da7439c0f9ef5a
+
+Count = 147
+Adata = c9eb714ed9858a8dc11a26ee3f00
+Payload = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17
+CT = 29a28be439bcc3447e851e5a1e0db26f765b631cc3a436590e87710559a375ece6ef2953b6aa2542
+
+Count = 148
+Adata = 07ca22271e95cb48a872046822b7
+Payload = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a1
+CT = dd35fb1a58664b58636c174a35892b389ac289562cab29ef998035c81716e2d1ed4b4d56ff18af5d
+
+Count = 149
+Adata = b65f6773516124317cfb4b1fcdf5
+Payload = e160e28e601a49d16db18f25410756b330b036c42e615fd6
+CT = c505f0f95dd95c72353e3d32db753f9150a36af05cfe36981ae73a9b6896d8fc1b8c0d772d632983
+
+[Alen = 15]
+
+Key = 520902aa27c16dee112812b2e685aa203aeb8b8633bd1bfc99728a482d96c1fe
+Nonce = ddf50502f414c1bf24888f1328
+
+Count = 150
+Adata = 22b4f8f1aac02a9b2ef785d0ff6f93
+Payload = 533fee7d2c7740db55770e48cb1b541d990ea3f8f08ed1a6
+CT = fc867b319e0e4ab45ec518a1b5dcec4f29982173f3abfd4d8a8f8d14d2bdac84c3737cfbd75b7c0b
+
+Count = 151
+Adata = d0a43de391d492746ecf322acd6e5b
+Payload = cced20b59a6b2c3c45ea6c87802440c9c47b1015e83d86c3
+CT = 6354b5f9281226534e587a6efee3f89b74ed929eeb18aa28fce59f5e6e3cee284b4cc747ff5ee13f
+
+Count = 152
+Adata = 3a789c06f87f05933c34a1cf9834a8
+Payload = 90939a4530181ad6900664f66bfc2ce0289432a0afe9babe
+CT = 3f2a0f09826110b99bb4721f153b94b29802b02baccc9655ddaef56d8255125f7c316c6c59ce779f
+
+Count = 153
+Adata = 785260973f112c56d9f891160c4c11
+Payload = 86cd926b9565b76a88fde73c31e9ac908ffd1e6ca30b59ce
+CT = 29740727271cbd05834ff1d54f2e14c23f6b9ce7a02e752555810cbcdf48f05d0a7808673c82d08d
+
+Count = 154
+Adata = bf6a144591c0ea7b10274fbd3345a1
+Payload = 6ecd1c1acc6290672f9cf639ed0cebcb21ed0c56f35a5ce3
+CT = c17489567e1b9a08242ee0d093cb5399917b8eddf07f700849e41e5d34a698ae1d96f16bc68da944
+
+Count = 155
+Adata = 7d9488b500d89a27f367f34a448a87
+Payload = b01e3f4fb5ee7501e8c2f4ccefb542ae20d7fd61a2c41c8b
+CT = 1fa7aa0307977f6ee370e2259172fafc90417feaa1e130601bc54e546d1a6fcf6187169feb1ea533
+
+Count = 156
+Adata = 060fc718e994edc7bac9962ca7f28d
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = 8d12ff411dec3b0ad61a7225902cc07c97ca898c29c8fe6ff2eb6c0ab42acf42985c721bfd576e71
+
+Count = 157
+Adata = cb6f96dd06015967279ade310a7401
+Payload = f96ed20b23c784015ff58f5f040798ca75e3b98045deca8e
+CT = 56d7474791be8e6e544799b67ac02098c5753b0b46fbe665ac502b8e65cc1329b6895afdd354f5db
+
+Count = 158
+Adata = 9aa6d501455019b4ef4c7fb789d22f
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = cb3311cd8ed070804105f7aa90ee14ebf6ae04ebf2ab9a9a87e5f8a8148f21adf721477c36bd99ca
+
+Count = 159
+Adata = ebd1d12bbd14176a0d4080aa1edb89
+Payload = 32d71e59634126ac6c6156a80a0dfa0175b29e9f40a31696
+CT = 9d6e8b15d1382cc367d3404174ca4253c5241c1443863a7dda9ea0427522dbeaa509a11755434760
+
+[Alen = 16]
+
+Key = 57da1c2704219ed59abfdf04743a9a93c87a63d471818de0f1564b2db6421562
+Nonce = 4b60a47b7e90f622fa0bf803e1
+
+Count = 160
+Adata = 0ae8c012ff39753510df3ee80707e4e2
+Payload = ddc3c1aa73fb6de92bb4db138e26f3c2e0543ab4f5924871
+CT = daa8256d4753fdf9cfef876295badaba89b45cc497f54d220ec2c6fb687753bca4580adc6aa2f296
+
+Count = 161
+Adata = d5b22e7697ba70e00c7ef32709563f01
+Payload = 34270576724083e9989764d08a0d5c1b4738f34927a1e436
+CT = 334ce1b146e813f97ccc38a1919175632ed8953945c6e1658f30b9c8e380c98bb939a4e8a85af758
+
+Count = 162
+Adata = 6b4edef415763aabcef01863e8197aec
+Payload = 904fe88e7a8e76447a64b488ef84184d0f1ab1b67f0c5a7d
+CT = 97240c494e26e6549e3fe8f9f418313566fad7c61d6b5f2e53e80d8ccc687fd303f4cdef44b6e8b9
+
+Count = 163
+Adata = 4c099809061024c010a77e9621fc2bcf
+Payload = 51fe7bac8f3255f17f64fb9322210fb7d8da8e762498b233
+CT = 56959f6bbb9ac5e19b3fa7e239bd26cfb13ae80646ffb7600c635dac5b70338dac3f33ce16a99145
+
+Count = 164
+Adata = 9d329439588164d5a96675a85c07a039
+Payload = eab6dbc13bb92df36b1882df2b8f34c3cefa41f95717fbd7
+CT = eddd3f060f11bde38f43deae30131dbba71a27893570fe84f996e8163affb1494bb3c12eeadf16b6
+
+Count = 165
+Adata = b768fc3daf29ff9e8bd575072d986e99
+Payload = c44c9c287d3eac7c30570d9c4adf2e4857c598f7c54cd126
+CT = c32778ef49963c6cd40c51ed514307303e25fe87a72bd47598b4206a9622d5631751a497dfb1f662
+
+Count = 166
+Adata = 3efc7cc2d16bf82d2bcfbc559a09b2c9
+Payload = c11b9c9d7607f387359c0038d3e8ec4d527562ce63c3384c
+CT = c670785a42af6397d1c75c49c874c5353b9504be01a43d1f7dd300167d267ad700dea37fb475ecdd
+
+Count = 167
+Adata = 0ff89eff92a530b66684cd75a39481e7
+Payload = cc17904b166f28df82f57889f391159a4a308e752d714ee5
+CT = cb7c748c22c7b8cf66ae24f8e80d3ce223d0e8054f164bb6303e9c9bd0d8e4aac42894ca03d6ab06
+
+Count = 168
+Adata = fbd11bc75759f0461e796f6917aeb42b
+Payload = 6f97e595ea2f40612ea84a2097b974d235055fe1dae59403
+CT = 68fc0152de87d071caf316518c255daa5ce53991b88291500953f46e0e9cf1369e9eb018a4df3c09
+
+Count = 169
+Adata = b79940952f42537484aa2907c72dffa9
+Payload = a48cbf933b88c0ec5ddcdd8fcad186391c2cbef308607de5
+CT = a3e75b540f2050fcb98781fed14daf4175ccd8836a0778b68a1702dfa0cd9c290c5ff9c35cc83705
+
+[Alen = 17]
+
+Key = 9267ebc99ccf648b146cba3c251187e24a9947d806ceb0ced6894211641a1e0d
+Nonce = 9b7298950280e8762ecdc9bbe4
+
+Count = 170
+Adata = 5824689453bc406bf891b85e4576e38fe8
+Payload = 967daf12f16f166b7b5038f83a1cf0b980f5abf4c7746f2a
+CT = 7cfe2a7a54306eb8d8a63d3d1ae86794f9a2c22198b2cb4f10ca926f1a430c08c12e23db3d913e93
+
+Count = 171
+Adata = cd15973753b94b77bb4b778de8b3b0cabb
+Payload = c4a756f6024a9dceabf6e264fffff9c719217fb418141ac5
+CT = 2e24d39ea715e51d0800e7a1df0b6eea6076166147d2bea05d5b674fd15410cc235dba6d8c8d82a8
+
+Count = 172
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3f
+Payload = e0d5de7d1eace211c0e70859ff315ff485d1200c6dd13f93
+CT = 0a565b15bbf39ac263110d9cdfc5c8d9fc8649d932179bf688750b5f36c86e7eda9015e960a7471a
+
+Count = 173
+Adata = cbbecf92551a15f5cf00a5be4a50b0eb17
+Payload = 05a4a4ba28fe8876f9bcfa5ec60651fd3fd4732f22049bd5
+CT = ef2721d28da1f0a55a4aff9be6f2c6d046831afa7dc23fb0d5fa842209dbbc04c87965f78500fec1
+
+Count = 174
+Adata = 873ba7f8b71517ec50297b21cf94cdb7a5
+Payload = 9cdebaeee8690b68751070691f49593668a6de12d3a948b3
+CT = 765d3f864d3673bbd6e675ac3fbdce1b11f1b7c78c6fecd67d147edbe114bfdb3f3b9b37d5719ef5
+
+Count = 175
+Adata = ac087420feb1e1e8c2546c2a8b8a5af0d0
+Payload = 5672e61cf664d73918dc1ca84df1fce82db0e305a61d57b9
+CT = bcf16374533bafeabb2a196d6d056bc554e78ad0f9dbf3dc57b4c2bbc377937d15b3b89543e29d0e
+
+Count = 176
+Adata = a12c690568114fd7a677f49d74e84fc1a6
+Payload = 0f5452e6b51540cf219998590995cd7f8785fa40b4f217fc
+CT = e5d7d78e104a381c826f9d9c29615a52fed29395eb34b3992e6ca774074b47b59adabeaf8835582d
+
+Count = 177
+Adata = 7a78ddfe5afb2dc90ee4a600c2fc014b0f
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae72f7
+CT = 7050bda358442a350db77d357ef4910f0dafd9670168d692bd320f48a7221537e3cbed5ac4154a56
+
+Count = 178
+Adata = 6053e466ed1f647a3cd88c4d2052ec00cb
+Payload = d17b8d556e83190c84d4a812957c64ffa7f336298f4e2c72
+CT = 3bf8083dcbdc61df2722add7b588f3d2dea45ffcd088881740574e201f9a26932a87c8d822505814
+
+Count = 179
+Adata = f7673e3beb526834d6507058fe62e34987
+Payload = 2eaef86b0f602364f86510eabc58bc9ad1e6f0a6f6df0b83
+CT = c42d7d03aa3f5bb75b93152f9cac2bb7a8b19973a919afe6837dfa3fdef2f012b6609de2ac5dd9d6
+
+[Alen = 18]
+
+Key = 7a855e1690ee638de01db43b37401dcd569c1ae03dc73dd0a917d0cadb5abc29
+Nonce = 8f160a873a1166c8b32bccbba7
+
+Count = 180
+Adata = 72674aca7eba2fc0eeafbd143c2c4d8aa6c8
+Payload = 33ae68ebb8010c6b3da6b9cb29fe9f8bd09b59ec39f4ce4b
+CT = b22afdf4f12c43ec23e01ac1215a3f5286059211207e957057e9a9203da74387a9468f8af5e27547
+
+Count = 181
+Adata = f7da3f100b80e2ade812f1700aab6b72f746
+Payload = dbb29817b86cb80e0d008742cedfbf52b236f15ee8cad50e
+CT = 5a360d08f141f78913462448c67b1f8be4a83aa3f1408e35a3985f12a49eac424a35c94645917e91
+
+Count = 182
+Adata = 4b05eaadf98505d0806c233b2cdcaf4254e8
+Payload = 145aa8cfd544a2f46bae1aa83cbdb3d21c3d1350078a3af4
+CT = 95de3dd09c69ed7375e8b9a23419130b4aa3d8ad1e0061cf4ab089a8724b87a1167180963d44ec65
+
+Count = 183
+Adata = 05a3aaa08b9a6aaeb84704431425d0e45a14
+Payload = 6b32e8906dc89194a69410b79cd041b62eb01afb28a3e10a
+CT = eab67d8f24e5de13b8d2b3bd9474e16f782ed1063129ba310a7d1520141892e140448292185c41c7
+
+Count = 184
+Adata = 74db01edc26a2d2044cb8eaad8b907b78863
+Payload = 545ed03588fd85a8bbfeee66d2082ae6f8e2f3c9dbd8725f
+CT = d5da452ac1d0ca2fa5b84d6cdaac8a3fae7c3834c252296472d3eee219d94bd788f62df4add5ec40
+
+Count = 185
+Adata = 5f2c6ddf5a2403e04dac8b2813c060b67e76
+Payload = 66dd5fd8611c551973a3d0c078ec2b4d39ad163d9168de3c
+CT = e759cac728311a9e6de573ca70488b946f33ddc088e28507c600496f4f8b1b7da118ee36d8cd57f8
+
+Count = 186
+Adata = a650a2a5e3c6f7c95614570aaefd0cdd9a42
+Payload = 6f364b3f778376cbf3f4b0b0c5350a8fa278f9d8c25faad6
+CT = eeb2de203eae394cedb213bacd91aa56f4e63225dbd5f1ed4710004d06ce7a7efbd19da4e3ce3cf7
+
+Count = 187
+Adata = 477c2484cf5c56b813313927be8387b1024f
+Payload = 3de4798d8ad84c460b92abc10b7f5e7c9fae46a1dd353687
+CT = bc60ec92c3f503c115d408cb03dbfea5c9308d5cc4bf6dbc304099641c4ec3dc2c54fdf4f48dbef2
+
+Count = 188
+Adata = 564e1df74aa2d7ee33b66cfeda810774e16c
+Payload = 7769b45fea11f530fb9a67f1b5b1964a34cfa32bbb03f4b1
+CT = f6ed2140a33cbab7e5dcc4fbbd153693625168d6a289af8a905c1b05e8945685f8688faea777eb43
+
+Count = 189
+Adata = d5e66502529b0045883d935e05acd242baa8
+Payload = 0c0a502b42f81b51806c7080a8155280f493f2922cdc7df8
+CT = 8d8ec5340bd554d69e2ad38aa0b1f259a20d396f355626c3ea5a3b6a8bafde4006b993cfb3b13557
+
+[Alen = 19]
+
+Key = 0ebdc6ddb4c502725dd6ee8da95d56a0d1044b4694d6ba8475a4434f23a8474f
+Nonce = fb717a8c82114477253acc14f6
+
+Count = 190
+Adata = 41e9d65632f74f449a6842d5e6c4a86ef83791
+Payload = c7360282c85484a5a33ab1c68dd70873ab4e74ffd4a62cd5
+CT = 2e961b3a2fa1609a4e6fd04bff6ac5e306ae2638706f997b42be2e2ba05c54b619850db5c9d684fe
+
+Count = 191
+Adata = 555304659bde926cb2553b8a4605251fcddd92
+Payload = 1332314d1cf783b9f64e0fa2d42d43d225da9fd5165b5f0a
+CT = fa9228f5fb0267861b1b6e2fa6908e42883acd12b292eaa4bbdee2605bc69601b1e83d1e7a0b400d
+
+Count = 192
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9
+Payload = f264da8606ea429e0e25da3f2efafe28beaff05b42097369
+CT = 1bc4c33ee11fa6a1e370bbb25c4733b8134fa29ce6c0c6c7304611baf530932da7954f714514d228
+
+Count = 193
+Adata = d7186a67061319b44eedc0677ebf5d932d5bce
+Payload = c9ee6482144dc61c43041324a2c18ede370011cb4882b0c5
+CT = 204e7d3af3b82223ae5172a9d07c434e9ae0430cec4b056b6d1d44e26404b7324767f0b3f7486f8b
+
+Count = 194
+Adata = 38f37d5e2da017f1953ff3701be0b38809ba80
+Payload = 40524a4d32a711e7d5a59809878c318f42b6e2375b77b8a7
+CT = a9f253f5d552f5d838f0f984f531fc1fef56b0f0ffbe0d095453724d2db19f606c85d00e49b0bb38
+
+Count = 195
+Adata = b3b2d249cd3517555fa692bbe9116f069e7405
+Payload = 961c15bd7dc34cd5409c9e8869988676ec6845ecb0ee85fd
+CT = 7fbc0c059a36a8eaadc9ff051b254be64188172b142730536db1e4112fcd650e8c0f0f6fbf2d07e1
+
+Count = 196
+Adata = f5b5bcc38efaff01f69bd3a106dcfca3cc6414
+Payload = 879568ab9ebdea768a5459ced1d3181d822536c3d1ba38c3
+CT = 6e35711379480e4967013843a36ed58d2fc5640475738d6d1cedb29e68322e47ff9997f859257d98
+
+Count = 197
+Adata = a2098e3e23826e01f31107a208202f710eff00
+Payload = 47cb57599686716c75d7ecef5541d20fb908e6d98c39925a
+CT = ae6b4ee17173955398828d6227fc1f9f14e8b41e28f027f41c12bf2a3571ed672592b27e986e9058
+
+Count = 198
+Adata = 20a3d53e77201599540344c4e746c3ae3a5f84
+Payload = 4a8667b5ee09d3d4a6dca9a95f4ad406f1da94b846dcc6b8
+CT = a3267e0d09fc37eb4b89c8242df719965c3ac67fe2157316f12b2be8f5966d96602111c28f87b104
+
+Count = 199
+Adata = 92c592ead4b3f193cc36687593d4f0f412a5d5
+Payload = 1dc9e32ac4176f64bd78a6edd651ebeea3ba85dfcd8298a8
+CT = f469fa9223e28b5b502dc760a4ec267e0e5ad718694b2d06776df0a0cf048892e65bd8ad77cb2255
+
+[Alen = 20]
+
+Key = 2ff64bbec197a63315c2f328dcb4837d0cdc21a5d6f89ff1d97cb51195330cd8
+Nonce = a235f8ee3de9896b71910ac02c
+
+Count = 200
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112
+Payload = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a
+CT = 1bf122798bd8ee8e73391d589bd046a294d1615794e69cb9e6f3ba30143acbc3a1c1c6ec74333107
+
+Count = 201
+Adata = 0248359f8071143c3cc1d61882a3547a0b3d2175
+Payload = 4a6a7151465c2abd7e7fa1fd13019ad098b6ebcd190e96f7
+CT = 1b8c01056a837081553cb646ef73115a3ddcd3a095074e6436cb510c13a039f4df8cc26a942f9911
+
+Count = 202
+Adata = cca77bc4cf6c0abd3393dac3fbe90fbc8a1154f7
+Payload = a94f5ede43929d48d2c5a58c3262d9127d2ac3cb2fbd5768
+CT = f8a92e8a6f4dc774f986b237ce105298d840fba6a3b48ffb7fe0dedc2899dff81a251cff16bf5897
+
+Count = 203
+Adata = 9c082a84646c070bb11b7d6b92b62f06ee5b5b71
+Payload = 7303bd41cf47289a3111366d08e8e21548baf293052029eb
+CT = 22e5cd15e39872a61a5221d6f49a699fedd0cafe8929f17886c43ac23800de60a1fd2caef0f03261
+
+Count = 204
+Adata = 1c3ede1982a807a410ae1e21947bf430f8db7027
+Payload = fa9743a67978c20316cb91801d7789e350079aae3aadbd43
+CT = ab7133f255a7983f3d88863be1050269f56da2c3b6a465d026f7907e235c09d3322c4092d2e88f88
+
+Count = 205
+Adata = deb05a30a026ff66ce71e98afa62f0255aef84f5
+Payload = 99599b4042dcdb685350cdecfdf24992fd5b165670025d0c
+CT = c8bfeb146e0381547813da570180c21858312e3bfc0b859f6bb44a28c145d49f49f2821d4044e4b6
+
+Count = 206
+Adata = 93dd9b00a3353e5331338dcfcb7ca7e0bb873a4e
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 14f771712219a85a79678ae220e5c0f9c4bf49c59c1507400f7d20aa3d792d6a3ebc5ee0df2fd89c
+
+Count = 207
+Adata = 0855263860043207543c8c34648d53ec51c4f47e
+Payload = b2db87b7787531968d603098cb20ca7c438b4af72623fea9
+CT = e33df7e354aa6baaa6232723375241f6e6e1729aaa2a263a7ca4733f0208668b0a7879305e861d71
+
+Count = 208
+Adata = ee2d3a66deb3ebca867a902bb9202226ed516ded
+Payload = ca18ce38086223e63b4f0b616d110010f9e45eac42f2ba46
+CT = 9bfebe6c24bd79da100c1cda91638b9a5c8e66c1cefb62d5d76b482ff20429da8f60f0f863e1af50
+
+Count = 209
+Adata = 8e531aaea849addab6a83497cbc504f489505952
+Payload = 5717ed5da5b8aa806a18bfe979502bab6632c9428d3a7725
+CT = 06f19d098967f0bc415ba8528522a021c358f12f0133afb6aab66e1ac2346ef97850a4985c64b737
+
+[Alen = 21]
+
+Key = 24e9f08a9a007f9976919e10dc432002e2e078a339677f00105c72ed35633a3f
+Nonce = 15977424eeec0ec7f647e6c798
+
+Count = 210
+Adata = 2d838eb51a4bc69a001a18adf2084a680f02a3c5fc
+Payload = d3416a81b4246eb0bf8119a72a886bbc0ac9449c69f71d2f
+CT = e001a8fae390dc5d672cdd18f86a1f728158ec83a002050def9af5679edbcbb7db20ab6af30698db
+
+Count = 211
+Adata = d83ee7ce22fd1a2882d8d552346e4d7b3efdd67da4
+Payload = 22b6f10b482448626f6c7bebb14f1497896d071738133b4d
+CT = 11f633701f90fa8fb7c1bf5463ad605902fcaf08f1e6236fd435a5a38f84387f63b13407f65ec86c
+
+Count = 212
+Adata = 2d5537b24d0b0f7a45703c1e131656ec9edc12cdf7
+Payload = d60edc830be8207ffd9e9f646d3b4343b10b3d56acb89d44
+CT = e54e1ef85c5c929225335bdbbfd9378d3a9a9549654d85662ede8a705f8c988f55459542bd631b1c
+
+Count = 213
+Adata = 1a750eb326923412d94ccb35f5acd0f87415268178
+Payload = 716d3132f449a9def383978102ae50ed3ccae0cb346ba1df
+CT = 422df349a3fd1b332b2e533ed04c2423b75b48d4fd9eb9fd986de774a612230ce6c71449d26732ce
+
+Count = 214
+Adata = b10fc523bc4562d44edfe5956f93c15c4ab38bba3c
+Payload = 063c2ae2a15f26f979bf90657d20643e3184f1a9f75a3aad
+CT = 357ce899f6eb9414a11254daafc210f0ba1559b63eaf228fe710431005264fa7d3fc04bac50fc1ec
+
+Count = 215
+Adata = fe4f60ce9634e7dbc5e56204c4bf8aa9be577027ec
+Payload = bdc513e56a5bb70c02abc041af04d6e45e735d10cc88357f
+CT = 8e85d19e3def05e1da0604fe7de6a22ad5e2f50f057d2d5d5c13bea6ad0cad724e6cd02c89517ffc
+
+Count = 216
+Adata = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e
+Payload = 7dc5d8cd90ce2faf76bbd0d52e5ae11b310fc2b0051c4377
+CT = 4e851ab6c77a9d42ae16146afcb895d5ba9e6aafcce95b55d2a5531655aae01e249f213e0e04af0d
+
+Count = 217
+Adata = 199ec321d1d24d5408076912d6bb2b6f192d6b347f
+Payload = 66c2696edec26ba3d07bd3f485a0d6ce8a1b0a85b20083e7
+CT = 5582ab158976d94e08d6174b5742a200018aa29a7bf59bc52a127ef341345f9641b26e91265e1482
+
+Count = 218
+Adata = 8b013f5782d5d1af8dbd451a4202866095dac975fc
+Payload = f4da8ac3e8fe5ec6a5b6a2f27b68396e850b46a024d441f0
+CT = c79a48b8bf4aec2b7d1b664da98a4da00e9aeebfed2159d2a005ca13c4bf715c3b7b2782f799b23a
+
+Count = 219
+Adata = e320df32b71cc530e8493b12b9afbeabc255c5eb44
+Payload = 244891cb4af66cc8e99a3784a2e82475e51bd5c7fde67cf5
+CT = 170853b01d42de253137f33b700a50bb6e8a7dd8341364d704642aff9cb9288d49f0e567dd837e05
+
+[Alen = 22]
+
+Key = 0ec1b22b8df05dc92135d2dfbefed8ea81458f5ea1b801e8a218faf6cbdf1a79
+Nonce = 97ebcb8575bb58260208d5c227
+
+Count = 220
+Adata = a2f6337f86dd00d1a58448851e95d8c9bace4a5c8710
+Payload = 2f59d94d4ab8eeb84c2a6fefb7fb0a3ac059c1e1a65ae34a
+CT = 7ca0b1dbe34b0391e524b868b0af08b3e096917664d6aa2cabc1f9d0132394149c9062b74b82f04b
+
+Count = 221
+Adata = abf26b05558252c8e38c52b1ace087bbd1eb3d561239
+Payload = c25381853f73a3dc4195fdcbc45dfa1a40eb8324749adb2e
+CT = 91aae91396804ef5e89b2a4cc309f8936024d3b3b61692486d7df57c6a792f6f6b24cb5f87e92123
+
+Count = 222
+Adata = a13ade56b47803897666e42ef2ef88be0e779ac86c28
+Payload = 8dc5226a2a13088c87f4bf94262e0c0413f06b35d2fda79b
+CT = de3c4afc83e0e5a52efa6813217a0e8d333f3ba21071eefd4ac19b0b74cd9d5e100598b96c9f1f2e
+
+Count = 223
+Adata = 3c5b68b65edf62755b7e064bd26c843816bf6c1cd481
+Payload = ee4b23039cd512cfab8c7a2d0f2c78d66764520bc88759e1
+CT = bdb24b953526ffe60282adaa08787a5f47ab029c0a0b1087a77a27eabfc79f192c0ac491280af8d0
+
+Count = 224
+Adata = 0213fe13c49083d7c00335e1864dc139c9e7123162d1
+Payload = 30b48d4021838090fbd5251069ff8c631452daee5ef899db
+CT = 634de5d688706db952dbf2976eab8eea349d8a799c74d0bd39935f91c1e29fc1e4c5c5427ca9da79
+
+Count = 225
+Adata = a32291746b151be8134e183798aa82bef210343feaf6
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = 717fc97b74739e53db427ec6262a9d8b12485bfbedac9bfaaeaec90ada2a1ffef64c3873af645a40
+
+Count = 226
+Adata = a30f2fd445820cdf800145540602c877da0e4c311272
+Payload = fe703ca0901e4a706ce1393c7d8ce18a03eb2caadbfa7b8e
+CT = ad89543639eda759c5efeebb7ad8e30323247c3d197632e87932952831d0ba25c77c18fe154d8ed8
+
+Count = 227
+Adata = ed438e393e0e37629cb25044ae89de9fd0d42d60c1a3
+Payload = 7043c67726870bb5816da925925bc2722478311c8a606cca
+CT = 23baaee18f74e69c28637ea2950fc0fb04b7618b48ec25ac234fd0241d00f3890a23ccd0bf16dcbf
+
+Count = 228
+Adata = 1013946815001a2c08acca4196e0d6668ffbb3883cf1
+Payload = 695e9712dbbf883e9bf8af9188bd01fc631968928258168d
+CT = 3aa7ff84724c651732f678168fe9037543d6380540d45febaf43498b0c3f70c119f82d5812db940f
+
+Count = 229
+Adata = 44cc9b2510680c4d73f1938c77de21242c8ee790ed7f
+Payload = 67ba90d22c6bb5f649bc0c505c5ed23a299882559a3bf520
+CT = 3443f844859858dfe0b2dbd75b0ad0b30957d2c258b7bc46db66dbb03a4c943ac089ed11eb214bbb
+
+[Alen = 23]
+
+Key = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Nonce = 451101250ec6f26652249d59dc
+
+Count = 230
+Adata = 7cc9c51b69f98a06391ab32742fb6365e15106c811fe8a
+Payload = 065ef9eeafbe077c1c7049f43eb0d8999708e8609f214d5c
+CT = 990065322a438e136860f7b019807e9feff52a642bf3d44a9163fa7a867f04cab6f52dc250070f31
+
+Count = 231
+Adata = 7bb1bc069a783d45d51d8ecd0a53ab7a386fa1f5ef12a1
+Payload = 69b2b056f2265e707d3e31e68bff6a060544c8a737b2a9b9
+CT = f6ec2c8a77dbd71f092e8fa2accfcc007db90aa3836030affd33dd9155619fb040dcd6038c7b7367
+
+Count = 232
+Adata = 0dd220919d0eeee3b7cec36c47e376b778583b38bf61c8
+Payload = b98d79aaa4c04171398c7f1189497acaa7546ef068bc7a3f
+CT = 26d3e576213dc81e4d9cc155ae79dcccdfa9acf4dc6ee3294fcba5a886b1f33cf1cf44618d28f01f
+
+Count = 233
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c112479
+Payload = eeaeb773ade5fb2d27b50bb892916333e0b123c6e3ae5bdb
+CT = 71f02baf2818724253a5b5fcb5a1c535984ce1c2577cc2cdeafe2c670eac203d5e90b9d520e7a618
+
+Count = 234
+Adata = 614b0ac4611b6c6d3b4ed089510dcd2215567bc3789f85
+Payload = f2198e1f91fde2672a1ef60403c0d175f366b6780ee9f1c2
+CT = 6d4712c314006b085e0e484024f077738b9b747cba3b68d4f0388746438e83b731b5588fef53f1f3
+
+Count = 235
+Adata = 866fea4483d4e903566844e31c24283571832dfae32c74
+Payload = ba37617342b4eefd4bdce8fad30c4751b206d47814973b3a
+CT = 2569fdafc74967923fcc56bef43ce157cafb167ca045a22cfca81f8b36d16698a600fd701f2c6424
+
+Count = 236
+Adata = 9d7546f7e8b949c539d21a357f81d0151e278d0bf2c5a5
+Payload = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f6
+CT = f6f3563424142a9d8a8edc1d384bea5d612e770ac247b8e04c15a6d292c7ed2f31cf9512435ec7d2
+
+Count = 237
+Adata = 42b692048c8b3cce1b5e83f4f33232a7d7d0bc20695e7e
+Payload = e0753d4248643642c7a96404de8d76c9d80527b659ec6d31
+CT = 7f2ba19ecd99bf2db3b9da40f9bdd0cfa0f8e5b2ed3ef427a2ad73179d0314b5fe52dd7217518cb8
+
+Count = 238
+Adata = f1dfb6fdb31cb423226f181c0988a52ee4015aef4536f4
+Payload = 79ba959c7221b293e2115f538d9394c64284c756563c04b0
+CT = e6e40940f7dc3bfc9601e117aaa332c03a790552e2ee9da69ccc5ba1caf933b80bfc6f281109688f
+
+Count = 239
+Adata = 8eafce9ba466fd53eb87f499d7c76bd486db0e90a3d281
+Payload = e1590206717a708cad9cca7d23a3b8ee5f7fb7786aa3be47
+CT = 7e079edaf487f9e3d98c743904931ee82782757cde71275173271ec36d92fff34609169f579c8f1d
+
+[Alen = 24]
+
+Key = ef4c1d2314e671f666cc6667660f1438a293208c7cc29b412d81277f0a635c91
+Nonce = 50b23b052922366c25dd40e348
+
+Count = 240
+Adata = cd0522ebe1fed82465277d1c10ae9316a98b4469be63b180
+Payload = c99c3e79125b6fd95e737326a842424eb6c6ecea4c0475c4
+CT = 76df4be4ec8373864399acda11294b220b9f7c3a7d2b3660b25764e40ac6a171e7e6bab4fdee4288
+
+Count = 241
+Adata = ce5bf070678cb07e963263b1562ff79311144addb6e4de4f
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 519d742d71422c63c2fe1661c32e7a45cf9f7f2290f4454ffca49758d17f2073066b82667eae6ce3
+
+Count = 242
+Adata = 07175be2475cc735c9a3c1140895277378debf8fb1c87c24
+Payload = 6d5579aaaf8737b01620424f3ddeaf538f10dfad094e5ec4
+CT = d2160c37515f2bef0bca9db384b5a63f32494f7d38611d607c1d64d7e9de47a6ad7878283da9d870
+
+Count = 243
+Adata = c821a8d4bab9d993c20dd206955304a55968e6db5ab6480d
+Payload = d0628b2027f06c246497977d05f211b2c2e302d5b82700b5
+CT = 6f21febdd928707b797d4881bc9918de7fba920589084311adc2bb471862d25cfe25e66fedb8e28c
+
+Count = 244
+Adata = 68439bc9d176feeeb4119d00ed5449dfefb72b5a582bfd97
+Payload = 6cc9749f48c61050e421afa3a10ad3dd3aa02cc3f8586915
+CT = d38a0102b61e0c0ff9cb705f1861dab187f9bc13c9772ab1319a493abc947945f1312395ea98d937
+
+Count = 245
+Adata = adb262c924942e4e1964e9d97c6a8c159fbf9bfedc5ff296
+Payload = 92d50736466e64e6225962e76bd90da824f716a3301a1a90
+CT = 2d9672abb8b678b93fb3bd1bd2b204c499ae86730135593421d0602d29447ba6b24a67509eaee1e8
+
+Count = 246
+Adata = fc7b08707d3c3dac7689ec18088ee6502ef08d3ffbff38ed
+Payload = 87c7ac031fd63e4c83280dce6b68a92dfafb6ea19388fa9f
+CT = 3884d99ee10e22139ec2d232d203a04147a2fe71a2a7b93be52a2eeacb1f023e849161b6306b6cfa
+
+Count = 247
+Adata = fd43dfb66041b117f2ac54c94f7b6e2677860864d9494175
+Payload = 6b53c46266b2f4284d8fe7f0549c98977344d67e178e9a8e
+CT = d410b1ff986ae8775065380cedf791fbce1d46ae26a1d92a0d8c5b1e96b21460e0b5414639abeb0b
+
+Count = 248
+Adata = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Payload = 8e7d8a44244daa7df2b340993e32dac50e05d7b2e103be98
+CT = 313effd9da95b622ef599f658759d3a9b35c4762d02cfd3c1c97260d20797d374c595cbc2ff080bc
+
+Count = 249
+Adata = 9895b24d12b004b215583eac70a95f4fba7442164f35c57b
+Payload = cec07df916ffb7a453d0eb588b7462096f22874bd5abf814
+CT = 71830864e827abfb4e3a34a4321f6b65d27b179be484bbb06cd287afcbdbc5531f11246080b22677
+
+[Alen = 25]
+
+Key = 8544808e8fbf8c3a5e1d4ca751d4b603af9fe119eabc6923205815e0e748b7e7
+Nonce = b44a58724596b4d8dea827c1a0
+
+Count = 250
+Adata = f5b2c88f5232c37273b1e66aa31cfa7201e33c21d60054d025
+Payload = 617d54fc6a23601c79e3984f93bfc2d151fde420863206b3
+CT = 57b3414db48982c6567265e1e0173bf38fdfaffe4461fbebc1411af83237c0f9eb0bfe8ed914da66
+
+Count = 251
+Adata = 8fabe14dcb3aa2fd28281147c326e98ad699ca7997f03a105d
+Payload = 337290d0b4ce1e87afc3cf01d6c98f8c17a4603120dcfcd1
+CT = 05bc85616a64fc5d805232afa56176aec9862befe28f01897ed6e23720b60ffe54bbb9f7ff371008
+
+Count = 252
+Adata = cf193eb3d755cb8e06c5be2334b5c8b7a22b6524d46d547ba3
+Payload = 01ef7ac6470aa02ccd8c1712827e52699d05751b78e4c5a6
+CT = 37216f7799a042f6e21deabcf1d6ab4b43273ec5bab738feb6aa6b284e7720acbd027a50317f816a
+
+Count = 253
+Adata = b4cadb5f9cb66415c3a3b71421b926f147566a174160a0bcc0
+Payload = 64fb9322210fb7d8da8e762498b233b0eb172c91231c50cb
+CT = 52358693ffa55502f51f8b8aeb1aca923535674fe14fad937058e9c0164ca079668097fde19e5302
+
+Count = 254
+Adata = 48400d76ff882d6d5129c8674acc71f445356c9db9c91f8256
+Payload = 291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4
+CT = 1fd4b1d21a105eac9b37075c91d66d2386495116fc18fbfcf988611d5ce0f65b217bb4787bf59bbc
+
+Count = 255
+Adata = 749d369d837002ad33feb8aa22c3f68705eb4872e1b8f85a7f
+Payload = 141cdd7f964a78815be144a785c6a2a298c54230e73039e2
+CT = 22d2c8ce48e09a5b7470b909f66e5b8046e709ee2563c4bad6251a5fd375a48583a6d0f8eb75cbb4
+
+Count = 256
+Adata = 80214108b16d030feff6e056c9a07a00a1d5e3ebb07abd3f4a
+Payload = fa2441cb7f9d072b8a3f1a496b2be6728a38b94a4f44c9be
+CT = ccea547aa137e5f1a5aee7e718831f50541af2948d1734e6af1dab0f105414293cb130bea285fd6a
+
+Count = 257
+Adata = 8b9fabe29718a8f297c9bf6f199c80bbc71f94eb3034a11ecb
+Payload = c8ce88ab40b62229223d46cc44f21bb39cfef27aa9fdccad
+CT = fe009d1a9e1cc0f30dacbb62375ae29142dcb9a46bae31f51cc3f7640a42460be877fb7059a3ed61
+
+Count = 258
+Adata = 8812f28a0cd5fdaa226fdd44ed857241007377057be3bea577
+Payload = cf59f75ca4d6d216cf8862b44b5192c382c140f862def117
+CT = f997e2ed7a7c30cce0199f1a38f96be15ce30b26a08d0c4fbbe0ddd2e7f4aa2024b3fec9281b6cac
+
+Count = 259
+Adata = c8f05e96d703a4850bae1421ae9ff3aec7531baf9b899dfd75
+Payload = 4eed58f381e500902ba5c56864f6249d191e14d1b1fad3dd
+CT = 78234d425f4fe24a043438c6175eddbfc73c5f0f73a92e85e5df1e5e96bb84f730fcb253d468278f
+
+[Alen = 26]
+
+Key = e19eaddd9f1574447e7e6525f7fd67e3b42807e44fbb60e75d8c3e98abc18361
+Nonce = a8c459ce0223358826fb1ec0f0
+
+Count = 260
+Adata = ef88f4393d6c1e7b7be55a12144209ee051bb779e440432721ef
+Payload = b3b0de10b7c0996662f1b064e04e528b7d85ca1166985d33
+CT = d63e6082c95c6c5ff2bc0771321a4f883ef61cff7b99e0ea8a20a1abe7c842ebc08c8c81a2743c81
+
+Count = 261
+Adata = a4c891c9dd1fcc982c35bc74cfe71651bae424602519672b466d
+Payload = 4f0b40913f07269550b7b06ab9027a4d9331f8ef98a45dca
+CT = 2a85fe03419bd3acc0fa077f6b56674ed0422e0185a5e013845e2d6de83ab729dd200a21088a1ec3
+
+Count = 262
+Adata = 4db5730cb9794f3b1facc9d6738115d02ba9f27ba02330fbb856
+Payload = 841e032773d58bc72a3237bc9b24c61b9efdd850fc2ea605
+CT = e190bdb50d497efeba7f80a94970db18dd8e0ebee12f1bdc10ed272c732247a696a608ef67510f9c
+
+Count = 263
+Adata = 471a900ee49f2cfa1d3eb37c951d810c349364d4cc3b5b64fc47
+Payload = b4db42e523e65557157b93dc0281601f7997e6731543a914
+CT = d155fc775d7aa06e853624c9d0d57d1c3ae4309d084214cd15f0df52e392c37ec15f7458469dae84
+
+Count = 264
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5
+Payload = 73e0ed35c0e847188e607cde46586eb9e237fbdc5d59163c
+CT = 166e53a7be74b2211e2dcbcb940c73baa1442d324058abe5421433dafea2b5484ba87b5050e1fb49
+
+Count = 265
+Adata = d563f5c048a1b45265182b99ca7b9004fdc73a9cb07806dd44fc
+Payload = 4f7669caaedee961dbba6bde9d09fee1a20eee55baaf98f5
+CT = 2af8d758d0421c584bf7dccb4f5de3e2e17d38bba7ae252cdf91749fe3cd52a9431d9a847a8c2a9a
+
+Count = 266
+Adata = d301a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a
+Payload = 154454fb74e9565c56775a8e4654f75a38b954dd28c4e939
+CT = 70caea690a75a365c63aed9b9400ea597bca823335c554e07563d37846f5185bb44d71be1ea6a73c
+
+Count = 267
+Adata = f74b48d168f77fbd3429728c0b168ecbd854264eaef70b74fffb
+Payload = 716b371857e68a17b20ea06651cdcfd4560a741830ca8a13
+CT = 14e5898a297a7f2e224317738399d2d71579a2f62dcb37ca55e93bc2d3f05d7016747690fb920e12
+
+Count = 268
+Adata = 3a257ce3592a8f88162f0bb4ecd5db3bb79b54ab17b0bbc61506
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb39303b4135269
+CT = aa55cdf1e6c6552366b55f36afebaa845dc045eda912efb01c46822f839f09c41b7aa6dc06035c93
+
+Count = 269
+Adata = 21916ebeca9e66b77cf55d1cac80a4c85d8b6b014f268ffa73ca
+Payload = b4b67ac551d1966caa20d951351387f384c2e5d81a76a92c
+CT = d138c4572f4d63553a6d6e44e7479af0c7b13336077714f54f8e77600c5bbc6d028fa25ba61a1719
+
+[Alen = 27]
+
+Key = 9498f02e50487cfbda1ce6459e241233bd4c4cb10281dcb51915dbc7fb6545c0
+Nonce = e3bd4bc3a60cddd26c20aa8636
+
+Count = 270
+Adata = 70cfcb828d483216b46c3cd22e2f9ee879e9e3059b566179b6e16c
+Payload = 0d16cc69caa9f19b88b05e151b3d26accd018ca4a5786a80
+CT = f1c4bedb8d6f91676881daa37656a7e6402f472735b04a0f1f8332f4236437737438e7aa1b5100c7
+
+Count = 271
+Adata = e7e5779282db80f424dc050b2c1e7754b2a5d3a8beae77beb74e34
+Payload = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c
+CT = e85f94f2b407756d46c94172eb5944b1f4fd7c625e3135138be2f6f356c2eb401468be15104e7763
+
+Count = 272
+Adata = d17e8189a94a559b07be9549f73d653172740e8e978f5b0a38ad43
+Payload = 00a23b25bca7c206edd051814d81083db1cd00048ce8ead5
+CT = fc704997fb61a2fa0de1d53720ea89773ce3cb871c20ca5a9646f2b6c2455603f1a6f20ea5a4611a
+
+Count = 273
+Adata = fda37ff136895de7ebeaf81e701e5751245201baed2e13d7e1b591
+Payload = a89409b0977f60a029dc4c1560ba6dbe7c65b068633acf74
+CT = 54467b02d0b9005cc9edc8a30dd1ecf4f14b7bebf3f2effb303fa5d8321241b1c9e18a5909d6e428
+
+Count = 274
+Adata = 9c179fd0d6277a5e073e77dd6abb4cba00ad9c9932e6c002b951c7
+Payload = e16c69861efc206e85aab1255e69d6d33c52cf058dec9d0b
+CT = 1dbe1b34593a4092659b359333025799b17c04861d24bd849e8cb01db1da077502814db1610662ce
+
+Count = 275
+Adata = cf5703228e615428d3d3805e428e754961d205c5aa0297ecdea71d
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 9ed11e0c94a00d79827cb97fac9fb60fc6b47e43ac28fe1d40a02a49857d7b280330b8105efac854
+
+Count = 276
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb796
+Payload = 790ac86c5e9d8ce8cbec1dfb7e4fc4dca3d0b1039adfe585
+CT = 85d8bade195bec142bdd994d132445962efe7a800a17c50a5ecfa9dd03e2db70aa212ee7dcb573fd
+
+Count = 277
+Adata = 96f0b7cd7439721d4c9cc4f69585f8c90a95bed8fea22150efffba
+Payload = 3cfacd61ea3398de20ca6bdb00e81af482320614bdfb8642
+CT = c028bfd3adf5f822c0fbef6d6d839bbe0f1ccd972d33a6cde17a7a0cd162945a3616892e101e3e93
+
+Count = 278
+Adata = ee71e53d0b4eef82575c2bd38d7bd21b41fabe58c6f571954fe159
+Payload = d75c153e34ae1c6d1fcf5b1052190d8882041e1f9c5490e2
+CT = 2b8e678c73687c91fffedfa63f728cc20f2ad59c0c9cb06d15fadc2d79841d230cd55c04379f22b4
+
+Count = 279
+Adata = 18a4aa894861c7720ddb43809c3d2ed2af2f1bfe8f9fd4f872c14c
+Payload = 0e728056c7c64214be8f1f1727408d8cca8c42e2ac7bf67e
+CT = f2a0f2e4800022e85ebe9ba14a2b0cc647a289613cb3d6f1b229b9bae4634eea6b723f432e19ae55
+
+[Alen = 28]
+
+Key = 3ac7d5bc4698c021e49a685cd71057e09821633957d1d59c3c30cbc3f2d1dbf8
+Nonce = 54c8ff5459702aac058bb3be04
+
+Count = 280
+Adata = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c049dd1ec
+Payload = 89198d3acc39b950f0d411119c478c60b2422ffe7e26e00b
+CT = 7717b8e4447afcea1eeebf3e39ffdab2f52828e7931ef27e475acd27900478f09fec1f479ab3a7c8
+
+Count = 281
+Adata = 9a04820205234795ecd540b6a0b2fbd0b19f18106c42f374a2b98425
+Payload = c0f61950f98110db4226e269cf197c7e2794c5b87ad68cf9
+CT = 3ef82c8e71c25561ac1c4c466aa12aac60fec2a197ee9e8cf7b7ed6e8ede6ef5a73b484bf13b3424
+
+Count = 282
+Adata = 0e4dbd167da0240298f4795102ef18ff9a8772c6fd73b3374cdfa30a
+Payload = 7960dbc9136880e2eea7956c3271adfe2aba7dca53da917d
+CT = 876eee179b2bc558009d3b4397c9fb2c6dd07ad3bee28308e47d08ea0788f7ca0ecd846689c8027a
+
+Count = 283
+Adata = 2de4291068a5d290b599a73c6a8ecff4f9fd6c9cc48f14c233e18581
+Payload = 0c5d7055bbfbd2bc213cfbbafa763b71b1fde6f4de96fa59
+CT = f253458b33b89706cf0655955fce6da3f697e1ed33aee82cd081f66b1c7b70718dc50367c3da6792
+
+Count = 284
+Adata = dedeb714f555575fcedbd9de8171484090e6466dd4fba3c6b7c42eae
+Payload = b5654edcc8f09e4f80d0258c9376d7c53fb68f78d333b18b
+CT = 4b6b7b0240b3dbf56eea8ba336ce811778dc88613e0ba3fece672883438da186741e6c542b3f805d
+
+Count = 285
+Adata = 03d340904ace1cd52d4b72a96d96afd77aee68ac3936415005ed0d56
+Payload = d796f3409a7eeb896c3d4ebef46e9c6e553aab28b1cc4a90
+CT = 2998c69e123dae338207e09151d6cabc1250ac315cf458e5cf58d4a5552bc8ed1b1dda46703a256e
+
+Count = 286
+Adata = c67f9aa8cf1be3b4377c30c175d33ab2af390982c6a015d99209acdd
+Payload = e4dd279a79a381c68de777df941a4779e50a1381c8aa9122
+CT = 1ad31244f1e0c47c63ddd9f031a211aba260149825928357f95cf2b57e06de4d01bbb6c0e39f37e1
+
+Count = 287
+Adata = fef1b2ccd661b9fac85ba005addebdf8317ab104920549d3a490a21a
+Payload = bbf0c267d952aeb6f810601b9cf1962a92dcaba7273e6902
+CT = 45fef7b95111eb0c162ace343949c0f8d5b6acbeca067b777589cd12984286af98908db88920323c
+
+Count = 288
+Adata = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b6349c2fc20f
+Payload = e8b13a263e0c4fb5645e500e88ab8074ab7d92e5a8dac6aa
+CT = 16bf0ff8b64f0a0f8a64fe212d13d6a6ec1795fc45e2d4dfee8fc441da990dd92c0caeac9d956699
+
+Count = 289
+Adata = 85e5df4ddec99f0bea14b3338b2eb190ab6584f5253c6c2ee3064637
+Payload = 067de2869333ed22c7b63ed7eeba1301bbac69b0d430adb5
+CT = f873d7581b70a898298c90f84b0245d3fcc66ea93908bfc0d502f5434bea8c3c13ad5422ff90e218
+
+[Alen = 29]
+
+Key = 948882c3667caa81c9b900996e3d591e6fcb3d08333eeb29911e9c6338710c17
+Nonce = 43b0aca2f0a9030f90559fa6d3
+
+Count = 290
+Adata = a516ca8405e5c8854e667921b5c5e1968bdd052915b55ac9984b7eefb3
+Payload = 8b9130b0c3c15366831bbb19f377e3209a8dbf7619cd09bd
+CT = 4646b2acdeb11174171da23999cd54e297daa32bbc13d30512e57c576b315f48c11877178389aaa0
+
+Count = 291
+Adata = db3121ea71294983b185207a9d8de3e484a66c0431bf07c962eb82977c
+Payload = 7f369bbc99b6f08049eeb43566269a174829d4dddb05cb9b
+CT = b2e119a084c6b292dde8ad150c9c2dd5457ec8807edb112366775e693f93af6575dccc7903538065
+
+Count = 292
+Adata = 1651cf38fd9b2da65ebb4922b97dcb861128eeefa060d6c1c94b25eb4e
+Payload = fd0900b5fa72e2fba43d611bad25de40a3507a5cc5d186c7
+CT = 30de82a9e702a0e9303b783bc79f6982ae076601600f5c7fb70d8de40c2068de96a274d3b5086b5a
+
+Count = 293
+Adata = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12cb3047625e
+Payload = 36318d80c02a1da41ef1652d9a752e155526b5f597fba226
+CT = fbe60f9cdd5a5fb68af77c0df0cf99d75871a9a83225789ee7da096d2fb28f20f64a000fe93e96e2
+
+Count = 294
+Adata = 0680d5bacefa2ab14aa12b0e517a1432862d4215dc72dc4d5ac6b96c1c
+Payload = 7a29aa2994d11215ab3ef3382b3db6ed581164a235c4b1d1
+CT = b7fe283589a150073f38ea184187012f554678ff901a6b69b88748a2de31261534cdb2237565bf8a
+
+Count = 295
+Adata = 9af701f0a9de52309267289bd170fb97c03c131c0a169d736137ff3d74
+Payload = 3542fbe0f59a6d5f3abf619b7d58b199f7caff0205093f8b
+CT = f89579fce8ea2f4daeb978bb17e2065bfa9de35fa0d7e5330c003eb65ceedc98ae4e38ef341ee47d
+
+Count = 296
+Adata = dab7845fb7ead205569475753c7e26540c09d3a74312f2de25181511f8
+Payload = 83c15520d9541c86b3dd809ede42de22bbb2b75ff18a023b
+CT = 4e16d73cc4245e9427db99beb4f869e0b6e5ab025454d8835c2fb596d8ff6a863604cd224fa3be42
+
+Count = 297
+Adata = a844d6dbd05545ecc736994dc9fc2260c5ab63ed6ffdc40b915f8744a1
+Payload = 793a188fa3efa32f41d6e4c5b42353b95024117d546c79ca
+CT = b4ed9a93be9fe13dd5d0fde5de99e47b5d730d20f1b2a3722ac782e2cd8ecb06172eef2cb9b0e331
+
+Count = 298
+Adata = f9112503884615c0e8a1d8414724b0d19298988f393a27c436b2b6734c
+Payload = 6b237444fb0e1f4150701546c4cb24021c5edad30d9b31dd
+CT = a6f4f658e67e5d53c4760c66ae7193c01109c68ea845eb65f814492b42571033f4dffc0282ea2f51
+
+Count = 299
+Adata = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c2c94d3a5b4
+Payload = 6342312e8a72f71f2e5afe04cfcde4d60a41556111752103
+CT = ae95b3329702b50dba5ce724a57753140716493cb4abfbbb75999099df2de6e436bd99f0341423f4
+
+[Alen = 30]
+
+Key = 3bf52cc5ee86b9a0190f390a5c0366a560b557000dbe5115fd9ee11630a62769
+Nonce = f9fbd02f28ecc929d369182752
+
+Count = 300
+Adata = ebf0b3e3199a5c3773c761c725c7600add5f9d8321c9f8e5e5fd1c7a5d2f
+Payload = 094b538110495e938b08cf748a6bcf3e0c80ff9c66570237
+CT = 4d8b53016fc8bc9677184c0fa15bbd3d671b9366d82ecb67f8562eadcdcbcdbad1299bea1523f5d2
+
+Count = 301
+Adata = a865b88d512e485ab3f2844c29e6dde0cf1151efa9ad3b3021d06fffb74b
+Payload = 23edddd8732cdbf03af08162f0e4a24c9222bdbb4549c663
+CT = 672ddd580cad39f5c6e00219dbd4d04ff9b9d141fb300f3359ff77cf0962455b3539dbf91f3077cc
+
+Count = 302
+Adata = 16918dbc785d94a8f1720c5ad234dde860219874c9fb076a5c290903f85b
+Payload = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0
+CT = 535828ec4840b24a3cc7c35daac685047a743c977247e0806dbed76d94c90595b49d50c84c3efc76
+
+Count = 303
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918
+Payload = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32
+CT = 49c2770fef2086a105bd2aa754e23ce8ff8b0598aa61266248fbe60c146056e5cb01268403e4b9f5
+
+Count = 304
+Adata = 2de5222a0609f058f60e9e581b6e4f0ddebed84fc8302c8e985d17b89241
+Payload = b0c3858231e284af6d231f043b95772f5e7b16a34ffcd2ec
+CT = f40385024e6366aa91339c7f10a5052c35e07a59f1851bbcacff35df1ec942b43eef5aef980cb038
+
+Count = 305
+Adata = 3fc7453df038a92829dc103d44b63ad097d7cd7f9ae7996547012090c7c4
+Payload = 319f396cc02834f8e69d65f77496d0eb31ce1a7b7e324820
+CT = 755f39ecbfa9d6fd1a8de68c5fa6a2e85a557681c04b817091a93f5fc28e5f4f351cfb888da763dc
+
+Count = 306
+Adata = 18f1e92bd3c4a597ed970911d03a78ff9a6790147c9bb0ca5f23b70cce7a
+Payload = 25550c03f8fa02b3781330f96e0fdc58681b0c0bc5e83fe9
+CT = 61950c83877be0b68403b382453fae5b038060f17b91f6b92c6a90ef2e9a969ec0576fae1d126a85
+
+Count = 307
+Adata = 09ecb2406054716418ff3600c3c5cacb0845a377a2d80542abc36ec81bb1
+Payload = 210ff7975e08388b9a46eb732230e3a3856a497549b5eb49
+CT = 65cff7172189da8e66566808090091a0eef1258ff7cc221959fd6aeb047200907911621e8756b45f
+
+Count = 308
+Adata = 62d515bb0525b565a6a3613ae20343c8da7424c8368e8cad6a862b7d37a5
+Payload = 5d867265965bb2aafebb0691de9e157a24066d06fe3cbd7c
+CT = 194672e5e9da50af02ab85eaf5ae67794f9d01fc4045742cc4db6d5fd910c83fd77aefba3f7665d8
+
+Count = 309
+Adata = 00617ca141e55b045a188e4934caf6db63d4577f634db92c22010e1cbf1e
+Payload = 396b27afd16a1081f37bbc1f742b549f5f68df799b93083f
+CT = 7dab272faeebf2840f6b3f645f1b269c34f3b38325eac16fdf5f21f32cbe5d272004f1c104cbcae9
+
+[Alen = 31]
+
+Key = e45bb1730d0d539aab3805350ac986540de9f0f6c239ee70395c291397b70309
+Nonce = d5c7824af715bb7822b6b340fe
+
+Count = 310
+Adata = 860f4a09ad8b3d345c2aa18ffb803f0bc3b734a4d047a1437701a5e3d95288
+Payload = bc8b3bc48c7a88c9fafde258b6ccaa9d4f0d018703d63871
+CT = 95f083ad6bbaee6ab540fe023858f8baf25e333fd3e89c00e678a392d228b210dc5c991905dacf3f
+
+Count = 311
+Adata = 8a84b57915bdbe7bf5a1c1a426512b3c178d883251cc46c95a8bbc8ed9e56b
+Payload = 9499ea48edab9bc21b91dd614f04934ca20db8630622f481
+CT = bde252210a6bfd61542cc13bc190c16b1f5e8adbd61c50f010fbdd3b305522dae6b652322d89d9ac
+
+Count = 312
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3fbd1219a21aaa84044c4f23c08f5d
+Payload = 73843a4e9e7937fed24bb1fae15822213b1aa86c07f1b5d1
+CT = 5aff822779b9515d9df6ada06fcc700686499ad4d7cf11a08b6b08548e794eaf85ad9f5de80b1c00
+
+Count = 313
+Adata = 61bb196b212feab645f05a8aa1986f6210a384c15bc749245d840b3565fb36
+Payload = a8e24266e5981b2ed14213a29f961cbbf7f02f63a33c987e
+CT = 8199fa0f02587d8d9eff0ff811024e9c4aa31ddb73023c0fcc73643a7ee9291e15137d7046a92f3f
+
+Count = 314
+Adata = a49c2df94ba65107f375ce1c53b72406143f6bcd270945de5b7811682fe361
+Payload = 3e3c402caeca41687d12897102e04312edf7b8c7d8567a22
+CT = 1747f845490a27cb32af952b8c74113550a48a7f0868de53204438662ea82f423a69c6e4e3c0623a
+
+Count = 315
+Adata = 7c48480e9bc87ba299e03899698b2259eef150ee0f2efff40a5583b80ab484
+Payload = cfa9292b9052ac6bb863205d3c0dc2d9e20d2ba6a680d2ed
+CT = e6d291427792cac8f7de3c07b29990fe5f5e191e76be769c6ea00b9cd881e3f4b1e838dfa31f6560
+
+Count = 316
+Adata = 5cf9744090366d828b477dc890eab8ebebd44f6aeaa5b101291bf67d12867e
+Payload = e0fe4e139ab0deb4fdf2145b719f35c50b869e6cb20608b5
+CT = c985f67a7d70b817b24f0801ff0b67e2b6d5acd46238acc4c59b3b87d722a58cd1de58f3963d12b3
+
+Count = 317
+Adata = 761d74be5fae170a1bdfa16081b44c1e49972e15ce0818df1390bf7204f619
+Payload = 665fdcdf55a1231e9912562eaa5a5011d69f6948e29e3f8f
+CT = 4f2464b6b26145bdd6af4a7424ce02366bcc5bf032a09bfe158759886124f1f0ce8147c94f4e7114
+
+Count = 318
+Adata = 9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cb
+Payload = 7b2d52a5186d912cf6b83ace7740ceda3f5f443530c5a49f
+CT = 5256eaccffadf78fb9052694f9d49cfd820c768de0fb00ee6310a79c9932456dbc00515b264f3168
+
+Count = 319
+Adata = 69dd1a050c8d79dafbbe3403af4dc1f070b9b2b980888aa796e6cff68d9060
+Payload = 3cea5ff50167c5641066852fd00061df35b1f66bedb894b7
+CT = 1591e79ce6a7a3c75fdb99755e9433f888e2c4d33d8630c6da7e97f9984a7db3b93aefb4316d9acb
+
+[Alen = 32]
+
+Key = 2e6e34070caf1b8820ed39edfa83459abe1c15a1827f1c39f7ac316c4c27910f
+Nonce = c49ccef869bb86d21932cb443b
+
+Count = 320
+Adata = d37e35d7cdccd9824a1ae4c787819735e4af798a3beb49d4705336d6496853ad
+Payload = 771a7baa9cf83aa253349f6475d5e74dba4525307b022ba7
+CT = eebac2475004970071dfa2cfb855c4e78b1add8dcbccfc0bd6b14027324b657a56263df148665393
+
+Count = 321
+Adata = ab22bc22bf2628b0e0ab245c3db2fc5128d13a011c2cc9b9fea05a79a3410704
+Payload = dad95a4b4d3754613f0542caa62cfe4e375dfbdd369ec32e
+CT = 4379e3a681cbf9c31dee7f616bacdde40602036086501482a8c810b6944815fd2e434193520b1d5b
+
+Count = 322
+Adata = c48c5aacf701137fc40fd0d3649641aaa5be427ceee702cf7ddf6408f458a581
+Payload = 3f28df9263e473be648fabad163aa4142b633388b16d8392
+CT = a688667faf18de1c46649606dbba87be1a3ccb3501a3543e8aa447b79284c588bef50b423de97908
+
+Count = 323
+Adata = 477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2
+Payload = f83107b50a1f192ed45cc43fa80e6b519bfd859173ea9ee9
+CT = 6191be58c6e3b48cf6b7f994658e48fbaaa27d2cc3244945d4f4a413eb3ac2c474134995d4db9a16
+
+Count = 324
+Adata = 143bc037f1d0bd4ec16825c58cb3796bf8989200d27bda9beabbbc49247f59f7
+Payload = dfeb324ba459ec4a5c54d2534e98002412e67db19cfc66bb
+CT = 464b8ba668a541e87ebfeff88318238e23b9850c2c32b11756a3fb2e06734b28fbd57942a609d914
+
+Count = 325
+Adata = ffc416f1dae4e43c1a01339a604c44d6a0f25ab9ca3978c6aacb6d270d510ee6
+Payload = 0765949e6f22c422ebd47dc1ed73f1b849d7a058a1656fc2
+CT = 9ec52d73a3de6980c93f406a20f3d212788858e511abb86edb94280d3c4a1cd8cb00705f60ae36f2
+
+Count = 326
+Adata = 6090b596b4082ec6926576137f6561cf13916860ad1cfc43650d1b5142a12041
+Payload = 6db320cbe76bc5b8cee9ef89aca11765571c6c501993195a
+CT = f41399262b97681aec02d222612134cf664394eda95dcef612caca26cc3bbb289da3be0616b3445f
+
+Count = 327
+Adata = 178ba75adb7c5bea6769270bb3b4f6ce208d4a786913d3ced7bb4090b5f65544
+Payload = 0875020959ed969cfb38636d1d5aabce9658b00171a7614e
+CT = 91d5bbe495113b3ed9d35ec6d0da8864a70748bcc169b6e26cc8c665289d907628eb0e299c2d411e
+
+Count = 328
+Adata = 90f0474dca998916075b1b1428df14d90be05491bb8d5d88e32e65ec890ba9d3
+Payload = 4f89ca6ad371f86a6e073ec12fb1b928bb10d6639233b918
+CT = d62973871f8d55c84cec036ae2319a828a4f2ede22fd6eb4f7e481607a2a0529f9cda1d5903325b7
+
+Count = 329
+Adata = 5ad8dd40ecdce52d5b30424ca0bccb666f34f66b0c9a4c1260051ac04ca06aab
+Payload = fe2009d0a4a1711b83057b948cd0b174a3a042fd97579ab8
+CT = 6780b03d685ddcb9a1ee463f415092de92ffba4027994d140a1b9ba2bfe5bf778b859f0ff0c29a67
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT128.rsp b/lib/crypto/test/crypto_SUITE_data/VNT128.rsp
new file mode 100644
index 0000000000..b796541cf5
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT128.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = c0425ed20cd28fda67a2bcc0ab342a49
+
+Count = 0
+Nonce = 37667f334dce90
+Adata = 0b3e8d9785c74c8f41ea257d4d87495ffbbb335542b12e0d62bb177ec7a164d9
+Payload = 4f065a23eeca6b18d118e1de4d7e5ca1a7c0e556d786d407
+CT = 768fccdf4898bca099e33c3d40565497dec22dd6e33dcf4384d71be8565c21a455db45816da8158c
+
+Count = 1
+Nonce = f7a5098b2a4d92
+Adata = bc498326755503ff25d02805eb3517221b54eb4fd79af0fcdf9312b2a9ad95f7
+Payload = 3e2144e2a381b718962a77e167778bf579957a8fae29612c
+CT = 98ce91033fabaa8fe853d347be6cbe5de102fdccf042e7be697b41c9a69acaf8386140ee6e36f406
+
+Count = 2
+Nonce = 732d2dd64b4a25
+Adata = 495b03df82e317e4f351c5323d17c673f4c77856983179d7c7cb75c2b0573c72
+Payload = 4bb0d170bdcc70fd18f19605cf9c6181082c4367f1e6fbce
+CT = 9bd9304259962448fa8487bc15d950303621213afd88f1e32d442ff663242fa269c4a742a220edc5
+
+Count = 3
+Nonce = fefd3ac595428f
+Adata = 91ffb6be8e129cef9189f7e0fec8e937afcfc6083b6a79a778a724bb3e8d0794
+Payload = 9e8c4f1292e8d7e5179b34ae5d2ba2491d7754acc54bb91d
+CT = a5d012b3062cc93b831860d76539169c88854b85550c67fc564a2f1cb7d77e0223287740d5ff9003
+
+Count = 4
+Nonce = e14d81ee3b873a
+Adata = ecdc5249ceb48e8d5a4483043921c00c1acb1843fae00155a28f3a127150b1c4
+Payload = f99e23288e6b5ae85c14610994d90d5fcbcab62b4ed1333e
+CT = cc4ee711d0202deb58664e00cf0cf70b737f48ddadcefd6cd217fb611daeb66fa2d8e1bd43cb2131
+
+Count = 5
+Nonce = 2cbeaba94dbbd1
+Adata = d129674c6c91c1c89f4408139afe187026b8114893d0f172f16469b183fee97e
+Payload = 1b42cb685bd462fbd40e0273a81c767aa81cb43f17d3c0c9
+CT = 1a1b1c7130aa63098dea17ffbb2216d1d276cb10145b0762a45116736e95d823e579d73dc31dc487
+
+Count = 6
+Nonce = 8a961df9c23f6d
+Adata = 07185502bf6d275c84e3ac4f5f77c3d4b30d8e106603be84410c11849a3c18ea
+Payload = 434e182d04ecda519a6119fbaa4c45e8c9803a9a3eb51dae
+CT = 3f603939c6226d8208b2b0e675b82557609ceaeeee4032c7837ed517dbd7e6fe34ea42b01c69d370
+
+Count = 7
+Nonce = d3604d390faab3
+Adata = c95e7329d36145664da69d25f24b301d334e1bca2baa74b2d5c325ed7d04fae4
+Payload = ee104be898a225eb1da99163bbf768d8ae6d5850af6f8767
+CT = 3e6a7683d9d804f791f77d2b69996102ba82477ec4557747ef2e0b322f51abb366a1e8e37f4fe4ee
+
+Count = 8
+Nonce = db5004a1cdae8e
+Adata = 1370fc9d5bf1ad2d071be5a28b235402a85270f536b5601c221519a3b329c71a
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 6db54d6f5c3f3efa6da67aea1234d46e8b679a5c257c66d82e4ef944778281ed186b4a8099b47fff
+
+Count = 9
+Nonce = 783477f981ef05
+Adata = 04bbf2a826bdf3d55069b1936c4f8e8e08189f54066a035c950c7347604b1b65
+Payload = 6150f132b25727ebbaed9f16bd91ebce00c68e5b39bc0ef9
+CT = 36f78cef22cacaf9f3d4464821737f7fbacd79be517b4727bc5c098625c51ac7fdd15da2cc9ef4b6
+
+[Nlen = 8]
+
+Key = 0b6256bd328a4cda2510d527c0f73ed4
+
+Count = 10
+Nonce = 21fd9011d6d9484a
+Adata = 66ff35c4f86ad7755b149e14e299034763023e7384f4af8c35277d2c7e1a7de2
+Payload = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2
+CT = 5a0be834c57b59d47a4590d8d19a1206d3c06e937a9b57f74034d9fdb43c3f48932aa72177b23bf6
+
+Count = 11
+Nonce = 97f940d7c1230bd8
+Adata = 78337ddfe38be7897372b0f805603a9a9e55598452285764641c3bb7aeb54a3c
+Payload = 772aeff60eb3adf5a9589ad54dda0401cc9765589609dbd3
+CT = ef5c408dc6d0b501925a47def54d8deb9880a07a3e6380bca20a3995cf25c5a7b9477d8916adff73
+
+Count = 12
+Nonce = acfdf302ed116ac4
+Adata = fe9d9989bffae3c9e6161eb0aa9d54ee8f5051f0dcabb5a750c5478c11798ce1
+Payload = 99ffe16de323a9b65fe60305a2d062cae490ccca6d9fe9da
+CT = 1bbc2c7877d845591660636cb6ccf4edcd4c156996a26a707d0e2fe322f203c08f44d7f9bd7258c3
+
+Count = 13
+Nonce = c8d36e13b7459c47
+Adata = 3f3c3a4c26dba18f385274ac5ac3df73282686488d91bc8190b7f61071b07f62
+Payload = 316ee95430329f706348886b8ac7779e3056809e25da0a03
+CT = fd2db9611a26a3e90f4861467df60edcc595f442332b089905fdd72307c3355b19ea66d4a16ef17d
+
+Count = 14
+Nonce = 5822755a3e47c27d
+Adata = 1d72d6b371e85ca359483761704f80b3360f4d6610e6d5e490b0d509f73c3233
+Payload = af4ae8f19cf6cbd199677fe033859f56906f1979b1b5926d
+CT = d5ed6f8d5c42f4f3ea527094173b278724a2ba787e416ad759124db19ab1373a5376f46ec7095ef4
+
+Count = 15
+Nonce = 6c1c94c2e71b865b
+Adata = 298cac1e4684182786f386ef3de79c11e30b2dab7579b8ca18d0312200860403
+Payload = 6e4d992d7541e02a4aa167e56c7e47206abc25fea6c5125d
+CT = 560cd43a502a6e8b1af478a3b640a68937d1a83057110d38eaa52d69ab9790edc384b9a5d8c91dbf
+
+Count = 16
+Nonce = ce7ec65cfeda31da
+Adata = 13c1298cbf7fe6a9ab378f86d3c2207944cc2a232f9383513ceb3b202086d365
+Payload = 196c80d02b663bdd89fdaa31e329b5a8f7c596236ee8dd80
+CT = 00174dd83a7f8edc71afbe5da095160336be9184f693db3db1f45de395e021c6fb1b2991c91bd643
+
+Count = 17
+Nonce = ddb739acda6c56ec
+Adata = 7f89bbe513b9a7ebe9be3f6eb88782080593c83e8cbe47fbe15bdc3e5782090f
+Payload = e95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d
+CT = 819d73dadaf095652cf39729b2e2cad7fc7783887a5acc15713d941b845d96a5bf65e9f80ae7f923
+
+Count = 18
+Nonce = d9bb71ad90152d5c
+Adata = 20bfcba120cdbeb07c5f4d70338ffce493822d78a03c9e80b5b934e16e39f70e
+Payload = f1fe98b50ea2f9f088f6f93910757cf744d5aabf3081966d
+CT = 36decda8ade6ab104a201c6d370412b907a559738eef59665e99761cb1ac77d772b9cce9345d9a75
+
+Count = 19
+Nonce = 2c9ec9f1f1358c50
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = d74badb8ad7f2c2bcdf67e497151d35a4fc2a3c4c871868a
+CT = 0e9066270da6e03cb4307c43adc71b4b596213a63fc8032085ce60506ac3bd97327904ad2e072a6a
+
+[Nlen = 9]
+
+Key = afdccc84f257cb768b7ad735edbd1990
+
+Count = 20
+Nonce = b7776aa998f4d1189b
+Adata = 9f9ac464de508b98e789243fdb32db458538f8a291ed93ddf8aeaacfbfc371aa
+Payload = 56d0942490e546798f30d3c60ad4e3e110fc04f5b1c1fa83
+CT = 96f124c74fd737819008ddef440320f4a3733d0062c83c893e259aecf12ba08f2a2e966a3341d6d4
+
+Count = 21
+Nonce = 278cf1f09b13f467fe
+Adata = af9627922758a9f7792345716782e8837ca78e8f9db16e3fe12a7124a3d4e99d
+Payload = aa9b9e80cef47b6db3816b1d665f233e696337e21bb8333a
+CT = 5eba7e3b3ecab78121b0d56acb9dbfc6756c1255b42f145d11751638ed36c1fd3c7268b71633c1cf
+
+Count = 22
+Nonce = 4ae701103c63deca5b
+Adata = 5872a1507c833c581ac2750b2b54add4b92be14e45d72db7679f8fa2b4d1eeeb
+Payload = e832b053854fbd40c0d8b6d6b8fd5de2da0c173f5fe594ef
+CT = 3b2b964c3a90d51c0ace186db79818b4d0f7b81236d36017d3635aa1d8167087600b01643b0a5ce5
+
+Count = 23
+Nonce = cfb5b12928e1c36849
+Adata = febe755bb8e4475d8d12f5e96269abd0d4e40d73cb966e2c523343e9a6d2d71a
+Payload = f46d6970dcc37d32d93ff062e68034c1906ee487fd28eefa
+CT = 0d5332a42fc583f4f81744b899cdf2a64cad1e78d577112fee6f8c4b252e10b42fbaf8c7af1e9f3e
+
+Count = 24
+Nonce = 68d5863cafc69e6ceb
+Adata = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab7da44d2887485954
+Payload = dd4438d7ba3edc73872e42dbbf78cf300fe4bf0eac9e16b6
+CT = 874d3ef7f916db2c2799b6892ef4bfbeb4729ecbf26ac4983a8639f21f8548fae45dc76de57bcee0
+
+Count = 25
+Nonce = ea09fbe5da0fa4fe91
+Adata = 63ee18eb720b21ee4c157dafcb8c7bcc6817f54d5c1b8dd7058c37228a03f8ad
+Payload = c1811d613bf0789beeef693611ef733cd173da703b66ab3c
+CT = cbe5c799952b28fadf414607a6cf8194e9f41194abace4541d3853a52971b0ab46cc0a3eded435c1
+
+Count = 26
+Nonce = 0021be18ed76b3a34c
+Adata = bb5eded483f0ae1106fd08c5e2b91cf06d3a7a73518ad4c479fb05e631ba5399
+Payload = 2d5531d1c51c6ea100b028596bf9f24dd90be14eab58f07b
+CT = 7af0449f7359b7f3e5f6c1e7bc264c7724037f4f16077fd0a2a8e3cfb827c7e6edabb34f7bbafd01
+
+Count = 27
+Nonce = 449b51ee0760179e35
+Adata = e99bdf783070a3a48431704e90277ca65a9704c12eeae2e2d70b62f816115267
+Payload = c4896d58442877c986e4f862a9f3a3179f0e9b96316a90d8
+CT = af7531c073df01077fd5c8ea9a5530c2fe1688d529e5c2f24aa8feae6a500919a336dbba1d9fb7e9
+
+Count = 28
+Nonce = 232114642e0c6b55b5
+Adata = da288d2014616f16a2abf5923dea49aded1748592adbcd97415c33ebfa57150d
+Payload = 11fd3f94b5a5ce94f2740a27a0771aeeac77f3155d2bc12c
+CT = f0c174a7927da0bb88e92917af8ae1df4ffc3527004e9e2d0b25cea7ed6e4fe9069a2ce49875230d
+
+Count = 29
+Nonce = 660cb6d654afcbdab4
+Adata = bd96c3c225099fc58cc1f97779304606b11efe9712fba13abf74fc1d7d44a900
+Payload = 793c0bc3deb6e0bec4c1d1fc17e455eb1aa5e9e25cada861
+CT = fa4b14a381ee41fec7b7279e58f0d06a3beec26d645f81336218635754d5563f2cd48bdbb267e5ca
+
+[Nlen = 10]
+
+Key = 6ccb68d3838d4ddf660b9cd904cad40f
+
+Count = 30
+Nonce = c4fb7519a19f13d9d1fc
+Adata = 092e64fef08b5655a86cdb8de63ffaa7772e8730844e9016141af8bad2216246
+Payload = 5ea35c082e2b190e9d98e6b2daad8672f587b4f2968072fc
+CT = cda5fe3d15d00150b99120c7f206b88a4c2c4a39ca9143425603ab284a73a38cc916f8b653c92ab4
+
+Count = 31
+Nonce = 45927852550961f1ae9e
+Adata = 53ae030474795ffda4d9ac0fc3c45afb592ddd761f7b5335c13a6747e21075a7
+Payload = 6c5f468077536b4c9a94ea4a6fe3cf621083a210daee45b6
+CT = 694847b6429cbc3902d9cb7049625aef1e97b569e1e3169035bb811491d142cf1b26350f8451bd14
+
+Count = 32
+Nonce = d8c54463dfcf02d0e327
+Adata = ff95c0ed0da32d1b5f57570b815a50592ecdc9c1c4e727e0f6dfd93fc10ce88d
+Payload = 7321a6de8d694ea05623206f5df438c5c2cdd6b1eccab4d8
+CT = 9cf8ef119aa5cf3d6305d50b2b520a0b10bcd240e27276749c68e8e641b0120f7dd66e8f0cfa4205
+
+Count = 33
+Nonce = f690f3a996928275050b
+Adata = 41c05fda535770699ed22cef253753b658437f833afe65c9c393581d835f0fea
+Payload = 56520a4bfd7b73a471e0446f9524a407e81c2681b7329e35
+CT = 14aa15f9f64c4c64f6e88094e012ecb24193249f044c033dda44a62f97c0fead3f65b28928bfbcc3
+
+Count = 34
+Nonce = 26eb9ef25be62148fa61
+Adata = 8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748
+Payload = c68094c26c7f017b79f126dc26b3bbcb95f97535ca412da5
+CT = 7ba8a0c2fe2b230768d1c1874085ddff8926931961bc4558f0d5444466bcc631bef8e58fe5818af7
+
+Count = 35
+Nonce = fad21bc27dabafe7a4ae
+Adata = dc5d7fd97bb3243ba585fa0d71a07191667af418e30a6b76bedd05b32c673403
+Payload = c247fa8d8091cd3f299cdacba7fb7af93549e9e3160f9cf8
+CT = 3097d2ec0f8bf00b22504ab03a75e740d3e59c269c3ee3f00b5419293a67eb008aef0f9f675201df
+
+Count = 36
+Nonce = c911348848fe67406dea
+Adata = 50d50a0b5ed4d6904ec3045263af0255a6494b7a7e2e95ea806c4bb788423dc1
+Payload = d846c170ae0111348362901503b26d58f5efc17b6d296aba
+CT = 5d72562f7dfb47bf34b90ee4ea11ff9f726c915b07f4d843dec5a554f4bbecbf6943ffdab8d8a26a
+
+Count = 37
+Nonce = bb921b46a16d20ae4046
+Adata = 7d17f8f60ad1e61a168b5b0e7fbbc90cee79b612b6d6c0d7ff6ede042341e8a1
+Payload = 71bb6ae84262646c9be95e0f4289ffeab7555ec6746c6ae9
+CT = bac123320888b553666249756e6d63b3498760791cbe9e34e5b1162b7489a59a50c0f0f3618e6c2e
+
+Count = 38
+Nonce = 61a8b8cbfc9bdbadb2a3
+Adata = 51cf2a8949e13eaa087a34c9ec4d7fd92b862efd6a0b1fef8b016fa2c6933426
+Payload = 362f9a46aab59fb6213c83d791b2129b34367ac2de2048fb
+CT = b8a57e8714d8789f4ef2af29e0efec21b1ef67fdabc7cdf0ed5505f1f0ff77723771338585c456b7
+
+Count = 39
+Nonce = 6bc4cd23c32a913998a7
+Adata = 92fbc970b5e64198ce2a138de92767edff8d82f12f8832444b346d159657356b
+Payload = fa442383da234cf8f0c5fb667218bc3bea0c091b3a8e6b77
+CT = cdfe3e83aba43a9804c5a1832e0e47a9a153359cc32db907714025f485c7f40256049f16f859b859
+
+[Nlen = 11]
+
+Key = e6ab9e70a4fb51b01c2e262233e64c0d
+
+Count = 40
+Nonce = 74e689eb5af9441dd690a6
+Adata = 42f6518ee0fbe42f28e13b4bb2eb60517b37c9744394d9143393a879c3e107c7
+Payload = ba15916733550d7aa82b2f6b117cd3f54c83ddc16cd0288a
+CT = dcc151443288f35d39ed8fae6f0ce1d1eb656f4f7fd65c0b16f322ce85d7c54e71ac560fd4da9651
+
+Count = 41
+Nonce = eb118fb41284bfcb1bc338
+Adata = b5a6067fbac46578cfc8d3fe04108588c9de077eb009249374f205553bba9d02
+Payload = 863da00c7accf45418d47c1eda72338734dcc49cd599f328
+CT = d64de7a56146b971e21bf5784d67bab32dd837cfb81591da4a0177883346dc896eb39e8a32bc1393
+
+Count = 42
+Nonce = caba2716d07e95de83855e
+Adata = 0e0ff2c73ea5fa8f8726a3514cf906ce1610a1a6dc19b22682f9e4619f762d82
+Payload = 2af6d5636ab65db2058b2ba16df257369fc4e8aef8b9481c
+CT = 3c9e006c7d8eff5f448b0cc9c27c964713241aa7fed3665d775ea25fb272981de8b8aa0a637498fb
+
+Count = 43
+Nonce = 314c136999e41d137bd7ba
+Adata = 366c659bc45d0a88acd54ef7eeaa3e140e1cafb1b01474a065a9d460c5e83bfd
+Payload = 217b19ea6a431a1f66bd9d02b718e8507a08ab8e6f603e3f
+CT = 33d7b672b23e8b03a39ff3fd1e7b0f2be67163e3e3bae072f2aaa211dec623947a50b1252bc5aad3
+
+Count = 44
+Nonce = 6fe51f5013f53d4e4fd907
+Adata = ff182f2e179d790e827cbfd0bd8b9297ecae57ffcef9e25ef114474a22e4ec5b
+Payload = c6bf582b49dd4ab6cb33f3f88e8a4d14fe32b308ee3b4682
+CT = 26cd5dc5eac2acda283ca03354260ad57af79e20c5e92f5775ed171bb0fbaa6f431c5411cf9b536d
+
+Count = 45
+Nonce = 24bc8dc1e2354667b79ba4
+Adata = d0d48d01fc79685c6bee04d45e40d06cdf1f4607542b1ece556fc2d1bb2b03f1
+Payload = 90f52ebb1bd5439386faeaa194623285f750672a7baae64b
+CT = a7f43f56c50705a1a101044b954414fdfbe32b518e934d38f391749ea3acd624c01e4583ab1506b7
+
+Count = 46
+Nonce = 89ce46b3de3afaf2518d41
+Adata = 5767202c913584d653f37d926a0c5ac1c67db3efd1dc58fbff998778a6856254
+Payload = b2ab379a0dd15baf91415eee3a4e56e7eca54d4c1c3094f8
+CT = 9f530e455a54b86835eacd8801b34c884a3b2ac819ba38f894e43a6b1cf73cb2d6a1dd8331549520
+
+Count = 47
+Nonce = d3208eb695e84c7a925037
+Adata = 91d8fa65a6885f162a795afe2898f391990a8b3a87c11f94734dcbddf5f58da8
+Payload = f15e39f0e4eaa5bf81359d8e30186522f1a1a415436668cf
+CT = 7f1d9fcd9e5cce3a81e3495bfecec817fd7180d8bbfe0abab27fb6425fcc3537ce471425a5b17dcf
+
+Count = 48
+Nonce = 067de2869333ed22c7b63e
+Adata = c31e441fd551b3fdfbe23ceec5ec1f838f31a5300f6055ad2a936a9d0c1c856e
+Payload = 1536d9c9a09302d142c85638202f5bbf0c287f68115d51d8
+CT = b1a5c7a7fd23228dc7ea26885802daa0719f6a23681e1d65dfb879c21b46f3307ef22f1da579303f
+
+Count = 49
+Nonce = 15f61b4526d19bceae1093
+Adata = b97b122af73e928e617e98684f845be4cb80566345739b7a884c6a3eec5102bf
+Payload = 37c81988c07a5b01e2b40ff9f9ada5f50ca764efb717ff9e
+CT = 0d93a5c77482d573b7f1b8c5e283f2571efc9f54216a4c01900504a73c8817ff2b55618b2602bf38
+
+[Nlen = 12]
+
+Key = 005e8f4d8e0cbf4e1ceeb5d87a275848
+
+Count = 50
+Nonce = 0ec3ac452b547b9062aac8fa
+Adata = 2f1821aa57e5278ffd33c17d46615b77363149dbc98470413f6543a6b749f2ca
+Payload = b6f345204526439daf84998f380dcfb4b4167c959c04ff65
+CT = 9575e16f35da3c88a19c26a7b762044f4d7bbbafeff05d754829e2a7752fa3a14890972884b511d8
+
+Count = 51
+Nonce = 472711261a9262bef077c0b7
+Adata = 17c87889a2652636bcf712d111c86b9d68d64d18d531928030a5ec97c59931a4
+Payload = 9d63df773b3799e361c5328d44bbb12f4154747ecf7cc667
+CT = 53323b82d7a754d82cebf0d4bc930ef06d11e162c5c027c4715a641834bbb75bb6572ca5a45c3183
+
+Count = 52
+Nonce = 6a7b80b6738ff0a23ad58fb2
+Adata = 26c12e5cdfe225a5be56d7a8aaf9fd4eb327d2f29c2ebc7396022f884f33ce54
+Payload = ba1978d58492c7f827cafef87d00f1a137f3f05a2dedb14d
+CT = aa1d9eacabdcdd0f54681653ac44042a3dd47e338d15604e86a0e926daf21d17b359253d0d5d5d00
+
+Count = 53
+Nonce = d8e133e7ff8e0a0ec6c4096e
+Adata = ef9e432c15d8c93a4b5c0666608e61c824cd466d7940d642acd3dc33057c0395
+Payload = 2836de99c0f641cd55e89f5af76638947b8227377ef88bfb
+CT = 5edb056d85dafeaaf74bdf4caa47339d6a75bf1ee998565e9f9cdf6ab825f6e026f5be2ad895033e
+
+Count = 54
+Nonce = 2fa8120398d1a946f391367c
+Adata = 377cd407ad28dc02bd3835a31d92f8295c9dbe597f56662ceda112c588dc73a5
+Payload = 7a37255b682766a0bfecf78e5162528885a339174c2a4932
+CT = 701f5f506fc7e9ea4a27a4db5cb890f7be3b4f6bcb20f97ed3021f6ad620648b8196ab1693710398
+
+Count = 55
+Nonce = 8d638ef43f56dece910139e9
+Adata = 87ea7b095388de70ac0ed23e86f502400910028a8ab5e3bbb91d05821c0d2d61
+Payload = 7370d9b453936955b9c9d336f4b283237986232de007bf41
+CT = be2f03f6ce1731418a5f53b6f6e467b73992a0c8102d8ffc2d236162688096d80b8733d2afbcd244
+
+Count = 56
+Nonce = f479ea8812b6b2f6ac78fe9d
+Adata = 20c2b8f5d3a65a66ba8a25e2ee339a779a32d45f5db91077efae6cf308feef50
+Payload = 59ff9f7581a781808d36fed378080963f35c00ea5a6e3932
+CT = d127c956349c16e2186f55b72254c677f03c61f1c4ada9e661bb9415b32d6a58f5f7647ed41de685
+
+Count = 57
+Nonce = 423515f7bd592d6a7a240866
+Adata = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032972c939db300d8c1
+Payload = 3c379f90b11c622a765756a15efc8fc3ca7b08b3281945f5
+CT = 15792e01fc17f5294c3405484291082c00a8f46dd9af8ca230ba95c4058501234a1b97543c998e9d
+
+Count = 58
+Nonce = c3f3da69e13c5733039744b1
+Adata = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc5731303fe0bd56b11e
+Payload = 9db6fe9adb8c0fee87cac9a7f01a7ed8a84f0512d09b1834
+CT = 9b6b829ca1dc4e90d4402188632ea3377cbec2ba60f0f072afca1b08b6dd589a17a32d49b6f7135b
+
+Count = 59
+Nonce = 0a57d59f21ead5b6d80cd2ce
+Adata = de5f2d413c98c6ea2a5640a7b1c424aebe75cbc78b06710b5bff8bec6afb5a76
+Payload = 0b5f6389f7c20f4ba326e8f05d373ca27b7ebe59e6d729f0
+CT = 0b704e14bc7d2977d89e0b2e7ed7fe3c9e0f2ea80d2d6165f344f2f1b2218d9b4283fe640a6d315b
+
+[Nlen = 13]
+
+Key = ac87fef3b76e725d66d905625a387e82
+
+Count = 60
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f3898390e90d0a0899f69f9552
+CT = cabf8aa613d5357aa3e70173d43f1f202b628a61d18e8b572eb66bb8213a515aa61e5f0945cd57f4
+
+Count = 61
+Nonce = 2a27257bfaadf23a87df082c57
+Adata = 0001dc666c9daf3560daeaf514270db0b5075d295068e6caf231c1de0e1a9300
+Payload = 6cbbfa6d736fbcc4cf73ab4d7be537420e0e574ee1f2d1b5
+CT = 72d525e6bb312bf2c20b91f41108779789c25720797ebffa4cd9d735f51430275387c565cf1a69bc
+
+Count = 62
+Nonce = b94ac8ed14895c80a91fda8367
+Adata = e1eaf35fb266f243a3fa407cd41815ae6432ad79877bfa59d8f196cbf19bfbb2
+Payload = e6ec561496ce18d96b26d594a47ffad02d68ef25d2d2edb9
+CT = c63500445239bbdf71a8dfe3f8c01061d659cfeb038b825dc89fb5f507f5aeefaa9365f0b18dcb3c
+
+Count = 63
+Nonce = bbae10aa491ac9c668a3ba8d7a
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 9c629c375f014e162895cfc25a972c29839f97407e7c7cca83d0a61d453d596fbc5c2e315d9780bf
+
+Count = 64
+Nonce = e0b10e78e9fb41ee970143e9e3
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf3c99c9d1a35bd8e4ed36596789
+CT = 867799b30558697d6efb4afcfe458cfad8da21139a0b43128e8f8e13b7896b244d0c9aa52ed31a95
+
+Count = 65
+Nonce = 17b61109f5e37754e4e92a28d7
+Adata = 0bc2fdd890c19882640f8d4188b88b9db99cc1934cc3e98a5df08589287968a6
+Payload = 347c1eb4aff917bc0012f005e74caadc93f4f18f2b614ece
+CT = ee19f3120991b67b2389e6f36543d99590f2e6d785c9c8ecc40eb85585cc3b7520a940a4e993327d
+
+Count = 66
+Nonce = db3ca9e80ab761804349379961
+Adata = ce01369d08d37dcda2c899c9fc0d11ccf94a0051b2816a1d6c3ad07fc8dd02d7
+Payload = f0e1af1276d2918be91a191814660bfe735463d3983de1ed
+CT = 0f1b1228729b181772d7cf55ad257fbcb19cd46f7b31a885401358c7b44aea27617b429583103a1a
+
+Count = 67
+Nonce = 1f57959cecbd377374477e33b3
+Adata = de1c7c83ac61e1f99ae99b198f4af5d24f8de60ea98fe637f3a801fab38b2a4b
+Payload = 42a42b84df098ceb43519c4cb86c14c2fafca39346159e13
+CT = 12425453de653d0fe8103013fde1ebf4a8fe18f76f0c9d60e93525fe8048c3b2147a149f12eaecd3
+
+Count = 68
+Nonce = c9db03e2efbab713b0b6404210
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918696a
+Payload = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c
+CT = 5cdc183c32b4c1878eb83e8473a17c55c88e2ad6b944ab1f64ddee42614aa737231207636c114575
+
+Count = 69
+Nonce = 89ed296a3ac03fbfb71422b921
+Adata = 1ffbe1aff0a1e7fa3e68be31a74612a1519b59397e7007ef61fc015f316d55b5
+Payload = bff42516e30c92ed46710013c656600406a48a84c1fa32ce
+CT = e08c1ab4ae7edb5184c30ffb3e74689ea855f50b0e890392f26b130720f75c422fdf66fb174383b5
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT192.rsp b/lib/crypto/test/crypto_SUITE_data/VNT192.rsp
new file mode 100644
index 0000000000..06e9ff5655
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT192.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = ceb009aea4454451feadf0e6b36f45555dd04723baa448e8
+
+Count = 0
+Nonce = 764043c49460b7
+Adata = 6e80dd7f1badf3a1c9ab25c75f10bde78c23fa0eb8f9aaa53adefbf4cbf78fe4
+Payload = c8d275f919e17d7fe69c2a1f58939dfe4d403791b5df1310
+CT = 8a0f3d8229e48e7487fd95a28ad392c80b3681d4fbc7bbfd2dd6ef1c45d4ccb723dc074414db506d
+
+Count = 1
+Nonce = 026a0b8b17be95
+Adata = 44caa8ecfaf38e5e773cb0366e1b04aa0b9fac5c34a362310f471960c4a1e1c9
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 3417044bad5fddd9455579123dda4fd342c273a57ff6333dfedf191496d88cbe17c6271b65096e66
+
+Count = 2
+Nonce = ea09fbe5da0fa4
+Adata = 1d9799f2bb0f7ab57fe3de27949ff64066131c81bfee172b308f9bb0b3171067
+Payload = 469ff9698cfc96b581d7115c822e4363d7355ec5daed2eae
+CT = 1dae7cc16f1b469290902cfad47b959784b4d6f48a79e690d47e30b635d10d1663477d61d7ffb55d
+
+Count = 3
+Nonce = 8d27bcbf9ebfd3
+Adata = a7070b85b7add9193c9dcd2e6c03f6e7ecc52ffe9e099866baf7472f20c03aab
+Payload = 225651d072dc9d93762dd79691ac2b6ddba00ec1252d69eb
+CT = 5da819adefbf794612eb458519debcd524c283763eb3d7252eca8766bdf0db6bb2dcc793e1749c21
+
+Count = 4
+Nonce = 13f560187b6077
+Adata = c4ab4244db75f8256e55c5b613a07b11c963c3cc24f66128aad4ba8b7ca99331
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = 3aedcf8347aa23fd3325ce08b6b00462536baed69968a753feab6761c55431bb5668e1f5b7505e89
+
+Count = 5
+Nonce = 61e0e28bf344a9
+Adata = 5f998952de70449ad46428f2ff8a01c5af43c0107a1bcc6930f19d4112598666
+Payload = db21b37e875d7709a02239ce6ea529cf37255d5b617c153d
+CT = b8f5fed39c723d7643d6dcf2efd3bbd1ba0da1ec901305fd64b2302ace4f66216ca8b4d776197692
+
+Count = 6
+Nonce = f6be4aad63d33a
+Adata = 18339be863fb8a887d04ae9ff3b4a7db095075cd5d113a9ec87b41fe85ea405e
+Payload = e53101e6eabcda32c13d7b1dd1d88e7c2ca3ddc2064f64c6
+CT = b758858ab60e1630a0883d4d330119a593729a3015c42525effb985b9c2dd9ec954bd25d9c464c67
+
+Count = 7
+Nonce = 2c1c59aa0d8eff
+Adata = d44af86b89fda8448a9b2fcae20ea156dd8738c8251699c02b785811c830bf72
+Payload = 1fd7188a43dee7b059420e8634d71d2c0658f6d0d308dc73
+CT = d046f845a67800a5a58f461e5a8641e8fc9b4c53b32e61d172adafffbacb297d67f6b5c02b982e04
+
+Count = 8
+Nonce = 48e4598edd191e
+Adata = 61588bdc980ea2310e87dec4c651e9a55c27e3858b6505cbf3bf85e51931badc
+Payload = c25868f390af5e59c035cb5830e018c62c5b96bd35b764f1
+CT = 0ece161bd77b7f969b3b20c818769a98c178d84524544664500ff4cfe66ade1832babc019778acc3
+
+Count = 9
+Nonce = 6d576ce3c5fcb5
+Adata = 92c598cb5ca2926c11f67c3b3cf25493d77606fa60d7290430e0e975091644a6
+Payload = bcd97479db934357a163a9e5f5a85999ca987f8243d8017b
+CT = bee185e11b3d42bac846b9d92c70a078aebfa630ab763840391031b3a22b2adeb9791ee35765c8cc
+
+[Nlen = 8]
+
+Key = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193d
+
+Count = 10
+Nonce = ad749d596d88a4b4
+Adata = c67219909828adef64422286008e1e306867a1c0b3da95444507a68b45c953e4
+Payload = bd92d6744cde446fc8621625658fc4bc00dcb97f06195ad7
+CT = 076cffd0ca978fe2bad411ced45a090abafb22a99896f6a75a1969276aa2b0cdb37ccaf2845dbf6e
+
+Count = 11
+Nonce = b1dc81d116d94f5e
+Adata = aa4b71906b6642f10f66c2391ec157c7cde97eb322db10045af4c5248807f691
+Payload = 9aa6dbe1cd3eb98d330c937d31ef93bee8938b6c5cfd38de
+CT = 720f6876ac91665f20147483f0655fdbe21963a01e36f1daa67e36d7cc8d54cfec0762514475127b
+
+Count = 12
+Nonce = e758738df5c89af3
+Adata = 5715fa238f432c926e62dd93708d0e3145428e0ed45e1efa8148d2c4ab6cba50
+Payload = ce80b99039a16e69018d1e3c239dd1bf06e94a78b0b1df37
+CT = acdf7ba3edca1563727ed85cabf085c2f0c8f27556c3c064ef50d85bc3ade6a773d956b2660ac367
+
+Count = 13
+Nonce = d586c4c67d535476
+Adata = 1e8dc63c6c54a540b6b02067ba7c719221cf289fa3897299722c9a2bd6eed05b
+Payload = 2f88305117f9a5d807d54b7e95ecfeb7327e52d9acac352f
+CT = e42b86e619be1a38973c934babeb4688243a9012c85d643d81e024aaf0a62b353f9bed36681288d2
+
+Count = 14
+Nonce = 77e83758f68d272b
+Adata = 25c80edef3d5bd8b049fa731215b80ca2ee9ee6fb051326e8c6d0b9e11e3d7ef
+Payload = 92e47b82b728d639777d5d5843de2a5c364956cb4b21cabd
+CT = 1b9177f5b76403cb8c690b39c3dd22b55da35cebccb9b64e05fe32f796f0b4a75a459fce6c7d740c
+
+Count = 15
+Nonce = 311dc245549206cd
+Adata = 87767f13bb4904d0df0d64eb22c9ddb65e81b5739baad86ad5e2c239ffde9f6c
+Payload = 8691c0301a216a5f3ed9123886d100309bd85630d6b845f5
+CT = f39fe3620a03b37a4bf457909e0770447b498ad2a2f0f9d7b75f9e4239e43bbf93066897e60f6fbe
+
+Count = 16
+Nonce = 2a17b70f10e120c0
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 92187955ee1ae702ef01a385537119b2bd4545402e8b2384a0c069a2439a2d8843302c6a9999e658
+
+Count = 17
+Nonce = e0b10e78e9fb41ee
+Adata = 9d072b8a3f1a496b2be6728a38b94a4f44c9be40c8793b69afd81d01696a6b4a
+Payload = cea28e7cd0eff0c5eafeec908d4aa8ba303e72ada33db087
+CT = c605e48f2e66e8e0a92471e466981ae5e31db3e4ad80b09f5005b06d15f63f2f015cfe447828da09
+
+Count = 18
+Nonce = 02d72dde23f9772c
+Adata = 2dc44c39940e2d9c94d2dbe40bbf5cca5efb4d4b250a31aa24f208b87e9c2453
+Payload = 809343e986f6ff47f54d4cac22ed39babd12271d4c7edb58
+CT = 0bb59581f22f6b15de76c0066645495a5c19e44381c349263ed92ebb789c314a89c83542b15ed694
+
+Count = 19
+Nonce = 28c4d6de3e2ce51b
+Adata = 913a8eda924589d3206ce0a951fef93668c6c0c454824b217997bff6b3026d54
+Payload = a19f65ffdafd6ad5ee43570f7e168f94a8b4a7b7402ac80b
+CT = f0c91a29f1222b906550ef5c7c0944c5c4236cb6c31122cfada8e796f2ce7f9449f42de504873868
+
+[Nlen = 9]
+
+Key = 8cc622645065c72d0d2aca75802cf1bbbd81096721627c08
+
+Count = 20
+Nonce = cd84acbe9abb6a990a
+Adata = 447b6f36acdad2d1cfd6e9a92f4055ad90142e61f4a19927caea9dbe634d3208
+Payload = 597b3614ff9cd567afd1aad4e5f52cc3fa4ca32b9b213c55
+CT = 2d7fb83e6621eed9073e0386d032c6941bef37b2cf36a4c6c5e36222d17c6fb0631c3f560a3ce4a4
+
+Count = 21
+Nonce = 1fc7a43ed124745d04
+Adata = c892b095173076a40e24522297be27fd3a765c8d417f24c71a9f03b3fe3d8e20
+Payload = 415cd8312dd20a1c26f4b90d98104cdfbe06739466fc0aa5
+CT = 7bebd6f55f15ae57ab73f92f7be6ff37ddd99740e988f01a7a2a13c22df4a156e6d6063235452c85
+
+Count = 22
+Nonce = 19ff5e7c1f2c594abc
+Adata = effcea4e4dbc57410426b39fcf51c9daecd9d310888590d77827973a29c4ebff
+Payload = 97fd2c259a4e672e9555a9a5b98f4c0ec8c4c49c7ade26a4
+CT = a460674c2f358762e97dfc958d90973e1e419dbc6a832e987579b2c4a6bcf0356f48cf8959cfa54a
+
+Count = 23
+Nonce = 64d9bd368ac2357cf2
+Adata = 62c5a16f946b4312517f67c80afe2614c822e3a01b87dc81538c00bbf3fc0108
+Payload = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f9
+CT = 8fb5e0954388b9b58519482962487e9b0768f0cee08afe9a92be2b06a0ecd2d00877abded7d9634c
+
+Count = 24
+Nonce = b4aaf2cd93efc0ce93
+Adata = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d1ae70413e4e43d14
+Payload = dd42449da4c95e858b796085b6b5b3b5eef484dbf3c2bc8b
+CT = 893f86e29972928c1f3c3e25c73947c8d677814bca7fff2cf8d301ceace678f9bf91fc361dff5812
+
+Count = 25
+Nonce = 132f3e19e12f462a74
+Adata = 176cc5a280f6171d00e247edacc81f05c1b9faa87fc831163ac9d76aae59a6c3
+Payload = 8ea05a5033ab8b009664fa2800c24e217488ce6888cad147
+CT = 4771d210ea678dbfab96e320e9c44b68f47cb05b01826ccf42ca4f4ccf986eb6a6b85b99db2fcd93
+
+Count = 26
+Nonce = de709ba64cb75704c0
+Adata = 0cf8e9ab95766b6fa85e88d86e4f349a17c0d90509939e343eede988e7462255
+Payload = 51dd9fda9549f25dd868245a6a54b8d59346d2f336adf9af
+CT = fccc3e44afa6bd2fbcfc5c834db63dc9d152c04c0dc0b43d393162252ae91ca46fb8e8338cbeb75d
+
+Count = 27
+Nonce = b11b4c1b7a26387265
+Adata = 14ed867cc909c0619f366918a7d5ae25279fb137e1dee7fd98ddbe3bd19d841d
+Payload = e35ea4a16e274fcab457fd4dc7886c3d81fc668c19e0f374
+CT = dcca8aa2eab8ac3f5db9cd9560ae0758d7df40d7d868d1f71f498ea6ec8251a6d149c7ca38b25fe4
+
+Count = 28
+Nonce = 20d03227a7fcaef1ce
+Adata = c5c15245e641687d0ca9e913406acd2de3f21fbaf2dc5e4e8963222da61d02a6
+Payload = 6775e5faffd0b13e78da70a789042245d5ef31eab5245380
+CT = 4bb8ed2207f36f40f62d3a2c90f8e3bd8f589059b69037118ce3ab864545ea81943ef0ea9489d223
+
+Count = 29
+Nonce = 267f76b9ec0f5e7c6f
+Adata = 2b421be47d07dcb12a0706f7490d05024fce8f433079e18ec78f4c8678f5f155
+Payload = 9330bb23428ab45f573923e977db74882282cbe1371da68e
+CT = c6ae24f82ac5cf9c18a2d98e610027eb2566a1ccfcf99945655e14c7bc8be97ea47388cb7b18bcf0
+
+[Nlen = 10]
+
+Key = ab72eef2aba30205c986e2052d6e2c67881d24ae5fceaa8f
+
+Count = 30
+Nonce = d7a46e726ed43f1580eb
+Adata = baa86f14271b2be7dbb37ddc7c95ce4857e57aa94624d594d7bd6ceeaada8d5f
+Payload = 2a794b84fc9e4a7e6d70a82b5141fd132177a86b4e8fc13a
+CT = 2d7f76464417613bb61d3657481346b74fc9d6abc6a3babd39365dce86859cd82395d11bfc8cf188
+
+Count = 31
+Nonce = d0afcbc1b2524a4a4553
+Adata = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da8
+Payload = bfc5ce1316ccdbcd8ac62484e7656c87947ff98cbba8e1e9
+CT = 4772c121367d0e8d3edade883342395f3ea065fe7dd7be8c8355b915ca2633fd557ca7ed41e00926
+
+Count = 32
+Nonce = 6eecffd227e8d5349523
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c122e0b1587302894c391
+CT = e2864c6e12ac089daaa1e94af4b2ed04060d7ef65d2f72f0e7d017514d498f1f3c07d650afde8293
+
+Count = 33
+Nonce = a67c0675753f725a8fd4
+Adata = 7dd546397a9a0129861fb6815d419a307f90d259d55f3503961754126cd1b776
+Payload = 80f1f1ea46c92d28f2d60eab39ce056a4aefe63fa688538e
+CT = 882c687c03eaaad9d7f591649e736f0c1c78f95e40d40cd77499a8544bc2a8fe95f55fefc7316f8d
+
+Count = 34
+Nonce = eb83928f0d5f7aa3a74f
+Adata = 060cd3e4aecdb03837dfa9f544318c0a16cdc37fa2a3135be7888ac67e7eb26b
+Payload = 81e9174e9472777b6b184707108c01d6ea6b5d108ec3c6c8
+CT = 243cfa0a0a36a4c20333968910e6f52acc04c6f74e704180623f3a13fc13db958cbac49f7421d6af
+
+Count = 35
+Nonce = 5757abe01f7a1183fdcf
+Adata = 744629263041f0eccfce4a1ebcc18c4c984010f9241d35966263a8b2f72ee26b
+Payload = 991049f26b529af8b0bee0cc83989cf817d248254182f332
+CT = b20469b5f33f0996e8de869ad10ce09924a0bdd7b67a89a09c447a3132fbe5213133650000d50b06
+
+Count = 36
+Nonce = d9adfc5b44ad7aa94b05
+Adata = aa6a5448c6ec87be75eca35725ad2e902dbccf840d25b2bdf7e62e4a8fa4a511
+Payload = 14682301a99bf680805d1ffe62e1506d48cee8c51ef1d255
+CT = 9b44efa185b0c10325bb4c3c0815e6a6e46eea366b9a416b5ae554cb440eadd875657fd5cecc214a
+
+Count = 37
+Nonce = dc3ca30782c9c0a7fe89
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = f9cb86f24536931a1b095b426a07e4621c000cf09b472bf8
+CT = 463f9124d1cc387a0f8b971d1e2da448f0efffc3956ebb2af8312986315522081f0989838ef0429b
+
+Count = 38
+Nonce = 9523f53f92b6e4ba86e5
+Adata = c3b123ccc916d26a2e6a8b5e30041ad69a944217e9b402b7acc0170c31e8c2e4
+Payload = b9bdcac80f64175836ab51bb1a1bee5ffe3a6b9b71afe3ef
+CT = c356b5a78cebd123808fb740754dc47a8ec7c9448bfacf39768e94f062e86129cc9210dfcd3e6128
+
+Count = 39
+Nonce = 16bdf18c09d60f3a2a32
+Adata = eedd0796f23612749e9fd282c864f3118d0683409d3bef1fda352e1422273c7e
+Payload = cc96133e473d197be1bafdfc1a21d58e57d0d89b2ba1c3ff
+CT = f9d78e9e3a41b3bcbfe756385a3715776eb84bb7d8d15432978757883f07802b25e9a5b15c43b451
+
+[Nlen = 11]
+
+Key = af84c6f302c59aeee6d5728ed5da2e3c64a5a781c52c4d1b
+
+Count = 40
+Nonce = df990c42a268950677c433
+Adata = a6ab5d78427f297a4b7e21f1091ff3a5b20caa3fe1cbcb09459d9df596a6c8e1
+Payload = 6db41aeb5f7c24df8929dbc30483b3c7934b3bd1cdce5bb9
+CT = 8c9328258bf71970d33e23a3ff81cc1c9cbe196a1294264bfd6a7255e4801963bb30a63de3fc5b82
+
+Count = 41
+Nonce = b7ea72641bbe2dca6d85e7
+Adata = 4e0f2ddf183281ec131693bdcea3fc9743733c07a486a42d5737735b3f6e3fdf
+Payload = 726844e41b1e4d883024b32fee0dcea38c889cb328885b7c
+CT = 9a133e4582c2ebc445862a9c6f2f4e39223c84081e322c8f262de30da6ef505fe640c53d765f672c
+
+Count = 42
+Nonce = 446fee1e75e79c0dfc9ddc
+Adata = 42b598eaee271e06d9e98dd94152b28ef10f506d65bd660b2fb8b1be9a2d7254
+Payload = 0cdcf348ecc9c3588001802c2106fb64be9c301adcc66e73
+CT = 0c2657b0482b6ca92e1b1c8fdf75eae3b0cd3af205e9bca396ecb1e46beb16000d585e1d9559ee22
+
+Count = 43
+Nonce = 2e6e34070caf1b8820ed39
+Adata = 8bd1ef3a1831fcc8919d736fb23111ca3ef4cccaf20264fab8eb3b071e56667f
+Payload = ca0860cc1e96506c2beb25b53d2947fbab634f0372afc8ba
+CT = 19e4774030e43e6853ab5bf176ba9c4b59f29f285977e3c15198cbe3e34c884c3f56a732974aa1d6
+
+Count = 44
+Nonce = 428542ecfb94a745980aa6
+Adata = 8efe01716b9018084e2ea7616f85b7333d945c0c970f8cdd400130b98db67cda
+Payload = bc6b59120ba2845b0e41f65a55e2ef1c45a81485c926c14c
+CT = cb48b0af6fad251d409d14ce0fbfae9cd9c40bf4a0c1e2b7e7cec415030997e1ac5db974b617b5a7
+
+Count = 45
+Nonce = eff703e6d72ddd23ff52d9
+Adata = d7fc74035e66709d2590b7bb3276245dd43824c9896fbd801ec1d07018b39b6b
+Payload = 1a5432e8085511ddac1be91be3e2945f85f0cdcc3a1c9f8d
+CT = c0a00cbaec65b7ca525fb26e80ee0cd18c7ef47c39c704833e59bfecf263bfdb24686627fd95e120
+
+Count = 46
+Nonce = 6a652ce21334a40a259dcf
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d34e141066f543526db6
+Payload = eb8f1988cb405041bf48d138ad41da7ef364d4ac59a9e324
+CT = d4f23166c09a15466c7e0e2b30627ee5a84f22d7e6135b4a0652b67d559a84b4a915ca6a420fd300
+
+Count = 47
+Nonce = 9382e12d447c0ca23cc9c3
+Adata = 239129eb760f8a770410c160e4e13a6b9497077c3e463b65397393fcd3cb5c70
+Payload = b40e80564263c7f450c53ef84df67247d72e8a04dbb284bc
+CT = 6de2ba26caa80874814816154784912c55e3d6da83488e7250f5a52f82211542b4e2661cf870c80c
+
+Count = 48
+Nonce = 2c3a4148cbb02504a2483f
+Adata = 33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44def0441dc528
+Payload = 60a31736d99c3dcf25b349f6110e1c152b93506e85a01e67
+CT = 4d5e705d08f3ed1ca6f1caa74b46e4b1eee18a0783686f207de16aaa41d06bc071657dacf14da754
+
+Count = 49
+Nonce = 691cdf6fe9ecc2154d0101
+Adata = dc096596644c4e09c44078b86e5e0887c45094042eb0d74a6a13aa2524463076
+Payload = 77e6441ee017a93dd876ff2c7980540c77ee15edb0f23933
+CT = 24cecc81c8ac7ca9906372dc5263f2220b4dd162f1e08283f07f23e65475a20fd96e45c6c695cd83
+
+[Nlen = 12]
+
+Key = d49b255aed8be1c02eb6d8ae2bac6dcd7901f1f61df3bbf5
+
+Count = 50
+Nonce = 1af29e721c98e81fb6286370
+Adata = 64f8a0eee5487a4958a489ed35f1327e2096542c1bdb2134fb942ca91804c274
+Payload = 062eafb0cd09d26e65108c0f56fcc7a305f31c34e0f3a24c
+CT = 721344e2fd05d2ee50713531052d75e4071103ab0436f65f0af2a663da51bac626c9f4128ba5ec0b
+
+Count = 51
+Nonce = ca650ed993c4010c1b0bd1f2
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d50d344340c
+Payload = fc375d984fa13af4a5a7516f3434365cd9473cd316e8964c
+CT = 5b300c718d5a64f537f6cbb4d212d0f903b547ab4b21af56ef7662525021c5777c2d74ea239a4c44
+
+Count = 52
+Nonce = 318adeb8d8df47878ca59117
+Adata = feccf08d8c3a9be9a2c0f93f888e486b0076e2e9e2fd068c04b2db735cbeb23a
+Payload = 610a52216f47a544ec562117e0741e5f8b2e02bc9bc9122e
+CT = 83f14f6ba09a6e6b50f0d94d7d79376561f891f9a6162d0f8925c37cc35c1c8530b0be4817814a8e
+
+Count = 53
+Nonce = b4cadb5f9cb66415c3a3b714
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 22bade59214fa4b933cb5e3dc5f096e239af4c2f44f582b0
+CT = 2296e3f8a2245224d274f1b90ed1287cbeeb464c70a89ee475ecb546efb8872a3f8b0281b3901752
+
+Count = 54
+Nonce = 72e6cebdaf88205c4e744286
+Adata = feaf010f462ad40a38eefb788b648e1cc292cd4bb08ebeff3c39182862296042
+Payload = 30655a6b5a5965db992e7248d24141055e988d726abb8e72
+CT = 69b27f2bbaa61c4f24e1c25e0779147fef79ec1582486b4651cffa571570618e2ada3376bd9f3e5f
+
+Count = 55
+Nonce = d8030fb31eca2c43f3f5eb88
+Adata = 66704365ddd0145febeb33f68b228a3f09e1e5a4b68149e6e06d886301841295
+Payload = 9d014a02507a6f266bd1ace21b55ab8b73983ff503bb9adb
+CT = 233a883650538ab8c0da30b90527f880fcad5b16bd435e762beeeea7a638c717e63764b3a5118a0c
+
+Count = 56
+Nonce = 58038cc35ad3dcd75195e125
+Adata = 3da7a757e942409a3b39ccdc0669ce6401f7e133c07c4c42e366d70a8e9bdd49
+Payload = eccfd817fa5e3a0146967fae13fc2471ee3944cee37969f4
+CT = 415a36872a04f5b4b5372f63394ab9fb353e0eb9b430450133a87fa29e5fbfa9bc0430b0cac00b7e
+
+Count = 57
+Nonce = acd82ae31bfcabd90af5af45
+Adata = ce22126f01bde16249c47102b4da68ad3edebcd4a16c24a16ea7ccdd5d364d10
+Payload = 9d2126d34963d3ba12cd841bd321036cb82cfb78f2a6535f
+CT = 88a5b889e6fd74fc15336e23374b430988416c7e6b6e7248b336cbbeb64fbebf2e7076a98ecf5bbe
+
+Count = 58
+Nonce = d24457d567fd0a65fdabf219
+Adata = 0091d39f3478d2c59bf874b96db9ce0f7e8b85a9b805e07dc96b219819d51663
+Payload = 6da3ac85505e93c4f391ea367a9e15fa9b388ef7ae2693c1
+CT = 7039a8a49cfa6402b4ba3b840e69200c13ac4a3eb1c709a30ea909047af4998c660afbaf346ed65b
+
+Count = 59
+Nonce = 50c59ca54eb64575b82b13c6
+Adata = 5e4e42cbf172853c351d597c7d6d38b1a9cbb7ac92c00863a80ac4a2d9f0e7fd
+Payload = 25b2ba0a937b71f3ee68e7172cf2c4524b662efcd08ce2b3
+CT = e95fc44287ce39c5ad6b91c88582563fa68a9e304094deb8b193dd767f17783f0b51ac0fb7323301
+
+[Nlen = 13]
+
+Key = 36ad1e3fb630d1b1fbccfd685f44edd8984427b78deae7a9
+
+Count = 60
+Nonce = 3af625df8be9d7685a842f260e
+Adata = 308443033ecd4a814475672b814b7c6d813d0ec2a0caeecbcaba18a2840cdb6c
+Payload = 8b9db1c8f9b4892a5654c85467bcffa2e15e28392c938952
+CT = 6bc6890fee299c712fb8d9df9c141f24ee1572b8f15112c2f8c99ccf2d82788cf613a61d60dae458
+
+Count = 61
+Nonce = 24eaeaa437649e61b706942b8d
+Adata = fff75462f96157d9554bddb6aac156fefd88fd4a90a8536dfc28cc577f19c83a
+Payload = 49ff4ff85f7407ca383cfa4fd7177adb4dab26e642c8186d
+CT = 3647fae50c588d792442f43a20125e77ab5db3c469391d24d0a421bbbc002eb9ac9ad01f625f824b
+
+Count = 62
+Nonce = 7325932d6694aaf61a8204c172
+Adata = be20ceb8ca14e9bef7158b280a26bcac763da79cd0eba9b1833ea808c5e7a66a
+Payload = 2861494eb40b9d964d339797c1b6aac63c6674187768957c
+CT = 286dc74001e2a6000a23db164f4b2912de4afcf1df8c3aa5ee32a7ffd4e7bc303d3482fbac431828
+
+Count = 63
+Nonce = 61c9949df5853e42599e5ee0c7
+Adata = 243d09ceb16755cb58d62065df84890b840ad9b7eec1132c6427cd7c3d843fcc
+Payload = 943a49073db6ae94a88844ed895f8fd99ed25c3f42a2f78c
+CT = d3c56bd265a2cb0811dd218f248800ceade4f02b5403b9635eb30cbec49cbb51c41cd5032b7fd759
+
+Count = 64
+Nonce = 07b6c18dd3b0fd9e8ff026a436
+Adata = e85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b8ca9f321a178a2056806
+Payload = a18b0a4618063c0519818d113b8e5435aaf153f664058f1b
+CT = 69f933a2a5e774e8d013cbf78c6ab0b73e6ca323d0c52691acb5cf2631987d3d963349b035324aac
+
+Count = 65
+Nonce = 0c075df70630dec2fe81834945
+Adata = f3f5c5ffbfe8247bc0c33c793652f749fe91b6dd141cf0db56e71cef8a2fd266
+Payload = ddc4bac4115e8cb06d29d22e400674dbc615a667f933603d
+CT = 26bdd25c9f204fc7520d26c161464c28fb35e395b295b3db4e239d33283d18415b54c2aad4bde354
+
+Count = 66
+Nonce = 0c2d20375057fcd4241d290f6a
+Adata = 70ff1b9ff8ec08fdb18b0e7dbe01127ed0cfe0b0a449ca2ace4992b7b6248b71
+Payload = dacbdf1979e000d52b573e74800761b30acc26681f372acd
+CT = 6a642c389433a3464fc64783ae6a14a9a45f0998b56a5b9162d7e0320dc930df3640a786d7ea9ae4
+
+Count = 67
+Nonce = ea0801cb3dab853750a922dd25
+Adata = d83360d0896e022bf014bd33710ab212ddedda6d95a54996f33db304e5f12f01
+Payload = 46cc5653bbd8300dfb0df6d0af3fb7c7639a830bdc9f68c7
+CT = f1b0728920351d9edfdbe7df360b21f6cc5b628dcf43a3f10d06b4a545609a2128a95d4d73471559
+
+Count = 68
+Nonce = 97e6de379c90fccf3fa8f27013
+Adata = 539f8eb802bfecaa4fb5b19debbf3d4847db9c4e0473a308ab3f3c859e68fecf
+Payload = 8b013f52a828905013f250fb9c006a173f6c66a64b5ba317
+CT = 556a439bc979dac1cfea8c5b64aa78547f52a62896c19893f3512baf72cd79ba9301194be204bcc0
+
+Count = 69
+Nonce = e832b6330d3e5e190598cb9c61
+Adata = 093be516277e8b197ba5e9c85a831529befff0f3971510ab611dfe0dfb50a2ad
+Payload = 635d2d7894bb816f154210946a369df37ea492993ba23af9
+CT = d8e19c67e5aa7f14a16ecaaac414a2b15a15bb5f966932e6b0bfe9a5857fd36df94aeadda7f83a79
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT256.rsp b/lib/crypto/test/crypto_SUITE_data/VNT256.rsp
new file mode 100644
index 0000000000..2817684910
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT256.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = 553521a765ab0c3fd203654e9916330e189bdf951feee9b44b10da208fee7acf
+
+Count = 0
+Nonce = aaa23f101647d8
+Adata = a355d4c611812e5f9258d7188b3df8851477094ffc2af2cf0c8670db903fbbe0
+Payload = 644eb34b9a126e437b5e015eea141ca1a88020f2d5d6cc2c
+CT = 27ed90668174ebf8241a3c74b35e1246b6617e4123578f153bdb67062a13ef4e986f5bb3d0bb4307
+
+Count = 1
+Nonce = 195c0b84baacc8
+Adata = c7d9557b2ed415652ce6faa8cff5217ac803530ec902890b31eaaf3eeb0aa98b
+Payload = fe012718481b2c4e1d7f9a7685e3daac43ccf22cad0df900
+CT = 893af0f130f1317de9f217234274b0c04fcc202cea9a0df882c00b5b463654adbf82888099a7d258
+
+Count = 2
+Nonce = 363e0e921c6f11
+Adata = 805678936d4e94746ab4818dc5f50c41e32cf32e7a8aafb300fb91af6406108c
+Payload = 7e7e33e1a07d4e8fde2f33304f21cb564d146860ccfeb49f
+CT = 645cdd11a1c232815ce1e07ca3ea83f372eba46cedafddd980adf2762a1617adfd4d8356bb48aa8a
+
+Count = 3
+Nonce = e323cc866af462
+Adata = 163c747f3ba4ffd68af87f2475f48f2714659a2ec43b9ed115e02fe0e3c8be99
+Payload = 2bfc76f3b108ba3118b07433c4d3d5f41564d22547c12822
+CT = 0db04c6b068e73e3c4d71059bdeee3d27622f99dfd07d868fb9c02753c57fec7e1a5fa8f3860501b
+
+Count = 4
+Nonce = 03ae777078b95d
+Adata = f1dacf9062dff9a6a3d0498f9d058782f891475684196bf2d8e7e905393acff7
+Payload = 38c4275a5f605fd1d99517e13deebf0c9794ef586070fa9a
+CT = df8f524872b5f06f3f219ba76524990b466409894930d7e0d104990e598eabd88cc8342ac16424b5
+
+Count = 5
+Nonce = 1c6c351d4fe9be
+Adata = 14285e97cc3cae452e1a52e2fa0bbe24df96abf2faf6b9779acc59764612eadd
+Payload = 9e2220f3c17532e1ce0d6f562b049fcef35bcaf9a7e196be
+CT = c274b28228a6b13b670c325080f88d188d40d78d385481eae004894b1861db5d2d8ae98ed8926c1e
+
+Count = 6
+Nonce = a121dc27479397
+Adata = 359421e9f78cc4a31f4f019977d7fd29780524e20288798c50002a682a6368b9
+Payload = d42b16b32e77637724144eaddb21ca8d7db4e7f73acbf707
+CT = 56e3e3e59e978161355e7d8573dc0657db400ca0b083dae8ed2ac2cb63e1b9d7dc598634198fe4fc
+
+Count = 7
+Nonce = b1f0e26b60bf1d
+Adata = 2ab4239fffd13762fb5391f5a4760d12d96ea12666a793b4d651e9f4891c22c1
+Payload = 9a2851083ad4e7b915bb0526bb4054e4c0b4adf8626edc90
+CT = 5b2e0215523ff37f0df46e84f996fc9fc779986c766fa51595b8a23ee377d5c2850f4ed95a385253
+
+Count = 8
+Nonce = 50412c6444bcf9
+Adata = 09cdcaa87ddf8bbe6db8411d14bb9064e4a121286cc8a6e97fce1844935f436b
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 05cbc32a6ca797684636dedd16ce65a1eed69bcab1b1bdbd514ef5cbf9991a919fb4974d55506ce1
+
+Count = 9
+Nonce = 225557b0faca3d
+Adata = 21611da060fa90cf7fd68b721caf303307a56e56453326495b628c7dc93cd175
+Payload = e831b739e8eb9f787f63c0bb071ddcc9f44cab8d5b447d23
+CT = a97e0879407eb3b7f93118ca73f17eb34e9f4baf43b07be2e8a3f7b848054cb235e1b58d6a12c5cb
+
+[Nlen = 8]
+
+Key = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+
+Count = 10
+Nonce = 790134a8db83f2da
+Adata = a7a86a4407b7ecebc89434baa65ef173e88bd2dad9899b717ca578867c2d916f
+Payload = 59eb45bbbeb054b0b97334d53580ce03f699ac2a7e490143
+CT = db4961070f528ccd1a5a0681ee4d0ce3515fb890bccedc2dbc00b1d8b2bc393a8d09e87af7811f55
+
+Count = 11
+Nonce = fb2441d1594a488a
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 1bca7b0d35a68c0ffc568ffc8221cca738b67b95e3ab26efee21c5738d1f7fddf3030d004a702704
+
+Count = 12
+Nonce = 0855263860043207
+Adata = c7fc24863c33f7e8cf97b337918495d52d864ac570c99cbb09d151758d6b504e
+Payload = 61fcd7ef9bf151b9d8a81dc1ba4f82c45e9c2e4784627acd
+CT = 9b939b6b188e1d0fe016f366fb01eb79a99ef7b1b57c6f7ab223454c57c714d96681cd4d55615afd
+
+Count = 13
+Nonce = 415cd251a5e36943
+Adata = 1a393c7e85fb286709f4eb50f09640e1d65ec1135cb4443820136b3cec69772a
+Payload = 66ae08d494dc9df9b7f8f53199fa37d0c88885458b168c57
+CT = 1731e260ae31b8068ad1099313b167d9e6cbe49f471da61a9af96d3ce4ea94213b60cb69d92050e6
+
+Count = 14
+Nonce = d95bd65242bb2265
+Adata = d0e20e1358be5cc1c45c1cf02c82d0a6d0824cfcb65774cf95f047b9f2cc1d3f
+Payload = 312c3791c64d79205a11eebfc14b2d7a6b00391793c9559b
+CT = c3fbe558ff9ea83ed86b7d66503ee38eee94e4a41fd53f0f627a352d056712e0d44404c61712e2ab
+
+Count = 15
+Nonce = 3f0bf0141dd3ace0
+Adata = 9dd4ed18209dd6cdf19cc76fee443827e7331aaf020960c15d7bbed0f6a3b1f7
+Payload = 08354480047eee3beeb5ab165da17d23f2f1a4ad98720611
+CT = 2db9d2c54134d37ebefcecb9e2076034b975677fde58ef6032645a322fa9bc8aace600f942a84db4
+
+Count = 16
+Nonce = 3fd8b3a3ff563a42
+Adata = e58327efebad3276a7cd1b1ccb56db0caddd02a303cd9fc7ea5c607a2ebefaae
+Payload = d1abd89351384e1a3c3366f77c3175f6390801554d7cd783
+CT = be284dcb357ae99ada7cc891730320ebb32ca627eb8c80623957a2a5b6164218fc83e12c42d5c532
+
+Count = 17
+Nonce = 14db1ffc1c87117f
+Adata = 6c2b091433833a0ed915354dcb70d982095b614dc51a95a22cec417184d8e786
+Payload = 0594307491f157821e63f50c94034f9284f095d5b897153c
+CT = a114c84a10071e359bba2b2ba4ea67f893e27e6ea880aa4b2cf16ce68a93f8839245baebb2278300
+
+Count = 18
+Nonce = 40b0f74ff27a3fc8
+Adata = 3b9e1f4e9b57a6dfb5e0ca7ef601fc6af30a1f8650228e51e0dc61180d0bec6b
+Payload = fc8b7dbceef6b0ffcbade789e09303044042cd671607e819
+CT = d00ef56074a8213740af8b8f974f778db560ac365d6ce916b8d191130e864bcfcd1dec94a1aaeaef
+
+Count = 19
+Nonce = 96cbe9cd19351359
+Adata = cf498fd042f9a07503e490cec4873d4df91162cfde60bd2cbb2b710c6681a9fd
+Payload = 315e81c9ce556dcf97a5b68503fd2228a7a6a174a15cd618
+CT = 7383c2de08bce3f0b7e504dc03d062f44396bcedd2180fd954e6ec9f6ae1e0976ecf04dbee6463c2
+
+[Nlen = 9]
+
+Key = 58ae7965a508e8dd2eda69b5d888a28a1cb3783bad55d59d5b0da87137b72e93
+
+Count = 20
+Nonce = caa3d928d2bf2b7f2c
+Adata = 304678b3ffd3200e33a8912bcb556b3cfec53ca17f70ecba00d359f9f51d3e3b
+Payload = e61bad17640ecff926d0b0238271ee4c9f8e801dd7243e9e
+CT = 7bb1137c14cb4d324a4a8f1115c619ebf74927f0bed60a8d5a9140ff50dc4da375c7d2de80de097f
+
+Count = 21
+Nonce = cf09ca67659a583bb1
+Adata = 5507c4c3107cb446d19975f91207dbf3e2a51d1dcfd7da2f082159dbc3f41547
+Payload = 1887bb0c02500093a30a44b99e137483704b06615d308c6b
+CT = 834d3b2e5f0915c2348c706b4d2ff2717983ab4490edcc63971f02b7122d1e4f78de9c3376520f5a
+
+Count = 22
+Nonce = 97f940d7c1230bd8d2
+Adata = 56be2c9e09b555373d58f6fe2a0ca9b4ddba899addddf12b0fda860ad791773a
+Payload = 5ac67c9bec9b95c54e187a4a6812f5d701c4ac8f847c005b
+CT = 9f372ba1c87a115847cd708aaf5b8a143b6981ffc2c61cefd30ece13481609809b218de04c4e5ed0
+
+Count = 23
+Nonce = 147c7ebb6c92245054
+Adata = f95d64a513a9f3e6c95c9ed27b22fafd7dd10da52636029523142149116aff53
+Payload = 08f199a8d7e3ea821dd3106e8947cd2e9d485342b25a6471
+CT = c438aa6d187643d030dfe4d6b5b578f84838f4dc5c396d700c0986ecd7dab44e5e97db37392a485a
+
+Count = 24
+Nonce = b9bad794d49cdac9b3
+Adata = de9ff2a43f49cdc502cd17a373989bafd13fa6ccff6660557ce05b6295186d47
+Payload = 40d1cd4063750184356a1d7cae1cf1824f552c5d59a62dc1
+CT = 9952b25f4f4f375440cd958456184fe61610381ba92ca48f38dd977042c4d97da84e4effa650799a
+
+Count = 25
+Nonce = bbe054fbef86db3ce7
+Adata = dcec76181e3b872a5a6e79f070354e38866c7f67fc428fbca29ae6d929b1dd7f
+Payload = 5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c
+CT = 4d176f48b09b772dde8adbdaef720aba128a8d38a902847ebf22c81a5d824b4916660be6f9b513e6
+
+Count = 26
+Nonce = 6a35e1a4307f6efc6d
+Adata = af28120505a84a75b0f6b18cc9d8c75c661bf143be29c11d8ede78b9bb98c98a
+Payload = 5e2f601395ec406fcf96785f768162e849f867dca77667ab
+CT = 4e305e26d34711c6aa775f490939cc6560d3cb6905f5b0f5588ace6fc303600abc8e5825cbaedc7c
+
+Count = 27
+Nonce = f6c237fb3cfe95ec84
+Adata = 038f8ed89444784417a9c23bf11e9b436174e6c10959e00faa1704ce2f7f2c7e
+Payload = dfd9cacbf7d73d688447ebab13d2e13f3613652379b386f6
+CT = fb16c17a6b22a8658f446203ad46a48b34808083b271cabb015a1f78abc287bd2a63381ead07c558
+
+Count = 28
+Nonce = 50d024a3e7455d7249
+Adata = 8513365786b7988b208984e11022c15573f978bbdc29e8a7a4745c8a81885a1d
+Payload = 400317786b7df63373ffe541efcee6318cfc95bb673aad3e
+CT = d33b3141fea3a9ebdeb80d1da32dae42680be78471fb3023721f714120162514555b60560afa4256
+
+Count = 29
+Nonce = 02769283d5a06c363c
+Adata = 292c0be3713c6c588cb4e29a1c43b3e6353e33556194e568e800e4e44e8281e0
+Payload = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb
+CT = b15b1789c323a68568f86f35483bd7e204beff8f318ae14351f5e62b3b923a937e6c307af202fab3
+
+[Nlen = 10]
+
+Key = aecc5e18088bf9fd7b17f089bdd5607b69903b04b726361f8a81e221b1c91891
+
+Count = 30
+Nonce = c527d309ab29ee91c5fc
+Adata = 8f9a73e7bc1c11e2919020ba3a404cbddf861e9e78477218e3be2cd4337b278d
+Payload = d4291c99901345afe29f58912a414a7498f37b44362bdf3c
+CT = 392784a9e0b14bcd37639ec5409d6ead3e75f855e5a92c33ffc040ef3977e0035ce6ea6d157c18d3
+
+Count = 31
+Nonce = eebc31a5813b4fb93b63
+Adata = 9c87ad77953bf8a811e001ddb946eefafbfaa598150e85f0701853fa307d77d6
+Payload = ebcfd71120b0f9a2cccb898e6dfa082998cbe10032de3e61
+CT = e38eaad1e2df77e85e7129a8ce0f82cfc32b0aef79ab651bade65aa17e4dfb0aafe18cf71a72b180
+
+Count = 32
+Nonce = 231b33dc406c9210f59a
+Adata = 38be46d271bf868c198052391f8a2147c663700d9bb25a0caaa36974f18dacea
+Payload = 9032f910347daf661092b5c1f15b5ffed1369b194d9e12f0
+CT = 868b85288828501cf1d06610fec25e8b8a4b437e2e4f5563b7f3b898a2356909784598f8a8916f5a
+
+Count = 33
+Nonce = f2a88c3ebc74e62f24c7
+Adata = 5f495c5da035cabeb77e8aef10e91a05bd5aa414d1a37fa1099af959b26e5403
+Payload = cfe8ee9b475e36058471e2984ae66f6ba1b3cb477b15155e
+CT = 22c16333ac651cd9c183e78aba3e9312fb3b77dd6f9199502788860aae5534cf84979e30c3327d37
+
+Count = 34
+Nonce = 9cbaf1c83ba60b1e90ea
+Adata = 7ef136bd9a5809676abbaa68016d6fc713e34ac4b768a8246b1198c959f43085
+Payload = c3bcb0aaea93893f05eeb6439c8619dec17670a6439e2921
+CT = ebd9fb86563aa8f10062624441336f982c161ce5717d990a599ca6ec1c61a14c37b5902389e47aee
+
+Count = 35
+Nonce = e25322845d87d8a76753
+Adata = 2a89b9f0e56a1cf87dd38ed78028b6286ef8b7141dd2b3c65c5a8e1ed79bf4aa
+Payload = ae622ff9381854f831892c318bae5c003e74b15199bc12c0
+CT = 144c920f0fe278f353d0b053563d907c7589e4f1479d7a93a0604deb3fd9cea2d89987833ff5c2f1
+
+Count = 36
+Nonce = f4d7978fad36223623cc
+Adata = 8671de7e994967f2521d263925e745af9273682d9c08ced07d4a98fc985f68a0
+Payload = ef9b4ff8da108cabc972192ffecd5f96594c6d0871ffa6aa
+CT = ae4948b3bc1e50beb9f5d005871fc0d3dbde295de1c9ec3cbc866ab47bea7a4d0070e52b492fb8f6
+
+Count = 37
+Nonce = 6597ffb9eaad0fd9d830
+Adata = d2967ddf69ef62a9e23c9118dfaa55df92b4116322f1c9275131e3875dc92faa
+Payload = 5015c894b2437ff15c46bca9236830ff4bb057cd5764f027
+CT = 0b1dcb3cb0b4c32f398f3c43eccfe8f4242f33c99a2a2283efcb3dacac25bed0304f227fd5b77b8f
+
+Count = 38
+Nonce = 80e376b87272d99cde28
+Adata = c9cc8f967dff45c05b9345d03813b6e30dace99556f7df75b7120bb6e5f55827
+Payload = 615f657e24129a3e0f119988959608821219ce8354c4be26
+CT = d3e8b8f7ff8faa666ffe2509187fa7befc7412fd4e3bdb06cd2f7494b1fb0a0c6a2184e5c4787fea
+
+Count = 39
+Nonce = 344cce96455541d403f3
+Adata = 748cce18fb40126ce125dbe341fbbc59d2aacc170ed5ef0293b15713c9184a07
+Payload = 828b6a4cd49f499a6e8e8508f9ab35255d8e9fed33ba4d91
+CT = b67e582a74d7f022a16ada2de7ec18caafdefa6b104baf4ed93b6f8c8a1bf72be75976e4ebe6dd1f
+
+[Nlen = 11]
+
+Key = 97bc7482a87ba005475dfa3448f59d4b3f9c4c969d08b39b1b21ef965c0f5125
+
+Count = 40
+Nonce = 0bcf78103ec52d6df28887
+Adata = 049c10f0cb37ae08eae2d0766563b7c5a8454f841c2061a4f71a0a2158ae6ce5
+Payload = b99bf4dc781795fc4d3a8467b06e1665d4e543657f23129f
+CT = 0d3891fa0caac1f7ebe41b480920ffd34d4155064c24f3b17a483163dd8f228d1f20cd4f86cf38fd
+
+Count = 41
+Nonce = ab6374c6b2faefd92fa3d3
+Adata = f19c044023e5cf339203738ee70e76527519763664c06ae00e002a5ba94c32c6
+Payload = a2e5c51f516db01688b64c173bb25645182a005018022ee1
+CT = f70c598df3c64d3527ebb7fc8408b7de2cfaa1da7984ec361f1ad61758d828b70d4881b7d6ae8cd0
+
+Count = 42
+Nonce = cfb89e7ddcba601e875110
+Adata = 052714010da516c896ac5842a839ae845324643cddb080e6206148432d0d0407
+Payload = 037f206cab78a6ca0745dc8fc137e22e14f3d7183917ef83
+CT = ccd675862502a2e2520a33250150b8b7b220e84db854888c316dd62075fc761e2bc80edc5c564bdf
+
+Count = 43
+Nonce = 967cb6f8530bf8a43adb42
+Adata = cf391a84d03e2e22aec1965cec821f99e7bf21a7c3580dffa531464b22d83225
+Payload = caa3d928d2bf2b7f2cd8a7f357055b6d6895a5e34f47972a
+CT = 4f4f509debe6e52eae4af8b1740dde0a5338f78711a3b4ebfc8b5aca6d606222d6af7cfea0d1f4e1
+
+Count = 44
+Nonce = f5b7b5dd2b5e1ec93710c9
+Adata = e7a6b228a67d37b9d29a38efc547e50b4a6d95d599b45ee189ece21101ac6b5b
+Payload = 4a74ff35418723f2cecec1012484b52114067b2b2393e7f4
+CT = 25b140922a9d4f2ce153a4ff86596a49d7de6a6184e931e8b2ff27a98029b23484e00c2a5d291887
+
+Count = 45
+Nonce = 713de00faff892977d99d0
+Adata = 14ea93488d4284d21d4c7ce14414adf45c1ed9d2d99db866d0e59accb6234dac
+Payload = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698
+CT = e4d92ab8d1ffb0976670d891cc8338da12f86d5d79b334103d2ae816edf857c810b6fdc7f2c71f1d
+
+Count = 46
+Nonce = ba87934808de09b2ae829b
+Adata = 30e2ea2a505f19e8760a0a84961000c7a0b7fe3460a9d3f5a38f54149be2e9ee
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 6df893eed2be958e5f542f8cb4adb392b34786cb4ce821ec93fc57997b977948d55bdb026db5bc48
+
+Count = 47
+Nonce = ea09fbe5da0fa4fe911e18
+Adata = 237dc8512b29bccdeb8ee39cf83b9b6dd203823d175c44d5f605b194e7ec136e
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = 2f204ebcf549ee2a800d870e6341b9a89a41ab4ae91b6902ff704a2bcfb8becd0226f76d68fbb08b
+
+Count = 48
+Nonce = 5b80d7affc4ab4a4b68bdd
+Adata = 3a38dd7da30f5c312fb1e978d87b7a39792fd9ea3e9ab1565874e99df587327c
+Payload = 5ff92f6d3ca791421363e10cc84b4e8e21e0ebe5d8c55d6c
+CT = 05472db7875d59f8bed45606f355a516de93740aa2baeba18df9400df42baee6b9a0d75b45840104
+
+Count = 49
+Nonce = 514bba483fe7f2b7e555cc
+Adata = ac8beb419099cdb42a39e9b46fd900cc52eec4b43a96ed18b37b899b63fb931c
+Payload = b0b11dfca9b3936d1b4a423c5acd3d012b399a487c19c994
+CT = fa20629d514c4ce7bf727629bca5aa1c0c7e7851fc1bfc5c847729a70d7b4cff5281aece37006015
+
+[Nlen = 12]
+
+Key = d6ff67379a2ead2ca87aa4f29536258f9fb9fc2e91b0ed18e7b9f5df332dd1dc
+
+Count = 50
+Nonce = 2f1d0717a822e20c7cd28f0a
+Adata = d50741d34c8564d92f396b97be782923ff3c855ea9757bde419f632c83997630
+Payload = 98626ffc6c44f13c964e7fcb7d16e988990d6d063d012d33
+CT = 50e22db70ac2bab6d6af7059c90d00fbf0fb52eee5eb650e08aca7dec636170f481dcb9fefb85c05
+
+Count = 51
+Nonce = 819ecbe71f851743871163cc
+Adata = 48e06c3b2940819e58eb24122a2988c997697347a6e34c21267d76049febdcf8
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 70fd9d3c7d9e8af610edb3d329f371cf3052d820e79775a932d42f9954f9d35d989a09e4292949fc
+
+Count = 52
+Nonce = 22168c66967d545823ea0b7a
+Adata = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4ac9f3b61e7e8047fd
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 30254fe7c249c0125c56c90bad3983c7f852df91fa4e828b7522efcd96cd4de4cf41e9b67c708f9f
+
+Count = 53
+Nonce = 225557b0faca3d6cbaedec5c
+Adata = c7aafe7d3b419fa4ea06143897054846ac4b25e4744b62ba8a809cc19253a94b
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb3
+CT = 2369b56f21336aba9ac3e9ba428e0d648842a7971182d5ffac57f6ae1080efab4ed93f8b4ce1d355
+
+Count = 54
+Nonce = 78912be1a35e156a70fb72f7
+Adata = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb80d77fab2c4900e0
+Payload = 113efd182f683596862ccd5eba2e2d4ffa709d9b85c6f1d5
+CT = 835a22eb8d718c0ee1531a2d1bb95f58215c997c612908eeed3ccaeb7a814f69d3ec1fbf2ee9792d
+
+Count = 55
+Nonce = 91ad90b58d2044abacf957e1
+Adata = 4fc795b9126c23dd7fd514c2e5a8ca583e88a783b28cbb2a5df09f8b520ba0d1
+Payload = ed55f6b9eb8fe74474c037ede94ffd84ada846ede4ecff74
+CT = ecb595276fd5d412a7cc3f5cfe960f47a0d0e2df0b08a11ac257d67143722a976c9d7f44b09a767d
+
+Count = 56
+Nonce = 4bbe4ca29122c4892ca09b5b
+Adata = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364449b2391230be846
+Payload = 8dd497bb777bbc3e56e3af25a43545007bb00f2b9e9f815c
+CT = 563d61fc0a5b82804a580a7d752a8e61d3342fb39372b39b6843a685bde3175695796f6e64f35901
+
+Count = 57
+Nonce = 218e7b8a8fd62927f90b70e5
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf001429122e46bde21735f63adba
+CT = aaceb16589b9de253c99d0d32409a631db71e8df8a7644bfd027e3466e8220144cb0552f9b2800e6
+
+Count = 58
+Nonce = eecc9f106a0721334cc7f5ba
+Adata = bf38d0ee11a796a517539bbc9ab00ff85a4ddbf0a612d46e2bc635180ad34c50
+Payload = 36cefa10af1a3446a2c8d4a1171144b9ddd8e33a7cd5a02d
+CT = 9bf3b2df93cf5b587ecc96f45fc75e6eb066cb286cb06f284c9027fc41bb8c848025fcf9d092a873
+
+Count = 59
+Nonce = e41af8ca408c4c12e37561a4
+Adata = e0b20892875f60b5d8763a04958487fa5b7cf8d67a456e430475b337245d671c
+Payload = 32a4da08bdd51336ed5798c7177b853a534bc98f2e6f7d4e
+CT = 95ffdc68f721cf2294d0d88002e3814167306fd906dbebdb7e6e0e5dc0a03826e51bd94269d7a41d
+
+[Nlen = 13]
+
+Key = 4a75ff2f66dae2935403cce27e829ad8be98185c73f8bc61d3ce950a83007e11
+
+Count = 60
+Nonce = 46eb390b175e75da6193d7edb6
+Adata = 282f05f734f249c0535ee396282218b7c4913c39b59ad2a03ffaf5b0e9b0f780
+Payload = 205f2a664a8512e18321a91c13ec13b9e6b633228c57cc1e
+CT = 58f1584f761983bef4d0060746b5d5ee610ecfda31101a7f5460e9b7856d60a5ad9803c0762f8176
+
+Count = 61
+Nonce = 8a56588fe5e125237b6cdc30f9
+Adata = b3aee5fbf409bcfe9b46ae68d570edbbed32c12d13926ffb5ddc60ff0bdb7f85
+Payload = eca81bbd12d3fd28df85e2cc3dcc2ecbd87408002fd00fe1
+CT = 9aad62a5443550d11f9efdab2de0eba74d47ae4f7d16adf4276664f6567f2f978bd4be4d80cd07be
+
+Count = 62
+Nonce = d908b04840caca2280e5293ade
+Adata = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+Payload = ad1109ea5c79bb55d22e9713eb2df42767cb29a2eba3ad2c
+CT = 61fdcebb158cd03151697ae7871c0a998802997e0672e5886e5a9df1b1d6284ef657cde6f74734bb
+
+Count = 63
+Nonce = 6df8c5c28d1728975a0b766cd7
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = 704f60f9cc3ef7bc00b4f7a271ca70a89f4d5605387b3e2f8cc80aa08572b90e9598d0a73712b720
+
+Count = 64
+Nonce = 6c6ebacce80dde9fefb7e5bb47
+Adata = 93f0fca0c8c84d5cc48160b25e246226d489225c0f8275e52856da592c715aa6
+Payload = 46820aec46ebd0d61706129584058a1498514928a87fe620
+CT = 00f6cccf45f046da1e6266afe61eed61c60c28515b2e1ab386b2c952055899184f0d95ffe3959f89
+
+Count = 65
+Nonce = b94bc20d8c9abca7645fc6bebf
+Adata = e1c083c93663f5a066ef337a61aa3fddde7c301a42463137c375cc2dcdd76954
+Payload = f1fca581d3dbbc61060c0c02adb47bc57954d25a283f66d6
+CT = 90c65d23e0e1786cebb95f9b1306d001b2e503842cdedb75e37a53d77b9e38605febdd7b2b666f98
+
+Count = 66
+Nonce = a4974791d417d7e9eea0f4ae8d
+Adata = 33602f308f3a0f7e1c75fc1e4321d545ffa278234958dbadd37f59a0f85349c3
+Payload = 41712c058d2d56b43b2c79278e790858a289320746c15a60
+CT = aab5656a1ef060c9b1ef7e2f3cc0bda40ff067900401182563ceb824708a20724c99c83f1caacd70
+
+Count = 67
+Nonce = 6003b771afe4e99e1ef1ed4a31
+Adata = f60d8362b2ebf523681bb051fd3ee13919ad86acd963c703c4178a5f01a84236
+Payload = b766022311c5e1d74a607fec7cb8ee805b8397a6c5f374c1
+CT = f73b2a6dbf8f798d4bfb489a6578c9c79152e42aa3b81b64a84e7af3116a18f7ce44ae93f420270b
+
+Count = 68
+Nonce = 27861168ac731a223dc35c03e8
+Adata = b7ba1c66282cb6092ba601407ff9578afdadf7ba7a4d08edef06dbbfd87171bf
+Payload = 0822e3e6ba982091d532cd5271fbde25305d1f6e71880f81
+CT = 5ab3e5296cd1f08704c82f6b42939702515b7733853d723d4009312bdae46958d844eca502bcb005
+
+Count = 69
+Nonce = ef284d1ddf35d1d23de6a2f84b
+Adata = 0b90b3a087b9a4d3267bc57c470695ef7cf658353f2f680ee00ccc32c2ba0bdc
+Payload = bf35ddbad5e059169468ae8537f00ec790cc038b9ed0a5d7
+CT = b702ad593b4169fd7011f0288e4e62620543095186b32c122389523b5ccc33c6b41b139108a99442
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT128.rsp b/lib/crypto/test/crypto_SUITE_data/VPT128.rsp
new file mode 100644
index 0000000000..f79db90b4d
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT128.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 2ebf60f0969013a54a3dedb19d20f6c8
+Nonce = 1de8c5e21f9db33123ff870add
+
+Count = 0
+Adata = e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603
+Payload = 00
+CT = 0ead29ef205fbb86d11abe5ed704b880
+
+Count = 1
+Adata = 98d477b7ef0e4ded679b0bc8d880f09823ad80e9732fde59c3a87da6a1fcf70b
+Payload = 00
+CT = 5b85d144bb51d4927074d3536a2db83a
+
+Count = 2
+Adata = 28f32de10b6c9d3c3f46efec7aee24006208a54c4d1c2bba4b8cdce166cab7d9
+Payload = 00
+CT = 01045de4a09486eea5efa33ecc6cd299
+
+Count = 3
+Adata = af397a8b8dd73ab702ce8e53aa9f0189995c6c9e920dcb75795149550b499deb
+Payload = 00
+CT = dfd75400b59c3ad387bc86dfbbfb52ac
+
+Count = 4
+Adata = 3fa956bfaa27e249bf0a1276468d808259f3b8e2687851d780885d44cc2f04bd
+Payload = 00
+CT = 2b11d2549b4e2f0a81c07ee90af4d081
+
+Count = 5
+Adata = babbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79
+Payload = 00
+CT = 10f76ab445f4ec158ccc1f7c6fee3ede
+
+Count = 6
+Adata = 7fba0bfda3b03c736c121cf9a257db55060b621be5168619ec4182f13ef6a408
+Payload = 00
+CT = 59e02d6a6aa3fb2692b04e65a0e735da
+
+Count = 7
+Adata = 057354a29808f4ed77671ed3dc36f8b03f5cd952caac5cb80dc3b319f3333e29
+Payload = 00
+CT = 367a2ade4087964dcb0ca2984d44657e
+
+Count = 8
+Adata = ec08b618602d091e9304715cb552b357c16fd1d7f7f023a28d84a98ba21ca0ab
+Payload = 00
+CT = 47cb92cd40bc89328d4dd44fbd727032
+
+Count = 9
+Adata = 45622834ea658b09b17f32777d18b34b387ef957bd344468f68e7178417a7c24
+Payload = 00
+CT = f5185afb8359b5ef995483c0bc4192c3
+
+[Plen = 1]
+
+Key = 6ae7a8e907b8720f4b0d5507c1d0dc41
+Nonce = 7f18ad442e536a0159e7aa8c0f
+
+Count = 10
+Adata = 9c9b0f11e020c6512a63dfa1a5ec8df8bd8e2ad83cf87b80b38635621c5dc0d7
+Payload = 0e
+CT = 4c201784bdab19e255787fecd02000c49d
+
+Count = 11
+Adata = 73616a428f1a567b2e9af86b1fc8aec6d597b1b55f2aa2219b3b662fa6bd3407
+Payload = 30
+CT = 72f14519f06b63fac3d5b2d9bbfa0cb758
+
+Count = 12
+Adata = 6d62f4e15e8bcc9ba4993bc50a046737121016f0d15020b90068250551167b1c
+Payload = 34
+CT = 7676b581a28ca0a0ba5178eba7fe028da6
+
+Count = 13
+Adata = 8f0b8289a1834ecc2167b59ce3c9d3b58465c4cfaad50c728d04360cb7e5bc41
+Payload = ec
+CT = aed99b805c0a4785ff2913cab3e50f6205
+
+Count = 14
+Adata = 477b2a6932f838f0d1bc420c0ca306981d8e2dab945b6f259e15fe888667220a
+Payload = ec
+CT = aeb50e41cd7af84a8fdb6aee144e904616
+
+Count = 15
+Adata = d6518d409b1f05708d0b44f18fb5721f20f3220f8d2f2718650aa9932e4579e0
+Payload = d1
+CT = 9312639c863974f077fe8236c943b464c4
+
+Count = 16
+Adata = 865e7cde73b558e9bfd05356923f8a697970811fc484acad2d5b3528baf1f986
+Payload = 24
+CT = 66d7265cde50bc7a3989458437baf06db5
+
+Count = 17
+Adata = f0c3c67a935eace53ed32435655dd0974fafe283622e8294a15d70977398eae2
+Payload = c5
+CT = 87063144b25d2268063815d1b42ebbac34
+
+Count = 18
+Adata = 341e71b2ef26e9db03882e06d06cde2c0617326cd157d5984d22f6f3407a9c39
+Payload = 34
+CT = 767da45c10d0d6498716bcf3f13ca7e26c
+
+Count = 19
+Adata = 31fce6735ba9a3385df11c153179b8e4141a3c6b8ad6eceaa211f3f17bfd0474
+Payload = 7d
+CT = 3fcb0a6f562974cfb3fb7c8d5cafd50f2b
+
+[Plen = 2]
+
+Key = 3d746ae6cac5cefd01f021c0bbf4bc3c
+Nonce = 597b3614ff9cd567afd1aad4e5
+
+Count = 20
+Adata = 90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad60
+Payload = 4360
+CT = e38fdb77c1f8bbac2903a2ec7bc0f9c5654d
+
+Count = 21
+Adata = 6bc3d30925c67371573271f1a4273ad76e91e07dfab65f7bce0b241b5e4cd00e
+Payload = 17c6
+CT = b72955210d62e1393e4fda647c2b2e59a47d
+
+Count = 22
+Adata = d1bb4cdfc3f2c16d92576068543692aa4b5a427d688387af0f1583e91a0e8b3c
+Payload = 6575
+CT = c59ad54fd88a47b9f6e39cb4606af86d13e8
+
+Count = 23
+Adata = ae6136df9ab43631ef143515dacedbe759b3459e951bfaf4712a21c86352f1c0
+Payload = b1dd
+CT = 11326de841af64b55bb7ebe3fd30ba493c7d
+
+Count = 24
+Adata = ffead34ac26e21158212d07c367c3a7cb6b795887ee2d3d8ae25c60556ea88d3
+Payload = cd16
+CT = 6df93a206339de534271f6469edfa5ed07d3
+
+Count = 25
+Adata = e768e7d867820d46c1cc62ee0e51d4dac6f5c4b5785b5ccfbf05236871bdce2a
+Payload = 12f5
+CT = b21aa8f65144f2ec5809e2ccb38c8760f7bc
+
+Count = 26
+Adata = 402e802885e4119df17fe85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b
+Payload = 39c0
+CT = 992f9af825957abe7d89e175b6e8c0b84b5f
+
+Count = 27
+Adata = 8a3a622b3d347c0c5210d484adf77fa33205ba02224ddceea71d89c9ad8429ae
+Payload = 912f
+CT = 31c025d6a12e91e84e355934547f6b5dceb8
+
+Count = 28
+Adata = 636114e5e5f83cec94e1df21d6babb9f6a14a532fcbfc3bcf649fbd79ac1abbb
+Payload = cb6d
+CT = 6b826db959a21e9e4ebf25ca4f98501b560d
+
+Count = 29
+Adata = 04e84f9156998c2eca9e96079a6001f2947dc49a081b3d75e47d75f71ed4a606
+Payload = 5bd2
+CT = fb3d2006ff22ff231a6646ae561923818a21
+
+[Plen = 3]
+
+Key = 3e4fa1c6f8b00f1296956735ee86e310
+Nonce = c6a170936568651020edfe15df
+
+Count = 30
+Adata = 00d57896da2435a4271afb9c98f61a650e63a4955357c47d073c5165dd4ea318
+Payload = 3a6734
+CT = 384be657bfc5f385b179be7333eb3f57df546b
+
+Count = 31
+Adata = 50f6e6dd57bd3a24f6bfdc8b1c7b5a36ebdd07fd6d194e6e82da47151d9c88fb
+Payload = 4ffad3
+CT = 4dd601b8ca97bda492546d82dccdebef441f8b
+
+Count = 32
+Adata = 70e132023acae1f88c7a237b68f5bdce56bcfc92be9f403d95d3bcc93b4477a9
+Payload = 8a594b
+CT = 887599fa0f3e397d9a580aa39c7028e1a508c9
+
+Count = 33
+Adata = 08d2b011f36e05dc728c1a8bda3d92c779a3d2f27c4b041810bd6222c852b14d
+Payload = 1f89df
+CT = 1da50d593460d335e2f7a6d40b8fe305b0f690
+
+Count = 34
+Adata = b207eb870aeeab27c6201ef04650bdc7ea30028a243420f7d198f1c9c9a43023
+Payload = 72e9c1
+CT = 70c513a2d49e1a113767ea4219107819d88b65
+
+Count = 35
+Adata = 74294088721fc9e7aabd5f1c66b5369b1e2d2cdb3e73abaa28ecd1c37d4ecea2
+Payload = 016083
+CT = 034c51dab1c819778be8453db163c882063af8
+
+Count = 36
+Adata = abbd347999a1c26368cdb17ab08bf57a8e942d1248296e952f5f42f2cabbf0e6
+Payload = 25f665
+CT = 27dab7537eb435df8d0e48c3f7e0bd1877c866
+
+Count = 37
+Adata = 231b33dc406c9210f59a5df1cfd595c803474db34b9b1848f0bcbe7b28df33c2
+Payload = 158606
+CT = 17aad4da549fc63d55b5910bbbf64435b95220
+
+Count = 38
+Adata = 69b851e63a78baef90637978e3dfe8c47be4b21e85bb89bf67051cf251004376
+Payload = b07452
+CT = b25880d5ee29fb2af47f8040fad585921057f5
+
+Count = 39
+Adata = 9b1f786c887d310b8efd3e8192fe504f603024c94aaa4ec9123736a40bf1605d
+Payload = 65187c
+CT = 6734aebc3ee43e10205f83143e0d3794a6734c
+
+[Plen = 4]
+
+Key = 7ccbb8557f6e08f436d0957d4bbe7fdf
+Nonce = bb8e2ef2ed9484f9021cda7073
+
+Count = 40
+Adata = fba1d18a74a3bb38671ab2842ffaa434cd572a0b45320e4145930b3008d8d350
+Payload = 4cabeb02
+CT = 32501f4235c4dd96e83d5ab4c3c31c523453c317
+
+Count = 41
+Adata = 78b3faecb2bdf6ed14ac2b86ded07aa791b60f5d54f9e24a965a8453f5131898
+Payload = 5ff73653
+CT = 210cc2137907d6a03e66403a7d9330d30d934a8d
+
+Count = 42
+Adata = db1239528eb464dd063e2a97ee83a87d6002ebb4fbafa77036f72c14f3fe959b
+Payload = 062fa9ca
+CT = 78d45d8a44f4bc78fbb969935076134437df82b4
+
+Count = 43
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cad710b4
+CT = b42ce4f459692911fea2e0034d06c3b2e89af3d1
+
+Count = 44
+Adata = 7381471a62b1fa6f5061c4c37e9721f07099d007ffaf8639aa2ae3f82da5a559
+Payload = 7ac716b4
+CT = 043ce2f468484e22381923bfcaed16e0cb85b0f8
+
+Count = 45
+Adata = 19bea6d92d5892216e8e4a30dda802387800bb046a6717817fc46c7edafe17b0
+Payload = 362da02c
+CT = 48d6546cd081de39c247df309c4b56c31c03690d
+
+Count = 46
+Adata = 8503c8eb9cebc6110f259e35e03a0740267768130ce6f61b1c7d1d25be942274
+Payload = de52b209
+CT = a0a94649c6c6bd7b3a9d7c4dfa2738847ea3cb33
+
+Count = 47
+Adata = d2445db6efecaa3f426b06de8d496ceed54a1d0171384cc762e21b31e265c6d5
+Payload = 8fe8b383
+CT = f11347c32ca874d18d0b790856837555f4d4699a
+
+Count = 48
+Adata = 8cda7d1e135cf5fde1ec9473c4b42c1bbb445c27fd87b5f73df61ceb2d0b6f75
+Payload = d8d6b2c9
+CT = a62d4689932c2f8d78e322aaffc90846025190f1
+
+Count = 49
+Adata = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5a4c25393ecbf2025
+Payload = 6a029e53
+CT = 14f96a13c346a4084918081b4bbe53b50d896788
+
+[Plen = 5]
+
+Key = 3725c7905bfaca415908c617b78f8dee
+Nonce = c98ec4473e051a4d4ac56fd082
+
+Count = 50
+Adata = 11bc87f1c2d2076ba47c5cb530dd6c2a224f7a0f7f554e23d7d29077c7787680
+Payload = f5499a7082
+CT = e378b776242066751af249d521c6eaebdff40b2642
+
+Count = 51
+Adata = d54219ef4fb851bebd1c546011ae3922b8337e19c28d4d58428efd66f80edcf0
+Payload = 513c46fcce
+CT = 470d6bfa68e7258df363e0e9af67a543c86db3c994
+
+Count = 52
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = 9d62e557c3
+CT = 8b53c8516572b7573e5b27a1d0e15cdb7b06c8857f
+
+Count = 53
+Adata = 77d9c306aa257379053cf1f2043c388a301dac2a9e2bb89eb8bab6eb3f150fe3
+Payload = 7a05db235f
+CT = 6c34f625f9de691a412ad54bbdb6ceac45ed45902b
+
+Count = 54
+Adata = 081568ae0b948aa647b9d4dda5d42641ad5de72aa9874d8d0717d872007720a8
+Payload = 30a22ca0fc
+CT = 269301a65a8a1bb8ba3d6763dcb1bdd3400e3459f7
+
+Count = 55
+Adata = 695ba4dea0f84baf190ec25a25fc00cb9898902d7a17e6f5ff2df323b974f7c4
+Payload = 35e25aa51f
+CT = 23d377a3b9403897d496cabcd5bd9de3282199a8ed
+
+Count = 56
+Adata = 1f3ba0336a634efdd11f8168c0fe25039f9403bfa70b3898f4dbe577dbd52957
+Payload = 8bde704c74
+CT = 9def5d4ad270a81f7cb0ab7ab2b495f51d66abeee5
+
+Count = 57
+Adata = 097b9ebff3ff93a143678d59721fdf359e95cbc82585ae47727a773317925d38
+Payload = 428542ecfb
+CT = 54b46fea5dce68e9b01a4462a2221bd2f3cadf64c0
+
+Count = 58
+Adata = 76d0341dd44c39e43a23dbcf4cb602f15d5fb9fee20c3d0d262d539c3fd1dfd5
+Payload = bd6866ded0
+CT = ab594bd876f2545964ef3978cad3387d61104bab84
+
+Count = 59
+Adata = 7e7c40ad64b511005b4546f9ec61ca24829390fbc4bd8507225bc348ae0807d7
+Payload = 5822755a3e
+CT = 4e13585c98002c41938a935d51905b2a708a2c5194
+
+[Plen = 6]
+
+Key = 80bead98a05d1bb173cd4fca463b8fa3
+Nonce = 8a14a6d255aa4032ebff37a3d7
+
+Count = 60
+Adata = bb4e706e73d21df66f64173859d47e247527cd9832e20dccff8548ed5f554108
+Payload = e479990bf082
+CT = 89c9246238878427f36b1f6c633e4542f32b50ca8edb
+
+Count = 61
+Adata = 9db2182c8a4f5471082bfa1a8496602cbcdef2790f7e8f71f791303bd48dcb05
+Payload = 017a7fd1aecb
+CT = 6ccac2b866ced76fe54da69af5edf8309c7f013bb07e
+
+Count = 62
+Adata = bf483f59fb73681f27b68168c998c90ea8ceea997654c6fab2bd737dcdc884f9
+Payload = 512fc5e4973a
+CT = 3c9f788d5f3f662f53d17f7cb6673415bb2324ca0666
+
+Count = 63
+Adata = b91e641d8210e1ef705fec2beb9f58a391c7d1a38935cd1d13f2c00363388ff5
+Payload = 06212e989616
+CT = 6b9193f15e1340c86156b1065b64af1e4d6c89b32603
+
+Count = 64
+Adata = 5cebf908e232d797fcce8453c4c3000868d4172622a4ee0d6a1bdd876a0b7c96
+Payload = c45629069ebc
+CT = a9e6946f56b9c07ef5349903b928e39e99e2e32625de
+
+Count = 65
+Adata = ab92cbc97f3aa6f9ea4dae5d8c3d9e91231f43ffff548da7b668e61c183ac2cf
+Payload = b949ced37725
+CT = d4f973babf205e40654ea16e83cc6faeaad668c416f3
+
+Count = 66
+Adata = 2c3d2f9c7e89c2b9e07317c4db6e9f00f5faadfad531c5bea79d164ac24d4543
+Payload = 517ff7b383b7
+CT = 3ccf4ada4bb23102a502dbba0c280e1d5fc627fe3a9e
+
+Count = 67
+Adata = d798e77ab0f3697768f23014fd31b9e8762ae65b6aa8a4bbc17ecb8cbe78461f
+Payload = b40d863ca4ff
+CT = d9bd3b556cfa6745fd4c954396e696697731e1f9a262
+
+Count = 68
+Adata = 45b44e3dec57e24d960fd1767797ffdbbab81e38bab37e6974df262c3d932327
+Payload = 56e00289a003
+CT = 3b50bfe06806bdf2b2dd47077c98234eae5d47c3b594
+
+Count = 69
+Adata = 645d27970ccce096d082fccfc1183955bad2611af0dd7c58c9d54430f28bd992
+Payload = aa22bb1de579
+CT = c79206742d7cea66649ad7e204a344d3234125aa324b
+
+[Plen = 7]
+
+Key = dc8ec91184ba18eae31ac2d3b252673f
+Nonce = 0da4c988f521f5648259f2bec2
+
+Count = 70
+Adata = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024b3651eb227e73bb5
+Payload = 2a5775986551c8
+CT = 4f259f2a718faea852a7c4358dfa9f5467357638acac90
+
+Count = 71
+Adata = ff0ab5021ef466e2e898b0993d691145168be558682c74914c172f2b5e863754
+Payload = 8db3c1ca0580f9
+CT = e8c12b78115e9f8767c76e707d48a2144e090812e0192d
+
+Count = 72
+Adata = 2ee03cc28f79773af139c4ea55ec4daa48bb2885b8adcd5f066eceda5c4ec27b
+Payload = 3c69e2e83236b6
+CT = 591b085a26e8d05486df740083c959fb62ef7e2e221602
+
+Count = 73
+Adata = f041504d4c1b3d5be358bd6d350af42921205d29ab22b44ffe221358adef5bb4
+Payload = 777828ab5ccb68
+CT = 120ac21948150ebdc4d2b86b2528f75db4a7f5423f4395
+
+Count = 74
+Adata = 81ea116832d69542ac8d3d22c16c82eecf2ccac39264dd933c4f9c13c8d0f1d4
+Payload = af556fef3584e3
+CT = ca27855d215a85a7b06d1b710baa15daef19069ecf46f0
+
+Count = 75
+Adata = 8a0a120ed290a62456f002da1c250a0ddb1ebd57185a733d8fb562aad482679d
+Payload = 98f26635351f14
+CT = fd808c8721c1723811129add52e1406d50cbff4aa82802
+
+Count = 76
+Adata = 12b5a76faedf6f855e328c2cb87be8aea78c5e926b32d828e167b46205c86de5
+Payload = bd22c1ec05dc26
+CT = d8502b5e1102401563d3da8a6cabb7515f642e42fb4b2e
+
+Count = 77
+Adata = 8dc32f35ef4bcbfd040ad25dc36d0bd2486f93d0cabb7704cd1582dc99f65449
+Payload = 2a87c0d64806fe
+CT = 4ff52a645cd89817609a21f703253e5e56beef4ac71759
+
+Count = 78
+Adata = 83ced632359a11eb0c4c99baad84df5cac15bc5453b6593d9ffb4c5e8c84037f
+Payload = f05f39eb0a3d64
+CT = 952dd3591ee302236c72f98da859b54be7c598d85c37eb
+
+Count = 79
+Adata = 771a818a24e7da7b98f4b4291ef34bec7e1656b0c6c6e9474a989a04ea7de385
+Payload = 59dad755af92c2
+CT = 3ca83de7bb4ca464c8cd38cbcc46e7f09bf3e1c6590c71
+
+[Plen = 8]
+
+Key = 19f97ef5318b8005fc7133fa31dd1236
+Nonce = 01ce9814c6329dbee1d02b1321
+
+Count = 80
+Adata = 85853f120981f33cf1d50fde6b8bc865fe988a9f12579acdb336f9f992b08b89
+Payload = 6d972a673fbe1ca1
+CT = 2f12a7e7acecae5d2563309efc19368cdee8266538ca89d3
+
+Count = 81
+Adata = a4ec5aee89e2cce2115b6c1f42570bc5062887cad08192a682d0b4508fcd936a
+Payload = 68b1b6367a15fe49
+CT = 2a343bb6e9474cb528096a5fec5e5359c369833eac3b7efb
+
+Count = 82
+Adata = f5499a7082bf1e6e2923211271f5f7f6d7c7b26db7963071705a58ddc4dca0dd
+Payload = 707023615563a40e
+CT = 32f5aee1c63116f2754a65863efb60c98dbb536e2b5a69d8
+
+Count = 83
+Adata = 765f267befe6fcfaaa4b46eda32e7bfab87f12ceb07fa3b37be74965bb664a21
+Payload = b56454bc50df3e28
+CT = f7e1d93cc38d8cd40b6e9b7f3b3541ffee66a1f668f67d28
+
+Count = 84
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154c55e40
+Payload = 962f765da3565bde
+CT = d4aafbdd3004e9227018c9db8baf6be349d93d4eef7d7c9d
+
+Count = 85
+Adata = d0125e30c36232a8c07cee9abc53453b276849a7c04ade80ad586ed8cbcede51
+Payload = 4f18bcc8ee0bbb80
+CT = 0d9d31487d59097c501b28887f05fd66f050525943d101f8
+
+Count = 86
+Adata = 90dfd9e7bb7bf8fb70c22a879ffa760d14cda7b79ce4968f69b8a7f2b7a59642
+Payload = ca293c9e1780b401
+CT = 88acb11e84d206fdda53dde2e1aef96b3658a7635ee54188
+
+Count = 87
+Adata = 58f518710e6b282482a7f1950fa353b13bdda10c9aaea6d5f0d7ea0a965d31e8
+Payload = b9df9fb4a6b299b4
+CT = fb5a123435e02b48b62a5ec234f1efd1b52c8fad1cf09890
+
+Count = 88
+Adata = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb07545e6802de7e807
+Payload = fb2441d1594a488a
+CT = b9a1cc51ca18fa76bc051ede6f37cf67543a7252d7d9b203
+
+Count = 89
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f266
+CT = 07948ca59d94409a5be4be6bc6b18104fac167b6e3fc15f7
+
+[Plen = 9]
+
+Key = c17944bfaeeb808eed66ae7242ab545f
+Nonce = 910b3db64df3728ca98219e01b
+
+Count = 90
+Adata = edf64f98b3ab593cbcf68ab37a8c9472e49cb849d4a744deae925a5a43faf262
+Payload = 7caae2640e734539d3
+CT = 0dae8b3ccf0b439f6ff8ee4a233dfb7753f6bfe321b3e26959
+
+Count = 91
+Adata = 29ac8fd6a20a5df4ec79660c44d373da42de7d7c5fc35982b6c29b480723b484
+Payload = e574b3a37af3bf2251
+CT = 9470dafbbb8bb984ed63b1477d9506a51ae23abbac179d8b02
+
+Count = 92
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b227
+CT = 5f3899f74deec1149bdb0986198bce2e486581c041029a81d9
+
+Count = 93
+Adata = cc8e789462879e348d20be4e1161d7b7fc6f8371d8f8cb2d25d13f0e07de47b0
+Payload = 16f22817c5b79f9fa6
+CT = 67f6414f04cf99391a0cbb2df2079a6eb964c3469f4f326122
+
+Count = 94
+Adata = c63061f2800228269015693336f78bb535ae8b88869e4ccf4ead2f3b0ea4e48a
+Payload = 64fe8076d4e8538e18
+CT = 15fae92e15905528a4a40ca7622acf7266b7c24cf0c3202e4c
+
+Count = 95
+Adata = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b787660e7b1a581af11
+Payload = 4814aaac48bdf43c92
+CT = 3910c3f489c5f29a2e7de20e98586cd5d684bf015a7abbe82c
+
+Count = 96
+Adata = 8f4947f8588ed866ed7477d7f1a28046430c6470806a50e3c9e80958c61f1b42
+Payload = 392a692b57a8a97f60
+CT = 482e007396d0afd9dc8d503f5d87818f7c0e173b857cef4288
+
+Count = 97
+Adata = 9d44f6df58c2b43db67e3daa95b176c81daff32e996d670e86405e15eae72e93
+Payload = cba1e00e345b0cb7eb
+CT = baa58956f5230a1157c85e2283d9e80700268a6459d1451d00
+
+Count = 98
+Adata = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f93006c1ca2ff66f87
+Payload = 22f5b6752582919dc1
+CT = 53f1df2de4fa973b7d1056aea3d3e4f7a5219170aaa52465e1
+
+Count = 99
+Adata = d6411fd5b25433f67ca75e4560ceb809d3721266beec358dde126b2f6a514137
+Payload = 6e1b55d6f5288c5451
+CT = 1f1f3c8e34508af2edfbfcf8200a8a3f8d995f50284a7280c8
+
+[Plen = 10]
+
+Key = 0fb9df6f638847f5de371f003dd938f4
+Nonce = c9ddf61c052f3502ad6b229819
+
+Count = 100
+Adata = 4f9938d5bc3dcbe47f6b256d5e99723d0891e50c6175aba41b011e4686113c49
+Payload = e10cc36bc1c5d3c646ab
+CT = 7f797367de50be6dc04e4cf0d8c24189affd35060cb7ca3dd136
+
+Count = 101
+Adata = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304a643141855adac10
+Payload = 15841284c959febe63f9
+CT = 8bf1a288d6cc9315e51c4148ef85caab151488c1a6b3df540d21
+
+Count = 102
+Adata = 147d77d509f642189594df17574a0ce62b52a838feb62310e11533995ba4c851
+Payload = a8b4e5829069c335d1d8
+CT = 36c1558e8ffcae9e573ddaaa1e7c22b3efa8362abb3d31ee8884
+
+Count = 103
+Adata = 0bb09658e23fe8a08c01a6994ef36cb8dcc9a806297a09c67efe3558ca56bb5d
+Payload = 1bb2da0f1ae7e044deb0
+CT = 85c76a0305728def5855317b141383ad38dd78569d5f846f2520
+
+Count = 104
+Adata = 34eb2e6149bad764837f6f25ddd96865e5b05d5cbf233c4f6cc2aa654dfea3b7
+Payload = 63af538196add9b3fad2
+CT = fddae38d8938b4187c374e6432971aecf6bf7cf5244d21f7f173
+
+Count = 105
+Adata = b69f26fda6d1cd92897e03758cae020c4e1beb019ce5ad987f872940780a9468
+Payload = 6ef2df5a1688ae795537
+CT = f0876f56091dc3d2d3d2e4d0ffc0f0add38a80c7ffe6b4701e54
+
+Count = 106
+Adata = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117d25f6d4ef9c2fcbc
+Payload = 3f46c83021069ac488a1
+CT = a133783c3e93f76f0e4447fdd0b2f29f39094ba5a7375e278349
+
+Count = 107
+Adata = f9b91f7298b4e43843fc739a2f41c57c3f2cf36378fe4c34b574a43f9cedee7b
+Payload = 86c10a6dfdd6a06ef638
+CT = 18b4ba61e243cdc570dd57500f913ee3f46801e1bba9d4db7ecf
+
+Count = 108
+Adata = 9d35876d9449a1642b5062dfbfc7a26a7ac080b7198f4aeff2c79e463565cfd2
+Payload = 196c80d02b663bdd89fd
+CT = 871930dc34f356760f1856a6b87519b4807a2114ced587f72189
+
+Count = 109
+Adata = f2d5e927eb507f889efc6f21d783851f638f978c74960cc347f89f2703476114
+Payload = bd27ae3ade0781a33d5f
+CT = 23521e36c192ec08bbba2101012808adefe9b8166e04685bd537
+
+[Plen = 11]
+
+Key = 006ff7d3153caf906ec7929f5aef9276
+Nonce = 57db1541a185bd9cdc34d62025
+
+Count = 110
+Adata = 7d9681cac38e778fba11f4464f69ed9ebfea31b7ffcaf2925b3381c65d975974
+Payload = 31be1b241cae79c54c2446
+CT = 9dd8a4244fbdb30b624578a625c43233476bbb959acd9edebe2883
+
+Count = 111
+Adata = 1b0012c468009bd2851653013782c7b71ef43c393afd4dc0aec4d6d0c3fa11c5
+Payload = 8802831e22092b30110cf7
+CT = 24643c1e711ae1fe3f6dc9d477ca066ec2befa854a1faef018ea8b
+
+Count = 112
+Adata = 48b216375c00ca7e9c4048834b37944d2543e24fa091fb3c7290e11c53a6b6a0
+Payload = 3b3f782d637319d7fd161d
+CT = 9759c72d3060d319d37723eb6be9a78dfbd9e16181679b782969ad
+
+Count = 113
+Adata = f3e06a45fcf1f6abeb00727bf2c9bcea00ce621d38f7b7eba17c27e51f04c793
+Payload = e98f5e5a20d02c80372d6d
+CT = 45e9e15a73c3e64e194c533d9574d95b821a5170e9b61d8e6b2ff3
+
+Count = 114
+Adata = b36e27729f9a139d8ec4f61215b7bf1149cbb4d93a5c14bebd7cfb7c6fe585cb
+Payload = ceeed4fde3406ec40f7ac6
+CT = 62886bfdb053a40a211bf8aa193d257907be1330abaa56bc4f431a
+
+Count = 115
+Adata = 8886ed7fa414d74aef704a9751b197cbab02c41c6aedcaf65cda019dc2d2d815
+Payload = b38f03449883773135c0cd
+CT = 1fe9bc44cb90bdff1ba1f31d92029a6428748664b5c815f15ca1b7
+
+Count = 116
+Adata = 816d81af167d2294497d9b06a39fdf75e37cbacf4d10c3a444068c891b361bba
+Payload = 8efb141db7b77c521003cf
+CT = 229dab1de4a4b69c3e62f1386e4ad7c72ce0081a85d4cfd34254c7
+
+Count = 117
+Adata = f427c47e10c45bb3c7e75e9e604503b3560427691470358efdef48ddaf3794d2
+Payload = 6dc38e37d1379732df4dd5
+CT = c1a5313782245dfcf12ceb98eeb05bc376a1042735569d5b63f8fa
+
+Count = 118
+Adata = f3df712b5e8dd8e4aa8b7c5f41e93bd11b0df66a3456a01f3d0094ad91482cdb
+Payload = e0e358aff203369dd5960c
+CT = 4c85e7afa110fc53fbf732065b03ebeb68a9153cb4ed152ce0d64c
+
+Count = 119
+Adata = 264f2c7b095a296eb8ff6b5151ab3d9497ea8dc0002a9e5b09c2fd0ccd32b6ff
+Payload = 57b940550a383b40f3c308
+CT = fbdfff55592bf18edda236fcd16c8360a408e2787f930ed275bf3f
+
+[Plen = 12]
+
+Key = 026331e98aba9e8c23a9e8a91d0b0c97
+Nonce = bccfe69bba168b81cbdf7d018a
+
+Count = 120
+Adata = 26e011143a686a7224ddb8c5b1e5d31713fa22c386785e2c34f498ae56d07ed5
+Payload = a82200ef3a08c390dec5cbf9
+CT = adf4fc6f9be113066c09248fcb56a9c1a1c3bb16fbb9fbaedacdb12b
+
+Count = 121
+Adata = 97a720ae4720546e31263a1a538ce1d35c198c23bd4362e0023a67536328ab9a
+Payload = 7fc58d1bb450b396b9161f53
+CT = 7a13719b15b963000bdaf025002120b619a391fbd23402e5edd4949e
+
+Count = 122
+Adata = aff6c8cefda055c67262e9c68825d1ad2a7488e5b09640a111fabf6254d96cc0
+Payload = e9ea182d7f895f312b9738db
+CT = ec3ce4adde608fa7995bd7ad48b6e9a8de0099a28cebbf5c2bad42ff
+
+Count = 123
+Adata = 35a3963b43f47855ef3df12af5de3626e0c5c8d9cd2a534c737cd695609b05a9
+Payload = cfbc8bcbb5e5bb744bb1f340
+CT = ca6a774b140c6be2f97d1c36df80fd62e751757bb0a32a987980afe6
+
+Count = 124
+Adata = 46a2e6bd3fd5336abf02eace3cd1e1f6dde505ab976a9fa596edd6fbde7175de
+Payload = a334f8f41897cbcaeb5cffdf
+CT = a6e20474b97e1b5c599010a93b211350c70adf9bab5c01081bdc6a99
+
+Count = 125
+Adata = d110651c00ac5540f9d1ed9eb175e06b97163fc36d43f048565e5d0c30a069b1
+Payload = 3f781267290e8e73c6355e75
+CT = 3aaeeee788e75ee574f9b103d7f65690d9a2fb6759d658c9bdfdfc37
+
+Count = 126
+Adata = 978644dc4e36f1d98a2a63e19bbf8af11785d09fce58a95c00cc6bf6cecf6161
+Payload = 3dc39dbb91efe8b16396d488
+CT = 3815613b30063827d15a3bfe0d5df472f49e7f713cd1373293810906
+
+Count = 127
+Adata = 5ae7528c5e965880b1533cbd78c1e81a8187379327a2fc3f76ff45829049e183
+Payload = 6caa8c0764512baa39dabac0
+CT = 697c7087c5b8fb3c8b1655b64bfca9ef00b0f2bbb03c1a3f7a0862e7
+
+Count = 128
+Adata = afe754828be6e3731d3eee54b021b4fa182247bd958e9074fb0094a11030f5e8
+Payload = b19bc92e2305883580dd7742
+CT = b44d35ae82ec58a332119834a03be1d1d262b03c0ab425d533fe4ec1
+
+Count = 129
+Adata = 0650859c635654ca4d815963c0a99f9d2f47456ad37f739c425e924d4360bd7e
+Payload = dab87e79544df1cc98096b91
+CT = df6e82f9f5a4215a2ac584e7da61ca8461925996880e2874393232d6
+
+[Plen = 13]
+
+Key = d32088d50df9aba14d9022c870a0cb85
+Nonce = e16c69861efc206e85aab1255e
+
+Count = 130
+Adata = 0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa
+Payload = 4b10788c1a03bca656f04f1f98
+CT = 89f15b1cb665a8851da03b874ca6f73242f2f227350c0277e4e72cdaa6
+
+Count = 131
+Adata = a533b3279db530eaed425842b0d3528f5c5e4c16acfa0f49de43d6491f0060a9
+Payload = de6ea86d3641d916c4394fdd31
+CT = 1c8f8bfd9a27cd358f693b45e594271cc06f81d510075728cfeb89222c
+
+Count = 132
+Adata = 8e6c1cde142e18635c1b4f0cb54d3cf817f22ad7c25bf6a022501682f6a7da1c
+Payload = 6f3b32adc8c0314872947f3d31
+CT = adda113d64a6256b39c40ba5e5ab1aefed75400a41447b2bd8f0605542
+
+Count = 133
+Adata = 248a4389da2d51b87907dc11c46253515503ba80de5d06c9b505cb89906614a6
+Payload = 0cc992a8c736b44fedb4ad498f
+CT = ce28b1386b50a06ca6e4d9d15b46b3a6463876f1a43a287748f339e913
+
+Count = 134
+Adata = 2e2c8244a2cbf53816b59e413207fb75f9c5ce1af06e67d182d3250ea3283bcb
+Payload = 98104fd3f3413ad1f57ef4912c
+CT = 5af16c435f272ef2be2e8009f8f625786bdc58af24b17c1ba34fa87baa
+
+Count = 135
+Adata = 4ada86d88d5f49dfcde13fc30ba9a1af58d5254b47fb1885a20fad915c87952e
+Payload = 3b4fec79d52d8b2a533917b75f
+CT = f9aecfe9794b9f091869632f8bd4a918290cf97208232c76908514b07a
+
+Count = 136
+Adata = 9e3b23232e5a9e69747f8bcb148cd6d282fd9b7ecd6d97e8bb5cdc261b2fc86f
+Payload = f10c19c76ae7ed55e1651155df
+CT = 33ed3a57c681f976aa3565cd0b01d6306bb91c315bb4a23fe23d496d09
+
+Count = 137
+Adata = ccea2c815ea4efadc3007f511d633e98f9fa38b0e0fb572b282ed6a610adf7a9
+Payload = fa34af376868d9a49aa200f59a
+CT = 38d58ca7c40ecd87d1f2746d4e620d9d3004587c5d510e2a857fc857ea
+
+Count = 138
+Adata = f7277fb296e2c0d2c9ceb7013ea8b59fe37e26b3b42a0b8cd01aaaa8d35283d4
+Payload = abe2fd996bb6804ed3286c057d
+CT = 6903de09c7d0946d9878189da982d2438a5138977bde5f514e2335c28c
+
+Count = 139
+Adata = 14dd1810df3eeee78ed3836c77edf510d91ea28f119bf57111e580d70da94b74
+Payload = 395ea6979b77dabd2042aee4ff
+CT = fbbf85073711ce9e6b12da7c2b78100a05448fa6e74bd3ed16c3bd364e
+
+[Plen = 14]
+
+Key = 7301c907b9d2aaac355c5416ff25c59b
+Nonce = 7304b65b6dab466273862c88b9
+
+Count = 140
+Adata = 2c5d114eff62c527cc2e03c33c595a80fe609bfc0fe13ce3380efe05d85cceac
+Payload = 484300aa3a506afcd313b49ead8d
+CT = 928ca58b0d373dc50c52afac787ce8eeb5d5b493661259a9d91ea31a5f7e
+
+Count = 141
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d778da52c4
+Payload = 8b318f75ed79a7978adc17c4d2d4
+CT = 51fe2a54da1ef0ae559d0cf60725552193439abfedda67d765d030cef30b
+
+Count = 142
+Adata = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7ea337e548cb706780
+Payload = 0256b0d154c768c85070da6ea8c7
+CT = d89915f063a03ff18f31c15c7d3615013c2bc9338868fad0d2fac11df019
+
+Count = 143
+Adata = 08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a3
+Payload = 89ed296a3ac03fbfb71422b92117
+CT = 53228c4b0da768866855398bf4e66c3c4cb8c50891d6523245e4c619aa99
+
+Count = 144
+Adata = 7d653792bb8683e07c7d2c800db6f7f08343c85af2377115df4fc86ff7d8fcaa
+Payload = 414b6acb1db479028f5cc8800f2b
+CT = 9b84cfea2ad32e3b501dd3b2dada792d2cb93e45811a4c897ae9d907c9cf
+
+Count = 145
+Adata = 4d73c1484f9429eb15742f29ab05cbab6552abf40e127b93427d649d195ed25a
+Payload = 163f67b3766c3c650ce26c5bd8b5
+CT = ccf0c292410b6b5cd3a377690d441983a87812eaa7b66c5a0e54a01cb882
+
+Count = 146
+Adata = 2fba7a881f019a8745691343d79ef3656e25bb37b93fb5ab7311889f92010a5f
+Payload = 9c5b4aa703c27d16d82013853e16
+CT = 4694ef8634a52a2f076108b7ebe7b0afabd23b33765a63753cad66b0e6db
+
+Count = 147
+Adata = a640343fd4a866aec07b667d25176e11a32fb4d8bfc08fde2c46dc9b492fa010
+Payload = 99eb86b3202c7ce68a2339065f47
+CT = 43242392174b2bdf556222348ab639b8d0f97540373a7b9061aa3b2f7044
+
+Count = 148
+Adata = 9efd58d3ef5f74f663b2b5ca5e96c5a2fe85ca5eac1495d7f1751c7d8b412b3e
+Payload = 3f5c1d038161e65c9ed955c961af
+CT = e593b822b606b16541984efbb45e312c803e29f7be7c5eb236401037a320
+
+Count = 149
+Adata = a7d7ba684c0903323f7efc83dc32815195df325394162fb5a18f201047be7999
+Payload = be8dea2b4e602a787ecd28f2f7f0
+CT = 64424f0a79077d41a18c33c02201fd929c717d75388387dc25bfcf90b707
+
+[Plen = 15]
+
+Key = 38be46d271bf868c198052391f8a2147
+Nonce = 6758f67db9bfea5f0e0972e08b
+
+Count = 150
+Adata = c6de3be97f11d0e2ab85c9353b783f25b37366a78a2012cecf5b7a87138b3c86
+Payload = 61bd1385be92097e866550a55278f0
+CT = 7c9fa8d99b38f825315ece6a2613f55e902f296dcce870263ae50cda4fadae
+
+Count = 151
+Adata = 7c8cf9c650511f33af82e807e60336ec086bd2d9400a5f35652b8c3fcf968ead
+Payload = 7e5e51301fa44a21f2734731ee3710
+CT = 637cea6c3a0ebb7a4548d9fe9a5c15cae8a9e4b606f5fbeac2b829b42a150a
+
+Count = 152
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75
+CT = 81c8805a3bf6b176ff72e06be0e670f5419c6085e5434f056162cf80f6729d
+
+Count = 153
+Adata = 238d3c9d9de32f2040b1dd0dd040b921e456c3653263f4020cffdc552b948a46
+Payload = 20660408d6890aed84aa65dfe23032
+CT = 3d44bf54f323fbb63391fb10965b377fedcc743389a9d48e6b871dc0dd63b2
+
+Count = 154
+Adata = 3b5d61ca21953fdd22280747dd4ae908a511750127875da84dfe7d0063a318c9
+Payload = 9ab83c81f2d2c896c6596660c3974d
+CT = 879a87ddd77839cd7162f8afb7fc488137e0a856d3d911af9f420b68d8110d
+
+Count = 155
+Adata = 78c1751e86144a78285a30dc04f51742bd47e3d36b607bab48d91cddabfff4b7
+Payload = c1ec469aa9c73b677af225a9f5f6f8
+CT = dccefdc68c6dca3ccdc9bb66819dfd5644448fa8445b6cd185bdf9b3718033
+
+Count = 156
+Adata = add33e9a1d7e91e2c160c1123537e3f7e3535881cb4aac1a80ecbe367379212c
+Payload = 9df1d6b6debffdd316aeb27143508e
+CT = 80d36deafb150c88a1952cbe373b8bbd38e4dc44f768cef0c51344e3a7f7b8
+
+Count = 157
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c12
+CT = 04cc4b4b35a7397491d696dab137172e7f2ec918099898b843a34c385f2a57
+
+Count = 158
+Adata = b40c8d22069b8a65cddb51c1ea3571160cacb19fd371552436b19c7122b28d08
+Payload = 2af5db43f2a5fe8b494b40661510bb
+CT = 37d7601fd70f0fd0fe70dea9617bbe94c2709685b0827cc42f3a25b579db28
+
+Count = 159
+Adata = 9de5559ea8ccc70f4375a436ce0b72551a75960ad5ed6a1949ee8f6c47548558
+Payload = 5de41a8ca8ed8011304fa9e9f36498
+CT = 40c6a1d08d47714a87743726870f9d63bf4b40ce7e672587816fdcda16efbe
+
+[Plen = 16]
+
+Key = 70010ed90e6186ecad41f0d3c7c42ff8
+Nonce = a5f4f4986e98472965f5abcc4b
+
+Count = 160
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f2
+CT = 8e4425ae573974f0f0693a188b525812eef08e3fb15f4227e0d989a4d587a8cf
+
+Count = 161
+Adata = b6fecd1edeb55a9a4148b1aefb716a1e162779a5ab2a682e4adce4479c527bd2
+Payload = 0e6118d0409751d36cb642504678535e
+CT = 3e171226f809dde516bc264351e47cbedf7f186e8d3d7c21c549c41ebcc7f505
+
+Count = 162
+Adata = 5c3933c30bf9d4841eff4000aaa1cb4d39cdf8ef1240e2aabbf9da95bdee5270
+Payload = 5c8a5fb36f860d00c21ae9e3f24097c4
+CT = 6cfc5545d7188136b8108df0e5dcb824810a68be1814f53c09aca4066527fef8
+
+Count = 163
+Adata = 7ca7ef30d3ac08aa51a9e5d3d84e8b6bb7fdde921e72b98ad6a93ebf2efc6b04
+Payload = ebd1cb4b35257790c9806be476bd25a3
+CT = dba7c1bd8dbbfba6b38a0ff761210a43cc30245a6e64625c4f6531d7497fb144
+
+Count = 164
+Adata = 90f1416768fca7dd48d01230dabf95f2f1a0c044bf2d755448aaf72316c8448c
+Payload = 842b7e5f22d921b2b8ab3131684b7eff
+CT = b45d74a99a47ad84c2a155227fd7511f10d85725dacc274034669acf7f34fed7
+
+Count = 165
+Adata = adc5c36849283d57acb2bcbc0e12465cb7c1830cb4e314b9ce6e25acbd8d460c
+Payload = f0c2cc5a1b4c4cbe839338fa0d7a3435
+CT = c0b4c6aca3d2c088f9995ce91ae61bd5f731b465eb59c4989e42020d86102a59
+
+Count = 166
+Adata = 80a7a483d1dbcdf00ed02a700e93d8b87fa6ac5c7368d1e81bd1b32cd1621cd7
+Payload = 2c1a5f906f2ae0373cc25e3519df2ba4
+CT = 1c6c5566d7b46c0146c83a260e43044484bcd2775448447ed801b3b0ff071c19
+
+Count = 167
+Adata = 13c02992992d2708250184a579c43bc29a3a8cf1e02dade4496cbd8b1214f97d
+Payload = 1da5190517546f1ad852f64263e1f679
+CT = 2dd313f3afcae32ca2589251747dd99901d1919f1451ad16f115cde863f15303
+
+Count = 168
+Adata = f6f18dfe093e4c0c3fbfa8a5b1f4a703c08addc2ab959741611a594b93d08bf7
+Payload = 13ccb08a580efea53dfba6a59626bbe2
+CT = 23baba7ce090729347f1c2b681ba9402ccae4f6ec07bf73d6f086cf09e2e14ed
+
+Count = 169
+Adata = 63708e12dfa14f192ec5ee5856dc3cf2403817d9628c31899b4613f65e1e61c2
+Payload = e0b5fbc6c2269d445a60273bf844892b
+CT = d0c3f1307ab81172206a4328efd8a6cb2bad8bf67d32a855c3940ac908397a5f
+
+[Plen = 17]
+
+Key = 79eae5baddc5887bdf3031fd1d65085b
+Nonce = 9da59614535d1fad35f2ece00f
+
+Count = 170
+Adata = 46603500af9e4e7a2f9545411a58b21a6efd21f2b5f315d02d964c09270145b3
+Payload = 001343e6191f5f1738e7d19d4eec2b9592
+CT = 2162e27bfbf1d00f2404754a254665fd9270f0edb415993588b2535e2e0e4fd086
+
+Count = 171
+Adata = 278afebc604bb7d87bed3574a2c5053de17eb8ca7e18ddc7892f2c54b38104a8
+Payload = ba47d5bfb36f6150a100e36caa116405c4
+CT = 9b3674225181ee48bde347bbc1bb2a6dc4778e3c4a11f3f9dc42554d45796379ef
+
+Count = 172
+Adata = 3239b2ce4efe4f6a6255dc53347400a6446ed3280c65422386fab471ef09eed6
+Payload = 96eccb7f9b0e16c6883de0a381e4767f5a
+CT = b79d6ae279e099de94de4474ea4e38175aab5540cc01d867f641c9b196fa159291
+
+Count = 173
+Adata = e2a5488d5f7930ea4ce399f2a6c0810265f7c0dc52fe824d19a0fa0d9ffd55e6
+Payload = d68f5990da1a2fe39ed81af145ab834fa4
+CT = f7fef80d38f4a0fb823bbe262e01cd27a46366fbe302e142dcf6aa16337d98550f
+
+Count = 174
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cdd4d8b3d8f6e4742793b456cefc9e686d
+CT = eca5792e3a186b6c3b701081a556d0006df88c07797267bf5a49b3d0f601a225ce
+
+Count = 175
+Adata = f5d6989587e463969d97aadabea9538511f8d109cc2d3cecf09ba7cc346aaea0
+Payload = e7d7fc60ae852b68102e01b506f9dab986
+CT = c6a65dfd4c6ba4700ccda5626d5394d1865c9fbf69d81cef238ac513562d4a0dd5
+
+Count = 176
+Adata = e0b5fbc6c2269d445a60273bf844892b26fed03b82869edacd6dd7a63fd69e8d
+Payload = be9f51abfbe2da5a56db0f9a31b67c9f83
+CT = 9feef036190c55424a38ab4d5a1c32f783e2c748c8c9e3190de095de8eb0650203
+
+Count = 177
+Adata = e6bd0010c98e60b9af7cf905c58e0653bc425e2ccc809bd4f9cd7b1f95c18786
+Payload = 81b9c73029cea1936ef8755c80ba8d4093
+CT = a0c866adcb202e8b721bd18beb10c3289305cf563c5b4ba4ebd5bf107f2ad3555b
+
+Count = 178
+Adata = b1688cbc058816974694cd26c0f28ba9418e9912867fc8c5f4e7bd9c891a8d2e
+Payload = 618dc26853ee339689467ffbc2a77be69e
+CT = 40fc63f5b100bc8e95a5db2ca90d358e9e60dbbd8f46343c8442b03a472da4e23f
+
+Count = 179
+Adata = 469e004fee9878ed40621b41d04ec34af175f213d64d16e2f77d0bb2b6efe2e3
+Payload = 4f18bcc8ee0bbb80de30a9e08629323116
+CT = 6e691d550ce53498c2d30d37ed837c591643352e46995e8c1aee43dbdb26b46c30
+
+[Plen = 18]
+
+Key = c14eda0f958465246fe6ab541e5dfd75
+Nonce = 32b63ca7e269223f80a56baaaa
+
+Count = 180
+Adata = 733f8e7670de3446016916510dfe722ce671570121d91331a64feb3d03f210e6
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb
+CT = b2dc1e548b3d3f225a34082f4391980a0788b4cc36852fd64a423fb8e872252b248e
+
+Count = 181
+Adata = b6ec659856866959ef6fd4e71ba930f0e3e5fd49d7465fd65f6813ab4ca1a770
+Payload = b8b342c49c28bffc2a1c457db0b537ad46bb
+CT = 6b17343e86e28518c5abf8af8d3aef21e08895a66eb5b902bb23a1a8584249409fda
+
+Count = 182
+Adata = 89eb3636fff80230352a3582be5698e3401c9e0579d48f2680c6e5e24d99f74b
+Payload = 37d694ba94d0af8df662134f20d142903839
+CT = e472e2408e1a956919d5ae9d1d5e9a1c9e0a7fa792fb7246218f7d56d5fa4a5476bd
+
+Count = 183
+Adata = 03434f3709e19a1e37edfcaabc215116763b71ab1c5e053dbdb599f86959f25d
+Payload = 90e4c0550cb7b279ef61f9140b7d94b8003d
+CT = 4340b6af167d889d00d644c636f24c34a60ea83dc3f0012ae6da32a15fd1684835ef
+
+Count = 184
+Adata = 0e2ddb65fcc72094ac388d53a1055c7e902285c4c3c33c13bb6fbb4f1956414a
+Payload = 69b851e63a78baef90637978e3dfe8c47be4
+CT = ba1c271c20b2800b7fd4c4aade503048ddd7f09d38d3dba01995e36bd685c8ea3371
+
+Count = 185
+Adata = a42b2538ee2fb5f6a85d4d00524b01ad3331f61c404069243f35f28e2c2d0a82
+Payload = b7dbf8382115199dd2a2d87938c6ae6c4241
+CT = 647f8ec23bdf23793d1565ab054976e0e472c89becf8d2bb935cb17f44b950df3ef5
+
+Count = 186
+Adata = 09bc5c426dc1faa4d71f50908bd6f297ec8e754d4d20def005585b4bc1fa31da
+Payload = d53698d719c51bf9eae346269c6a1da07162
+CT = 0692ee2d030f211d0554fbf4a1e5c52cd75196e28badf0202097e80561451796194d
+
+Count = 187
+Adata = 2ac87e59c2c86532cf165af3e8ff4871d730f5e742cccca38bbcdffff4472c93
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb3
+CT = 1c7f059982909afe194f55f140306f0bb880710d4d7f66660891ac655d6eca4a3f3e
+
+Count = 188
+Adata = 05d2fbc3d0ec81f52f31cb0c4bf960c2076867f6d9f0174ed9176e20177b2693
+Payload = 56fdf10dc0c1dfd10965b83938e557459c61
+CT = 855987f7da0be535e6d205eb056a8fc93a52f90ab18925fea6964490f364a975a473
+
+Count = 189
+Adata = c2c3902cfe8622254b3787cc13e79c5a3c388c2357c29f1c1ab5539a10bfae5c
+Payload = e7c9812eda2ed7dcfc80fc5fe0d43e1e5982
+CT = 346df7d4c0e4ed381337418ddd5be692ffb168a00e5e7a39b371024927d3ac98fe43
+
+[Plen = 19]
+
+Key = c5e7147f56ba4530b8799ababeb82772
+Nonce = bdd38e173fb20b981659c597d6
+
+Count = 190
+Adata = 3a069a2bfda44abbb0a82a97e5e9047258c803da2c66190d77149e0f010b3af9
+Payload = 2f3bf0b566440912a1e47a0c07f1cfd39cb440
+CT = bd6265dcba9e14c59e515e395dc60bd053345fa6d7568c738e3a7fdf142d8f2d1562c0
+
+Count = 191
+Adata = 7709132415c94960025cc39c950ead208703a9d5a71e224fd022dc0a1817d0f4
+Payload = 7c880d787726c4ddeb2304b5d161b4a257298e
+CT = eed19811abfcd90ad49620808b5670a198a991f22337efa5cb7db7240e7518b67ffbb1
+
+Count = 192
+Adata = aad77595f87a27f2c7995fc7149317f4cbebcece8336db2068380070784a4283
+Payload = 08c43bbfa706512aa39e2bfa5c365aca11e22e
+CT = 9a9daed67bdc4cfd9c2b0fcf06019ec9de623140bac6094528f02eeda093312fcf716f
+
+Count = 193
+Adata = bdb1b82ba864893c2ee8f7426c7b9a8460b00a50f164fc8f2ff2ae9cddab8657
+Payload = a531c0ed8840b2fcf08d76eca71036153b6e11
+CT = 37685584549aaf2bcf3852d9fd27f216f4ee0e0c041d86dd483c1d6da366e91bd826dd
+
+Count = 194
+Adata = 38b3b9f45041ceb743fc2655b409213fa081427e41c833a2321a09fbd566c80c
+Payload = 177946b4dc3b0b825a505f097a0a203eb21c00
+CT = 8520d3dd00e1165565e57b3c203de43d7d9c1ffde45ca2a83dec2f930bb652a6fcdc5f
+
+Count = 195
+Adata = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878742de83154a578da
+Payload = a2634ef20a2a418b2c3be64f0b5f79d7ea9b7b
+CT = 303adb9bd6f05c5c138ec27a5168bdd4251b648b89aa22cd7d0170a975565cd3a33dc1
+
+Count = 196
+Adata = 8f6c1de4efdc5ac2d6e5452b5b4f58416d618da672f521332fd297ede8350134
+Payload = 40e52edaad5acf2d4eedfb3f9ac2908112e9b1
+CT = d2bcbbb37180d2fa7158df0ac0f55482dd69aed960b33c3df5cd38a82980dc0950ada4
+
+Count = 197
+Adata = b0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0af
+Payload = bf97780f498c23adcf1c49f60873780a235969
+CT = 2dceed6695563e7af0a96dc35244bc09ecd97638fa273c4102b5ca050b23044ac2064f
+
+Count = 198
+Adata = 7d02a323aa769a8201549bf48a520d940bf6f69ed6106f1ce68856c22a594216
+Payload = 58bfe1eb2d38d91f80b3467db94fdcb84ff5f3
+CT = cae67482f1e2c4c8bf066248e37818bb8075ecc15438af1bafac3eac61e1c24ed00ab7
+
+Count = 199
+Adata = d4b90ef8abad08c552c8c3b080b8c37df314d514049d45e27ec4527cb06cdf85
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59
+CT = 305f3482ac73cf9c8a520b04144a55ddc8cf464422d9e2f4f84fde49e9701296294d5a
+
+[Plen = 20]
+
+Key = 78c46e3249ca28e1ef0531d80fd37c12
+Nonce = 5de41a86ce3f3fb1b685b3ca4d
+
+Count = 200
+Adata = e98a77f2a941b36232589486b05f4278275588665a06d98aec98915cc5607e06
+Payload = 4802422c9b3b4459ba26e7863ad87b0c172cfe4b
+CT = daea2234ea433533bf0716abe1aa3844b6d3c51e9d5ca3d8ec5065630d2de0717cdeb7d5
+
+Count = 201
+Adata = 5970a836de1f1e91d94d7eef79742cbbd46a759c413715eb0224fd6a27145333
+Payload = 796a69ad0e9379173ef6b66f44f5c84fa70a0e28
+CT = eb8209b57feb087d3bd747429f878b0706f5357d0ff0648ddb07f42f815b38bfc95688b1
+
+Count = 202
+Adata = e3f08834c4894f6fa66a55a280c0e677a79e97c1ef9488b21384e74e57b1b51f
+Payload = 98e1f8cf250183b13ad418024dc40c1a6a7ee8ac
+CT = 0a0998d75479f2db3ff5e92f96b64f52cb81d3f93ddd9a6977ea8e7adf5c5234346e560f
+
+Count = 203
+Adata = 18349be2894d49290339b97f4db28c92b3e112ffac77100abbf9c093935b1a46
+Payload = 4a856d9b50a5b40d6566b38eae6a53ed0c192805
+CT = d86d0d8321ddc567604742a3751810a5ade61350bdee05328a7ea8cc6c2e42bf3faeeda0
+
+Count = 204
+Adata = 7355e34ad13880de17a1d66b02672ea5c9f51774019f64ecbe36747ffcd9b671
+Payload = ad048eb2ad75266b43b59d9d1f073c44e4cbf25e
+CT = 3feceeaadc0d570146946cb0c4757f0c4534c90bafb1435cf929db35ec5986aabaf4a7d1
+
+Count = 205
+Adata = 4be21ba2eb26234ddcbb6aac6b4c3be7ef644af64edf51b7c29ffc3ddd80036b
+Payload = 5b527ac6cc6d1b4c3c56f8315bc96dae91632df9
+CT = c9ba1adebd156a263977091c80bb2ee6309c16ac736be6563cf9f5bce97486b7cc6f1c18
+
+Count = 206
+Adata = 266e0e3365e06d3b1e864c6e5897145df7bdde90eb744013a7b36632d4cf6580
+Payload = cee059cb0fe91a39faccc2914340baeab4b644ce
+CT = 5c0839d37e916b53ffed33bc9832f9a215497f9b2e90335fcea56b969b4fce65442768dd
+
+Count = 207
+Adata = 55a723883a340877d85ad1a5f264f2c834d824c7bbf207cdd8500c9d11ef9225
+Payload = 85321fef6a2b7d31cbd079c4bf2bfbbc979df90b
+CT = 17da7ff71b530c5bcef188e96459b8f43662c25eacd6afdb3578ebc75e8a408d32758931
+
+Count = 208
+Adata = 773864475a1a60a778468a66cbe13dfe3458094e62abb593f50c8495e3a8b81e
+Payload = e227b8d44320bd3ce9d3f7d688f3de887947b1e9
+CT = 70cfd8cc3258cc56ecf206fb53819dc0d8b88abca19fb73fc0488d9f29a09c1b47e3e066
+
+Count = 209
+Adata = f64f3b00c9117aed3c486aa4c8d574b44d679be4069e1078bb7100af38cdb190
+Payload = 206e9eb2bc3f8534d844a38debf1306df808744a
+CT = b286feaacd47f45edd6552a03083732559f74f1fce2c5ef8cdce76b358739e2a1b173fb3
+
+[Plen = 21]
+
+Key = 8883002bf13b3a94b2467225970df938
+Nonce = 818a702d5c8ee973b34e9acda1
+
+Count = 210
+Adata = 545aeac737c0ca2a3d5e1fd966840c3a0d71e0301abbe99c7af18d24cc7e9633
+Payload = d516bbff452e7706c91c7ace3e9baa76d65ff7050f
+CT = b85242fdc06344f2bd9a97b408902ebcd22aece3d42f2da4dd4d817c9fa2d44bc02163a0a9
+
+Count = 211
+Adata = f032db01da60ca078d35c3fb5d05d6750fce1c01911a0422e827e8976946e4dc
+Payload = 590d1aa655fed50ca2e402299f2da6fe20eed56071
+CT = 3449e3a4d0b3e6f8d662ef53a9262234249bce86aa180f41bccbcd47c8b7890754c032269b
+
+Count = 212
+Adata = 71ecb4252518997b53491cf42a3e0fe1496a2af2329a16f9fcd9c4f249900341
+Payload = ecd86cdb7d78d310dca5b477cd9da2612f5a05ab39
+CT = 819c95d9f835e0e4a823590dfb9626ab2b2f1e4de21d6ba58cc2eb474401851bf9502c3413
+
+Count = 213
+Adata = ec7abed9bda4a52fdf1bf278b6bdd6b0a27d4688deb9ff5ca9c8c865a4d2f730
+Payload = 0024b14c283df032cf80c22ad8d2c96289ee229092
+CT = 6d60484ead70c3c6bb062f50eed94da88d9b3976499b94d4b7a2044696c72322e850537b6d
+
+Count = 214
+Adata = c2c77d7ad7b27d7c0f976a1e28881ea4ec7ad03b63a4e67f47280a40b8f58086
+Payload = bc6965d8f62d066d118c14044c1fd2a224b9d95110
+CT = d12d9cda73603599650af97e7a14566820ccc2b7cb9d8da8e718570caf8bed7909fbff3ec6
+
+Count = 215
+Adata = 28929286bd1391468ac75f5c03689f74780ddd7585fc16f9a9bf7b00357a72e5
+Payload = da4a630cabaff0728a1cc3e6a79721a7176b708f1d
+CT = b70e9a0e2ee2c386fe9a2e9c919ca56d131e6b69c6e671012690c61fe3c9abd50a78eb4736
+
+Count = 216
+Adata = ed360d22081b019dc979420a3a45c21c8903c59daedd9f1b4ef2bfdedff0ec1d
+Payload = a95058f8e1f6bc0f143a9ca7e4425a2a63eb2f7e33
+CT = c414a1fa64bb8ffb60bc71ddd249dee0679e3498e8e657e2250427130acef7032454cde7b6
+
+Count = 217
+Adata = 2b4022d0b951fe48635d04fb3e2fa032c07c855fdd73f45670953bb9ddc77cb4
+Payload = fcbbc7f9d1ace60e830ca56ec84814fbd2579993d4
+CT = 91ff3efb54e1d5faf78a4814fe439031d62282750faac6ff0a264b8199550d93c1f06063da
+
+Count = 218
+Adata = 48e553a87a7d3c1bd68af39f96aca67583da86e06701d5e4c4ed404dc66d70f3
+Payload = b95d298d391c6b893c6cad66f9780534516e71455e
+CT = d419d08fbc51587d48ea401ccf7381fe551b6aa3857e68bf636e81c332f72063dc0d6fc2b6
+
+Count = 219
+Adata = e8e2835e47144365a2f218d4c95d7522e824fb43b66d4727ee570f8303dd6dd3
+Payload = bc79d444dff9d9e722effab07b068cb7723ae8fae0
+CT = d13d2d465ab4ea13566917ca4d0d087d764ff31c3bdf3af9e9c4e04bad261dc17cf00a00dd
+
+[Plen = 22]
+
+Key = 5cea00ee44cfb9cfbb598d3812e380ef
+Nonce = 948788a9c8188cb988430a7ebd
+
+Count = 220
+Adata = 50422c5e6a0fb8231b3bb6e2f89607019be6ad92a4dae8e0fe3f9e486476004b
+Payload = 33bfd0713f30fcac8f7f95920ac6d9b803ddd5480dd8
+CT = b168747dea3ae0fbede4402af9a3dc3185d6d162f859d828101682de32923788c70262b84814
+
+Count = 221
+Adata = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192eada64ae00c726b2e
+Payload = 5576d94b577ed26820fb13c00ab0e2d1a1c3589bfdc4
+CT = d7a17d478274ce3f4260c678f9d5e75827c85cb10845bafc4ae4d31907def6f648b081174e2a
+
+Count = 222
+Adata = 5140324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+Payload = 13303e14068205cbfa992d4ccb6a265804ea64a15d7f
+CT = 91e79a18d388199c9802f8f4380f23d182e1608ba8fe314e378e9ed6e725a14c07632b02bdbd
+
+Count = 223
+Adata = 74da07d324060e590356988f27d9879fa3a3ade0fe71e2a0e49054211cfa1fe1
+Payload = 567e6d14b446add630d53ea86a537c0938537c4604a8
+CT = d4a9c918614cb181524eeb1099367980be58786cf1295bc2f2f9331536f7f70be09c41bda0ad
+
+Count = 224
+Adata = 0e403cff47adee3ec5bb6b178dabfc7d53b60a04eaad33a2fedd9db705358a4c
+Payload = 9f3d165d44cf1c5770346d211d4ff34ca2ecd6b28549
+CT = 1deab25191c5000012afb899ee2af6c524e7d29870c86b59cc9c3c008bc5876ef86327859cbe
+
+Count = 225
+Adata = 211e6ce3d0c3abdef069e6e4fa35015797bd8a9d64bc9b75f20b028b12cca04a
+Payload = d726e599db6a6d40629bc4bda5e3fa2e5aeda229cea4
+CT = 55f141950e607117000011055686ffa7dce6a6033b25135e6d59a5385a78658d60d254f99962
+
+Count = 226
+Adata = 3c5c67b083322115e1b3112c2b6968efc050094e23e646dce982eac9d6e67d10
+Payload = 42646cfb8a99e48a35cee3f5f9b3e6175695973f6de0
+CT = c0b3c8f75f93f8dd5755364d0ad6e39ed09e93159861e234e83d9a0570dbf2b2fa59ce3cdbd9
+
+Count = 227
+Adata = 37a931f1dd05755b376d1a164aa36b8de802e39f8108a0453c1114754665fe46
+Payload = e814c7b5c72d973a9bc7ccd463f107325ffa3321783b
+CT = 6ac363b912278b6df95c196c909402bbd9f1370b8dba2084e352b1b157267228576dd056c1a3
+
+Count = 228
+Adata = f1ddc2c49da7363526ba36c600c589b4c3121fbb8c5b9a8aa0de0e7453b30568
+Payload = 4f7a5618870945b89f194e31b1aa802c5350326dc691
+CT = cdadf214520359effd829b8942cf85a5d55b36473310bf88ad35ee338e489e55bb49732447cf
+
+Count = 229
+Adata = d14b3d3803df432488b5d66704abef6a500d397e855bc2c2574df746a515cf70
+Payload = f555216840a1f40b411d44128e567617e2694caf1621
+CT = 7782856495abe85c238691aa7d33739e64624885e3a07ab67f9397a81371ef6ebc775cb7007b
+
+[Plen = 23]
+
+Key = cb83f77751e72711401cbbf4f61aa0ed
+Nonce = c0b461b2e15b8b116ef9281704
+
+Count = 230
+Adata = 2bd112231f903fa0dff085db48a2e2a96ec0199249b005d5ab4c2eab753f9ad0
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06
+CT = feb114b7bd3b43497b62454a675a632c3546d2802462c6af57647efda119c59862cd5dd3904efc
+
+Count = 231
+Adata = 864e0e728aea856fae6c6daa6357d1542cef7177f441ba21a563f6c4f6fdc1dd
+Payload = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0c
+CT = 9a394d88d7405656df1a50e7e45fa8ddcca85e9ed5a3cc2af4027ca5824b41c7bb238d3e8eeebf
+
+Count = 232
+Adata = dac7f3cba0b5a47f67f85b226b66df695a8ae2501355e36aad105375bb95f732
+Payload = 66e34540d7accf377877aa2d3e6d2db0cfafc608a1eb3d
+CT = 768c5047e50dbc42dc0126fa23723db5882ffb7a2452fdf7fbd7044ce1d7b266bdf545247a3c2b
+
+Count = 233
+Adata = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c930905aadd156b1dd56e
+Payload = a9ebd04fba7155c39b5c29c5571b5354c9ae228f5e5b13
+CT = b984c54888d026b63f2aa5124a0443518e2e1ffddbe2d3afabc559b552cf7c7730c7dca25bc3ed
+
+Count = 234
+Adata = 2d24e79abd157af2c21b60932947fd9f9d6478f09ec56fffd341ea04a17b8e5f
+Payload = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381
+CT = e116203ddd955c7acd6a23c8d69e0e3a2284dc3fe82a41488ca99e0f85ac388f981ce25560b8f9
+
+Count = 235
+Adata = fea280f710379e4665b5ed3d1620729a7bc164899dc83e6aee3612d538fa20db
+Payload = 6c19a18eab544acc883c5886eaa89f54d61ae5f1f1368c
+CT = 7c76b48999f539b92c4ad451f7b78f51919ad883748f4c9156faae3d8860bed216e8d497a75962
+
+Count = 236
+Adata = 18f2e3457127c35f2e0cff2d821af8178028fcc7803bc795c49f4a435b37abeb
+Payload = d0df1bdf1df6203241722fb9c9c1cf7405017497ae1545
+CT = c0b00ed82f575347e504a36ed4dedf71428149e52bac8588cd7791c544d1098b2de49d04b1e0c1
+
+Count = 237
+Adata = 35221f0efcb109cb93c38a62c58b5ab8b236437e171e8507cf417a569af1767c
+Payload = 479526b33c42c240b9a4549ca70cbfb691f16ae3be8888
+CT = 57fa33b40ee3b1351dd2d84bba13afb3d67157913b3148c523fd8a2524717f63dac75c22268fa6
+
+Count = 238
+Adata = 95f2ab02af01aeacce86b02cf846f9fbd516963d06e350e8b7f6df2778765a01
+Payload = aa6761148b254a2ff202b620c2ec2c5e623bf61f05e483
+CT = ba087413b984395a56743af7dff33c5b25bbcb6d805d4392904f05dc2397596543df73de5aa708
+
+Count = 239
+Adata = 3746a36154e42dd600049d506f5ce4d034864263b1a65cecd24c8e25fb9c82e1
+Payload = 2f298f106703b8a994cbb20acf47f9442e44f6b5e82c38
+CT = 3f469a1755a2cbdc30bd3eddd258e94169c4cbc76d95f8c3cbfecfa3f75fb111ef0011222b7948
+
+[Plen = 24]
+
+Key = 43c1142877d9f450e12d7b6db47a85ba
+Nonce = 76becd9d27ca8a026215f32712
+
+Count = 240
+Adata = 6a59aacadd416e465264c15e1a1e9bfa084687492710f9bda832e2571e468224
+Payload = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5
+CT = 14b14fe5b317411392861638ec383ae40ba95fefe34255dc2ec067887114bc370281de6f00836ce4
+
+Count = 241
+Adata = e82fc3ffd276218a82aede65fe5abf4fd35c7059a26923f8dbb97a59c903a7f4
+Payload = eab8cef576816a82ed036f158e5036f5987b195e60582a6f
+CT = 4b0f27aa559a3ad6b7830e7e46db62a2e578476540f489460d2d30268e9f1ce0e7c762993297d828
+
+Count = 242
+Adata = 776aae7f62225556b6da522c0c9432ac70fe72ac6f3f361071ef3deb4a6715e8
+Payload = 566ef9ce1d397be2547c385639507a9e7d6f9eed9a3b1055
+CT = f7d910913e222bb60efc593df1db2ec9006cc0d6ba97b37c0939e56f0b7200d1b1409f3f8e8179cc
+
+Count = 243
+Adata = d9aef0955922f89747ba4a8ddcdb8c1c7579aefd3c2eb8ad0589c66576a8504c
+Payload = 8c28b6d93b23f1ea031d5020aa92f6608c3d3df0ee24a895
+CT = 2d9f5f861838a1be599d314b6219a237f13e63cbce880bbc138e3b817023993608be06fe92efca8b
+
+Count = 244
+Adata = 13c222a65ce30570ecac85a185a2a0922a8c96d633339a1ca067ce57ae426e1d
+Payload = f0c1cd60f5fa8d1efd5e2e1ab37c4f7e6aef76d15e8d6ac8
+CT = 5176243fd6e1dd4aa7de4f717bf71b2917ec28ea7e21c9e1f3ca13b4ab7fd0d4badf158972570c06
+
+Count = 245
+Adata = ce40fb0cbfdf07676ed55b040ae6be5db8f0a0f28816ae8ea71da3cbd71661d8
+Payload = 570d5f79aa8db14b1ac99ee567cc105ae9e238e482b52628
+CT = f6bab6268996e11f4049ff8eaf47440d94e166dfa21985010a79fa4e8b27a31ff360a1b6c05ff844
+
+Count = 246
+Adata = 446b01d09cbc41b6393ef81ca65ab7e099018187d5f9d22f5074dfc491e72077
+Payload = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4
+CT = dd919b7c2761a912eaef0b2e37551e09b99f76833c0e8e8d5d34ef0ca0b47d6a2ec7442cbb739504
+
+Count = 247
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2398e86ac3fe48bc7
+CT = 6a46fbbbd89e7738148905f4f56971e5448dd8971f4828ee8f607d154393e35fd1efc1ae8cb244e4
+
+Count = 248
+Adata = 5032b818d202872f3fe2b08fc7940696df02cf393a6d6247f5c6f5f2125cb08b
+Payload = 4324a89788e8ddae5d560cf937df701743cbbc3bf980558c
+CT = e29341c8abf38dfa07d66d92ff5424403ec8e200d92cf6a5617d9cebea38591a00c9fba4ef9c8e71
+
+Count = 249
+Adata = 27b661861717f00a3ae22ead78f4dc3f32b40e8fcb8ed58167a31a61f2becd77
+Payload = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad1
+CT = 7ac530d240e740f8a5fdaf87c6adc5ff73cdbb312e39d9f897062a1ec759a515b938780f902fa7c2
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT192.rsp b/lib/crypto/test/crypto_SUITE_data/VPT192.rsp
new file mode 100644
index 0000000000..abf1775dd1
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT192.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 086e2967cde99e90faaea8a94e168bf0e066c503a849a9f3
+Nonce = 929542cd690f1babcf1696cb03
+
+Count = 0
+Adata = 58f70bab24e0a6137e5cd3eb18656f2b5ccddc3f538a0000c65190e4a3668e71
+Payload = 00
+CT = 3bf9d93af6ffac9ac84cd3202d4e0cc8
+
+Count = 1
+Adata = 760d065275e345900a7bbab451cc9309fb161e6cfec526538b98800e4102e14d
+Payload = 00
+CT = b0078a769ab68db44e723993da382abc
+
+Count = 2
+Adata = ffedc67efd355ea404fcbcb3993d3bae81386ded86230270771deb747163bf44
+Payload = 00
+CT = 31fbff2d715a2eb9af54e8320a8e42e1
+
+Count = 3
+Adata = 55153ff5e4d208d2e647794f382c788e0e36f293e63e7290ba9ff2657ae0f167
+Payload = 00
+CT = 945839d62c9d1b899f6dcd0ca9517e68
+
+Count = 4
+Adata = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe6ffbad084f639915
+Payload = 00
+CT = 903f90d23321a6882d6c4c1955b14847
+
+Count = 5
+Adata = 7b95cd827ab93507f1819ae76627d6e2a31d29890c092e5c300f0e2f9e4ef4d2
+Payload = 00
+CT = 652ec5ab43088eb568186d0d9887b30f
+
+Count = 6
+Adata = bd144c9bb974729aaa1188ceefdf85e1d9fddc0b0c8afe8828ba204aa9293feb
+Payload = 00
+CT = e6c1455d1117eec49338c96f51007309
+
+Count = 7
+Adata = 92b911cdc3137a6f7f32651b788eb82975660aea52b2c03b4759755a6da4a0f8
+Payload = 00
+CT = 1cf3c32fb229dac209523eaa517bb59a
+
+Count = 8
+Adata = a8200dbbfe4086015cdbdec2fc8e4934d0d663527430c424627ed44065ade091
+Payload = 00
+CT = ee10bfeb1cf9b3cd5a0faebd4d8f3fe1
+
+Count = 9
+Adata = 3b7f37b6b8e3c1390a99d59c47f7c102cf659d361a132ef8b4e70b9585bafebb
+Payload = 00
+CT = c51ed994253adb9bb5b9a8c34a27f225
+
+[Plen = 1]
+
+Key = 992d38768b11a236945bd4b327c3728fac24c091238b6553
+Nonce = b248a90b84b0122a5ad8e12760
+
+Count = 10
+Adata = 27cabc40da0e1eda0ea5f8abbb7c179e30776250a7b30d711b0e106c5ee9d84a
+Payload = 1c
+CT = 1a96f58c3f38c44d1a345f3e2da6679f20
+
+Count = 11
+Adata = dc2e28d5ae726c1beadb1e7e92ae7d14f5546320deb81a910bf170cbe0210eaa
+Payload = e9
+CT = ef0579aee7c17482691f3f832d867ffea7
+
+Count = 12
+Adata = c579f912ac1b45d5aa8cf20f78f0a1ace32abd3dc7fd0b3f3a7182a008795c7f
+Payload = 97
+CT = 913452d8ece38ffa1d4107d6a053acd8c8
+
+Count = 13
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9fd48894c9b55e6e8eb360a6211
+Payload = f4
+CT = f20d760b9fe29530738157db0ba2d253f0
+
+Count = 14
+Adata = 622835dea57b2c70cca8f7548d6210714070b55b36adde7a4c547269c07aba9c
+Payload = 9f
+CT = 996fc21f24dee7b52f51d69eea30819f4a
+
+Count = 15
+Adata = 67ebda0a3573a9a58751d4169e10c7e8663febb3a8cf769d81bc872113f0720f
+Payload = 43
+CT = 4594c5b8db0064426a77dc536814c56147
+
+Count = 16
+Adata = 255412e380e9a28cbcd345be172c40f72dec3e8a10adfd8a9ab147e9022524e1
+Payload = c1
+CT = c76d36c0b0d699a22da3116dfb8f453181
+
+Count = 17
+Adata = c7c8e7151eb6844a954d091b460f83add0f0a634aa5ac213b774f2451aa497fb
+Payload = 31
+CT = 370c3a1690acc3f0eb09c9cfd3396c7fa9
+
+Count = 18
+Adata = 63f00b2488809fdc49ca5f05d54e98468906308115f7e702da05ddfd970b5537
+Payload = a7
+CT = a1ad45070fe4c61270c13cc52247fee411
+
+Count = 19
+Adata = 8e2c5e55c0bf70014e9897b6f6940e4e738b1e84e8269b6382f0b1fe59b0e162
+Payload = 40
+CT = 46b2a2a8b283ff7eeff5c2670f77b8809d
+
+[Plen = 2]
+
+Key = 5012db40ff6ae23c1e1ce43768c5936c4400b0e79ae77f30
+Nonce = b67e500b35d60ad7264240027c
+
+Count = 20
+Adata = 40affd355416200191ba64edec8d7d27ead235a7b2e01a12662273deb36379b8
+Payload = 0c6c
+CT = c996ef3d6ef9f981557506ecc8797bbaaaa7
+
+Count = 21
+Adata = c5e12e17e02bcc12b3a4c14cf837250e2886db3ee1c717d28bd11e8a3b764ddf
+Payload = 23df
+CT = e6254405257a837c5343b59d5689d6de5269
+
+Count = 22
+Adata = 213b5b6015d472bd593be5acf85ebba6d6a09f3a962be302ba83c6d70c61f241
+Payload = 0dc2
+CT = c838e93e67d37d2367bb1f27f71b54b29317
+
+Count = 23
+Adata = fc1b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+Payload = dc88
+CT = 1972ca3744a4ab375af9060621a9dc4f4c32
+
+Count = 24
+Adata = 5b2eb1a6fa585d61d1fb3da68f5b93829c8e2d5e4fe03782617553d7a130ecf1
+Payload = 8179
+CT = 4483172626e930d24052bc056d8609c4175f
+
+Count = 25
+Adata = e2b3c3bf33cf847660929e48cce51d9d9289945169651aaecb1e939756e93105
+Payload = 01fd
+CT = c407852310207be8d3417de800b372700da2
+
+Count = 26
+Adata = 6051f12cd8aae68b4023aaf7178fd086aa582b8d8821e36637abc97025f5e858
+Payload = ca18
+CT = 0fe228553bc037954dbf4ce5db99792c2c7a
+
+Count = 27
+Adata = 2d3555faf285caaddfe95c010c2a7f233e09c2fc0cd30d644035269280527ad7
+Payload = a855
+CT = 6daf904725668634d6345bd8f90a3831b452
+
+Count = 28
+Adata = 4fca820dc545bf93bdffed33a04b67eb45384e696f092c2197e5d79cecd09913
+Payload = 5555
+CT = 90afdf6098cb3135c3045a54ffce88efaceb
+
+Count = 29
+Adata = 1789ae403e183d2225f431f001d475b53bccdec66572bb027340ae592839ba8b
+Payload = 11dd
+CT = d4278568e8c08ff5ee5ea0a608589c2fc029
+
+[Plen = 3]
+
+Key = fa15cc7f0de294d7341b1fd79326c8be78e67822343c1992
+Nonce = e5257aed2bda0495aa44591db4
+
+Count = 30
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+Payload = bcb898
+CT = 68f08298d9a2147776dca9c1a42382bce323b2
+
+Count = 31
+Adata = 4863dd810ee70ef0f5da81f60c5ce550abb96454619032322e34657af25207de
+Payload = d1da2e
+CT = 059234a9a77755b324f3a557217752ade14ed7
+
+Count = 32
+Adata = 173594fc26b167f044aeaf9bfe920cab99a27eb2b01827d61f7553cb2018b5fe
+Payload = 394f31
+CT = ed072ba4441a79a90e228a28069fe109d5d876
+
+Count = 33
+Adata = 71cdd16eca9255aeedc23bd623513918ea97da21485074415fe75bcc42f454c0
+Payload = 868bda
+CT = 52c3c065f272f44c5210b5bcc571e819580910
+
+Count = 34
+Adata = e84418d332d16d2298e69e7ff3c37bc7b6e030cc822e73b3f4a0029bc2ea4d80
+Payload = 52d6bf
+CT = 869ea559c5f7f73a1b5f419c9f63ca401894a8
+
+Count = 35
+Adata = 42d962109bea1d50be0f3d83b4c2a6033d53b3d7112591866b1ae52dc84cb5d0
+Payload = 6f8d58
+CT = bbc542220b828cf5365137fb3f1df67cc8d2a1
+
+Count = 36
+Adata = 943b4327b5c70dba63c82f27e0412b3ada012bc0f7dd39ebb13db2f864daf80e
+Payload = fda286
+CT = 29ea9c422b0f41075ac79a0afa2d1047cbbfb5
+
+Count = 37
+Adata = 6076b94caabfa476ab7e6482e4fda9b29f2e2b2883efe44d668c7c74628505bb
+Payload = 8651fb
+CT = 5219e1ae68cd6d6815ecbfd01293d160d4d38a
+
+Count = 38
+Adata = 3e4bb5781f84b4bbd23583e3dae561c6ff4af8eff35e2a4f35b50d2f360d3469
+Payload = c3e179
+CT = 17a963fbaa81cfdbcaee476860cd5102f556e4
+
+Count = 39
+Adata = 364008acbad330d0b8d574641a97b0682c49279cfdc80ff309b7514514d18a44
+Payload = 4a97d5
+CT = 9edfcf7ad1520564b68824a3a939371c21a336
+
+[Plen = 4]
+
+Key = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf
+Nonce = 2ef29d62b40d8643848797cde8
+
+Count = 40
+Adata = 1225b036e6044df52314016760e92750de0936120395de750a2c54a7fa0cea82
+Payload = b46b343e
+CT = c2c39d6f9344e2de064f269d065a2a6108605916
+
+Count = 41
+Adata = aaa6257d6783936a4445833c2ac3bea8cb7334f22ade9c035d515bbc91d6a78a
+Payload = cb216301
+CT = bd89ca50693d90b8297b90bc41c231d08b0204fb
+
+Count = 42
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c1124797e564b63e008e7b8ab
+Payload = 697a8696
+CT = 1fd22fc79d0146fe373437c529fb2eeb169e4bd7
+
+Count = 43
+Adata = 864d0f786497c7ce283762ca0959ec9c825ed445a5dbe5b4b2e5772fe88ce7f5
+Payload = 6bee3db9
+CT = 1d4694e8e389c549bfc4ede936d7896e544b23ad
+
+Count = 44
+Adata = d5388b0b548c58886dcd335dff2b1ed23ce3eebbb708fb5bbd831c83e959d3fa
+Payload = 85d95855
+CT = f371f10495177a9fe6d9329a585c8737c92a4d29
+
+Count = 45
+Adata = 83cddd189736f224cad6a29efba45e43c75450a14f1541713b7fb926ffc768c6
+Payload = e8b23340
+CT = 9e1a9a113914431a10b1f94a2b99b9e442f3dca4
+
+Count = 46
+Adata = 8fccbd1fc5240691cf24e8807bf3416c1b2d87fc86dbf3955fa2e52b9a3a8457
+Payload = 595c4d7c
+CT = 2ff4e42d383d8dc98b22010dd93cd0cbb396d9e3
+
+Count = 47
+Adata = 513d45f6f37f3f051667dc743215059e06e4fdc8945789b16d50556a2e839368
+Payload = 314e0c7d
+CT = 47e6a52c40c513bfc92d1a7db5ed7cab2d8212b0
+
+Count = 48
+Adata = 70828be102e554f0d4b07641fa3254bc8db06eefaf5b85a7c97e01c217fc8f3f
+Payload = 35753e32
+CT = 43dd9763ea98f4ac6b3eabd483f1e6ab92f3b83c
+
+Count = 49
+Adata = 343d5a4ad39acf81adcf24e9807618932abcb3bc076734f179174c77c8cb89e9
+Payload = a531c0ed
+CT = d39969bcf99fb67b1e2aba2d232db2445e6aec2a
+
+[Plen = 5]
+
+Key = 30419145ae966591b408c29e5fd14d9112542909be5363f7
+Nonce = 27e6b2a482bbc6f13702005708
+
+Count = 50
+Adata = e04e81e860daf9696098c723085d8023c240ebe7a643131e35359ab04bd650fe
+Payload = 8ceaeb89fd
+CT = ec9d5ed36243ddf77b33d8cf2963ba76fd4e19f3c5
+
+Count = 51
+Adata = 6217cd581d4b3b2f7bcf1b8dad9ad6430e2e3a0063cad52260e0a1cd6fc9e73a
+Payload = 7e51d6f870
+CT = 1e2663a2ef6b73fe9e638e205b27f78ed1bb9b0ed0
+
+Count = 52
+Adata = 8aa7847e496f5e9f1f87851442de844f27a21c1b48f82fe525f0dd5a88b8ec38
+Payload = e0023b674d
+CT = 80758e3dd25936115e23158aff1916edec241fad56
+
+Count = 53
+Adata = 3612abc865a4d8d7b86a84109388584df6526525adb1006ec6c8d00048d725bc
+Payload = e2b5b6f36e
+CT = 82c203a9f1f15aae4b70dbee244be1daa74475d7e2
+
+Count = 54
+Adata = 849a99c6f1cae0ad4bcde4bd0811e87ca5ed7b913de1a8285a206e980b4b7043
+Payload = 9a17e4a22a
+CT = fa6051f8b5bbff424487848385f8501ab5a77f327c
+
+Count = 55
+Adata = 9066367c784de0a4d1116bbe95ce55ded85edddb6273c2049ee24e0fb3429352
+Payload = d4e765fc78
+CT = b490d0a6e772d8d5da6f593a8d9956731b42645aa9
+
+Count = 56
+Adata = e7aa9f767fa8920f96f91c41d9e86755faaedaeda596a444b65f99b7a9e23e85
+Payload = 1074349e10
+CT = 700381c48fe3eca12b835dcfd08166ac8831585626
+
+Count = 57
+Adata = bc0db1ebf910b6f4dcad5401401d6bc2272e23130947dc236ca664d5b5ed6d66
+Payload = a46dd7fb58
+CT = c41a62a1c72bcce66018e9e552d2c8a229301361df
+
+Count = 58
+Adata = fcbeba2d0d73239d05f691a52b08152c9dd871f8dc76c2c18b8a638a74460d31
+Payload = 2e0ca09221
+CT = 4e7b15c8be3e41a50a28ea3be14baadf12964a37c4
+
+Count = 59
+Adata = dcdefce64ae4339f46c0759a4a10b29d59daaaf1e5dbf75cf11b4e4f73c5025f
+Payload = 2e108ce0fa
+CT = 4e6739ba65bee2ab25bfafa76dc3e54832b2f76864
+
+[Plen = 6]
+
+Key = 748ad503388a34041a7bdae6361d57894357c333bacf02ca
+Nonce = 518b79d194579b19f2d8845b70
+
+Count = 60
+Adata = 691dd98f61fd213b0840ec5a6f06ef9a1420be0d59bde5e43546347a2a865a94
+Payload = 24d6880aed7e
+CT = 270120f9634ec15536e21d961c675070ec4cff9037bc
+
+Count = 61
+Adata = d1fd047cdb18463766841abb1fcd25257f1458b595bfcf24066ff9385232fa97
+Payload = 2298028d0213
+CT = 214faa7e8c239b303af0b098f902dc24e66fe56adc6e
+
+Count = 62
+Adata = 65a480d120a0459dab69e8f23094801e10092666cc56f9fb2549662982bda6d0
+Payload = f248e5225e3d
+CT = f19f4dd1d00d1b657925a9740d6828bd85cd12205764
+
+Count = 63
+Adata = b738a53fbc9689dd49f68f97f5a99665258cd52e74dc653b594cffec045508aa
+Payload = 611dade00cec
+CT = 62ca051382dc395a1c49129ef6cce0ad5f6ef378aa1c
+
+Count = 64
+Adata = 7006f54184f0ff0ab215ca408d46325b86c1cbae6da7838435b1826ff81f55dd
+Payload = 5871a8300471
+CT = 5ba600c38a415e68468d1b2b516be3d688567d84ab80
+
+Count = 65
+Adata = 9e6e6675d4c6b1e0f3894aac071f4c99a364708edea12f319cbc27b40fabc0f1
+Payload = 3ca8a7520e94
+CT = 3f7f0fa180a40ba1af163049d16817021665d183bc9e
+
+Count = 66
+Adata = 10ceef716f54b74d7c8a435d6aa38a10ff23939ca29e2de7b6c3e0a8269a23c9
+Payload = 9c2a0070fbba
+CT = 9ffda883758a670f35869da9821b6ff1fab3e6062ad4
+
+Count = 67
+Adata = 3ee0865f29be50160273b4a94ec078932b9cd10a858e31838d5b607867e1ce69
+Payload = 436179c74fd2
+CT = 40b6d134c1e208f395250fd79087c858b83755411114
+
+Count = 68
+Adata = ec2b8bfe1ccd491b02aa4a9178fd6f099556963e39e2ca5fe6ecb6b5d2a46085
+Payload = ecfa41c614c5
+CT = ef2de9359af5afcbd9af2d584a0f638d066f2496d9be
+
+Count = 69
+Adata = 5b6f6369643d83b1db33d75257d7dea761e574e6e1f1ecead64e5e354a2f4235
+Payload = b48c10105dbc
+CT = b75bb8e3d38c17861882b8930296fd51d969a1e9489e
+
+[Plen = 7]
+
+Key = b930cca30a3fd230c237c8f3cc6792d0c4084dff5c18d775
+Nonce = 7574802fd82fe96c05431acd40
+
+Count = 70
+Adata = 1cf83928b6a9e525fe578c5c0f40c322be71b3092239bff954dd6883738d6d71
+Payload = 2a755e362373ef
+CT = f06238b0450fd1f4b6cab1383adb420c4724aa7bdfefb7
+
+Count = 71
+Adata = bb5450f66273f63b2f79dce177381ce846584ce4f7a0ad5a0171a56e149370bb
+Payload = fab43224bf8989
+CT = 20a354a2d9f5b7a1f99175d3dff5a73f0053a95c36fd8d
+
+Count = 72
+Adata = 3e5e1037bd2922eb20c34200c470b76e537baf7e7f1d8dd2f7a184a593c66554
+Payload = e3aed6715aa429
+CT = 39b9b0f73cd81734b4ad0e41117940abf530093dac648e
+
+Count = 73
+Adata = 3cc88a096a1a440827f5b7da675389e50b5cce35fa2cc36674d6bfc5a3a966b2
+Payload = e78db0f83997cb
+CT = 3d9ad67e5febf5663a8324014550430c7eaeffbd8568f7
+
+Count = 74
+Adata = 2cca33a10b9da7ba99a6b552d1405f2df3fdfd15358d8fdab5e15296b38f9135
+Payload = 726557906845b1
+CT = a87231160e398f34ab635c4eb5b38b86e71da8af3840ae
+
+Count = 75
+Adata = 2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947
+Payload = 043a759b578be4
+CT = de2d131d31f7dabd9961766e03eaa7e8888227c98d1f42
+
+Count = 76
+Adata = 8b8e3d7c88fa16d70130cee290b7e2eecf0ce711118cd9265093b11467e63554
+Payload = f31f2fb4b3fd80
+CT = 29084932d581be637842d96d13c4aab97e296458745a9d
+
+Count = 77
+Adata = 6341370e126097f9721a13c977eb4875cf1286e15c3adfa4e7597e0e13d93b6a
+Payload = 7e3c8224104669
+CT = a42be4a2763a57a51ac46611366c666cab6bfd3d1baaa5
+
+Count = 78
+Adata = 227926b62f7cdd90e4d3b0cb5457e71fb087d329671f0fa891ec06eb8edeb58a
+Payload = 26a0528ae6f9c1
+CT = fcb7340c8085ff8c7d7e5aec14845f844ad38544a2f11d
+
+Count = 79
+Adata = 05b50c40b02e79b74b94d726a7ce8b2b7216ef8af6e7a42d041d2a692a58ad83
+Payload = 61dcf53d1a184e
+CT = bbcb93bb7c6470f1605ab8a2332012b759ccd2eedbed24
+
+[Plen = 8]
+
+Key = 314c136999e41d137bd7ba17201a9fa406025868334e39b3
+Nonce = 65f7a0f4c0f5bba9d26f7e0ddb
+
+Count = 80
+Adata = 5c7ce4819b30b975ae6ce58dcc1bfa29a8b6dda8f4b76c7e23516487745e829c
+Payload = 4d54d8b06b204445
+CT = 2baf90c490b11f9607482362ab3f157c42d0e9c6c5cffcf0
+
+Count = 81
+Adata = 90257ed88679197b8219bc4c2434a71a4e3664d5859c4ffb9a075654898ffedf
+Payload = b2a35df881cd63a2
+CT = d458158c7a5c38715389509b5b6f2df1faf7e8c39203970f
+
+Count = 82
+Adata = dff8ad83525d8235eacdccc91abeb80795e6b5f463fd28af35c46199f646ceb8
+Payload = e98f5e5a20d02c80
+CT = 8f74162edb41775395328747ca544e987df28883d0377b35
+
+Count = 83
+Adata = cde159c5343cd9d98001cd719d3e9ea25e47e1ff13fc87055d4a53b741f59285
+Payload = 90c3e48313cd4fe4
+CT = f638acf7e85c1437a4ba841883a0d7aeda398c043161966f
+
+Count = 84
+Adata = fa88cf5a08be4fb0c1a7960f45726c303eb559861fa60d17aa8dfe8bb5795382
+Payload = 8ad6d5a28ec075e6
+CT = ec2d9dd675512e3509195efe66c5faf413e0f68df8cb647d
+
+Count = 85
+Adata = fe9e93a9370b43efa1560aeb017ff04fca7f207191e6f707c1c35b2e90c44eb2
+Payload = eb83928f0d5f7aa3
+CT = 8d78dafbf6ce2170b51af067ad69ad96009e50ead3d03f02
+
+Count = 86
+Adata = 35792c854fdf1c8cf7f3f8ed2b8ec4f31fe17bf8d4ba49caec03f954bd8bb17a
+Payload = 4cd74ed2fd083011
+CT = 2a2c06a606996bc26b1cb03ee76587f84364825f7c1fcbe9
+
+Count = 87
+Adata = c084108f9c0a74cbf70f614dceae592546865006930db0401828a0eecff98671
+Payload = 52365f94579e0646
+CT = 34cd17e0ac0f5d958fa70c5e195f1f955d64892f532b7683
+
+Count = 88
+Adata = e8045949de61c5c18a63e628330a4d1d12782379a8f9187755409d1825f453c5
+Payload = 8fb85c857a3e38e7
+CT = e94314f181af63342ddf297bdad58083645a052815d29a83
+
+Count = 89
+Adata = 53cfdfd66d63c2924bd583487b90b1dd9ec199f90d660cb9c3a763a4776abfe1
+Payload = 43d2828e86f7856b
+CT = 2529cafa7d66deb81ad3b2be41dbc39df4c0145dcbae3e76
+
+[Plen = 9]
+
+Key = a19f6be062ec0aaf33046bd52734f3336c85d8368bef86ab
+Nonce = 7f2d07f8169c5672b4df7f6cac
+
+Count = 90
+Adata = d68d5f763db6111c5d6324d694cb0236beab877daae8115ecb75d60530777b58
+Payload = 13511ae5ff6c6860a1
+CT = b3859b757802ebd048467fd8e139eb9ee8fcdca45ed87dc1c8
+
+Count = 91
+Adata = f6e219b29884dab9ea9bad34d9ef8a50ae389c9a908de7154a1f2e894f27141f
+Payload = 7e7e33e1a07d4e8fde
+CT = deaab2712713cd3f3789d0ee8323ea2ee7a68aaaa9c49b98df
+
+Count = 92
+Adata = bcca002d69d9d1044c40ae741ea33ce6b8463f5a28d0514e044fdae2fe7d3c3b
+Payload = cc88980c73e6c5f0cd
+CT = 6c5c199cf48846402437c9fe3d9feb0485e6d7c04423b77a53
+
+Count = 93
+Adata = 39cac8f0825ffdb0668455933ad1581263a23b9e5f1305340528f0320d4b1269
+Payload = 34cb528f50d073cfdc
+CT = 941fd31fd7bef07f35b87e90a71ffe6c30bee1771078a701ab
+
+Count = 94
+Adata = 510a02a44d142c8e975d1d933f828fd7e47d28b88223f1698cf009dc3b079be6
+Payload = cbce3df86438a61065
+CT = 6b1abc68e35625a08c9e9c5be0657649448c38692e8d703d30
+
+Count = 95
+Adata = 40e0418cd52f74d78a8e18ed86210e3661a86d8574aedcee540340d8996d9852
+Payload = 80a2b835f8b0729a4b
+CT = 207639a57fdef12aa213e5f2bfd33101597cfae7cf334a8528
+
+Count = 96
+Adata = 1f2938b3bde19e1af91299c08638061dc3c1ea3284c259d415e996477cb37b0e
+Payload = dd04794e65ce34127a
+CT = 7dd0f8dee2a0b7a293516a7310fbd4ceb90d8db9a86cb6311b
+
+Count = 97
+Adata = cbae5b46e35fa2a279dcaa4c724b923805d4707412a84252b64228c91cedd019
+Payload = 00c4101052f54462d5
+CT = a0109180d59bc7d23cef6165af65f3522dfbfed0293db39ecd
+
+Count = 98
+Adata = d0f27c7f42892f3ad4c0029c5b698abb1d035ba5869a665b1de8861db6c055e8
+Payload = d0865445d3b26b6f49
+CT = 7052d5d554dce8dfa00726434c1349e3e874a2d6bf598d05fc
+
+Count = 99
+Adata = ab0f5a829a9319a74d5d5179aa0a410a0fcf52f344a7a896aeb1f7a6c5d398ea
+Payload = 7c7c8580b944ed3fd3
+CT = dca804103e2a6e8f3aab491e60fc97b3cb5248291e4866dcab
+
+[Plen = 10]
+
+Key = de1c8263345081d2dfa9afdf37675971135e178df554a4d8
+Nonce = a301bb82f91a582db01355c388
+
+Count = 100
+Adata = 9ad52c041390d0d4aaf65a4667c3239c95e7eae6178acc23fb4e70a852d483c6
+Payload = f777aba1fa70f94e6de9
+CT = 9d8bff6d2dcde77104ac6aba025abc01416a7ca9f096ab2529cb
+
+Count = 101
+Adata = b49c7e7b47870c1cc339c7c09aaacfd6115fa8a0f04990367eea10cfacb9d23c
+Payload = 349feebfbe58f93ea3c3
+CT = 5e63ba7369e5e701ca864acb200e85a0d4753a8ba226aca72f98
+
+Count = 102
+Adata = e61ca7310172eec16745a73e34516f65844eecd0dbc5566ac5213626b9096ef1
+Payload = 678a40b4c2c7df0e4c9d
+CT = 0d761478157ac13125d87869784e3321183d8c044657a020e9b9
+
+Count = 103
+Adata = 690f5e5d8da6cdb0f492e80449e152ffe88fea9742564d8383c79cef739a7f74
+Payload = 2b81e0533313664bf615
+CT = 417db49fe4ae78749f5070634d00b1facf0e9e9979ca257a71e2
+
+Count = 104
+Adata = 78e34b0a1d61ccd411cbfd306ea2ef3ce89c0b085deb4cfbaec2ab72ce16daa9
+Payload = 1ac63aa38a206d8e7d68
+CT = 703a6e6f5d9d73b1142d994630ed92e2973b22773f229b45bdad
+
+Count = 105
+Adata = 51bacfcf87ea11da34b76acba8c444792ec3db3c8ee6e600d69679975a682a54
+Payload = 027a7fd7897808ec7a56
+CT = 68862b1b5ec516d3131304571b015bb6b4651f1eb9f6fb3a7b74
+
+Count = 106
+Adata = 5159357a133e4743f903d05bd641da369a3675337760fcd2424a99221ba70b78
+Payload = 1086953d352e94a51a6d
+CT = 7a7ac1f1e2938a9a7328bb0e11ac4608081fd0702a137da0aea3
+
+Count = 107
+Adata = f567820865340314d46a17f520ff315efb6b33bdeda590ca9c4fad604c2d8e8d
+Payload = b8b148aafec4a035e9a7
+CT = d24d1c662979be0a80e252c9ec1317ce30dffeb4c9bf3fd0bbdd
+
+Count = 108
+Adata = 0cfec933831644b468724e808bb3d25fe8f15850ce513fc341da46089c845208
+Payload = 884242a87779d3921f8e
+CT = e2be1664a0c4cdad76cb691e32be3cdd9721a13aabad26dba58c
+
+Count = 109
+Adata = 8edc2b85d44297ac66bdd90d05d8df38124033d6a583bb8dda18a2246ba096e8
+Payload = 25c32770a299020d8500
+CT = 4f3f73bc75241c32ec45333a381be77800654aac335bf9220ac9
+
+[Plen = 11]
+
+Key = 248d36bd15f58e47fcf1c948272355821f8492e6e69f3661
+Nonce = 9e8d492c304cf6ad59102bca0e
+
+Count = 110
+Adata = 9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f5
+Payload = 33709d9c7906e2f82dd9e2
+CT = 9114d36b79b1918b2720f40cddce66df9b4802f737bea4bd8f5378
+
+Count = 111
+Adata = ba13974d95f2eeb367b63850609c53dc66c2710f682f10bef0142d48f851b430
+Payload = 84172985e7d194ba28a87c
+CT = 26736772e766e7c922516a12c94615be2bd81bd598f3022f5775a4
+
+Count = 112
+Adata = 5f16180bfac9b7483774cb0e1d57a43e9bf3cf03bf6fe758293aadcbbef25b80
+Payload = 9a34d32070c71d7de8f512
+CT = 38509dd770706e0ee20c042758e936750e335702542bc598e211c4
+
+Count = 113
+Adata = 4352057bdd1735a85dc0fc4dbeedc73279c27eb24a97641236f03f11cdafb8c0
+Payload = 2054a268b1f6fae4f15d91
+CT = 8230ec9fb1418997fba4870762bb2a7d04ba2ad251d595d0619dc4
+
+Count = 114
+Adata = ddf118ae403b2509e75eb7a26d17e73e527acbacfbe49a56fa3210169030144b
+Payload = f71afe9a60f08a0ef694aa
+CT = 557eb06d6047f97dfc6dbc27d85594da3fd35bd8498d7e389ee7cd
+
+Count = 115
+Adata = 973904409e8154132439926f0dc45c0d81bbbd5793f7f81e20eb818bfa374d58
+Payload = cdf5b47ff73306aa55c496
+CT = 6f91fa88f78475d95f3d80055936db383a8ad10b152046d721d3f7
+
+Count = 116
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f3
+CT = 3cdbdd9338e3992f9d5de5d57e228369e24fe955fd8924526af6e5
+
+Count = 117
+Adata = 8321f65baf9dc856ac1c24f3fee5c74d697eb0b50470d59d8f4a14b506e86c53
+Payload = 685116faa5cc527ac8bfa1
+CT = ca35580da57b2109c246b76c23abfb3b4eb39deb8da2064390dfa8
+
+Count = 118
+Adata = a4e7738038a5116592bb9d92d6d4ed191ab774310f6409e4e45fe907674c006f
+Payload = 9e8c4f1292e8d7e5179b34
+CT = 3ce801e5925fa4961d6222b4272c0639e8e6a1d356fb4fea86762c
+
+Count = 119
+Adata = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005adfe9faab253b572
+Payload = 3ecc2ba566c723462eb0ea
+CT = 9ca86552667050352449fc0633a0f9cdc9490231ec2dd69f6e35db
+
+[Plen = 12]
+
+Key = 77a67fb504b961028633321111aac2c30eb6d71a8cf72056
+Nonce = acadc0330194906f8c75ac287f
+
+Count = 120
+Adata = 8c18486d52571f70f2ba6a747aaa3d4b3ebc2e481ee1b70907dddb94bdfa0ca6
+Payload = 10554c062d269ff6dcd98493
+CT = 7f8b0cad79b545e5addf0b04ff4b0f2b2a5067283210aba8630d0306
+
+Count = 121
+Adata = 4e0b4771c7f6c66f9577c430611fdeec5702296ee3691b6bb8c6a81217edabe4
+Payload = 1c9e7875cf02129ac52daeb0
+CT = 734038de9b91c889b42b21275b16dbdf0b9be3c8c82ac652992d630d
+
+Count = 122
+Adata = 4a687e1d0a95ed2efb95b4c6b040999fcd35136811cd665f934d10224b6064c2
+Payload = 34575694dde459d195b7357a
+CT = 5b89163f897783c2e4b1baede629274d654ef5a4480e24f6bef3bc8c
+
+Count = 123
+Adata = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf823641a12bfce9f5
+Payload = ab20c8e8aab1aac1e4f64206
+CT = c4fe8843fe2270d295f0cd9142ab5407a08b648ce24e9955e28fe47e
+
+Count = 124
+Adata = 4f19bbc3135d7a216465b4c1df2616e8bfc3cc64af0bf52bdc42543f4d2448d4
+Payload = e556ca05bcd1991d2c9836a9
+CT = 8a888aaee842430e5d9eb93e151e94d311c7cd2c1b9048575076ceac
+
+Count = 125
+Adata = b6ffc7387b19786282bda7caad52eb37fbe7e557afcb80faaf57767e2a0f178a
+Payload = e5b665600a2aa413e117c538
+CT = 8a6825cb5eb97e0090114aaf61b71330d72506050368186a5619f180
+
+Count = 126
+Adata = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731203ba3f25b52497b
+Payload = 870864a611aa0475d120bc40
+CT = e8d6240d4539de66a02633d7ea21e36f99e5aab6ffa85994d13d5bb0
+
+Count = 127
+Adata = 8215753d9efc51325f182199e39f9082cc3fe524400f2a7434c68df7eb2b06d4
+Payload = 71afe8d00c6f2ea8c8b050d4
+CT = 1e71a87b58fcf4bbb9b6df437cc93a50dea11c5e0b19f14b9c8f16bd
+
+Count = 128
+Adata = eb8f198da6ee92a03913c6575343f6c749d2377a09430eb751b13c041e6edbea
+Payload = 7021f18b8f398a5999fcdcd1
+CT = 1fffb120dbaa504ae8fa534699cbfd1beafa2d2942f6812b8dfc88e6
+
+Count = 129
+Adata = de2ee30359e390db72f682c2ca0f14b72b60ff9bccd8c6fbd19a512b12add794
+Payload = affca856eb412f0b3276ae6e
+CT = c022e8fdbfd2f518437021f9337405235dce6161441caa25cc6007c6
+
+[Plen = 13]
+
+Key = 0d423519e4110c06063061323f8c7c95387776b6ee4e4b6e
+Nonce = 39abe53826d9b8e300fe747533
+
+Count = 130
+Adata = cdd9bf1b4f865e922c678ec4947ea0cb02e78bd5c1538f33aeb818ad3f47e519
+Payload = 4021ff104ff1dbd91e46db249f
+CT = 7953d3cd66d093785d123f65ba37f16761dd6aedbfc789ad96edf1490d
+
+Count = 131
+Adata = 342de5fe61e05c2e58ac2978a871fbdf186a7294ec5f85c4631c21b584231211
+Payload = 95050ca1d494bdb561d4840f8a
+CT = ac77207cfdb5f5142280604eaf8f8e855ae975a1fc64bcce3e7492e9d6
+
+Count = 132
+Adata = 7871482948d8d09d0a7491d915543082cb5fc7d6c1e82ee2218279f54c15c154
+Payload = c45823203b20821a48502f9c67
+CT = fd2a0ffd1201cabb0b04cbdd42017a6515156691b3161b747576078da4
+
+Count = 133
+Adata = 65781d018f27ca0c72a9fa9ab4648ed369646dd3ce45d7ad3a54f6b051f1b6e9
+Payload = e901661b7d47c9918244ee1077
+CT = d0734ac654668130c1100a515225cec7d2566a07cd78181ae94577befe
+
+Count = 134
+Adata = 05556b04dae5cde8525633d1862aa200c54af534e302d2cbd34ddc2b78532a60
+Payload = 5556f799d6a6cffb343f28c1a9
+CT = 6c24db44ff87875a776bcc808c133f51dac00f973fd42e0948fab70ea9
+
+Count = 135
+Adata = 151304e3e4f3c2d4d3227e035d849e0d3841ba00cf6cab1cf2e3e4d6cc760623
+Payload = 56bf26be81c7b55ef898e23981
+CT = 6fcd0a63a8e6fdffbbcc0678a4fe78bdeaa8d408ffe8fe64811aa87742
+
+Count = 136
+Adata = f870cc1fe67d6169279f905b0fe5fd9a0436c36498e4b7c6f584f00f7efe8784
+Payload = 36b304a72dbf4acfffa1d7d624
+CT = 0fc1287a049e026ebcf533970197228d155dda2bc814ff33ebeb9a7ffd
+
+Count = 137
+Adata = 5692c9d452ea1c067e62fdc554ddd2b18c8433d59067f971316797fd9853ae6a
+Payload = fb529eb5ae79a0830474ffbc98
+CT = c220b2688758e82247201bfdbde7ba03e144e34a4ab34791a372a2b8ab
+
+Count = 138
+Adata = dcf7fe16b7ca9e27ec3291103398eaa2e77c7b770b67f8858c215af4c523822d
+Payload = 6218c778955d9a56360f06c704
+CT = 5b6aeba5bc7cd2f7755be2862103c2eb5ef0657306d12b753a0694efcc
+
+Count = 139
+Adata = b0f1e2668611dca86e8d0f58c2a4cf4a9472d81ba013e271800b75841fe5ffde
+Payload = bf6b143fb713a81c965c5a9d8d
+CT = 861938e29e32e0bdd508bedca87cc6119151393461ecf65bfe06e0163b
+
+[Plen = 14]
+
+Key = a60cf7ceb62bf3118532bc61daa25ce946991047f951b536
+Nonce = 7499494faa44a7576f9ed5580d
+
+Count = 140
+Adata = baa482c64eefd09118549a8968f44cfea7a436913a428e30aa4ab44802a4ba35
+Payload = d64f9426febce6a84c954dd5ded5
+CT = f7580f17266d68237747bf57c7ed8242ac1a1979c5a9e7bc67d7698c7efa
+
+Count = 141
+Adata = 2ad8ecc5ac9437ace079419f17e6018625b10490120fbe2f12b41e64b73b653c
+Payload = fcd9b67717bcadeceddea336c671
+CT = ddce2d46cf6d2367d60c51b4df4918abced491c063d8bfd0e7341febddc3
+
+Count = 142
+Adata = 7585ee95e74d7a869bdc0b59ca9939dd57e7b09afab179079d467bfe0668416c
+Payload = 18232d7c792fb80e6ca1c8f2c3cc
+CT = 3934b64da1fe368557733a70daf4659ecbb3dbfbcdb0f913abedf8afab05
+
+Count = 143
+Adata = 41be6ca6188f34da1ce83fb8c27652848dc2a71e32bd3631fb9b33ae69e5d879
+Payload = 764dbefb42644d18d23e5e456868
+CT = 575a25ca9ab5c393e9ecacc77150a220d5ec0b5397d6b4e323b5dc7d1b63
+
+Count = 144
+Adata = 197cee3b15320d57996191dd13106fbd4546a5cc3d2bcf0c886af52ea3d9a855
+Payload = 8003586af34bdd0acae4f5547394
+CT = a114c35b2b9a5381f13607d66aac3a5f713f5d0793b732c6e114805cc9b3
+
+Count = 145
+Adata = ee0b647a47656a6e9e09c2d64f734a2cc3fd45b7ee52fea51c24af59ee22a006
+Payload = da143266516a4145cde92c93f961
+CT = fb03a95789bbcfcef63bde11e059ed90e8650bc16f590789dcc625b9e63d
+
+Count = 146
+Adata = 9f5bfffa01f1425d95465723735b49fc1dffbad06cf37a00ca4b59efa21739c1
+Payload = 3842b033f3ca31a6f8e5a638b39e
+CT = 19552b022b1bbf2dc33754baaaa6bda183dda1aef021d92210e27cdd7c5e
+
+Count = 147
+Adata = 64e92ba2748d07f602808f7c5ded15cb0e43140400d37107e59a01e7d45b4c9c
+Payload = cedf60b17185fc71b957cb759260
+CT = efc8fb80a95472fa828539f78b585e4087fb314f893937e95383e66745c0
+
+Count = 148
+Adata = 6ebcaeb4bd44ff4c990305ac64264dfe2ada5f7cd4b294eb9f492865cd28905c
+Payload = 035f449bb28f43365f4a0556096a
+CT = 2248dfaa6a5ecdbd6498f7d410520a71ce5813c578532b742d704fa92276
+
+Count = 149
+Adata = db617207dccd1f6baea5f2242d5e577adb8d69af3bb1707a7a53a8b75452455c
+Payload = 9a2a45424f4965a71270e77cc403
+CT = bb3dde739798eb2c29a215fedd3bb7fc45d15d6939668065d2282fc589c7
+
+[Plen = 15]
+
+Key = 82d4bc9aac298b09112073277205e1bf42176d1e6339b76c
+Nonce = 70325ef19e581b743095cd5eb1
+
+Count = 150
+Adata = 6d14bb2635c5d0ae83687f1824279cf141173527e1b32d1baf8a27f7fe34a542
+Payload = 25a53fd3e476dc0860eeeea25fcb0c
+CT = 4a1cfd0023557a184b929965b0a445cb3993ca35acf354cb2b4254ff672e7f
+
+Count = 151
+Adata = 9f8a56fecf32fa7d50f033b2524c3d798e254bc87245cce57e38edd6ee5d5f1a
+Payload = 797dca47597947c057789433309b67
+CT = 16c408949e5ae1d07c04e3f4dff42ea25b5eb103bac224cad66ec0f100875c
+
+Count = 152
+Adata = 86f15b8b677b7655f358a2c7fd5785bc84d31e079ed859b6af88e198debd36fc
+Payload = e61f9a663d3a2b50ea2f9475971270
+CT = 89a658b5fa198d40c153e3b2787d39b598cc6ec2295c586e7ae270a01846d1
+
+Count = 153
+Adata = 4de6bd43c28143ea5d40919cb5330a7e674f5bd8aeb7b178343a2851281c8668
+Payload = df990c42a268950677c433555319b3
+CT = b020ce91654b33165cb84492bc76fa97ff732093f7d0a96b30d8cdfd1bd583
+
+Count = 154
+Adata = a5c3a480dea1b2a1e3a0ce416148b04f60104217c9d24a5b267b4aa6aa07a4dd
+Payload = a7e72fb4bec3768594a2f6f5b4379e
+CT = c85eed6779e0d095bfde81325b58d7ad98e32a9156e125ff021ef6951b0c40
+
+Count = 155
+Adata = 51b041f1666c59045d333fe63d43457107e1adad34fcbf965e0d191f3e414776
+Payload = d3d1550047cf90eceaea7000d8e280
+CT = bc6897d380ec36fcc19607c7378dc9390f10df08a84c21031626861b201fbd
+
+Count = 156
+Adata = 22f8a3c9d85b2d53ffd92078d3c94373f855ecd01a8ac521d1abd0f2c7cba9ff
+Payload = 756412c4ee6416f2f4e0342011cde2
+CT = 1addd0172947b0e2df9c43e7fea2abdd5d840bb8c4348a9a548482e6b93043
+
+Count = 157
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 666e4a4b3f6cf598aa763cdada4109
+CT = 09d78898f84f5388810a4b1d352e403f0d49927cd6103e3705ba201e8f73c6
+
+Count = 158
+Adata = 2db3ded385ef9c82fd39ea5782d9befe66e8a070066269b2aa7c4bbfac3711c3
+Payload = eb9013a74352b0677a88bd73052477
+CT = 8429d1748471167751f4cab4ea4b3e2d97f7c2b3b42bf570cce79bf30ccc50
+
+Count = 159
+Adata = 194c9e1eaa8e376f9c41bf33823efa28ee60a9213438665b7002cf0fcad7e644
+Payload = e3126400e3c571a4d39b37bc938a22
+CT = 8caba6d324e6d7b4f8e7407b7ce56bd3c2a4fc45d014a0c54edab2930a5bdc
+
+[Plen = 16]
+
+Key = 6873f1c6c30975aff6f08470264321130a6e5984ade324e9
+Nonce = 7c4d2f7cec04361f187f0726d5
+
+Count = 160
+Adata = 77743b5d83a00d2c8d5f7e10781531b496e09f3bc9295d7ae9799e64668ef8c5
+Payload = 5051a0b0b6766cd6ea29a672769d40fe
+CT = 0ce5ac8d6b256fb7580bf6acc76426af40bce58fd4cd6548df90a0337c842004
+
+Count = 161
+Adata = e883dd42e9ddf7bc64f460ba019c28597587d06e57c3b7242f84d5e7d124ab81
+Payload = b31dfa833b0cda20eaa84d2ecd18f49a
+CT = efa9f6bee65fd941588a1df07ce192cb8707b1a4d9ce3def33703e19eaab6dda
+
+Count = 162
+Adata = 409401eb49cd96b1aad2525c5124c509766ff86f88b2011c67a1d501d3485e31
+Payload = 24bc8dc1e2354667b79ba4d7061448ff
+CT = 780881fc3f66450605b9f409b7ed2eaefd9041ddce37d88e79fba28e385b2327
+
+Count = 163
+Adata = 83bf5c063bf1febf71688a832d615e09d6f14badedeaeb6ffbfe343fc7274e78
+Payload = d41d95a1d2326e12cba636910ddfca53
+CT = 88a9999c0f616d737984664fbc26ac0291d971893543868bd8c69078fc2bdb24
+
+Count = 164
+Adata = 8cdd70524e24318c64d681aa27752d4c86c5348c05c9e48f06ed41594785a6e6
+Payload = e8a4b80e081919f1912542d3136764f2
+CT = b410b433d54a1a902307120da29e02a3866b23e4c991f4007e56a1ee9265c6cf
+
+Count = 165
+Adata = 615985f63571c0f94ffcd4df77326abd41e84f388f061d97573a181da7ee5695
+Payload = 7fca7388058d6d1438b6eee0292131cb
+CT = 237e7fb5d8de6e758a94be3e98d8579a2abbea637996b954027efa9464ced6b9
+
+Count = 166
+Adata = 17aa90f2bff0419011b01dee62be31354431cbc89f22332704b096143d4743f4
+Payload = aa540554ee80dbffa475f702d862d6b6
+CT = f6e0096933d3d89e1657a7dc699bb0e757bc8d48d82ebefc76f17323c518ecc2
+
+Count = 167
+Adata = 85288b2be612e42335c144fb058a7dcd567c382fbcee3962bd5be4cc7a7000a8
+Payload = 6d745581831edba437e70ea89cad217d
+CT = 31c059bc5e4dd8c585c55e762d54472c65470c81e487a26cdc26830f2b51bd1c
+
+Count = 168
+Adata = 288f9f52824b54b608dd7226a0a89d43ae8c05107dbae761e1c756911a003b74
+Payload = 811a61869c7a6b2aa9ac0fcc523ef784
+CT = ddae6dbb4129684b1b8e5f12e3c791d5a3043722be9448c3ef144f2288066f75
+
+Count = 169
+Adata = 51dbaba180d4746edbb3420461919b5b735797bf7dd19f84d80475f5efc2748d
+Payload = 378a4e39817f308ed1e639f943b694c4
+CT = 6b3e42045c2c33ef63c46927f24ff29549aba95e04e11cf18ddf73773d395c1a
+
+[Plen = 17]
+
+Key = 3cf8da27d5be1af024158985f725fd7a6242cbe0041f2c17
+Nonce = 07f77f114d7264a122a7e9db4f
+
+Count = 170
+Adata = 30457e99616f0247f1339b101974ea231904d0ef7bd0d5ee9b57c6c16761a282
+Payload = f6dd2c64bf597e63263ccae1c54e0805fe
+CT = ce3031c3a70600e9340b2ddfe56aa72cffdc5e53e68c51ee55b276eb3f85d2cf63
+
+Count = 171
+Adata = 42370f115bbd4b31bb99fe82cca273b3c93072f96b2e09bdc6718d926d48db69
+Payload = f45fee3e086c28a7c590ec0cc05b972664
+CT = ccb2f3991033562dd7a70b32e07f380f65c6328a7476db2c10ec7bca3f6bd3df42
+
+Count = 172
+Adata = e2d692c5678124998a7862b8e87276b0a19e293a609103c99583b36305bcb2b0
+Payload = 4ad69a8ab433ed8909825c71f6081f64a7
+CT = 723b872dac6c93031bb5bb4fd62cb04da68080f0d51d3b8841683eff361984f7e4
+
+Count = 173
+Adata = b5b38791160959dd2836ec1ad25286c1ba410d7212347a95b5738a3d725bb651
+Payload = 3d47071c13f994cb42fb2887e5c6e53a54
+CT = 05aa1abb0ba6ea4150cccfb9c5e24a1355c1428ef5d40bc9e363817f219af2ed56
+
+Count = 174
+Adata = 02691171795a77d1e3bdad513b6fab5b50d1def81bcc1df15012de3433a6aa78
+Payload = e8a4b80e081919f1912542d3136764f264
+CT = d049a5a91046677b8312a5ed3343cbdb65fdfb37dfd1236198035c8461b304152b
+
+Count = 175
+Adata = 7371d8ae79e628f53ffede174eb068db2318c05e2f6d94ad2233a59369b16db0
+Payload = 549aa84bb182312dd016e3107f3b1f9c5b
+CT = 6c77b5eca9dd4fa7c221042e5f1fb0b55acefde0e84a3ce0cb702ceb73ca1dd9a5
+
+Count = 176
+Adata = bb1e1f51082e470f7245458ec902098e1e41d0ed28efa31be71d21ce86527ff7
+Payload = 31a12ca6d69db2e6e252474d7d59ed6552
+CT = 094c3101cec2cc6cf065a0735d7d424c53f8441d46dc5456a587b765e1a820c11c
+
+Count = 177
+Adata = 7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b4
+Payload = 5bb121e70452a954f420a56aca8cd5c059
+CT = 635c3c401c0dd7dee6174254eaa87ae958d0daddcfcc92349ef059149c54a25cd0
+
+Count = 178
+Adata = 505687182c06e6f4effe7fe03c1f436199a9015380ff21d0b2aa9453cfa10b1d
+Payload = 5b80d1cf745b14cb71cbc8dfe0bc7c7358
+CT = 636dcc686c046a4163fc2fe1c098d35a5948c1242b89490c6ee69dedc1e91286ee
+
+Count = 179
+Adata = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee451bd1429cbb33fc1
+Payload = 79ac204a26b9fee1132370c20f8c5bcada
+CT = 41413ded3ee6806b011497fc2fa8f4e3dba2ddd54e509bca0a45dcf2fd514e1496
+
+[Plen = 18]
+
+Key = b46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a
+Nonce = b79c33c96a0a90030694163e2a
+
+Count = 180
+Adata = ea9405d6a46cac9783a7b48ac2e25cc9a3a519c4658b2a8770a37240d41587fb
+Payload = 56d18d3e2e496440d0a5c9e1bcb464faf5bc
+CT = 01baba2e0d5b49d600d03a7ed84ee878926c0ca478f40a6fbde01f584d938a1c91bf
+
+Count = 181
+Adata = 72340d595f3dbd23b46513f8f2b73b6249328c705e7968084bcb647fe734a967
+Payload = 7a76eac44486afdb112fc4aab939e4d1eedb
+CT = 2d1dddd46794824dc15a3735ddc36853890be4646492b6f4cb169383c075756073b6
+
+Count = 182
+Adata = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e06bb90e07460172e
+Payload = 48348c5ec996f7a97ef0ba2cd6885572fe64
+CT = 1f5fbb4eea84da3fae8549b3b272d9f099b4f584289f560cbf76606942fe1a92dd63
+
+Count = 183
+Adata = ffa6277395d31d5db13034d362228a87610e441c98ca3038e252a9db12bdbcef
+Payload = d5c58f10e1a03d8a2501d1eaf5fcdfff3ae5
+CT = 82aeb800c2b2101cf57422759106537d5d355964f5f5532d7cddd7207f0e9a6aace9
+
+Count = 184
+Adata = daf83d02a9bd992ea58c23e7ad18d41796314bae20e864e729f40ccc215454fc
+Payload = da2a863ab1c58ddde320ecadeecac9c5d2d8
+CT = 8d41b12a92d7a04b33551f328a304547b50890ae047e35aecfc38ffdc07e7d8f5705
+
+Count = 185
+Adata = 21ddad5f550044dc5cb123ade17eeef549c4e0173b216bcc602c1e736764cca8
+Payload = 4573969afa831c244817230406fe51183091
+CT = 1218a18ad99131b29862d09b6204dd9a5741b2bdf539ceaa35015712dd15265ca476
+
+Count = 186
+Adata = 9228265ae5c3daf1485ff8011738da508bf2a73731396c5d9aa56fc554e0c00b
+Payload = edf5557e15473b747a819398c9ac1459ffdb
+CT = ba9e626e365516e2aaf46007ad5698db980b241412124ae20b84c13b0c3671d305c9
+
+Count = 187
+Adata = c0a2ff0de21b3ba961e06015ccd71374856a65a4c57cf8cde0a1643aca8ed868
+Payload = e139263478900df806a0f3446bd6600c1aeb
+CT = b65211245b82206ed6d500db0f2cec8e7d3bee9803747bf9fa63412bfc4e10aea89e
+
+Count = 188
+Adata = b54378f031a31cf3985f573829c9ffca14616742e0a7e03b0a2d7f05eff0219e
+Payload = 660eaff0f113eaa2f5f7ad4b62bb849a3a25
+CT = 316598e0d201c73425825ed4064108185df55afdf430b57845dcf622d4f25cdeb2a3
+
+Count = 189
+Adata = e67f35c18a9336469eae23040f98f52338ca8d0cab269ac32fe6bc7605d3ea56
+Payload = 0f89897271f5d0349d57399005ea60c0cadc
+CT = 58e2be6252e7fda24d22ca0f6110ec42ad0c7ed4c04c4b4dd585891ecfddeab8cc87
+
+[Plen = 19]
+
+Key = 7b71045ccef735bd0c5bea3cf3b7e16e58d9c62061a204e0
+Nonce = 2b9ecfd179242c295fe6c6fa55
+
+Count = 190
+Adata = b89166f97deb9cc7fdeb63639eeafb145895b307749ec1a293b27115f3aa8232
+Payload = 890d05420d57e3b3d8dbef117fe60c3fa6a095
+CT = f842ff6662684de8785af275fa2d82d587de0687ebe35e883cbd53b82f2a4624c03894
+
+Count = 191
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a49569a5b27b
+Payload = 6b425cdcdf8304e7fbb70b2973d55e6940025b
+CT = 1a0da6f8b0bcaabc5b36164df61ed083617cc807d4824f0a98db2d87365a42ca3b80e1
+
+Count = 192
+Adata = 9b4fc98fcdcf485205e7054bc9d1e02d0d8584420537e20d3821de2fd6824787
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2
+CT = b9f0ee7ba0c4018d6d9b513fe92670eaabd221404e631735c544edeeb4c0105c55bf0b
+
+Count = 193
+Adata = 45622e1472542be2f63f463d253617eafd4f2ad609f9020884905dd5c22fba53
+Payload = 12b5a76faedf6f855e328c2cb87be8aea78c5e
+CT = 63fa5d4bc1e0c1defeb391483db0664486f2cdc16a4cf37e8e96eed1217d21133e83d1
+
+Count = 194
+Adata = 958689aea3c6cd19020eff9d635ef44ee0793424df38fdf13a238b969d429777
+Payload = f0927c3cb0a876d7877466507da8bfa0bd9a16
+CT = 81dd8618df97d88c27f57b34f863314a9ce4859facf81a636351f6e67d6ec12636ae0b
+
+Count = 195
+Adata = c22911efc36fa739048af0c951ef2449bb3605c52f65120c4d71fe5976026032
+Payload = d2c5d4e2362f19c99de66da7bd9c495c03d9a1
+CT = a38a2ec65910b7923d6770c33857c7b622a7327ce73a7e2db69d30441f89a03fd0e84e
+
+Count = 196
+Adata = 799da61e2c10ebb4783f618b8f69da7704a1b2b925cebc228af57d7ceebb9825
+Payload = 1c9d7f5b329ef4d384b8b7955a20f8a3fc15cd
+CT = 6dd2857f5da15a882439aaf1dfeb7649dd6b5e8d787a9d06b8533ca96fb1db8aecc8e5
+
+Count = 197
+Adata = 14a8e18afe0b9fe18ddfd754219a7e18ed36f419f8262d91678e10daffb31c81
+Payload = 3a64414c3588d7c26871d7d054ac6c8420d491
+CT = 4b2bbb685ab77999c8f0cab4d167e26e01aa028ff5f819d552c08054b5ac02063e102a
+
+Count = 198
+Adata = 7294a8b4ad97c81969e4a2876a3dc0ee322d554726997dc9ed98c5601985ee5b
+Payload = 545dd71bea9967e07a89f84a2027aacd132187
+CT = 25122d3f85a6c9bbda08e52ea5ec2427325f141cde5af8fada67c47cbb5787a6b2d9c9
+
+Count = 199
+Adata = 99294b22d73805805630fb416d20d4fca67419ab660ff45cd19a3729e81b9f69
+Payload = ec1b17b885c018272652453f47fa6e9ed972b9
+CT = 9d54ed9ceaffb67c86d3585bc231e074f80c2a7412640b179bd3e8a417dc38462c16e8
+
+[Plen = 20]
+
+Key = dc7c67715f2709e150cceff020aaacf88a1e7568191acbcf
+Nonce = da56ea046990c70fa216e5e6c4
+
+Count = 200
+Adata = f799818d91be7bab555a2e39f1f45810a94d07179f94fe1151d95ab963c47611
+Payload = f383bd3e6270876b74abbb5d35e7d4f11d83412c
+CT = 377b5df263c5c74f63603692cbb61ea37b6d686c743f71e15490ca41d245768988719ede
+
+Count = 201
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d27ad5132d507504898f61e
+CT = a5a59286e8ff1d8b9aec209ecc84cd022e76df5ea9bc8cfaf2a1734a792076618c4b9690
+
+Count = 202
+Adata = 4586f73a1f162b2cdb65f6e798a60b5f48938d40b4612d84c1f39244f14efdce
+Payload = 6e923e1f404002aa5cf8f8aaf1b9772da425e21c
+CT = aa6aded341f5428e4b3375650fe8bd7fc2cbcb5cc5122df904b052e4d5580fdeddf5297c
+
+Count = 203
+Adata = 9f7ae892e5662803408d4d062265846441a43c1fa202da59f640ae722a692671
+Payload = 68115771505daa18bb3ce90054bfb7d077e1f37c
+CT = ace9b7bd51e8ea3cacf764cfaaee7d82110fda3ce0ba1bb1af18e15ade3316c21d6b41fb
+
+Count = 204
+Adata = 1f0769a7ae82bd985661e031c4a892c15d3ef37bdcfb45243d02f40fdb51d34b
+Payload = 681fd2a324b3fea4cfebed567ae4546ba373c8f1
+CT = ace7326f2506be80d820609984b59e39c59de1b1dc71e342fbc44289ef7e53e28edf3839
+
+Count = 205
+Adata = bf957ef5ab2805e58ea752da5793f7f23d98fce1b2b67738929e5de8a15f9801
+Payload = a7b9d2d069941e8b943706a02d2847ea713bb103
+CT = 6341321c68215eaf83fc8b6fd3798db817d59843ced1fb4a2a3e349aa590aabbfc3d13bc
+
+Count = 206
+Adata = 833264c1bebb597043b4158087cb651960915d9023189c9509c0d2aed84e7fe4
+Payload = 9b946e8198ce69d2173e970f4e0c103a47ee4160
+CT = 5f6c8e4d997b29f600f51ac0b05dda68210068205079f6c2739e2b789b6e3d3c60389374
+
+Count = 207
+Adata = 94c8414cbbec52e2d73bb8f02ef687c91432495c0c744666317d02e6d46706d2
+Payload = 81ac4618f3db6bcf9bbf67220b7671be4bb4f8a2
+CT = 4554a6d4f26e2beb8c74eaedf527bbec2d5ad1e22a02f287db7217148317d897f65f6a0c
+
+Count = 208
+Adata = fced1131dab3dabdc1a16d3409fa09a90ffe02f0e2c814a63f77f771c08c3389
+Payload = 90851933d4d3257137984cdb9cba2ca737322dac
+CT = 547df9ffd56665552053c11462ebe6f551dc04ec362df9f8b41b1dd4821f8f14e9e633d7
+
+Count = 209
+Adata = 495dfcf91f4735ab35c6bc4deef8468bd988e4099cd291a32b4707f93e13d82b
+Payload = c14ce6d57f0fe7367331c9fe159ae1fb8f1ccb2c
+CT = 05b406197ebaa71264fa4431ebcb2ba9e9f2e26cf61ffb51e56497ca9f39c6665fcbdfa8
+
+[Plen = 21]
+
+Key = f41e369a1599627e76983e9a4fc2e963dab4960b09ebe390
+Nonce = 68ef8285b90f28bcd3cb1bacea
+
+Count = 210
+Adata = dbe3e82e49624d968f5463ceb8af189fb3ad8b3b4122142b110d848a286dae71
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326
+CT = 9f6028153e06d14d30b862a99a35413413c04a49dc6f68a03a11cf00d58f062a7b36465d13
+
+Count = 211
+Adata = d9acfd611e5bbb08c5d05d56791b8aebabf8d69734ec89153c91a1f65b2e1adb
+Payload = 35f6bb3f6a388f3a5a039b0a495b676d0b928aeb19
+CT = 2b3bac123fd395813c44aaffb0362b469fb10781e3ca1fb470b666523a19f83481f16481ed
+
+Count = 212
+Adata = 6003b771afe4e99e1ef1ed4a31b10540d95f4ac49885f0c8e5cdcb63d213127e
+Payload = 6aa7e3802b5a29d4f9ca88eb59f94af783d1054466
+CT = 746af4ad7eb1336f9f8db91ea09406dc17f2882e9c53cb05bfcd64da2b45c2e9a89a380b49
+
+Count = 213
+Adata = c371644275a6290821e7d308714bec2bf62d36c30f7fa77a0d60b28894f1c82a
+Payload = 13332b67ba5ba18137c306bd860dc3eb0a9a0b871a
+CT = 0dfe3c4aefb0bb3a518437487f608fc09eb986ede048f70fbc680cf7092b3dd90b943fc6e5
+
+Count = 214
+Adata = 8eceb15300ec4220510ed5b7deb3429de6ae5f618e1c222c28990a9ab4b4bac8
+Payload = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4
+CT = 1b550aef3ff6a8638484e9ab50c99df7a01154873ee386f33c0b8da8d0c5934e617dd618e5
+
+Count = 215
+Adata = 96d1cf3690c48c77a155ce13e67bbd62e6f03d88c893c1f7c30a6435d5ab36e0
+Payload = 60249343a8cd4d33c6edc583ea7e5c221ef3064787
+CT = 7ee9846efd265788a0aaf476131310098ad08b2d7d3d2db1360fb1121893f4d197731bce4f
+
+Count = 216
+Adata = 379bbc9f919dc2a8687f2a86cc9c3291804240a9b566c58519956848102e6155
+Payload = 79003a8d3d20d412f468f11712cec4d37cee847440
+CT = 67cd2da068cbcea9922fc0e2eba388f8e8cd091eba335ce1bfafc0948f2523e75f2aad86f9
+
+Count = 217
+Adata = 9bff9c9a8f94cd77e7016748da31f86d1b9c68465cbf954511c93a4776981524
+Payload = 7d078a8b200514a00628756250d410f7a0f8a769e6
+CT = 63ca9da675ee0e1b606f4497a9b95cdc34db2a031c7dc265e281307f0f4c38cddc556ac725
+
+Count = 218
+Adata = 25125a4668c31dc2e8a68b6c4c95ad7cf9322852e371b415a357d09acb01b587
+Payload = d9b0eaaff786165f882f41a98dbc0c355b3a1aaf40
+CT = c77dfd82a26d0ce4ee68705c74d1401ecf1997c5ba61c78a2f85a447c3e62b6197d65b9065
+
+Count = 219
+Adata = ad34d8f0902a5b79fb145b8206bb4d3b77e0bd8ae2d0964815389eacb33b4007
+Payload = 17b517ef577f588da374340d2522cc9ea642c8d8ae
+CT = 097800c202944236c53305f8dc4f80b5326145b2540312d067c08a9b4400e1df8bb7ed671a
+
+[Plen = 22]
+
+Key = 3289e59e3a7b29bf4a309afc253030bba4b9bdd64f0722f9
+Nonce = 30259ce106e9bd7a8bacbaf212
+
+Count = 220
+Adata = 2870bd9a26c510e9a256920899bbc77a4eb9b53f927045a943d5ed6b13638cf3
+Payload = 53911a67b65738f87fc7c20d6db8044bde1af95838d1
+CT = 70cf37d4b6f7e707376b1574ce17c040b5143da47abb2fe9afafc2fccd98ccf63b0fdec30eac
+
+Count = 221
+Adata = 611032a95ee87f89ad6be7c0fed8bd245c5f81076087b3bda4cde5587b8d14b6
+Payload = 46917e38b8a542296d290d065b0aa7c8aaa38950c386
+CT = 65cf538bb8059dd62585da7ff8a563c3c1ad4dac81ec102dfd8c231d6a355f079c213ce6858e
+
+Count = 222
+Adata = 2e7ea26d1cceaca3b7862a7a8469e366b52ec27ca127e3317222ee651d8da4a0
+Payload = b527828c89f674dc6f024f8cdd80c694bb3ebd57b2d9
+CT = 9679af3f8956ab2327ae98f57e2f029fd03079abf0b36df11febe34dd568da12c374674b9ac4
+
+Count = 223
+Adata = 0bf4413010daec585de34142224d1cad3072f9720f91ac664ad152820e838741
+Payload = 78230f73f9c0150f630eca4cd679818551d449db82e6
+CT = 5b7d22c0f960caf02ba21d3575d6458e3ada8d27c08cb2916540d9439b832aa44236a7e187ac
+
+Count = 224
+Adata = 2e7cae3306582eb5bad148247aa6c6ec943f8748e84b8a069ca9488b11844716
+Payload = 847bb12e0e56fa07a086eeda5907ae148148fa4107d2
+CT = a7259c9d0ef625f8e82a39a3faa86a1fea463ebd45b80d0768a18dead55700901408aa3f901a
+
+Count = 225
+Adata = 63036dc4ad13aee5dc1832e867f7538da108188fec7b08262af440d07579c451
+Payload = ec59e208c4bb429a371f1b3ffdf07fce5dea8a05f0ce
+CT = cf07cfbbc41b9d657fb3cc465e5fbbc536e44ef9b2a45f2073605d2a441805b6ff89d8beb68c
+
+Count = 226
+Adata = f9ec5ce4b63156d57e451eb67ab6d7a59cc397f43f6d26dc07d1036f0fb4a8cf
+Payload = fb12d94bd21b5748b23132a03065c78dae65a0bd2cfb
+CT = d84cf4f8d2bb88b7fa9de5d993ca0386c56b64416e91dcabef6907811c6b7df4e74c7a63d83b
+
+Count = 227
+Adata = e13a204e16f42bbf4716e95f1cb7e125ffac66a87f591c8ef2c7b8485ff707fd
+Payload = 239fa31d4a65de0318bfc5b60a06d706c129dcf255ac
+CT = 00c18eae4ac501fc501312cfa9a9130daa27180e17c626aa8aa37e858cd990f5593d9ef35f2a
+
+Count = 228
+Adata = c4591c3ad984a1e189c526b719212f8248289eeb277827272b8205d78191eb2d
+Payload = 57caadbb1a56cc5b8a5cf9584552e17e7af9542ba13e
+CT = 749480081af613a4c2f02e21e6fd257511f790d7e354d81e424d6b4528901ae46fb35f8b3106
+
+Count = 229
+Adata = cf4795bc7f43c30d3c3a8fd1b8a9d77d69bf59eb8b59d0f464315f40cb52335d
+Payload = a68c74e05f0a44d4a0372c0e5915b83d8e6729efacbb
+CT = 85d259535faa9b2be89bfb77faba7c36e569ed13eed1f25a4bfda35e1390f3f16f638dcd4047
+
+[Plen = 23]
+
+Key = 40f1aff2e44d05f12126097a0f07ac0359ba1a609356a4e6
+Nonce = 0df3fc6396f851785fca9aa5ff
+
+Count = 230
+Adata = e9699b20b0574fce8b5cbc4ef792eb96e2c1cce36b1b1f06ea2a95fe300633cc
+Payload = 8d98c580fb366f330dbfda20f91d99a0878b47efd14c6d
+CT = 579cdf9da62a2df471e03450516adb4ce99ae0f70b1776a39c3b429a1f922fac0b59e29a122e43
+
+Count = 231
+Adata = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402677aeb51e216335f
+Payload = 7391ba60fabe2c632bbaca16af9a235b2c7dae61691c0b
+CT = a995a07da7a26ea457e5246607ed61b7426c0979b3471067bf538e40f9366adf8758968f06ce8a
+
+Count = 232
+Adata = 4f263cda4a50b0e5379ec2fb546b326a07943527c1d175c029455a917753883b
+Payload = 7e1e93a6ca35a2c0e4f08fdb2e7ee22b9f486f0ab919e2
+CT = a41a89bb9729e00798af61ab8609a0c7f159c8126342f964a1199251b54f419720a30de83161de
+
+Count = 233
+Adata = 4d43702be4f0530319555d7f1a3356160f6cae48051f12e22a153d7e405c1149
+Payload = f94ff053c7413f34f96eae41fd1ac101151069af5a9428
+CT = 234bea4e9a5d7df385314031556d83ed7b01ceb780cf33b417e4cceb8dcf45ef33cc0007755bbc
+
+Count = 234
+Adata = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259e319266042db8887
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c566990
+CT = 60030c2802e3fa28e822c465432f75b671e0af548c328bd35aed57f49dcfecf248cf9d246ac024
+
+Count = 235
+Adata = 12e4fe727b1f27a619dd67bb976ddc2b18b2ef8b7184290d9553494a500d933e
+Payload = 872940780a94680a791c937994ceafd2c8b7a22b5f4927
+CT = 5d2d5a6557882acd05437d093cb9ed3ea6a6053385123c97cda0e04d2ff65c2e06a8276bdf6f97
+
+Count = 236
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830
+CT = 0d1c7e9a22393a1c757245d27ed6bb18079b3b2db6232b3494dd2ee0a0fe5bfc9f69234c8142ed
+
+Count = 237
+Adata = cefc4f2fb796c2502329ca3d8f8af3200dd9edb8f164e15acec90536a15b6fdc
+Payload = cda681aa3109ebf5f21ee3a849098ea3a551e844fae4b4
+CT = 17a29bb76c15a9328e410dd8e17ecc4fcb404f5c20bfaf9008ead8e923997508eebf5e776198dc
+
+Count = 238
+Adata = 94fc7eb8febb832097ba6eecd2697da91b5a8a1f2248f67a7659e0ac55a09a0d
+Payload = d4f8d262870b5000a40b8fcce88f55c65c4d12e729975e
+CT = 0efcc87fda1712c7d85461bc40f8172a325cb5fff3cc45f136cc6ea1b0fdb554e0803053875b89
+
+Count = 239
+Adata = 459085184094e302b2e921cc04270b676e75bbcf0e4b53ed387df2bd0e75e0ac
+Payload = 732f211061c0a32c6ad124c58418d560ef5eab2602314c
+CT = a92b3b0d3cdce1eb168ecab52c6f978c814f0c3ed86a575da8ceccae093888daaf92c95817fc3d
+
+[Plen = 24]
+
+Key = 91f9d636a071c3aad1743137e0644a73de9e47bd76acd919
+Nonce = 1bf491ac320d660eb2dd45c6c3
+
+Count = 240
+Adata = 3bdfd7f18d2b6d0804d779f0679aaa2d7d32978c2df8015ae4b758d337be81dd
+Payload = 4eaf9384cad976f65f98042d561d760b5a787330dc658f6c
+CT = 635530cab14e3d0a135bb6eebb5829412676e6dd4995f99cb7e17f235bd660e7e17b2c65320e9fd4
+
+Count = 241
+Adata = 9de45b7e30bb67e88735b8fb7729d6f3de46c78921b228bad8f17cc9c709c387
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 7444449ff443f1ab73fdfda2ea2a04d5163a1209e868b1d99f40890c7d650afccda40fb2a4cd603b
+
+Count = 242
+Adata = 783477f981ef0551b5e7a714b640bbb38316c53756c96e30c898cdee3b72e6f4
+Payload = 4e7f3c86d846ff351db81dbe1d2e9ed73ec0450587ae681b
+CT = 63859fc8a3d1b4c9517baf7df06bc19d42ced0e8125e1eeb50236cf1a12a9e3542a4051788f9775a
+
+Count = 243
+Adata = 2851d40243512a43f70f9c25e9b18c122a1433f05c61e65017e197e88b129e43
+Payload = 2db7cb2739c839383b64c2c93c7d5c906d984756c3dedaa9
+CT = 004d6869425f72c477a7700ad13803da1196d2bb562eac59b1bbad9861192df356c6678b2f561ea3
+
+Count = 244
+Adata = 1cfa2d62cc1f6313fb0c6eb21803e09cdf61ee3ddb15192529560e5d8096cafb
+Payload = 2f2b82497c78369890809460d80a16be4f3330e8a0089165
+CT = 02d1210707ef7d64dc4326a3354f49f4333da50535f8e7951da4211d4c28d2d91568117fc99fd911
+
+Count = 245
+Adata = 5a14b556156191b2704936f64df0bf1dd2bd8d587418f4f85472338fcf86aa52
+Payload = 7cfefca725da1b6bb5d9545e3e50f5a624a8160bdb0e7d4e
+CT = 51045fe95e4d5097f91ae69dd315aaec58a683e64efe0bbeda99be0e054bb881a25a74b547d3ed5e
+
+Count = 246
+Adata = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c680d71fd1f9801fa
+Payload = 5205165c4e9612974dc92f60d1e328d68aa9466e27dbd499
+CT = 7fffb5123501596b010a9da33ca6779cf6a7d383b22ba2694c1fedb47fa30ff2ead6bf382431b2de
+
+Count = 247
+Adata = f852e38703097cc37c589b7860dbc333e091411462d5576dc9909a8cf6ac99d4
+Payload = f968f2833427abbc9fe1cab7e7a3f905a3b23a35802029ff
+CT = d49251cd4fb0e040d32278740ae6a64fdfbcafd815d05f0f338762a4e4299615c67130a28b56a383
+
+Count = 248
+Adata = 43df03a0e23c7ad0d13485150ca224c0b3f39d4e5f2d718db6308e003d3dc683
+Payload = 67da6ca42655188af0b8e389152b2a1b6e2c3ed88926afa5
+CT = 4a20cfea5dc25376bc7b514af86e75511222ab351cd6d9559dbdf61387294812f483aad76d48d899
+
+Count = 249
+Adata = b297dce04ada2ddebc7e94eff7c51b87eee2f98c410c5c0919d0652653ab7458
+Payload = 9777cf90dd7c7e863506686fc3ba6d3d05328f78b350f92f
+CT = ba8d6cdea6eb357a79c5daac2eff3277793c1a9526a08fdf078177541e19b11dfec995f40c99af70
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT256.rsp b/lib/crypto/test/crypto_SUITE_data/VPT256.rsp
new file mode 100644
index 0000000000..e9cd7eefe9
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT256.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = c6c14c655e52c8a4c7e8d54e974d698e1f21ee3ba717a0adfa6136d02668c476
+Nonce = 291e91b19de518cd7806de44f6
+
+Count = 0
+Adata = b4f8326944a45d95f91887c2a6ac36b60eea5edef84c1c358146a666b6878335
+Payload = 00
+CT = ca482c674b599046cc7d7ee0d00eec1e
+
+Count = 1
+Adata = 36c17fd901169e5b144fdb2c4bea8cd65ad8acf7b4d3dd39acf2ad83da7b1971
+Payload = 00
+CT = 67747defe5da5fecc00b9bf3b249f434
+
+Count = 2
+Adata = 9a37c654ab8e5a0c6bdfff9793457197d206ed207d768cbc8318cfb39f077b89
+Payload = 00
+CT = c57ef5d0faf49149c311707493a4cfd4
+
+Count = 3
+Adata = 5ab80169184541393a6975f442ee583cd432d71a6d1568fa51159df7c5b8f959
+Payload = 00
+CT = bc2fb5571a7563bb90689a229d2f63a7
+
+Count = 4
+Adata = c78a22a667aafab0c94047e03837d51b11490693d5c57ea27b901ff80b6a38f9
+Payload = 00
+CT = 428888c6420c56806f465b415a66e65a
+
+Count = 5
+Adata = e11e30cbf63623816379f578788b0c8e6b59ee3c9c50aa6e1dcd749172d48fed
+Payload = 00
+CT = 9f1b7520025e1075731adc946b80121d
+
+Count = 6
+Adata = 05716168829276ff7ab23b7dd373db361e6d9e1f11d0028d374a0d3fe62be19f
+Payload = 00
+CT = bd36b053b6a90f19e3b6622cba93105d
+
+Count = 7
+Adata = 3e915389639435629fcc01e1b7022d3574e2848e9151261ad801d03387425dd7
+Payload = 00
+CT = 458595a3413b965b189de46703760aa0
+
+Count = 8
+Adata = 2f496be73a9a5d9db5927e622e166c6ec946150687b21c51c8ca7e680f9775ac
+Payload = 00
+CT = 8b259b84a6ee5669e175affca8ba3b1a
+
+Count = 9
+Adata = 0a8725bd8c8eab9ed52ca47835837b9f00a6c8d834ab17105b01eb4eb30402e7
+Payload = 00
+CT = c5f35fdf2b63e77a18d154f0ddcfedbf
+
+[Plen = 1]
+
+Key = cc49d4a397887cb57bc92c8a8c26a7aac205c653ef4011c1f48390ad35f5df14
+Nonce = 6df8c5c28d1728975a0b766cd7
+
+Count = 10
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a
+CT = a5f24e87a11a95374d4c190945bf08ef2f
+
+Count = 11
+Adata = f6cfb81373f1cbb0574dda514747d0099635b48cb809c6f1fa30cbb671baa505
+Payload = 40
+CT = ffd43c5f39be92778fdce3c832d2d3a019
+
+Count = 12
+Adata = 5a88b14bada16b513d4aa349b11ce4a77d4cda6f6322ff4939ad77d8ecb63748
+Payload = 41
+CT = fe753b7b661f1aad57c24c889b1c4fe513
+
+Count = 13
+Adata = a92b95b997cf9efded9ff5e1bff2e49d32e65f6283552ded4b05485b011f853f
+Payload = 06
+CT = b91c5ac66e89bf2769ef5f38a3f1738b24
+
+Count = 14
+Adata = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd24aab5f2bbe112436
+Payload = c8
+CT = 773fe64379cea1a8ae3627418dd3e489a2
+
+Count = 15
+Adata = d3029f384fd7859c287e38c61a9475d5ddbfd64af93746b1dc86b8842a8c194c
+Payload = e2
+CT = 5dabc529442ff93005551b7689bcb748f7
+
+Count = 16
+Adata = 51ca3d3b70b5e354451a5177d7acfd8e7b44eae55e29d88b5e8eb8fc1e5c62fc
+Payload = 1a
+CT = a5ee68e416617ac974b3d1af7320cd51f6
+
+Count = 17
+Adata = 8c6c6791f1ac957b18bf008e260a0af4a5b7bfdb1e0008d6eaaa227f45cf4f62
+Payload = dd
+CT = 6243883d93d7066991e0fac453400b4fbf
+
+Count = 18
+Adata = b0a1af969a95025385b251afd1e89f353426ed6e5d71019cd73366aa31d5b464
+Payload = 4c
+CT = f3b940d416f3435812f9d1b18f441b7721
+
+Count = 19
+Adata = 7e72b2ca698a18cb0bf625f5daddb0d40643009db938340a9e4fe164a052fee1
+Payload = 88
+CT = 371d27e9a32feea28a6a7e7da2d27e1cc4
+
+[Plen = 2]
+
+Key = 36b0175379e7ae19c277fe656a2252a82796309be0f0d4e1c07fdde88aca4510
+Nonce = 021bd8b551947be4c18cf1a455
+
+Count = 20
+Adata = b5c6e8313b9c68e6bb84bffd65fa4108d243f580eab99bb80563ed1050c8266b
+Payload = be80
+CT = ecacc3152e43d9efea26e16c1d1793e2a8c4
+
+Count = 21
+Adata = 38e5032c5949c2668191ef1af5bb17eddc28abdb4e5bb41eaffec2523b2525d6
+Payload = 82c9
+CT = d0e5d06bf4b50ccce0b2acfd16ce90a8854d
+
+Count = 22
+Adata = 0b50f5173249fb7118f80d25874d6745d88e4ce265fa0dd141ad67ae26c31122
+Payload = 8239
+CT = d0158d784f486c1dc4a2bafd5b02ca1e1c05
+
+Count = 23
+Adata = 0296743a3125b103a2b2a78a109e825ea10834bd684215ab2e85cc4172e37348
+Payload = 16c1
+CT = 44eda3377002a48f9fe306d157358e6df37d
+
+Count = 24
+Adata = a94e64becb803e211785ba51db7f3db042fbf44a7a821509156a6828b0f207e9
+Payload = 2801
+CT = 7a2df6c09bf1dcb1c82bd98c6e2c13a8d7a5
+
+Count = 25
+Adata = 105358cc17b12107e023a23d57b44c66a2c58d8db05100311575e1ea152fc350
+Payload = 65e7
+CT = 37cb2ea363c0d8864363056467570959ba03
+
+Count = 26
+Adata = 669f9a63cf638a202dca1965c4116273249813ce0b39703887d89bdf5b3b12d6
+Payload = 819d
+CT = d3b16519377e6d0252b5f80cdf3d0253eccf
+
+Count = 27
+Adata = e288590a3eba28ac6847a50b0294ab6bd0a548716ff5102c44a5b656b2d9ddd6
+Payload = 761e
+CT = 24329a4dee6ca2cde473f08f76f779856c3c
+
+Count = 28
+Adata = 5b222aae3c7786c3b9021ba672f9136190ec931cf055f84c85706127f74c6d5b
+Payload = 56de
+CT = 04f29e65c0f01e644e74092253b470cd5511
+
+Count = 29
+Adata = 2082f96c7e36b204ad076d8b2f796cccf5cbc80b8384b53a504e07706b07f596
+Payload = b275
+CT = e059809fa107f379957b52ac29fe0bc8a1e2
+
+[Plen = 3]
+
+Key = ddb739acda6c56ec9aefc4f4cbc258587f443da4e76ddfa85dbe0813a8784944
+Nonce = 0bddf342121b82f906368b0d7b
+
+Count = 30
+Adata = 887486fff7922768186363ef17eb78e5cf2fab8f47a4eb327de8b16d63b02acb
+Payload = db457c
+CT = 54473c3f65d6be431e79700378049ac06f2599
+
+Count = 31
+Adata = 0683c20e82d3c66787cb047f0b1eb1c58cdde9fb99ee4e4494bbf27eb62777d1
+Payload = 62a6c5
+CT = eda4853b186edc15c22ba24e470eb5a072da9f
+
+Count = 32
+Adata = 413074619b598f8bed34cab51ddf59941861ba0169ebe7570a5ed01d790c08e5
+Payload = cc67bc
+CT = 4365fc52a1fb5a58bd51931230c1a7dfb1a8c1
+
+Count = 33
+Adata = 2d65a5175c29a095dc082dab9cfcf4b895efbfa715c57614589d4db159543ce9
+Payload = 33800b
+CT = bc824b7d3810f59176cb108c7e969da51d4d79
+
+Count = 34
+Adata = 6a831b6059456be98e6fce608d8c71cb8efb04a96b45c2dfbdaeabf5420a1482
+Payload = b2c826
+CT = 3dca6646ffea832595c9c86e6517215541ddbd
+
+Count = 35
+Adata = 3a04a01160402bf36f33337c340883597207972728c5014213980cd7744e9e41
+Payload = d7e620
+CT = 58e460e89a6725f0fc35622d89d2f3e34be90a
+
+Count = 36
+Adata = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f6a2443ee03f6390b
+Payload = 795af4
+CT = f658b4b1bd7ad5d81686aeb44caa6025d488bd
+
+Count = 37
+Adata = 7bef8d35616108922aab78936967204980b8a4945b31602f5ef2feec9b144841
+Payload = 66efcd
+CT = e9ed8d0553c801f37c2b6f82861a3cd68a75e3
+
+Count = 38
+Adata = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe01ec1b66eee216341
+Payload = 78b00d
+CT = f7b24de3eeb8ea6c08b466baf246b3667feb3f
+
+Count = 39
+Adata = 71bf573cf63b0022d8143780fc2d9c7dbd0505ac31e9dce0ad68c2428b0878a0
+Payload = 9dd5e1
+CT = 12d7a11db811640c533794bfec6eeb977233ec
+
+[Plen = 4]
+
+Key = 62b82637e567ad27c3066d533ed76e314522ac5c53851a8c958ce6c64b82ffd0
+Nonce = 5bc2896d8b81999546f88232ab
+
+Count = 40
+Adata = fffb40b0d18cb23018aac109bf62d849adca42629d8a9ad1299b83fe274f9a63
+Payload = 87294078
+CT = 2bc22735ab21dfdcfe95bd83592fb6b4168d9a23
+
+Count = 41
+Adata = 75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e
+Payload = 0f28ee1c
+CT = a3c38951b5de3331078aa13bd3742b59df4f661a
+
+Count = 42
+Adata = 8fb9569f18a256aff71601d8412d22863e5a6e6f639214d180b095fa3b18d60e
+Payload = d41c9c87
+CT = 78f7fbcae52afe7326a12a9aaf22255a38d4bd0d
+
+Count = 43
+Adata = 8b62d9adf6819c46c870df8a1486f0a329672f7d137bb7d8659f419c361a466c
+Payload = 046bc0d8
+CT = a880a7957543692a72f0d599de48b5e5f5a9413f
+
+Count = 44
+Adata = fd98f8f39dfa46ea5926e0ffacbabbe8c34205aade08aa0df82e1d4eaaf95515
+Payload = 39bd4db8
+CT = 95562af530fc357f5482b9004d466bf858586acb
+
+Count = 45
+Adata = 09bf4f77a9883733590a3cc7ee97f3c9b70f4db255620e88cd5080badc73684c
+Payload = b43cdd3a
+CT = 18d7ba77a9e8db046fdd548b52d40375c1e9a448
+
+Count = 46
+Adata = 40326d765e0f6cf4b4deccb128bebf65a7b3c3e5bcf1d58f6158e1e9153b7e85
+Payload = e0052e9b
+CT = 4cee49d64efbdd4ad8d3e863172d9372fca07c20
+
+Count = 47
+Adata = aa5ae6dcdc21b5446489bdabf5c6747bdf3bbfdb3de2c03170efefe5ccb06d69
+Payload = 696825f6
+CT = c58342bb95bd661b32bc18025808f8b4035acad6
+
+Count = 48
+Adata = d3d34f140a856e55b29471fde4c0e5f7306b76d03faab26db79c10f95ffb3122
+Payload = 7eb07739
+CT = d25b1074ac05b072264e31a4b2801a6d790512d7
+
+Count = 49
+Adata = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671194646e0b0136432
+Payload = 9cad70b1
+CT = 304617fcc00514d260e1d211de361c254369e93a
+
+[Plen = 5]
+
+Key = bc29a16e19cfbe32bf4948e8e4484159bc819b7eec504e4441a1a98ca210e576
+Nonce = 4f18bcc8ee0bbb80de30a9e086
+
+Count = 50
+Adata = 574931ae4b24bdf7e9217eca6ce2a07287999e529f6e106e3721c42dacf00f5d
+Payload = 3e8c6d1b12
+CT = 45f3795fcf9c66e1a43103d9a18f5fba5fab83f994
+
+Count = 51
+Adata = 99cd9d15630a55e166114f04093bd1bb6dbb94ecaad126fe5c408dee5f012d9f
+Payload = 76fc98ec66
+CT = 0d838ca8bb6f3cd579294f706213ed0f0bf32f00c5
+
+Count = 52
+Adata = 1516fdf7a7a99f3c9acc7fff686203dec794c3e52272985449ddf5a268a47bc3
+Payload = 6564c247cc
+CT = 1e1bd603117d38e026f706c9273dbcb6dc982751d0
+
+Count = 53
+Adata = 0c9c35be98591bf6737fc8d5624dcdba1a3523c6029013363b9153f0de77725b
+Payload = c11b9c9d76
+CT = ba6488d9abc3e46166767c6ad2aeffb347168b1b55
+
+Count = 54
+Adata = e74afe3ba960e6409dba78ecb9457e2a4ce2e09792b1d2e3858f4c79f7ddba62
+Payload = 45a4e0d7dd
+CT = 3edbf4930033a7dca78bcbf4d75d651ee5fadff31b
+
+Count = 55
+Adata = 96cbe9cd193513599c81f5a520fabaff51ee8cbdb81063c8311b1a57a0b8c8fd
+Payload = e5861b2327
+CT = 9ef90f67fa11585167c83105ee16828a574c84ac86
+
+Count = 56
+Adata = 2e7ea84da4bc4d7cfb463e3f2c8647057afff3fbececa1d20024dac29e41e2cf
+Payload = f5b5bcc38e
+CT = 8ecaa88753ffaba456f78e431f4baa5665f14e1845
+
+Count = 57
+Adata = be125386f5be9532e36786d2e4011f1149abd227b9841150d1c00f7d0efbca4a
+Payload = b6cc89c75d
+CT = cdb39d838034714731f9503993df357954ecb19cd3
+
+Count = 58
+Adata = 3fa8628594b2645bc35530203dca640838037daeaf9cf8acaa0fb76abf27a733
+Payload = 3802f2aa9e
+CT = 437de6ee436c1b008b7572752f04362b2bfdc296bb
+
+Count = 59
+Adata = 642ae3466661ce1f51783deece86c38e986b8c0adea9e410e976f8a2fe0fe10f
+Payload = e082b8741c
+CT = 9bfdac30c1a3f7c3c29dc312c1f51a675400500e32
+
+[Plen = 6]
+
+Key = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9ccdf139f33be76b18c
+Nonce = 7a76eac44486afdb112fc4aab9
+
+Count = 60
+Adata = a66c980f6621e03ff93b55d5a148615c4ad36d6cbdd0b22b173b4b1479fb8ff7
+Payload = 1b62ad19dcac
+CT = 4ad1fcf57c12b14e0e659a6305b4aeffae82f8a66c94
+
+Count = 61
+Adata = c13f65bd491cb172a0f7bbc4a056c579484b62695e90383358d605307d5be0a5
+Payload = 3ef0faaa9b79
+CT = 6f43ab463bc779fa7932d365e2da9b05c00a7318384a
+
+Count = 62
+Adata = 59dcca8fc50740831f8f259eb55d4db11f763a83187d93758d78d166f4d73cd5
+Payload = 1a98ddbf35f1
+CT = 4b2b8c53954f813229912137b7a4945dc07cea24a974
+
+Count = 63
+Adata = 578509ca4f57aadb78056794bf18b0714090970db786e2e838105e672165761c
+Payload = f46a7b1c28ea
+CT = a5d92af088546e045f19f737a24c8addf832ed3f7a42
+
+Count = 64
+Adata = 696c0c6427273cf06be79f2206c43af9cbda0b884efaf04deba0c4bf0a25cb26
+Payload = e98f5e5a20d0
+CT = b83c0fb6806edaae8a7dcd3b0fbb59438f88743ec6e8
+
+Count = 65
+Adata = 95a66b60249ed086eecaeb9bc449afcee9de212619e87516ca947351b25120df
+Payload = 06319c0480e2
+CT = 5782cde8205cd9cb636ca6543c4e35964f47341f2814
+
+Count = 66
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112e1130c21d411cdf16a84176d
+Payload = f4c723433b7c
+CT = a57472af9bc2ec82eadf4eb1f055da1a92a82052ab8b
+
+Count = 67
+Adata = ff3bff3a26fc5a91252d795f7e1b06f352314eb676bff50dc9fbe881c446941e
+Payload = 02f809b01ce3
+CT = 534b585cbc5d01b10a7ae24a4ca2bfb07ea2a3b31a97
+
+Count = 68
+Adata = f6be4aad63d33a96c0b5e9c4be62323c9e2308b29961fff980ba0dbda0549274
+Payload = 2b6004823a29
+CT = 7ad3556e9a97231323a4b88af5d7d0b07c0e73ddce1d
+
+Count = 69
+Adata = c3706a28d7420b41e072dcecc06b6b13116cca110bde8faea8e51f5107352d71
+Payload = 236c60cba4fa
+CT = 72df31270444db30eb33d2ede33abbe22f37704fe68b
+
+[Plen = 7]
+
+Key = f7aaeff3a1dc0cc5ecf220c67ad9f6dda060b4f1be3cc609cb4f18b2342a88a2
+Nonce = d0d6871b9adc8623ac63faf00f
+
+Count = 70
+Adata = e97175c23c5b47da8ce67811c6d60a7499b3b7e1347ad860519285b67201fe38
+Payload = d48daa2919348d
+CT = eb32ab153a8e092fa325bafc176a07c31e6cc0a852d288
+
+Count = 71
+Adata = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b6df8e69e5e1111fa
+Payload = f95b716bfe3475
+CT = c6e47057dd8ef1a24840f4f40a7963becde3a85968b29c
+
+Count = 72
+Adata = efcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd64
+Payload = 4862e3677083f0
+CT = 77dde25b5339748f2a4a5c276727e0a210fc2efb5aeabe
+
+Count = 73
+Adata = 360bcb407603fe92f856bf677625b9882521e6dae8f35fdfc3dc737f9398f609
+Payload = 7f1ca0728f6d65
+CT = 40a3a14eacd7e1051734fc31232ab2ab63474020ab4dc9
+
+Count = 74
+Adata = f12ee9d37946cfd88516cbe4a046f08c9bbba76a3973ff1e2cb14493405bd384
+Payload = 67478ef73290fa
+CT = 58f88fcb112a7ec715244f307609ffa253e4e3659b0ece
+
+Count = 75
+Adata = 5833dde0c577b2be4eb4b3d01d7b0042fa8441ad7043ea462bbbbd56a59790ea
+Payload = 36bb9e511276c5
+CT = 09049f6d31cc41f11047da612d2987fa2e50ada5ae7f9d
+
+Count = 76
+Adata = 1e103c63d8ead36b985f921044cd32b8f9f04a2ba9fa154a09e676ffaa093970
+Payload = d68d6556c5a5b1
+CT = e932646ae61f35382f7648718127ebae7eb7443ebd2c2c
+
+Count = 77
+Adata = a1cfb61d45a140bdea6329ba0fe80429ff9aa4624a1d31bc752f7c97f1d390a0
+Payload = 0568cca4ff79dc
+CT = 3ad7cd98dcc358cc40a5e7fffb1fb9a5dd9d6ba91bede1
+
+Count = 78
+Adata = 116b5b015e44ceef0061b2d2e73fa0b386d5c1e187782beebdfc6efb5a1c6935
+Payload = bd93d08eea4263
+CT = 822cd1b2c9f8e7468d2b70c311732f11ed72b57d83e500
+
+Count = 79
+Adata = 3d55882e6f3f89309b6940a3b408e573458eedd10fc3d0e1f3170eb313367475
+Payload = 4fb62753024e92
+CT = 7009266f21f416b41a70f548e359add30c0e5746fbeb2b
+
+[Plen = 8]
+
+Key = 493e14623cd250058a7fc66a3fee0c24b6e363b966c2314aff53b276b6c2ea7b
+Nonce = fe2d8ae8da94a6df563f89ce00
+
+Count = 80
+Adata = 579a637e37a0974cd2fc3b735d9ed088e8e488ffe210f043e0f9d2079a015ad6
+Payload = e5653e512d8b0b70
+CT = 75d31f8d47bee5c4e2ba537355ae8ab25cc9ed3511ff5053
+
+Count = 81
+Adata = 1583138aa307401dddc40804ac0f414d338fc3ffb2946f09aaaa7079426fc1ee
+Payload = 2c4ba9ce52e01645
+CT = bcfd881238d5f8f1781a9e359804831f31a1efb1ae1cb71d
+
+Count = 82
+Adata = 78d3dda40e433bba7a330ca3e5bd5170f0895f2e3e438402344ced79fcb0c719
+Payload = 5eb2d054a0e58c62
+CT = ce04f188cad062d62dcc77c4e1fe2bafd477598977835f0c
+
+Count = 83
+Adata = dfc762466fa84c27326e0ee4320aa71103d1e9c8a5cf7d9fab5f27d79df94bd6
+Payload = bbbf7830d04ab907
+CT = 2b0959ecba7f57b308946723baf0dbf613359b6e040f9bd5
+
+Count = 84
+Adata = 7e8ea82d1137c1e233522da12626e90a5f66a988e70664cb014c12790d2ab520
+Payload = 10c654c78a9e3c06
+CT = 8070751be0abd2b2003bd62ca51f74088bbbd33e54ac9dd4
+
+Count = 85
+Adata = 873da112557935b3929f713d80744ed08b4b276b86331dbc386fba361726d565
+Payload = 668d32e322e1da3e
+CT = f63b133f48d4348a67e65e7f2cdedf6ef8cc0ee7a6dcfb02
+
+Count = 86
+Adata = cfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82
+Payload = e39f6225e8eab6cc
+CT = 732943f982df58780532f8c6639e5d6c7b755fcf516724e3
+
+Count = 87
+Adata = 01abcfee196f9d74fcaa7b69ae24a275485c25af93cc2306d56e41e1eb7f5702
+Payload = 6021a00f6d0610a4
+CT = f09781d30733fe107fd7a33828413ebc252dd9d015773524
+
+Count = 88
+Adata = ce1c31e7121c071d89afab5a9676c9e96cac3d89dcae83136bbb6f5ca8f81e5d
+Payload = bbaf0ac4e77ee78d
+CT = 2b192b188d4b0939d3d51368799325ad1c8233fa071bade0
+
+Count = 89
+Adata = bb210ca5bc07e3c5b06f1d0084a5a72125f177d3e56c151221115ae020177739
+Payload = 98a2336549a23a76
+CT = 081412b92397d4c25d1ea568637f773174a7f920a51b1fe1
+
+[Plen = 9]
+
+Key = b23255372455c69244a0210e6a9e13b155a5ec9d6d0900e54a8f4d9f7a255e3a
+Nonce = 274846196d78f0af2df5860231
+
+Count = 90
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d
+CT = f019ae51063239287d896e7127f17d13f98013b420219eb877
+
+Count = 91
+Adata = 162d0033c9ea8d8334d485b29eef727302135a07a934eea5fee6041e9f1f47c1
+Payload = 0d9168eeab3b27ba69
+CT = 9cd5b4f54443433d997cc2cd61da9358b4045fef32f8192cbf
+
+Count = 92
+Adata = 3f4ab57efa32f51a4c00790280e77c0e55b85bbda4f854e242368e9a289b5a81
+Payload = 6287dcffdd5fb97885
+CT = f3c300e43227ddff75d280f0ffdd560fb8915978e3bd6205bb
+
+Count = 93
+Adata = 945d18134c148f164b39fd7c4aef0335045553f6ea690a3b1726418d86f0de00
+Payload = 6e5e01b3fd71d16b9c
+CT = ff1adda81209b5ec6c7dbf90420a1ff2e24bd6303b80cfc199
+
+Count = 94
+Adata = 23af12893431b07c2922ab623aed901c0eaaeb9a24efc55273e96aea4dab7038
+Payload = b51521e689b5247362
+CT = 2451fdfd66cd40f492d741f4329ae7cc77d42bf7e5f2ec5ab6
+
+Count = 95
+Adata = b15a118b3132c20c31e6c9d09acdee0e15fcc59d6f18306442682512d22eb10f
+Payload = 7f973617e710fb76fe
+CT = eed3ea0c08689ff10ec9ffdcc2f36edac14613b1d85baf25a9
+
+Count = 96
+Adata = dcfbeb6490f5fa7eaf917462473a6cec98bebf8f17493fe9b994119a6d5a5457
+Payload = 7e909b6727ac3fd02f
+CT = efd4477cc8d45b57df5a61a28bb10265b26043d7a8dd357713
+
+Count = 97
+Adata = 77e9317294f046f315a0d79e3423f29f7d9ebcd36d6eaa2a3fb2f4500309478c
+Payload = a5075638932b5632f8
+CT = 34438a237c5332b508d321c371ae1fd01bdf3b6c75a597da6e
+
+Count = 98
+Adata = 3aa8f204eb127b547e13873ed0238018394e13686c8734e49e3e629deb352c77
+Payload = c10f15a0de78db8aa3
+CT = 504bc9bb3100bf0d539393d1635bc40ac62405a39155406c47
+
+Count = 99
+Adata = 7f67e6f97c6c258f014d721a4edaaa0ddb3f9f09993276ab7b714ea9356c231d
+Payload = 8294f830cfca42cfbe
+CT = 13d0242b20b226484eff89641e1bd5ad6cc827441b17c45ecf
+
+[Plen = 10]
+
+Key = dbf06366f766e2811ecd5d4384d6d08336adc37e0824d620cf0d9e7fd1e7afa9
+Nonce = b3503ed4e277ed9769b20c10c0
+
+Count = 100
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b22719
+CT = e317df43ab46eb31be7e76f2730d771d56099a0c8d2703d7a24e
+
+Count = 101
+Adata = da77c6d5627a2aa34911bd1f7cc5f8aa68a2c6546adc96a186b9af8e5baac4cf
+Payload = e081c43a07450ce0dfa2
+CT = 2daaebd62095206346c5bcc7a8260ef361dc39fdb776d041f0d4
+
+Count = 102
+Adata = 134d2d9726400d09dd3521326f96fbef993ddc0c4088770057b0f8d70356456f
+Payload = c381d2ae5e72fc82324a
+CT = 0eaafd4279a2d001ab2d19f0cbb0899f221aac9762f2650f8058
+
+Count = 103
+Adata = 0d065dfde1de1f21784c7869eb566c977f807cfbd53578f4616995b51d7dc045
+Payload = 737f4d00c54ddca80eec
+CT = be5462ece29df02b978b3dc92a9bd26b9653e5917359c331fcff
+
+Count = 104
+Adata = 95c54d187f2415535451cbb9cb35869749b171f7043216ce6886dd77baeecf60
+Payload = 4e9e251ebbbbe5dbc8ff
+CT = 83b50af29c6bc958519891dda72c27d272561e00f7041845d998
+
+Count = 105
+Adata = 0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5ce773dd4c67ca967cd691b
+Payload = 0db72b281ab4046d15a6
+CT = c09c04c43d6428ee8cc1928ac628758ad58fc1b5a768d4722848
+
+Count = 106
+Adata = ad840bc55654762e5eba0e4a9e7998992d990a06d70da1b1ca922ef193dab19a
+Payload = 4f7b4f38ff1ba4df5a59
+CT = 825060d4d8cb885cc33ed11dad4dc8b265a53cf0bdd85c5f15f4
+
+Count = 107
+Adata = 911e9876ea98e1bcf710d8fd05b5bf000ea317d926b41b6015998ee1462ab615
+Payload = 58ce55379ef24b72d6d6
+CT = 95e57adbb92267f14fb18eb659a5a7084be48d099467da4395df
+
+Count = 108
+Adata = 3f68a4fb4043bcf9b6d277c97e11365d949c705bd6679c6f0aaf52e62330ad79
+Payload = a219028a953ce1544835
+CT = 6f322d66b2eccdd7d1523b2b2583fd117cec47b1c84d3863159e
+
+Count = 109
+Adata = 02f32242cba6204319075ea8ce806a57845355ae73e6b875955df510096ebff9
+Payload = 83b0ee9a52252c456105
+CT = 4e9bc17675f500c6f8625456eb2b6a2d35c649a84051f843153c
+
+[Plen = 11]
+
+Key = 4dd555bd3a5253a90b68b5d4d46bd050340ee07ddad3a72048c657b5d76bb207
+Nonce = bdb1b82ba864893c2ee8f7426c
+
+Count = 110
+Adata = 9bcc5848e928ba0068f7a867e79e83a6f93593354a8bfcfc306aeeb9821c1da1
+Payload = 8015c0f07a7acd4b1cbdd2
+CT = 8e9f80c726980b3d42e43a6512a0481255b729a10f9edb5f07c60c
+
+Count = 111
+Adata = c2e75952ab49216f305e3776865791ce877cef8c0229ca97561787093fddf1d8
+Payload = c97b62a719720b44b7779c
+CT = c7f122904590cd32e92e748c514444f00ffdb80a4bb7e9eb651946
+
+Count = 112
+Adata = c76a3ff4e6d1f742dd845be2d74c1a9b08e418909b15077deb20373ef55caf91
+Payload = cb7c17ef62464ecc8008f6
+CT = c5f657d83ea488bade511edb609dfc1929ac1ba5753fc83bf945b7
+
+Count = 113
+Adata = bdb69f99f9a144b9ad88c6cfd8ffb8304c201de9b2818552ce6379e6042c1951
+Payload = 893a690cc5221de597d0e8
+CT = 87b0293b99c0db93c9890053b74283296d0fca83b262915289163c
+
+Count = 114
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf0
+CT = 8e79a41300dc6d60b1d21888a34955893059d66549795b3ac2105c
+
+Count = 115
+Adata = a9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5
+Payload = 641c6914920a79943dca39
+CT = 6a962923cee8bfe26393d1377c4e2f20aaa872a9a0b1d1d7f56df0
+
+Count = 116
+Adata = f0c2cc5a1b4c4cbe839338fa0d7a343514801302aef2403530605cf4f44d2811
+Payload = 2286a1eddd80737a724ca9
+CT = 2c0ce1da8162b50c2c15415545aa0c1dd11551891ae553d3a91908
+
+Count = 117
+Adata = 9842922499ad4d487488b3731f48765efe0b4eb59e7b491ba5f6636f09ed564d
+Payload = d8c63e7d7d332198249c0c
+CT = d64c7e4a21d1e7ee7ac5e4d9e07ec5806360843676ef27d811b246
+
+Count = 118
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf
+CT = 450bc07a2b989fc0ff5e27483b8727c5753ede25e1fab0d86963be
+
+Count = 119
+Adata = 2c186c5c3463a4a8bad771feb71e2973c4f6dede2529827707bf4fa40672660f
+Payload = dfc762466fa84c27326e0e
+CT = d14d2271334a8a516c37e64b5c3c1dc577ee8fcf6ef3ebc0783430
+
+[Plen = 12]
+
+Key = d3ad8cda9a0d91a205c4c05665728bb255d50a83403c9ab9243fcbbe95ae7906
+Nonce = 0b5f69697eb1af24e8e6fcb605
+
+Count = 120
+Adata = ea26ea68facdac3c75ba0cdf7b1ad703c9474af83b3fbfc58e548d776b2529b9
+Payload = a203aeb635e195bc33fd42fa
+CT = 62666297a809c982b50722bd56bc555899345e0404b2938edf33168e
+
+Count = 121
+Adata = 0b32069fc7e676f229f1037d3026c93eef199913e426efd786b524ce1dbde543
+Payload = aac414fbad945a49ae178103
+CT = 6aa1d8da307c067728ede1449b15447c904b671824c2ca24c4fc7ad4
+
+Count = 122
+Adata = 7a8658302e5181552292aa56e8209de63b5d86934167549b0d936202681757e1
+Payload = 7ee0ce371329192618e3cda0
+CT = be8502168ec145189e19ade7ea13850e99ef9300c65f5abc9419d13a
+
+Count = 123
+Adata = 4f05600950664d5190a2ebc29c9edb89c20079a4d3e6bc3b27d75e34e2fa3d02
+Payload = b0a1af969a95025385b251af
+CT = 70c463b7077d5e6d034831e8486c93c31bbedc9e5ffa2f4154bceea9
+
+Count = 124
+Adata = 4530e4dc6a4c3733b8ab7e77e384223cc1a8c179fb66818c08aca47e5c705d89
+Payload = 9f6c6d60110fd3782bdf49b0
+CT = 5f09a1418ce78f46ad2529f7f18b556e7da59fd2549dc57a17bf64f8
+
+Count = 125
+Adata = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381c5439b098ff978b01b
+Payload = 90958d7f458d98c48cbb464c
+CT = 50f0415ed865c4fa0a41260b30aad3a838680cbd313004685a5510c5
+
+Count = 126
+Adata = f6df267e5cbc9d2a67b1c0fd762f891ee3b7c435884cb87d8228091b34aeddae
+Payload = 9f7ae892e5662803408d4d06
+CT = 5f1f24b3788e743dc6772d411d57b89ed0c91251aed37a6ca68a50c7
+
+Count = 127
+Adata = 4372e152b1afd99c7f87c8a51dbc3a5c14c49d04ea1c482a45dfbcda54972912
+Payload = 817074e351455f23cb67883d
+CT = 4115b8c2ccad031d4d9de87ad79a3b0feea16ff5fbca16211ea6fdd9
+
+Count = 128
+Adata = 82b6cd1c6618c42ba74e746075dc28700333578131ca6fde6971d2f0c6e31e6a
+Payload = 1b7da3835e074fdf62f1eb3c
+CT = db186fa2c3ef13e1e40b8b7b49f22737c4b2f9fa0a7e3dd4b067fbaa
+
+Count = 129
+Adata = a5422e53975e43168726677930f6d3e13281bdbd13c67c168340ed67e45d15b0
+Payload = 57473e7a105c806867379194
+CT = 9722f25b8db4dc56e1cdf1d3ef43a48dbea8c1547455ad0197af88a2
+
+[Plen = 13]
+
+Key = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b1cfc90a4a9cb06df
+Nonce = 55b59eb434dd1ba3723ee0dc72
+
+Count = 130
+Adata = 9b1d85384cb6f47c0b13514a303d4e1d95af4c6442691f314a401135f07829ec
+Payload = 8714eb9ecf8bdb13e919de40f9
+CT = ba6063824d314aa3cbab14b8c54c6520dac0f073856d9b9010b7857736
+
+Count = 131
+Adata = fa17c693d0997140fbc521d39e042d8e08388106874207ca81c85f45c035d6e6
+Payload = a0837676e091213890dc6e0a34
+CT = 9df7fe6a622bb088b26ea4f20820a423dd30796b6016baff106aaef206
+
+Count = 132
+Adata = 27663597b389b78e96c785ca2f5510c8963a5561d2b0b24c4dcdf8e58562c12c
+Payload = b8a2ce7e051b8d094ec43f2a7f
+CT = 85d6466287a11cb96c76f5d2436032bc79c4aef1f74da25e92b0aa7f8a
+
+Count = 133
+Adata = d8f1a83371487d611ce704e0a6731f97a933c43569690022fce33cb5aecdc0a7
+Payload = 9e4103ab1dfb77ae3494507332
+CT = a3358bb79f41e61e16269a8b0e658123d2e5bb324c7ead8897f8e32b0a
+
+Count = 134
+Adata = 05c57aab99f94b315cf8bdd2d6b54440c097fe33c62a96b98b1568cdee4ce62c
+Payload = fb3e3d1b6394d2daebf121f8ac
+CT = c64ab507e12e436ac943eb0090270758ab09f93fa3ba7d7a2aa8eac789
+
+Count = 135
+Adata = 1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef1434
+Payload = 549ba26a299391538b56ce4bd7
+CT = 69ef2a76ab2900e3a9e404b3eb2293813f1bcb96564f772e9308e42b2d
+
+Count = 136
+Adata = 9f5cf9149f556124d6bb4e3e243cca1502c02682709392cc2ec7eb262fd4d479
+Payload = 287f31e69880823df7798c7970
+CT = 150bb9fa1a3a138dd5cb46814c81877380d5cf097c2fb5177750f8b53a
+
+Count = 137
+Adata = 1a49aaea6fc6fae01a57d2fc207ef9f623dfd0bc2cf736c4a70aaaa0af5dafd3
+Payload = 040d18b128ae4a1935f9509266
+CT = 397990adaa14dba9174b9a6a5acf42c75787edc62a180568c6ef56545d
+
+Count = 138
+Adata = f29a0b2c602ff2cacb587292db301182e6c76c5110b97ca8b706198f0e1dbc26
+Payload = 92441cbe8d70820870bb01ad63
+CT = af3094a20fca13b85209cb555f56d47a0631f2038103e3904b556ba7a5
+
+Count = 139
+Adata = 01fcf5fef50e36175b0510874ea50a4d2005ad5e40e5889b61417700d827251e
+Payload = f11d814df217de96333dee1cbf
+CT = cc69095170ad4f26118f24e4835be15b7ae24edccd0b0934e3af513ed3
+
+[Plen = 14]
+
+Key = 3ae5be5904bae62609ac525e2d1cad90133447573d7b608975a6a2b16cb2efc0
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+
+Count = 140
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f38983
+CT = 37a346bc4909965c5497838251826385a52c68914e9d1f63fd297ee6e7ed
+
+Count = 141
+Adata = 52f6a10a022e5ee57eda3fcf53dcf0d922e9a3785b39fad9498327744f2852e4
+Payload = 23fe445efa5bcb318cc85e2ad1ac
+CT = 81c90102c44e7cc9cee2de5b09ad364b603de6afbc2d96d00510894ccbe7
+
+Count = 142
+Adata = d236e3841b9556b32dbd02886724d053a9b8488c5ad1b466b06482a62b79ebb6
+Payload = 762fdc3e0c30c7ecf2ec8808bb79
+CT = d418996232257014b0c6087963781a4321c2ddbc35ce4864457d611219e9
+
+Count = 143
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+Payload = b6813d5fe8afa68d646c197337a2
+CT = 14b67803d6ba117526469902efa3296e55efebb17fe145cdca9b31ea7bcc
+
+Count = 144
+Adata = 7f291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4090e94b3ef5fd4
+Payload = 4ce8b6578537215224eb9398c011
+CT = eedff30bbb2296aa66c113e9181059270a0510e7cc1b599705853af2144d
+
+Count = 145
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f38f50bd
+CT = 3c88d63806415da4d58e73fe88bcb55847573bf21e946ce9bdc5f569e3ff
+
+Count = 146
+Adata = 5a44ff94f817c7c028a8f3db35a4d01364d2598432469f09ded86e5127d42d35
+Payload = da989cc7d375ed5fac4d7f938d74
+CT = 78afd99bed605aa7ee67ffe25575b8a61c5687ea02f0276824b8316b76f1
+
+Count = 147
+Adata = 2a755e362373ef27a911c4d93ca07bc97135645442ad7ad6a8ef98146c71e9d7
+Payload = 6fbab5a0f98e21e4d15904af5948
+CT = cd8df0fcc79b961c937384de8149a07ee02791011129fcacffcfb1bf4145
+
+Count = 148
+Adata = f7988873f45a5de314e5381d3f14d8f8c48c9b649bf3e745ed5dc882d507da58
+Payload = b610349e8b370a7c195598573637
+CT = 142771c2b522bd845b7f1826ee36d34204b1ce23f5f58a8eb7cf1fa8cfa7
+
+Count = 149
+Adata = 95d2c8502e28ab3ee2cac52e975c3e7bccb1a93acc33d9c32786f66d6268d198
+Payload = 1d969fd81dab5ced3e6ee70be3bf
+CT = bfa1da8423beeb157c44677a3bbe9c618bb88bbcefb008a5ea6bed4ff949
+
+[Plen = 15]
+
+Key = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Nonce = a5c1b146c82c34b2e6ebeceb58
+
+Count = 150
+Adata = 5e60b02b26e2d5f752eb55ea5f50bb354a6f01b800cea5c815ff0030b8c7d475
+Payload = 54be71705e453177b53c92bbf2ab13
+CT = 788db949697b8cd9abbc74ed9aa40cd6852dc829469368491149d6bb140071
+
+Count = 151
+Adata = 210c04632341fbfc185bfe3cbf6fe272bbe971104173bcb11419b35ab3aaf200
+Payload = 22197f9ad14591e7a6d5f8b18c969a
+CT = 0e2ab7a3e67b2c49b8551ee7e4998556940dc5a7e44bf10234806d00a012b5
+
+Count = 152
+Adata = d3a205dd017e79a67400a937a20ef049f4c40d73311731f03ab857a3f93bd458
+Payload = 096b2f530933c1273304a6ad423726
+CT = 2558e76a3e0d7c892d8440fb2a38390898f7dbde25b0b70d335df71a06987b
+
+Count = 153
+Adata = 0c9b3ba4faf5fc2f310ad1bab06c4ca13474b714feeffb6ad615c1b850bbd6a3
+Payload = d44fdfd9da3a63c1083afe574e91bf
+CT = f87c17e0ed04de6f16ba1801269ea02fd10d1f21b6b963c05aeda8eb09e272
+
+Count = 154
+Adata = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841528cccb79fd791b3
+Payload = 8d836acc13ed83c2b2c706415c9679
+CT = a1b0a2f524d33e6cac47e0173499664491d23d90ff55abca17e9d943b98c7f
+
+Count = 155
+Adata = 69dc21eb6f295b12ba493ee8fe6c40d78af946067ce772db316a3cbf00d3c521
+Payload = 2a68e3fe746f593c1b97cb637079c3
+CT = 065b2bc74351e49205172d351876dc9616886c6b2adc97db5a673846b6662c
+
+Count = 156
+Adata = 095eb52135dc6d9c1f56a2571c1389852482e7aa3edc245a3904a0449db24a70
+Payload = 39799b001ed2c334c269acb0f2328c
+CT = 154a533929ec7e9adce94ae69a3d932441dcae1760db90379bd354fa99164e
+
+Count = 157
+Adata = efd7270e0396392fde8b0ddaab00544cbbd504f4d97d4e90d749d1946de90dcb
+Payload = 42143a2b9e1d0b354df3264d08f7b6
+CT = 6e27f212a923b69b5373c01b60f8a9c7c7deb28bdcf84886ef843216b94449
+
+Count = 158
+Adata = 8bc181ce2e66294e803a8dc3834958b5f173bc2123c0726e31f3fca25b622ed6
+Payload = a3dcf26327059a4245b79a38bb8db6
+CT = 8fef3a5a103b27ec5b377c6ed382a935061ae3cd892ba63c44b809d6d29421
+
+Count = 159
+Adata = c39ec70c2c71633ae0dccc41477ac32e47638c885cf59f34ebd4a096d32f91f9
+Payload = 3d54883449ecca8f153436c25a0a01
+CT = 1167400d7ed277210bb4d09432051e3c9ae69a4c59ff8e251c2fe022d065a9
+
+[Plen = 16]
+
+Key = ee8ce187169779d13e443d6428e38b38b55dfb90f0228a8a4e62f8f535806e62
+Nonce = 121642c4218b391c98e6269c8a
+
+Count = 160
+Adata = 718d13e47522ac4cdf3f828063980b6d452fcdcd6e1a1904bf87f548a5fd5a05
+Payload = d15f98f2c6d670f55c78a06648332bc9
+CT = cc17bf8794c843457d899391898ed22a6f9d28fcb64234e1cd793c4144f1da50
+
+Count = 161
+Adata = a371ca29b92ed676bab5dfc4d78631bb6d9bb23a29f822907084a1f0fe17721f
+Payload = 60d55a8d5ab591a51e87fdf6aaa2ad25
+CT = 7d9d7df808aba2153f76ce016b1f54c68b55bbe42d8c97504b97c34a5f16e6a6
+
+Count = 162
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2
+CT = d6b93591a99b14dc6ff85768fc5fdc51017d8706acd676ae99e93d5312a4113c
+
+Count = 163
+Adata = eebd2bbf1e9f6d817cd8062a6a9680e7f10464eefeb50b07cb46b14b9b3fcb2c
+Payload = 865b89aa38ee1b5a3ce56620307e8937
+CT = 9b13aedf6af028ea1d1455d7f1c370d45982f0fe5d951a8c62c87894657301e4
+
+Count = 164
+Adata = 72863362612f146699f6b2f6ec3688f2ca6cb1505af7a309c91c1933e34d516a
+Payload = a8efc37d1b8b51f2a47b21dd14da383d
+CT = b5a7e40849956242858a122ad567c1de5addfddbb59f4985947fb3a9ab56333e
+
+Count = 165
+Adata = 9c9efc6593f96207678db813608f2b8bc33ed1bef974ed77ed7b6e74b621b819
+Payload = d9b0eaaff786165f882f41a98dbc0c35
+CT = c4f8cddaa59825efa9de725e4c01f5d6b651053516673402a57538db1a9ce7e9
+
+Count = 166
+Adata = dc482a051b58d8a3904d3af37c37b51983f634a504451bbba6f77d71337f8e78
+Payload = df49d972b6ebbbb18ee975ac635d847e
+CT = c201fe07e4f58801af18465ba2e07d9d86d772b1a1991b7be6589bbccad36171
+
+Count = 167
+Adata = 51ef065a43caa23faf750b02a41ad6ba701aeb8058f6d8738d6f6b005bec7f60
+Payload = 78318aa5cd16699b77bdcea2fc9d1d20
+CT = 6579add09f085a2b564cfd553d20e4c3569387a1a6bcc826e94012670820576e
+
+Count = 168
+Adata = 88e2a74d2920c89c6a101f5f06d0624a6d5eabd9bdb51395ee3983934c55c73d
+Payload = 8e20d65d02dd9a64379f75b6d8328f2d
+CT = 9368f12850c3a9d4166e4641198f76cee9c788b4aae9b2c6caf0c44aa9bd2ed0
+
+Count = 169
+Adata = ada3ed7db2dabbfbc441ef68a5656e628d6d5bd6c1574369688497179a77601a
+Payload = 97e8d8513af41b97801de98cc4269096
+CT = 8aa0ff2468ea2827a1ecda7b059b6975f1df0f01944641a1b04d753e6ab8d3cc
+
+[Plen = 17]
+
+Key = 7da6ef35ad594a09cb74daf27e50a6b30d6b4160cf0de41ee32bbf2a208b911d
+Nonce = 98a32d7fe606583e2906420297
+
+Count = 170
+Adata = 217d130408a738e6a833931e69f8696960c817407301560bbe5fbd92361488b4
+Payload = b0053d1f490809794250d856062d0aaa92
+CT = a6341ee3d60eb34a8a8bc2806d50dd57a3f628ee49a8c2005c7d07d354bf80994d
+
+Count = 171
+Adata = 4ae414bc888a42141d3060c71c2dbbffd425b6a952806982271a8e756b3c9e24
+Payload = 51eb190c6a9f46e8ec1628b090795470c0
+CT = 47da3af0f599fcdb24cd3266fb04838df13c1c5755a5a240c33b2b890a486aac8b
+
+Count = 172
+Adata = 7b7f78ae1a5ee96fdc49dacd71be1a6ac09a6a162d44dea0172886eca5674e46
+Payload = 25144e807e389bb0e45b6dc25558caf61a
+CT = 33256d7ce13e21832c8077143e251d0b2b4cfca1c19abf447d7bc0898d61885144
+
+Count = 173
+Adata = 03f31c6143b77f6ad44749e2256306b8bf82242f2821fad4075b09b388ba81ca
+Payload = dbe1ee14abfe2ecf4edf6db206cf9886ce
+CT = cdd0cde834f894fc860477646db24f7bff229cc7a390867a245dcb7c434f1db347
+
+Count = 174
+Adata = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa001d553375cc63f8a2
+Payload = db6df31f12bf552f81deff5fa2a373fc22
+CT = cd5cd0e38db9ef1c4905e589c9dea401135361b539f9fe0fb7842907c2326aef63
+
+Count = 175
+Adata = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a7b9bb2bd99392c8a
+Payload = ff2a97b49fcc6a50d4549c979d53ccc51f
+CT = e91bb44800cad0631c8f8641f62e1b382e8ed10943929e7d7bf798b2ae8371aae5
+
+Count = 176
+Adata = 4d1513478fc1fb0a18eb6d2a9324fefbd975ecd1b409025de826bc397462acc1
+Payload = 73ddfa0185200a890b7690a7e3986d8818
+CT = 65ecd9fd1a26b0bac3ad8a7188e5ba7529f92b9e49ab83f113f8949dc9e4a36e0d
+
+Count = 177
+Adata = b26a7ff61bfe94864249af7cc9b4a723627dd4463f5a22f0ca6063769522eab7
+Payload = 5c7604f9ac8fdf30ee5820e5aeb75b65d7
+CT = 4a4727053389650326833a33c5ca8c98e6d0e53223adff22a08e3dddf66fff23e3
+
+Count = 178
+Adata = 960f9a85cfbfb6eab223a4139c72ce926a680ea8e8ecc3088cf123de659ad310
+Payload = d44fdfd9da3a63c1083afe574e91bf01c9
+CT = c27efc25453cd9f2c0e1e48125ec68fcf833f49a42521a7a2367f91bfcc2180b7c
+
+Count = 179
+Adata = 3718467effb5d5dc009aaefce84d8cb4fe8f80eb608f4c678f5d0de02ea11e59
+Payload = bb515dc227abb9acad8fefaa14771bb77b
+CT = ad607e3eb8ad039f6554f57c7f0acc4a4ac08bd395c6807223311070659f550934
+
+[Plen = 18]
+
+Key = 0786706f680c27b792d054faa63f499a8e6b5ddb90502946235bf74c022d772c
+Nonce = f61ef1c8c10a863efeb4a1de86
+
+Count = 180
+Adata = 67874c808600a27fcab34d6f69cc5c730831ad4589075dd82479823cb9b41dc3
+Payload = 6a26677836d65bd0d35a027d278b2534e7df
+CT = d1c1f3c60603359c7d6a707f05ecb2296f8e52f2210b7a798ad5c778ee7cfd7fe6e0
+
+Count = 181
+Adata = e0c27cddf919d3092d9a34766c89a5ae6dcf39fe954d1e6f1a70ddf96805def4
+Payload = 4021ff104ff1dbd91e46db249fd82198b0a1
+CT = fbc66bae7f24b595b076a926bdbfb68538f00923bb5a347af13df12f234fca5f03ef
+
+Count = 182
+Adata = 7ae9eca03f616ab39ebb3be26b848842b4aa584e5c8e5695065ad5af34951175
+Payload = 6a681f164efce199a787bccff223b8ae1a98
+CT = d18f8ba87e298fd509b7cecdd0442fb392c9d03ed7bffac83e890caceb6903d9cab5
+
+Count = 183
+Adata = b47c9bc4eb01c74f5db2e6a293bef80db18c58cf06feef7ee0f8a7a9a51c22bb
+Payload = 7861dac338ba3f8274dca04c8c6f92b6d44c
+CT = c3864e7d086f51cedaecd24eae0805ab5c1d4dd8f30870025b2bd1e2a2511574d3e7
+
+Count = 184
+Adata = f6afd661f218c7426b92ee53e65d14898cd0c78a7e594fcc6ac0e3fb5cab1c9c
+Payload = a3f0473c620d2739d5ba4f7156f88d0fb669
+CT = 1817d38252d849757b8a3d73749f1a123e386046d17f337f3cb49884d94995edbdc9
+
+Count = 185
+Adata = d3802911e341577046cfc61d9043b4af059fb4bef3c6a2ff46ccdcb05670af37
+Payload = 07c535d9456a6ff1e41321150d16dae3f7a3
+CT = bc22a16775bf01bd4a2353172f714dfe7ff25fdc77b43bca254d6459263cdfed8fbb
+
+Count = 186
+Adata = db60720db67a60ca286fe744d46173c231fbcc7deb4c9b0d87d52a2247e06b74
+Payload = 5ee220720a896249efdab2ce418318bb5ebf
+CT = e505b4cc3a5c0c0541eac0cc63e48fa6d6eedd1a1d36c8164c55d55dbf0ff1e9517a
+
+Count = 187
+Adata = 57f70ba5493265b30491decc726354e2065e7971a2efd56db9cf0f79b1d76859
+Payload = 98e4eb0361c8bf40bcbe0539b0850e4c35ff
+CT = 23037fbd511dd10c128e773b92e29951bdaeb476e2ca48fd52bec0539b00744a8a07
+
+Count = 188
+Adata = 4a29b9ad548964942f87f28ba267ec0d0e8f72c73b3823ee57693dd63c2605c1
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72
+CT = c4e0d10096f1178ca63ebcc70c5056fea523fad68c62b81d62f2d490ae74f5bb1465
+
+Count = 189
+Adata = acbd2e9911b3218a230d9db5086d91dccac3fc93fc64b0f4a15d56954906b2b7
+Payload = e99ed2ac6c38e033061b5d85f3e77dd72518
+CT = 527946125ced8e7fa82b2f87d180eacaad4913b15d8000266c61ba5aec898eb35b52
+
+[Plen = 19]
+
+Key = bac55f9847d93325bf5071c220c0a3dfeb38f214292d47b4acb7b0a597fe056f
+Nonce = 05b50c458adbba16c55fcc454d
+
+Count = 190
+Adata = 89ad6ae1e550975eaa916a62615e6b6a66366a17a7e06380a95ea5cdcc1d3302
+Payload = c1a994dc198f5676ea85801cd27cc8f47267ec
+CT = 7c9b138177590edaafec4728c4663e77458ffbe3243faec177de4a2e4a293952073e43
+
+Count = 191
+Adata = dfddb719d00398bf48a6cefd27736389e654a93b8595cd5ac446af1996e0f161
+Payload = 791e232bfb42fb18197adc1967da1a83f70168
+CT = c42ca4769594a3b45c131b2d71c0ec00c0e97f8422f736fc435687634d42254b22fd99
+
+Count = 192
+Adata = 58ef310997dcaf067dd217274921504da6dbf0428a2b48a65fe8a02c616ac306
+Payload = 3d4127942459bb8682e662dfc862467582fa68
+CT = 8073a0c94a8fe32ac78fa5ebde78b0f6b5127f38a96e68ef7dbaef1b460cc0980eacd4
+
+Count = 193
+Adata = 511e5d5e100b595f6b20e791830bca37e23f7b785e482a58405bffe7a632a5b8
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd6
+CT = b343016147b47ce03873efc86345faf0d223c15c5c702a82d468929227502e4e35796f
+
+Count = 194
+Adata = e48dfaa53b6807ea6f01d8dca67960b9f321f7851f324459a9bf61fe0be73abb
+Payload = e0f1cd013e6aea4fa484fc3fa35d348b1a2399
+CT = 5dc34a5c50bcb2e3e1ed3b0bb547c2082dcb8e89188c0940182dd99a902d158c5b0810
+
+Count = 195
+Adata = c12c0423fe36e4c88775dd00b4af267b85b7dd2a37a742a3156923c8917c97a3
+Payload = b1cc1946b4fc1dbd033254cdf536f61e9f9cd7
+CT = 0cfe9e1bda2a4511465b93f9e32c009da874c015849acbb7af1892790300bb84fb0558
+
+Count = 196
+Adata = 4255f8af18df7237e0abe98421aec9634443561752d893aaffe76380e829ef32
+Payload = 87284658928208e3bddca83e3ceb13708d88d4
+CT = 3a1ac105fc54504ff8b56f0a2af1e5f3ba60c3e75aaf3077ac6dfb5454851ec3910de6
+
+Count = 197
+Adata = ab83567833d2f3461b5fbecc0e366694bb5ea00933b2b3e792ec3aefe20325df
+Payload = bdb79f931ef3035a33bdd1b032fd9de8f6b2ba
+CT = 008518ce70255bf676d4168424e76b6bc15aade70f42e3e1f2b5bb58433bd11f5dea1f
+
+Count = 198
+Adata = bd1446ba3185d1c16551730947c22142142caa8cc1c540e89ab734ec297401bc
+Payload = 1f9c3a8eb8bc59f3869e10f73883aa8f8990cb
+CT = a2aebdd3d66a015fc3f7d7c32e995c0cbe78dc564f6248cefe5fc7cfb547c90a558925
+
+Count = 199
+Adata = b87577755d2d9489194f6f7cfabf267dc3433a9c91954e81beb72c5e06870922
+Payload = 5f28809181f9a889894da8d6fe1fde6cce354a
+CT = e21a07ccef2ff025cc246fe2e80528eff9dd5db52249d812f7f235afa0732e984e91b2
+
+[Plen = 20]
+
+Key = 8beedeb85d42c2a7fa6f7237b05acb197dd8e1672471ac878064fe5319eab876
+Nonce = 8479bdfad28ebe781e9c01a3f6
+
+Count = 200
+Adata = 7aebdfd955d6e8a19a701d387447a4bdd59a9382156ab0c0dcd37b89419d6eff
+Payload = 7b125c3b9612a8b554913d0384f4795c90cd387c
+CT = 6cc611d816b18c6847b348e46a4119465104254a04e2dfeeeac9c3255f6227704848d5b2
+
+Count = 201
+Adata = d119f300fbd74e754a200ea2c3f9fabc1466d02078c84245db693eef3f5672a6
+Payload = 8b013f5782d5d1af8dbd451a4202866095dac975
+CT = 9cd572b40276f5729e9f30fdacb7e67a5413d44338d48329997c5981d678b5e24a6f01b0
+
+Count = 202
+Adata = d6204303b86acf62d5ab860ca70161288ede56e3cf017c08dca56fd2d6f8f6fe
+Payload = b2b1d82a5523b72ea366a680922ed3a4624536c4
+CT = a56595c9d58093f3b044d3677c9bb3bea38c2bf2a77e3ab68e0a73519591a33ed098b758
+
+Count = 203
+Adata = 8557e22eb4529b43f16b1f8ae47c714ac8a2c827c1408a47704778b4c5b52601
+Payload = f8c4eb4285d3d7744da52775bb44ca436a3154f7
+CT = ef10a6a10570f3a95e87529255f1aa59abf849c1cff6c24251c2fb7b8604dfa10c60ef4a
+
+Count = 204
+Adata = 8c1a4187efbb3d38332f608f2c8bbe64247d9afa2281ced56c586ecb4ab7a85e
+Payload = 6e7fe35fa39c937a0e6b3a8c072e218650f42b8d
+CT = 79abaebc233fb7a71d494f6be99b419c913d36bb6c3c39f915d081d34559179869b32d81
+
+Count = 205
+Adata = a41bb1f256228302cd0548ae2148ff42774d18c2d6d3e38b36bc4938da13bac3
+Payload = 917b467d841850fc6e648f1bc298a7f9f1ee38ca
+CT = 86af0b9e04bb74217d46fafc2c2dc7e3302725fc9389a6a6a74c6eb0e1f87562469f2082
+
+Count = 206
+Adata = b0b024e20c4f75a6dad54c21a9edbce846792e957878b1c8ed2d916c757e2b3c
+Payload = 2b4314fe1a6bfa786b7cfc13fbee861b348efbf6
+CT = 3c97591d9ac8dea5785e89f4155be601f547e6c03bed3a2f5dfdbfcc0d7ac26c88d1962c
+
+Count = 207
+Adata = 42153925c46fc9d5d328312d62f59bb99fdc4ac479a3386d5f88fefd4b32f577
+Payload = e19fa7f83c79920cbff45c41a9dee8fc99e97396
+CT = f64bea1bbcdab6d1acd629a6476b88e658206ea035ea1d99be344fa1467ee91c73bbca67
+
+Count = 208
+Adata = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711a08da6acd42299fe
+Payload = 53e0475cf492b3d39dad600f5c58eb0bd0021554
+CT = 44340abf7431970e8e8f15e8b2ed8b1111cb08627936ec10a81b36768b606e9a38b2f4c5
+
+Count = 209
+Adata = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a7977eda6de045878
+Payload = c119a383d9a3d4bff4270a1d22076b346db5f61c
+CT = d6cdee605900f062e7057ffaccb20b2eac7ceb2a11575ae03ea8a57bbe4a67c060367b74
+
+[Plen = 21]
+
+Key = c3a0c126cad581012151c25cf85a44472c23f83b6095b6004f4f32cd60ec2db2
+Nonce = 94ab51ce75db8b046d6ab92830
+
+Count = 210
+Adata = 2a243246bfe5b5ab05f51bf5f401af52d5bbaa2549cf57a18e197597fe15dd8c
+Payload = 73b09d18554471309141aa33b687f9248b50fe3154
+CT = b7e8264ca70fd2a4fb76f20a8ad5da3c37f5893fb12abeeaef1187f815ca481ed8ddd3dd37
+
+Count = 211
+Adata = 0595306eb7441622a49800edee0134492d82320707fceba902af2e0c95fe634a
+Payload = b64d00f3a4df754fa4ee6376922fb67ccce0c6209f
+CT = 7215bba75694d6dbced93b4fae7d95647045b12e7accc2b55011dbe92ce7619e0ad48b4ccf
+
+Count = 212
+Adata = bd439dbefec589e120fb4f9825b315bf86523b85c61791cd4da4c8d474ba2714
+Payload = 2b11d1ac74ffe701ec733d32085b1054132726e622
+CT = ef496af886b444958644650b3409334caf8251e8c71e8b1f4d70d8f4c7df4f22847d36b394
+
+Count = 213
+Adata = cfebe1cf82267394065bcecfada6709c6c35a3ac835644f560d4c9a8c1848364
+Payload = a88f22424643a523aa3d7d88f4364f1290f49dd0a2
+CT = 6cd79916b40806b7c00a25b1c8646c0a2c51eade47a85e76a9d07b7b361ca56d53c34cda50
+
+Count = 214
+Adata = 7a37255b682766a0bfecf78e5162528885a339174c2a49325739d2bd8877e64f
+Payload = c81427bc84c6a3cfefd4c4cb210fe82212977e1947
+CT = 0c4c9ce8768d005b85e39cf21d5dcb3aae320917a2fddb010e7508ad03ad287068ecee6020
+
+Count = 215
+Adata = 619f2ae80070e278615466a3fd6c9acb7b510c5679bed7038889c77e78d8bd32
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447
+CT = ec9c6d8acc67468feeac4b64a0af139c4c46625aa2ddea785e6c470c52c4fdf432fd78b66e
+
+Count = 216
+Adata = b2571e56f66a857daffbdc99370ceddd4a7bed3867d600cc797000a3b7b57a9d
+Payload = 4c88151cafef75832bacef43a06e862349d56b67ee
+CT = 88d0ae485da4d617419bb77a9c3ca53bf5701c690b91232cfbd7ffff252498b35274fb2995
+
+Count = 217
+Adata = db409636e3e3bcd606a91aeb7592009896f9ad2c4cc6b7f578e6ad59c0f8fa22
+Payload = 572855e22ce89bc2bcf09cb15a1765d99973449d61
+CT = 9370eeb6dea33856d6c7c488664546c125d633938472b2c50e5e391ad104f9ee33b94f2872
+
+Count = 218
+Adata = 62c89a835721207a182968c516dc8be45774ec846e8dcab9ab8611888f2a76a8
+Payload = 89ce46b3de3afaf2518d419b1a2ac24cabca269a96
+CT = 4d96fde72c7159663bba19a22678e154176f5194732d69c5d6db1b130102af3dae0690673b
+
+Count = 219
+Adata = 33f30ddd83002eea50fd4a8fae39d0980a04160a22ac88b755ac050f1d1f8639
+Payload = edf1682a626e9fbf3d57bb260e0876c6f92ba5b114
+CT = 29a9d37e90253c2b5760e31f325a55de458ed2bff1489903365970c2673c9fd457e1077aad
+
+[Plen = 22]
+
+Key = 9cdebaeee8690b68751070691f49593668a6de12d3a948b38ddbd3f75218b2d4
+Nonce = af1a97d43151f5ea9c48ad36a3
+
+Count = 220
+Adata = f5353fb6bfc8f09d556158132d6cbb97d9045eacdc71f782bcef62d258b1950a
+Payload = 3cbb08f133270e4454bcaaa0f20f6d63c38b6572e766
+CT = 3966930a2ae8fdd8f40e7007f3fde0bd6eb48a46e6d26eef83da9f6384b1a2bda10790dadb3f
+
+Count = 221
+Adata = e3a1555ffe5f34bb43c4a2dae9019b19f1e44a45fb577d495d2a57097612448d
+Payload = 946e86795c332031e2d1ee09d3d4a101fb6800d00911
+CT = 91b31d8245fcd3ad426334aed2262cdf5657efe408a5587bdd120a7d08cd3841cb117af444fb
+
+Count = 222
+Adata = 9c5d43c1a1269cde199509a1eff67cc83a1759b71c9e7a6ee99f76b98c6e23a6
+Payload = b76ce2ab0065ba1c0a754494991c8c452cb416f18ab1
+CT = b2b1795019aa4980aac79e3398ee019b818bf9c58b0545b32f81dcf03e2bcc2aaf62ad366e97
+
+Count = 223
+Adata = b07452a7900a289b91b2771dfdd5108852536659aa259def7b41e38f80bd03ab
+Payload = a3e0d8d0784155bfc45769c52711d4fa68e8bc390c20
+CT = a63d432b618ea62364e5b36226e35924c5d7530d0d94fea17d78533bc9e022dbfb460afdf499
+
+Count = 224
+Adata = 6b30f55c3101540523a92380390f3f84632f42962061b2724cde78ac39809397
+Payload = 6e6a88abbb52a709b47365ad6aa8016fa9a03a9bd834
+CT = 6bb71350a29d549514c1bf0a6b5a8cb1049fd5afd98056defc6dcaeec80b1c639350ab6f1fde
+
+Count = 225
+Adata = 9fc62d14f8b7a6026509275cff80312ff1ade2b5d9c274cb72a506a571439fc1
+Payload = eba1810d537041821121aeff8e0914ac26a550072c8c
+CT = ee7c1af64abfb21eb19374588ffb99728b9abf332d389d37b7251fb8c0ef2b37c36d51219d0f
+
+Count = 226
+Adata = 6b9389cc42113d639fd2b40cbc732ae0dc7c14513b88b36b45a6ea5a06fe4d2b
+Payload = dfc6692cd2442e5ff1f918c8812a27f81d107d16a12f
+CT = da1bf2d7cb8bddc3514bc26f80d8aa26b02f9222a09bd279d9da4437c8a2a252436508134c56
+
+Count = 227
+Adata = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad166c77952a50318bd
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae
+CT = 9f0ea330e4d4a17a0ef3a2575ff28bfcd9c75f865f1a63943543bc1c5f5991ecc5964a288f79
+
+Count = 228
+Adata = e98b710c47a4d12a73cd8aa2613fc2910c16f4195ea7f15650132493521d19be
+Payload = 9f5a05db89e0e336da066ce81b79ad9be1d0ec4fb7b8
+CT = 9a879e20902f10aa7ab4b64f1a8b20454cef037bb60c0a49ee2b7ceddcbd28abb24b77d5edee
+
+Count = 229
+Adata = 527817316fc48b105f8ab178dd2db1fefa09c50461aa9d8bdf3c03482343bbf9
+Payload = 58f31e5770070a5d4031fb795dc2d298561d3559960d
+CT = 5d2e85ac69c8f9c1e08321de5c305f46fb22da6d97b9b099a68cfa3572d974e03232e09f37fb
+
+[Plen = 23]
+
+Key = d34264a12c35cdd67ac105e2826b071e46f8131d1e325f8e0ae80a6447375135
+Nonce = 3891e308b9f44c5b5a8b59004a
+
+Count = 230
+Adata = 0cda000ed754456a844c9ed61843deea9dadf5e723ea1448057712996d660f8c
+Payload = 79ac1a6a9eca5e07ce635bfd666ef72b16f3f2e140d56c
+CT = 1abcc9b1649deaa0bfa7dcd23508282d9c50ca7fee72486950608d7bcb39dcf03a2cab01587f61
+
+Count = 231
+Adata = 3fb6ddb76809b8e6d703347664ef00a365955124c603900d5c8d4ff476138252
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f
+CT = 15c1fde7b60a2dac84a74125f7ff4154132eb0e139e05b1c4fb40e5c8bc37152a173d4bbb18c3e
+
+Count = 232
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab4a5667c472c98b2626
+Payload = a027c28fbe22111fd4c8a226cfe8531c16d7790d561eca
+CT = c33711544475a5b8a50c25099c8e8c1a9c744193f8b9ee019c359008adae3070b5a543ead0effb
+
+Count = 233
+Adata = 7a459aadb48f1a528edae71fcf698b84ed64dc0e18cc23f27ab47eeabeaf833f
+Payload = fa597e37c26c38694abdcf450f9edc529160fa0d651979
+CT = 9949adec383b8cce3b79486a5cf803541bc3c293cbbe5dbd099ab134756b90746762a92a4a9f7f
+
+Count = 234
+Adata = 484207909dec4c35929ebe82fcacf20d2af6d850bd69364ebac9557adeadfbd4
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a0
+CT = fd5c59724fdd3a0cb49cefbda632cf063e9c2f470ef684fa4f6adfec85d055310107ba89198afa
+
+Count = 235
+Adata = 88b5448372548e6aab1b262630a28a471d285514703f1bdb10c695850e18fe6d
+Payload = 7d9582cf9e3bb9ee34dce965f56b08e716589486b0641c
+CT = 1e855114646c0d4945186e4aa60dd7e19cfbac181ec338915d23eb2e952afcc89fbddb567d9d75
+
+Count = 236
+Adata = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb38842d7795d830d2e
+Payload = 5a387e7cc22491fc556fe6a0c060b4911d01f0c11f801e
+CT = 3928ada73873255b24ab618f93066b9797a2c85fb1273aaad6c31828314e24198f005955ca8f5e
+
+Count = 237
+Adata = 2aa7a28da38c42fda2e578d9d6340cd8e80b9b32047c3db296d0640d517b0872
+Payload = 87946e910059cbaf48df63b220f397049c65ca10cd1920
+CT = e484bd4afa0e7f08391be49d7395480216c6f28e63be04e531ebbadccfe47182b41904bbfebcfe
+
+Count = 238
+Adata = 3382051c268891da04e6ca73adcead4029f6a1593be4acfe3968e7351a6a2fb5
+Payload = c62f67d208f1c8ffd5d57df9de15ef54f97fbc07d1630a
+CT = a53fb409f2a67c58a411fad68d73305273dc84997fc42e7c582414154236c09ee704cf4a5de411
+
+Count = 239
+Adata = c352828b1920e53bbb60f2ea6a5f15639659e6f3243405c26f6e48628d5519a9
+Payload = 697e73eaaf562d31bdbf7ce9e78c7426fe1c87e421def9
+CT = 0a6ea03155019996cc7bfbc6b4eaab2074bfbf7a8f79dd57c9990029c89d1b37988745fa5737a3
+
+[Plen = 24]
+
+Key = 4ad98dbef0fb2a188b6c49a859c920967214b998435a00b93d931b5acecaf976
+Nonce = 00d772b07788536b688ff2b84a
+
+Count = 240
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75b8af7746d4e570c848
+CT = f28ec535c2d834963c85814ec4173c0b8983dff8dc4a2d4e0f73bfb28ad42aa8f75f549a93594dd4
+
+Count = 241
+Adata = 1ae8108f216defea65d9426da8f8746a3ae408e563d62203063d49bf7e0d6bdf
+Payload = 2b223932fb2fd8433e4b1af9e8234a824569a141f6c96a69
+CT = 4546c70127abacf84a87e513b8b90331639d386dcff38f6f4de907a59c5e4d3f21e1348d7cdf92b6
+
+Count = 242
+Adata = 460f08114b1015fe8b7a9b5dd1b9e6a3d28367c4bd15f29b13c02a8cb9a53968
+Payload = 4d57cbe4a7e780d4ed17267d5ebc91750c2f0209e0444bd2
+CT = 233335d77b63f46f99dbd9970e26d8c62adb9b25d97eaed4ff4239544e2f354d6c6837cd9c23b884
+
+Count = 243
+Adata = 860f4428259d9c5b17698cc95363db6cfee603258582e3a3e8feb886599d4ac4
+Payload = fda8665f87c618646a89c7abdca275fd10c31453ad4b9c99
+CT = 93cc986c5b426cdf1e4538418c383c4e36378d7f9471799f3f6c6f7cc494201069344e2d6d41bd9b
+
+Count = 244
+Adata = 1b43c482f83780c21583f88e5afcf6938edd20f21b74d895161b60c27a6a42f0
+Payload = 98104fd3f3413ad1f57ef4912cb50097dca379a58c47b0d2
+CT = f674b1e02fc54e6a81b20b7b7c2f4924fa57e089b57d55d43787a15352cfceb028202c8730beaa7a
+
+Count = 245
+Adata = b082ccd964617c27a5607b7324faad237ee53acfc18c35502dbf7c1937a9dfcb
+Payload = b46b343e64d2d70e0bd909dbb3f6bedf7e4adc74321be526
+CT = da0fca0db856a3b57f15f631e36cf76c58be45580b210020f3a0ca3da647eb31893e867956097983
+
+Count = 246
+Adata = b8539ba93ef17254ec1d8d62e8f4eae4d41ee1e75345bf90c9cbb26c63bce501
+Payload = 8e12620bb575e6b167b085255b2b5631ff28e04cbef8826d
+CT = e0769c3869f1920a137c7acf0bb11f82d9dc796087c2676be663fbbebbc251b9f1760afa49e89e71
+
+Count = 247
+Adata = b6b09463b5ef5ead1f17f4021693a0d8452e98dcbb8e7590f9fde6394970a6f8
+Payload = 792aaa23b923d1b53173fe19853b9aa402a301d48529873e
+CT = 174e541065a7a50e45bf01f3d5a1d317245798f8bc136238da90cd87e9d9ca5d85430a150e682752
+
+Count = 248
+Adata = 390f6de14d5e1f2f78dbe757c00b89209d0cf8bc48cbbea035779f93de357905
+Payload = ddc5b4e48970ebd72869be6998e9103c014475e8ae6ea29c
+CT = b3a14ad755f49f6c5ca54183c873598f27b0ecc49754479afc0cc4601afb61efa7059cfe49ec9dde
+
+Count = 249
+Adata = 1d75c9e7acb09932db332498d30f82e4009025cb1827047c59a8f97812b568a4
+Payload = d2b66096c475a77648c27235e6972ba8f18761330d3c6adf
+CT = bcd29ea518f1d3cd3c0e8ddfb60d621bd773f81f34068fd9cf7474962c3602dcfcb50039f43e3d6f
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp
new file mode 100644
index 0000000000..0e56a03d42
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 4ae701103c63deca5b5a3939d7d05992
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 02209f55
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 9a04c241
+Result = Fail
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = f5f915df
+Result = Fail
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 7a3c3499
+Result = Fail
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = f09c2986
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 4ae97e71
+Result = Fail
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = ecb38c8b
+Result = Fail
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 9c4dc530
+Result = Fail
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 67299ef6
+Result = Fail
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = b0538d02
+Result = Fail
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 88200ea8
+Result = Fail
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 19867aa5
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 3b392a52
+Result = Pass
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 1c5e47e0
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 97a56b8b
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 75d582db43ce9b13ab4b6f7f14341330
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 3a65e03af37b81d05acc7ec1bc39deb0
+Result = Fail
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = efc5721e0b9e4c3c90deab0e1d5c11bd
+Result = Fail
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 91b4b779823f4f0e3979ced93b99736c
+Result = Fail
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = e2e87ca82523ccfeb416b42af9d9aadc
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 7b85fd105cc960df86ad86846d178274
+Result = Fail
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = ffa140be27b25f307a6efd9697d66c9b
+Result = Fail
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ed356542e0a804a724bfaa422e98a970
+Result = Fail
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = e31dd8dc920fe7900e1b1817fe845c7d
+Result = Fail
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = ae5a0777f03bbf541f305d00acff0396
+Result = Fail
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 957dca58616c1cbe99f94fd8f7c257d9
+Result = Fail
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 0e150af422f6da238bb476810b2d5bc2
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 8e1150756ff3a733a1274470f072b74c
+Result = Pass
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = a1f70df3fa9cfeb95f869b3fe08466e0
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = fdf3f6c177aa1d71fe3474a5a2eb6bb1
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 90156f3f
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 88909016
+Result = Fail
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = de547d03
+Result = Fail
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = ea4bad52
+Result = Fail
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 1bc82b3d
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 92e72250
+Result = Fail
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = e81f0647
+Result = Fail
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7cb906ec
+Result = Fail
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = d60f815b
+Result = Fail
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d3d4f3b0
+Result = Fail
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = a9df97ad
+Result = Fail
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 36a37a59
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = dba02a36
+Result = Pass
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 25dcb3c5
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 1d2832d0
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fb04dc5a44c6bb000f2440f5154364b4
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 5447075bf42a59b91f08064738b015ab
+Result = Fail
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = fdc992847f0815fac67aa935b35208ed
+Result = Fail
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 2cabd690a45e59854b7587b26dd77f8e
+Result = Fail
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 3dacc71169f6da77ec91ff1d2f649ed1
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 97a2eb170ef03fa12124f1315e3b694f
+Result = Fail
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 94d85a83169d8dc76f58baf4d63ecfee
+Result = Fail
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = d3903c6289ca3684b8ce1174c23153a4
+Result = Fail
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 5cbac5c418374a68bd7085454c4b0c13
+Result = Fail
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = 26317f6b8b0130097441ed04b8009aef
+Result = Fail
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = b82ab6f3bbf59b6caafc54f05570f74e
+Result = Fail
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 1ae34207e74c8c78890ae17e320e84bd
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 5c5fa254c0be503b02caffade6b85259
+Result = Pass
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 9340266730ea36207bb734819d3553e9
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = ec17cccf33bd9a0d4ce7aa20690c1333
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = a90e8ea44085ced791b2fdb7fd44b5cf0bd7d27718029bb703e1fa6b
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 50aafe0578c115c4a8e126ff7b3ccb64dce8ccaa8ceda69f23e5d81c
+Result = Fail
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 512ed208bf10d57406537e94d20a5b6e2e9ab0683dfdc685869a97f0
+Result = Fail
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = af72db9cd9d6f46607d6f9542ca69988dd15255c5c91171c838e7f95
+Result = Fail
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 47d71409a03c330be9451b3f92c9d21c584391ad1010e9d609b89801
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = e562c7af0384ea16431ca20934a293a058d722cbfc3186c8eaf5f825
+Result = Fail
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = 004d9d89c401aa79919c2805fcd5de69316e191df56426c05ec1aa6a
+Result = Fail
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = d623673d7f6d57c208bde112ca858561f3af5cc2bf5de926f3586c6f
+Result = Fail
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = fd4733d158b5630f4f6c03ab26b11bff0cbe0d5d3df99a735fa40618
+Result = Fail
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = d352cb996c3075ff367a8dcacbbae46a12fbef08aa96ec835bf4f930
+Result = Fail
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 31730fac20e21eca0aef591faa9fa90b3c058e32af1ce48a66f0496e
+Result = Fail
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = dd175905a7ea3aef9fce068e6cb78e9cc60519755a178c77b753181c
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 8ad6b76f54392ee0f2834f09142545bcde9bf03d04d64aa10876f2da
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = 808eb3e04c39abde64674f0f7716dde11699cff8dd367c4cd4f7fc07
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e074d13aad43f7b2364d47db0a02326641ca3b2ad61a1c49973a2712
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 24ab9eeb0e5508cae80074f1070ee188a637171860881f1f2d9a3fbc210595b7b8b1b41523111a8e
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 7ebfda6fa5da1dbffd82dc29b875798fbcef8ba0084fbd2463af747cc88a001fa94e060290f209c4
+Result = Fail
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = cbf133643851f91ddc7a1e19a0c21990459f2b7728da58f5cf3b8e6c8aeb5eeb0a5efb3700be45a2
+Result = Fail
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0de7567a945c0af4a2291a651de411e8d0438508f2d4da80f7bd61a0158accbca28913e39fe80906
+Result = Fail
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = d43035cdb5a1868aa430e8b41a1dc57a639087238e38bd628feeda2e8f249dd93a8358def7639875
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 389547260b354a6cbc909de057d367677049e80613877f6fbf19f89da977e56f308373c616299ad4
+Result = Fail
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = a95aa33483ed3711470025394616bf98fe624fbca8aa6fbc21366b9da457ede2a673351475b53d41
+Result = Fail
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3d53b6ab8925f429ae14a0065cd203d4f9deddd402a79ac6d889a7cae55efd71b369cd6d43ef363b
+Result = Fail
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = d5e6e82cb5f8034a89e58adf8298476253f18981bcb3b0364be7f19463dd330a4b9f3cbb30b88fa5
+Result = Fail
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 02f69107d62ff77145c7d57684c70ba671d55f1c63bb2ad8c2df063f7fdbae27f0736a37fd065fb4
+Result = Fail
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 64ec2f321111da9c5389e8255bfe69876d4f548f94cacd529b45d54cc24cff1b1d8aa1df32fbd81a
+Result = Fail
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 37d63c2bbf44d2eb155ecc1a844841d5c33f1a6d443419330217a4f1f4fb302257b0de7c9da2e750
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 33e0dce4410e51bed5323ea49490207084ac91732bae429236a305d520a1a24930a70a311aa3695d
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 1d732c334319bd775e7cf93dbdc4204bbdb58192be08280481e3d64ed546b6b70ee088a693f55fbb
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = c92fc2f0d24593f67d9c09d326158a8138237c4096093f0d737719dd84ccfb397a4f61b70c85262a
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4a550134f94455979ec4bf89ad2bd80d25a77ae94e456134a3e138b9
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 118ec53dd1bfbe52d5b9fe5dfebecf2ee674ec983eada654091a5ae9
+Result = Fail
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 6b0fea26e4dfe902b5e876c7ba92afbad8aa52d3c1d00ae578b6bcc4
+Result = Fail
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 640c740e2b8af851712a05948ecee055b25b145ccb82ca58ac542b09
+Result = Fail
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 05f20b2ae70fcb0ea79aa1845c15b899a799ca60f51e6c296413020a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 9fa576a8a5c72468afa372338cbbc33fef81ad5a873eb38a142d5636
+Result = Fail
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = 8d26582c74b2b4d960ee9e417c6395daafaebb3aff45d477f3757b6a
+Result = Fail
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = cb62a13e38e17cc6635e409c922956ece38f593189a51b99a7001a16
+Result = Fail
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f3e29b792423c7fbe743a3b2f890a2bff29519f3636a6232050e9225
+Result = Fail
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 136e60d6714d906d1f4c02b7bdbb5f3ccdd2165306912dec850ec9f0
+Result = Fail
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 49b6d0b6eeff74af0de70072d9ccdc68a0ee36a5ddbf098b4eb95533
+Result = Fail
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = a2a59041c3f78f6e10c3045118e8a475945e24c85b02abc40f8fb949
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 19b4ad222795326cb031cfdb07b652dbf64ca5db5ff5d6d569d8ab41
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 76b66b908657f4df8a329c34ccdde50ae7fc71c4a718b712f00fe764
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 20df4662ce6c8c4ce49b14fa791e41ff8598ec93d8a825e879f9eb72
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4bfe4e35784f0a65b545477e5e2f4bae0e1e6fa717eaf2cb6a9a970b9beb2ac1bd4fd62168f8378a
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 0c56a503aa2c12e87450d45a7b714db980fd348f327c0065a65666144994bad0c8195bcb4ade1337
+Result = Fail
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 5f69d6c21f771eb98dc724f891f530b1c045f49a054de103a85f868739404b64a7cbdd61b577c388
+Result = Fail
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = d335ba572520c336f711edf27ea738ba5e6b0d772ea443b8b2b164f3c255b699cbf75330d96c3c13
+Result = Fail
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 9fa846ef8d198c538f84f856bab8f7f9c3bed90b53acb6a32658e077687315eaf11458bdf6e3c36a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = b7095030acdc5fbb8fea2c24717c1c236231f9737bcc78f463db3756abba1feef626a956794d7e56
+Result = Fail
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = d6911d5831163c8ebad0916af1833051b885aae822f9f6657d6fee1de626bc7c93f2caa27a3ecaa0
+Result = Fail
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 6b10a098c96c2bbf9aeb5c9adcf91e4812838dff319f8be989e2d235192f33ba0f357492112d98f4
+Result = Fail
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = aecd11cbac04e1f79b0fd24052c8cedf393dce9df350d24f800b81e834ea5dd2bdc2c688d9505359
+Result = Fail
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = d3a7a25f71b1988482dc852ed713d55abdcc4bb1129ddcae430889cd5c97343cc0dedfbd62e6b6eb
+Result = Fail
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 368e1574a433d78d0276ce4a1cacfba834a216693536c00b15acded53c41010554e1c1fe937a7605
+Result = Fail
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 99e40b3c67aca95dd4462c20cbd6b2741e7033fc4f41a975c9390fbdb9ec416267096ccbf2c148e5
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = de079418c25ba67e5fda009998e3fce61bfdc3b7787cf06655c18ae38b7ee7f00f96cfca4fe9a2ef
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = fbab64d8dd8b6e33c7cc6124cd65f004d7247277fe98d5d3b35357a35ff9e58e18d6d80df9fc335d
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 372b9af0655df2d0c830b4949a2d2faa8db251ee922a3bff9aba89639f4033be9ba9f3c101acc1bd
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 782e4318
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = a04f270a
+Result = Fail
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 97dfd257
+Result = Fail
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 6c202a1c
+Result = Fail
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 1be535a0
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 4fb6617d
+Result = Fail
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = c056bd3e
+Result = Fail
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 87048576
+Result = Fail
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = ea8c0407
+Result = Fail
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 41c12dc5
+Result = Fail
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = de84cf5c
+Result = Fail
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = e617e006
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = b7909395
+Result = Pass
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 8a05d2ea
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 8643ba47
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 41b476013f45e4a781f253a6f3b1e530
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = f9f018fcd125822616083fffebc4c8e6
+Result = Fail
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 534cc67c44c877c9c908071ee1082f4c
+Result = Fail
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 201c0ef2ddaa51b645911b5c37d76e95
+Result = Fail
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = ec774d9000763bba3a5ac307418827b2
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 75798c3fe5202f0e33c9183c837aeaf5
+Result = Fail
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 32601de5960c11c925444b5c47d42289
+Result = Fail
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 4c1cd6a774c8e6f4e261db1f73b0aa20
+Result = Fail
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 8bd9c00ff23310216bbd24981c1e2cf7
+Result = Fail
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 174efd089409f9932b8e631965e762a6
+Result = Fail
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 8de80f620bd41eee6a58925dc8404bfa
+Result = Fail
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 0b9d79e8e33ec45532af5515a99f05df
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 1583e1e5a86001bbcec62292ccfd4d48
+Result = Pass
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = b72caac6362e68e445f69f605f21e0a2
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 352769a19ac75b8a116be031b33d6449
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 9f69f24f
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = e17afaa4
+Result = Fail
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 07155b7e
+Result = Fail
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = d538cf2f
+Result = Fail
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = c283466f
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = aa8d8098
+Result = Fail
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = a44b69b0
+Result = Fail
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = f395733f
+Result = Fail
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 1e9e9237
+Result = Fail
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = e9d2a722
+Result = Fail
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = a90fc438
+Result = Fail
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = 48f3a1ec
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 24763def
+Result = Pass
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 63394bee
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = d79b1686
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 1859ac36a40a6b28b34266253627797a
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = edf8b46eb69ac0044116019dec183072
+Result = Fail
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 66622ac26c7227a0329739612012737c
+Result = Fail
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = e4c9e86493ee78b1cbf6e55e94731b63
+Result = Fail
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = 8b5bfe6b5b5552007300bae71172612f
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1848be3cb7665ac68874c617a75d8bd2
+Result = Fail
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 65a23b7b5ee78af9c7d0113447f78ab9
+Result = Fail
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 90a420b6d2252392e161dcf4fb953d7e
+Result = Fail
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 004cbe11292887e246de7704a4a1a05f
+Result = Fail
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = ad7af41e39ea0c0cd072263e826f3cf0
+Result = Fail
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 16b1a4fadbadc906a949592d6ef319a3
+Result = Fail
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = e9cfb1069380434f221db4229a083a76
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 380cb57fd531bb1dcf22350518bbf8af
+Result = Pass
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = fbf2becc35b5024078bfcfc1f831b669
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 080203eb842b3f98a730abbbf98f493e
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6be31860ca271ef448de8f8d8b39346daf4b81d7e92d65b338f125fa
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4cc57a9927a6bc401441870d3193bf89ebd163f5c01501c728a66b69
+Result = Fail
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 1f16c6d370fff40c011a243356076b67e905d4672ae2f38fee2de18c
+Result = Fail
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 46edb001d58a01dce1bcf064cfc9a04accc82c42b33ba16524537a81
+Result = Fail
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 9b61335f96fc5b31274cc1fb275f29c1105d68c67b70654f9405edb1
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 97b5eb2d55847f5d5d9f8c762dace481d8efb19ccfd72265548effe3
+Result = Fail
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = f5cc8198dce8e890587b62572b07413a915bfb55628c901c03459b29
+Result = Fail
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 50c0b1f6c5e4c86a0c938ecbc762eeaf99b9fe04c2820a43963b04f3
+Result = Fail
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 1fdbe91189da01c5098cf1538addd85b1cfef0abd0797c141330f633
+Result = Fail
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = 462e7cdf9a6a553bca37d4d93bed4986b715d0349238613e10c1f6d7
+Result = Fail
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 7d142f26aa6c9d55850c5c9f58ab36a66670d47c515bf93cd37e5543
+Result = Fail
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = f7122cbcec93d53fc7e3fc629ea15d28363cad1c83a23bb3cc5e0c4a
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = e1cad7f946b20c373323218c8a89e56edf3030662e50d459fc12a512
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = d4741814466a23e26107d773f103a4c83db9d772dbd5fdc1c2eaf895
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = ed35ff66bc7f6d8ec7acf896f994d79f5792cf6d22d6691ff92fa2f7
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = b351ab96b2e45515254558d5212673ee6c776d42dbca3b512cf3a20b7fd7c49e6e79bef475c2906f
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = df1a5285caa41b4bb47f6e5ceceba4e82721828d68427a3081d18ca149d6766bfaccec88f194eb5b
+Result = Fail
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 04a29fc109dfc626e8297e0f586d0bfaf31260017d95f62d5eb4f0875dda5ccd9b94026ba49fb34e
+Result = Fail
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 77e4cd5d319353ecb6b89e2de14bcfee4fbf738b61df14f3920843994def41aed3103995d3392eed
+Result = Fail
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = e676f5dfde8ad810d9e729d142670eef77f2878369a28797d57603d5c45606c68be5535c671d5432
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 60c51e5c3fe4197454d64fa14017639bcfd1423b9d74e506a0bfd54fb786208e1e49c6d0e645d9fb
+Result = Fail
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 64d1160365062eca1027cc7036862b027bdda3a9abdf794daf8a9b7a5c50b0be4596290a4d405e79
+Result = Fail
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 968ca115583c645710d2b47fb196cf55f6ef33f2b01400e22ce9c776932ecf7fddd849be58096b88
+Result = Fail
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 4985821b16ff6d4d3416573e2fba4d53186d912f0b023a99915d0020da92f483a5a7914cba14b1e7
+Result = Fail
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = c7345b031ef85bde766226a7603adaa7dcb07a7b2a8be1b571420e036ea48dddd671be622d372c5b
+Result = Fail
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 11460b9acccc13001be236814da6b73f2c8e0467574f151bb619a331f8d67d70c3f3a59b3fab53a5
+Result = Fail
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 1bcff940a2d9d48e93bbfd13aed5947237485983e6ae04b8b944bb46306a9b1e783f3e54c92d5f5e
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = 3b6c1570c85f297079be14cd66d335251c7b52e131a636f148608963f3037763843b70c35d7011f8
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = b540cd8cbe733e0ca2ba2112ea785596d2c1d707f41608514ba2d0944c68cc36d4125b3ef9071d69
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 3c9c1481f1428acf202b510dca67e5e6b2abc5dd71a954da51387922af7182b7d46a33c703e6e7a8
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 934f893824e880f743d196b22d1f340a52608155087bd28ac25e5329
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = f43ba9d834ad85dfab3f1c0c27c3441fe4e411a38a261a6559b3b3ee
+Result = Fail
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = c686eac859a7bae3cce97d0b6527a0a7c8c2b24ece35f4370bf6688e
+Result = Fail
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 2b28355ecf7246ddb08d65c464dcaa90af85f434ff95267280ed869c
+Result = Fail
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = ecde42091baa1f5c17b79746e21c3de5c78984570748021ccd399507
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 5c338435ed4f148342604c9aed63e907c100453d719fda2a3da37b66
+Result = Fail
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 30eac1042015eb82729673edd9939bf9995b2575da4d6c4c7e75dded
+Result = Fail
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = ebd3ce55b40e4bbd8172033948c6c78049161ee8f949eb50722b9c87
+Result = Fail
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 20f79b36ca83baac97600fd8a6dad22c2cd0f9b7e770576048c042e5
+Result = Fail
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 77b76f249f936fb19bd47fe28ad4dbb7725dec365a1cb23a885ba975
+Result = Fail
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = cf6763a23c2eab730845d1eb79bbba9f54ee899fe3d70570aa799e79
+Result = Fail
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 1f8086a43c1b2dea557952db88e0dbbdb96aafdb345eddae6c0b0104
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = c0c5f92285b114e0a0777e1bc22b810e7cc4f68c28cd5ce047a28dd8
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 56327f4db9c18f72bbefc3f316d31f9795dd77f493385ab7b7543552
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 37d5b17995fac8c94302ec9ba20a36d97678e85199b677f8ee39867e
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0e
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 50038b5fdd364ee747b70d00bd36840ece4ea19998123375c0a458bfcafa3b2609afe0f825cbf503
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = 78ed8ff6b5a1255d0fbd0a719a9c27b059ff5f83d0c4962c390042ba8bb5f6798dab01c5afad7306
+Result = Fail
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 4b91d8e616d3f60452fd3a576bd7c265b7f549523ed4a5d7a3463394cf3c25bef8af8f244d0c0b00
+Result = Fail
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = ab8cf8891ab62924c0c6f49dd253cfa0c3d6260d0ee4d9ba88caf8ae59d9d1131626da0dddf8722d
+Result = Fail
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = c6b7680f321132a8bd00e8e92f785d0b828b100af6392a04d1292373a76970eda77a8194f6276262
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = aea98867d3d707c43a963c1d7fdcfc953cbd707803b2b5f0a97af19d0b7bf7c7ce398cb0b44d73af
+Result = Fail
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = c55e17ba7886eb58126d50bde8c5c211cc1aafd71a3d9e5b343065b4bdd973ee072dbf5160d310f3
+Result = Fail
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 791a62d5fb39ff9735ad94507e1afe2647714d5cc56b6ff4233ec600bca1d31f704807494fb0f18d
+Result = Fail
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = f98a081998e29500f15ebd8978a95423aed4e8e78e0279d17ec183db0e2a33ebb147d0e2363fbb01
+Result = Fail
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 7779814dc295a23b4100ca94bec0ad4ce2f6be6fb75a0c217e67ea2577ade5836c26a89760e0959b
+Result = Fail
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 55640eed12c7595a36ab423da8d8241905b6ff1e906db9624978a7865df8369635269411b3aaeb32
+Result = Fail
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 7fcdce0ba567b9a708d54fdb16125de71dce952f4741684f4f9d302e4f1d2a2aedf2768d7b29163f
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = d42111ba22987eac1ead5cc6cb8548bcda190d118dcd5461a50036af67fadab163e9daa8bd8e9030
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d2f1322ac69b848b001476323aed84c47
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 9d993b945476ace0b9ca932963ac8835e1bd02e8065da2d816786c4d8cf14c03b031ff723311b3c4
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt
new file mode 100644
index 0000000000..1606dcb21e
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 4ae701103c63deca5b5a3939d7d05992
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 02209f55
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 9a04c241
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = f5f915df
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 7a3c3499
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = f09c2986
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 4ae97e71
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = ecb38c8b
+Result = Fail (1 - Adata changed)
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 9c4dc530
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 67299ef6
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = b0538d02
+Result = Fail (1 - Adata changed)
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 88200ea8
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 19867aa5
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 3b392a52
+Result = Pass (0)
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 1c5e47e0
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 97a56b8b
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 75d582db43ce9b13ab4b6f7f14341330
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 3a65e03af37b81d05acc7ec1bc39deb0
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = efc5721e0b9e4c3c90deab0e1d5c11bd
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 91b4b779823f4f0e3979ced93b99736c
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = e2e87ca82523ccfeb416b42af9d9aadc
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 7b85fd105cc960df86ad86846d178274
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = ffa140be27b25f307a6efd9697d66c9b
+Result = Fail (1 - Adata changed)
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ed356542e0a804a724bfaa422e98a970
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = e31dd8dc920fe7900e1b1817fe845c7d
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = ae5a0777f03bbf541f305d00acff0396
+Result = Fail (1 - Adata changed)
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 957dca58616c1cbe99f94fd8f7c257d9
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 0e150af422f6da238bb476810b2d5bc2
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 8e1150756ff3a733a1274470f072b74c
+Result = Pass (0)
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = a1f70df3fa9cfeb95f869b3fe08466e0
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = fdf3f6c177aa1d71fe3474a5a2eb6bb1
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 90156f3f
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 88909016
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = de547d03
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = ea4bad52
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 1bc82b3d
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 92e72250
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = e81f0647
+Result = Fail (1 - Adata changed)
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7cb906ec
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = d60f815b
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d3d4f3b0
+Result = Fail (1 - Adata changed)
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = a9df97ad
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 36a37a59
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = dba02a36
+Result = Pass (0)
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 25dcb3c5
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 1d2832d0
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fb04dc5a44c6bb000f2440f5154364b4
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 5447075bf42a59b91f08064738b015ab
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = fdc992847f0815fac67aa935b35208ed
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 2cabd690a45e59854b7587b26dd77f8e
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 3dacc71169f6da77ec91ff1d2f649ed1
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 97a2eb170ef03fa12124f1315e3b694f
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 94d85a83169d8dc76f58baf4d63ecfee
+Result = Fail (1 - Adata changed)
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = d3903c6289ca3684b8ce1174c23153a4
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 5cbac5c418374a68bd7085454c4b0c13
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = 26317f6b8b0130097441ed04b8009aef
+Result = Fail (1 - Adata changed)
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = b82ab6f3bbf59b6caafc54f05570f74e
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 1ae34207e74c8c78890ae17e320e84bd
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 5c5fa254c0be503b02caffade6b85259
+Result = Pass (0)
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 9340266730ea36207bb734819d3553e9
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = ec17cccf33bd9a0d4ce7aa20690c1333
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = a90e8ea44085ced791b2fdb7fd44b5cf0bd7d27718029bb703e1fa6b
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 50aafe0578c115c4a8e126ff7b3ccb64dce8ccaa8ceda69f23e5d81c
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 512ed208bf10d57406537e94d20a5b6e2e9ab0683dfdc685869a97f0
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = af72db9cd9d6f46607d6f9542ca69988dd15255c5c91171c838e7f95
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 47d71409a03c330be9451b3f92c9d21c584391ad1010e9d609b89801
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = e562c7af0384ea16431ca20934a293a058d722cbfc3186c8eaf5f825
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = 004d9d89c401aa79919c2805fcd5de69316e191df56426c05ec1aa6a
+Result = Fail (1 - Adata changed)
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = d623673d7f6d57c208bde112ca858561f3af5cc2bf5de926f3586c6f
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = fd4733d158b5630f4f6c03ab26b11bff0cbe0d5d3df99a735fa40618
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = d352cb996c3075ff367a8dcacbbae46a12fbef08aa96ec835bf4f930
+Result = Fail (1 - Adata changed)
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 31730fac20e21eca0aef591faa9fa90b3c058e32af1ce48a66f0496e
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = dd175905a7ea3aef9fce068e6cb78e9cc60519755a178c77b753181c
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 8ad6b76f54392ee0f2834f09142545bcde9bf03d04d64aa10876f2da
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = 808eb3e04c39abde64674f0f7716dde11699cff8dd367c4cd4f7fc07
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e074d13aad43f7b2364d47db0a02326641ca3b2ad61a1c49973a2712
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 24ab9eeb0e5508cae80074f1070ee188a637171860881f1f2d9a3fbc210595b7b8b1b41523111a8e
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 7ebfda6fa5da1dbffd82dc29b875798fbcef8ba0084fbd2463af747cc88a001fa94e060290f209c4
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = cbf133643851f91ddc7a1e19a0c21990459f2b7728da58f5cf3b8e6c8aeb5eeb0a5efb3700be45a2
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0de7567a945c0af4a2291a651de411e8d0438508f2d4da80f7bd61a0158accbca28913e39fe80906
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = d43035cdb5a1868aa430e8b41a1dc57a639087238e38bd628feeda2e8f249dd93a8358def7639875
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 389547260b354a6cbc909de057d367677049e80613877f6fbf19f89da977e56f308373c616299ad4
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = a95aa33483ed3711470025394616bf98fe624fbca8aa6fbc21366b9da457ede2a673351475b53d41
+Result = Fail (1 - Adata changed)
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3d53b6ab8925f429ae14a0065cd203d4f9deddd402a79ac6d889a7cae55efd71b369cd6d43ef363b
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = d5e6e82cb5f8034a89e58adf8298476253f18981bcb3b0364be7f19463dd330a4b9f3cbb30b88fa5
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 02f69107d62ff77145c7d57684c70ba671d55f1c63bb2ad8c2df063f7fdbae27f0736a37fd065fb4
+Result = Fail (1 - Adata changed)
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 64ec2f321111da9c5389e8255bfe69876d4f548f94cacd529b45d54cc24cff1b1d8aa1df32fbd81a
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 37d63c2bbf44d2eb155ecc1a844841d5c33f1a6d443419330217a4f1f4fb302257b0de7c9da2e750
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 33e0dce4410e51bed5323ea49490207084ac91732bae429236a305d520a1a24930a70a311aa3695d
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 1d732c334319bd775e7cf93dbdc4204bbdb58192be08280481e3d64ed546b6b70ee088a693f55fbb
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = c92fc2f0d24593f67d9c09d326158a8138237c4096093f0d737719dd84ccfb397a4f61b70c85262a
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4a550134f94455979ec4bf89ad2bd80d25a77ae94e456134a3e138b9
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 118ec53dd1bfbe52d5b9fe5dfebecf2ee674ec983eada654091a5ae9
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 6b0fea26e4dfe902b5e876c7ba92afbad8aa52d3c1d00ae578b6bcc4
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 640c740e2b8af851712a05948ecee055b25b145ccb82ca58ac542b09
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 05f20b2ae70fcb0ea79aa1845c15b899a799ca60f51e6c296413020a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 9fa576a8a5c72468afa372338cbbc33fef81ad5a873eb38a142d5636
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = 8d26582c74b2b4d960ee9e417c6395daafaebb3aff45d477f3757b6a
+Result = Fail (1 - Adata changed)
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = cb62a13e38e17cc6635e409c922956ece38f593189a51b99a7001a16
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f3e29b792423c7fbe743a3b2f890a2bff29519f3636a6232050e9225
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 136e60d6714d906d1f4c02b7bdbb5f3ccdd2165306912dec850ec9f0
+Result = Fail (1 - Adata changed)
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 49b6d0b6eeff74af0de70072d9ccdc68a0ee36a5ddbf098b4eb95533
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = a2a59041c3f78f6e10c3045118e8a475945e24c85b02abc40f8fb949
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 19b4ad222795326cb031cfdb07b652dbf64ca5db5ff5d6d569d8ab41
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 76b66b908657f4df8a329c34ccdde50ae7fc71c4a718b712f00fe764
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 20df4662ce6c8c4ce49b14fa791e41ff8598ec93d8a825e879f9eb72
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4bfe4e35784f0a65b545477e5e2f4bae0e1e6fa717eaf2cb6a9a970b9beb2ac1bd4fd62168f8378a
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 0c56a503aa2c12e87450d45a7b714db980fd348f327c0065a65666144994bad0c8195bcb4ade1337
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 5f69d6c21f771eb98dc724f891f530b1c045f49a054de103a85f868739404b64a7cbdd61b577c388
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = d335ba572520c336f711edf27ea738ba5e6b0d772ea443b8b2b164f3c255b699cbf75330d96c3c13
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 9fa846ef8d198c538f84f856bab8f7f9c3bed90b53acb6a32658e077687315eaf11458bdf6e3c36a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = b7095030acdc5fbb8fea2c24717c1c236231f9737bcc78f463db3756abba1feef626a956794d7e56
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = d6911d5831163c8ebad0916af1833051b885aae822f9f6657d6fee1de626bc7c93f2caa27a3ecaa0
+Result = Fail (1 - Adata changed)
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 6b10a098c96c2bbf9aeb5c9adcf91e4812838dff319f8be989e2d235192f33ba0f357492112d98f4
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = aecd11cbac04e1f79b0fd24052c8cedf393dce9df350d24f800b81e834ea5dd2bdc2c688d9505359
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = d3a7a25f71b1988482dc852ed713d55abdcc4bb1129ddcae430889cd5c97343cc0dedfbd62e6b6eb
+Result = Fail (1 - Adata changed)
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 368e1574a433d78d0276ce4a1cacfba834a216693536c00b15acded53c41010554e1c1fe937a7605
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 99e40b3c67aca95dd4462c20cbd6b2741e7033fc4f41a975c9390fbdb9ec416267096ccbf2c148e5
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = de079418c25ba67e5fda009998e3fce61bfdc3b7787cf06655c18ae38b7ee7f00f96cfca4fe9a2ef
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = fbab64d8dd8b6e33c7cc6124cd65f004d7247277fe98d5d3b35357a35ff9e58e18d6d80df9fc335d
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 372b9af0655df2d0c830b4949a2d2faa8db251ee922a3bff9aba89639f4033be9ba9f3c101acc1bd
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 782e4318
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = a04f270a
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 97dfd257
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 6c202a1c
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 1be535a0
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 4fb6617d
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = c056bd3e
+Result = Fail (1 - Adata changed)
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 87048576
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = ea8c0407
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 41c12dc5
+Result = Fail (1 - Adata changed)
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = de84cf5c
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = e617e006
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = b7909395
+Result = Pass (0)
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 8a05d2ea
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 8643ba47
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 41b476013f45e4a781f253a6f3b1e530
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = f9f018fcd125822616083fffebc4c8e6
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 534cc67c44c877c9c908071ee1082f4c
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 201c0ef2ddaa51b645911b5c37d76e95
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = ec774d9000763bba3a5ac307418827b2
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 75798c3fe5202f0e33c9183c837aeaf5
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 32601de5960c11c925444b5c47d42289
+Result = Fail (1 - Adata changed)
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 4c1cd6a774c8e6f4e261db1f73b0aa20
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 8bd9c00ff23310216bbd24981c1e2cf7
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 174efd089409f9932b8e631965e762a6
+Result = Fail (1 - Adata changed)
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 8de80f620bd41eee6a58925dc8404bfa
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 0b9d79e8e33ec45532af5515a99f05df
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 1583e1e5a86001bbcec62292ccfd4d48
+Result = Pass (0)
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = b72caac6362e68e445f69f605f21e0a2
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 352769a19ac75b8a116be031b33d6449
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 9f69f24f
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = e17afaa4
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 07155b7e
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = d538cf2f
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = c283466f
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = aa8d8098
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = a44b69b0
+Result = Fail (1 - Adata changed)
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = f395733f
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 1e9e9237
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = e9d2a722
+Result = Fail (1 - Adata changed)
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = a90fc438
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = 48f3a1ec
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 24763def
+Result = Pass (0)
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 63394bee
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = d79b1686
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 1859ac36a40a6b28b34266253627797a
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = edf8b46eb69ac0044116019dec183072
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 66622ac26c7227a0329739612012737c
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = e4c9e86493ee78b1cbf6e55e94731b63
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = 8b5bfe6b5b5552007300bae71172612f
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1848be3cb7665ac68874c617a75d8bd2
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 65a23b7b5ee78af9c7d0113447f78ab9
+Result = Fail (1 - Adata changed)
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 90a420b6d2252392e161dcf4fb953d7e
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 004cbe11292887e246de7704a4a1a05f
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = ad7af41e39ea0c0cd072263e826f3cf0
+Result = Fail (1 - Adata changed)
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 16b1a4fadbadc906a949592d6ef319a3
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = e9cfb1069380434f221db4229a083a76
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 380cb57fd531bb1dcf22350518bbf8af
+Result = Pass (0)
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = fbf2becc35b5024078bfcfc1f831b669
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 080203eb842b3f98a730abbbf98f493e
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6be31860ca271ef448de8f8d8b39346daf4b81d7e92d65b338f125fa
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4cc57a9927a6bc401441870d3193bf89ebd163f5c01501c728a66b69
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 1f16c6d370fff40c011a243356076b67e905d4672ae2f38fee2de18c
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 46edb001d58a01dce1bcf064cfc9a04accc82c42b33ba16524537a81
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 9b61335f96fc5b31274cc1fb275f29c1105d68c67b70654f9405edb1
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 97b5eb2d55847f5d5d9f8c762dace481d8efb19ccfd72265548effe3
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = f5cc8198dce8e890587b62572b07413a915bfb55628c901c03459b29
+Result = Fail (1 - Adata changed)
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 50c0b1f6c5e4c86a0c938ecbc762eeaf99b9fe04c2820a43963b04f3
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 1fdbe91189da01c5098cf1538addd85b1cfef0abd0797c141330f633
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = 462e7cdf9a6a553bca37d4d93bed4986b715d0349238613e10c1f6d7
+Result = Fail (1 - Adata changed)
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 7d142f26aa6c9d55850c5c9f58ab36a66670d47c515bf93cd37e5543
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = f7122cbcec93d53fc7e3fc629ea15d28363cad1c83a23bb3cc5e0c4a
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = e1cad7f946b20c373323218c8a89e56edf3030662e50d459fc12a512
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = d4741814466a23e26107d773f103a4c83db9d772dbd5fdc1c2eaf895
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = ed35ff66bc7f6d8ec7acf896f994d79f5792cf6d22d6691ff92fa2f7
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = b351ab96b2e45515254558d5212673ee6c776d42dbca3b512cf3a20b7fd7c49e6e79bef475c2906f
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = df1a5285caa41b4bb47f6e5ceceba4e82721828d68427a3081d18ca149d6766bfaccec88f194eb5b
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 04a29fc109dfc626e8297e0f586d0bfaf31260017d95f62d5eb4f0875dda5ccd9b94026ba49fb34e
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 77e4cd5d319353ecb6b89e2de14bcfee4fbf738b61df14f3920843994def41aed3103995d3392eed
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = e676f5dfde8ad810d9e729d142670eef77f2878369a28797d57603d5c45606c68be5535c671d5432
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 60c51e5c3fe4197454d64fa14017639bcfd1423b9d74e506a0bfd54fb786208e1e49c6d0e645d9fb
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 64d1160365062eca1027cc7036862b027bdda3a9abdf794daf8a9b7a5c50b0be4596290a4d405e79
+Result = Fail (1 - Adata changed)
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 968ca115583c645710d2b47fb196cf55f6ef33f2b01400e22ce9c776932ecf7fddd849be58096b88
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 4985821b16ff6d4d3416573e2fba4d53186d912f0b023a99915d0020da92f483a5a7914cba14b1e7
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = c7345b031ef85bde766226a7603adaa7dcb07a7b2a8be1b571420e036ea48dddd671be622d372c5b
+Result = Fail (1 - Adata changed)
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 11460b9acccc13001be236814da6b73f2c8e0467574f151bb619a331f8d67d70c3f3a59b3fab53a5
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 1bcff940a2d9d48e93bbfd13aed5947237485983e6ae04b8b944bb46306a9b1e783f3e54c92d5f5e
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = 3b6c1570c85f297079be14cd66d335251c7b52e131a636f148608963f3037763843b70c35d7011f8
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = b540cd8cbe733e0ca2ba2112ea785596d2c1d707f41608514ba2d0944c68cc36d4125b3ef9071d69
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 3c9c1481f1428acf202b510dca67e5e6b2abc5dd71a954da51387922af7182b7d46a33c703e6e7a8
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 934f893824e880f743d196b22d1f340a52608155087bd28ac25e5329
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = f43ba9d834ad85dfab3f1c0c27c3441fe4e411a38a261a6559b3b3ee
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = c686eac859a7bae3cce97d0b6527a0a7c8c2b24ece35f4370bf6688e
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 2b28355ecf7246ddb08d65c464dcaa90af85f434ff95267280ed869c
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = ecde42091baa1f5c17b79746e21c3de5c78984570748021ccd399507
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 5c338435ed4f148342604c9aed63e907c100453d719fda2a3da37b66
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 30eac1042015eb82729673edd9939bf9995b2575da4d6c4c7e75dded
+Result = Fail (1 - Adata changed)
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = ebd3ce55b40e4bbd8172033948c6c78049161ee8f949eb50722b9c87
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 20f79b36ca83baac97600fd8a6dad22c2cd0f9b7e770576048c042e5
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 77b76f249f936fb19bd47fe28ad4dbb7725dec365a1cb23a885ba975
+Result = Fail (1 - Adata changed)
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = cf6763a23c2eab730845d1eb79bbba9f54ee899fe3d70570aa799e79
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 1f8086a43c1b2dea557952db88e0dbbdb96aafdb345eddae6c0b0104
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = c0c5f92285b114e0a0777e1bc22b810e7cc4f68c28cd5ce047a28dd8
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 56327f4db9c18f72bbefc3f316d31f9795dd77f493385ab7b7543552
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 37d5b17995fac8c94302ec9ba20a36d97678e85199b677f8ee39867e
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0e
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 50038b5fdd364ee747b70d00bd36840ece4ea19998123375c0a458bfcafa3b2609afe0f825cbf503
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = 78ed8ff6b5a1255d0fbd0a719a9c27b059ff5f83d0c4962c390042ba8bb5f6798dab01c5afad7306
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 4b91d8e616d3f60452fd3a576bd7c265b7f549523ed4a5d7a3463394cf3c25bef8af8f244d0c0b00
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = ab8cf8891ab62924c0c6f49dd253cfa0c3d6260d0ee4d9ba88caf8ae59d9d1131626da0dddf8722d
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = c6b7680f321132a8bd00e8e92f785d0b828b100af6392a04d1292373a76970eda77a8194f6276262
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = aea98867d3d707c43a963c1d7fdcfc953cbd707803b2b5f0a97af19d0b7bf7c7ce398cb0b44d73af
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = c55e17ba7886eb58126d50bde8c5c211cc1aafd71a3d9e5b343065b4bdd973ee072dbf5160d310f3
+Result = Fail (1 - Adata changed)
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 791a62d5fb39ff9735ad94507e1afe2647714d5cc56b6ff4233ec600bca1d31f704807494fb0f18d
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = f98a081998e29500f15ebd8978a95423aed4e8e78e0279d17ec183db0e2a33ebb147d0e2363fbb01
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 7779814dc295a23b4100ca94bec0ad4ce2f6be6fb75a0c217e67ea2577ade5836c26a89760e0959b
+Result = Fail (1 - Adata changed)
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 55640eed12c7595a36ab423da8d8241905b6ff1e906db9624978a7865df8369635269411b3aaeb32
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 7fcdce0ba567b9a708d54fdb16125de71dce952f4741684f4f9d302e4f1d2a2aedf2768d7b29163f
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = d42111ba22987eac1ead5cc6cb8548bcda190d118dcd5461a50036af67fadab163e9daa8bd8e9030
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d2f1322ac69b848b001476323aed84c47
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 9d993b945476ace0b9ca932963ac8835e1bd02e8065da2d816786c4d8cf14c03b031ff723311b3c4
+Result = Fail (2 - CT changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp
new file mode 100644
index 0000000000..e0978a99ac
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = c98ad7f38b2c7e970c9b965ec87a08208384718f78206c6c
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 9d4b7f3b
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 80745de9
+Result = Fail
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 2f6fa823
+Result = Fail
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 3cc132c6
+Result = Fail
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = c79d5557
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 41e0eea0
+Result = Fail
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = 1f129266
+Result = Fail
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 41b0e4e2
+Result = Fail
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 5082e06a
+Result = Fail
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = 70587cce
+Result = Fail
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6aaa0acd
+Result = Fail
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 22976e42
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = f440ea1d
+Result = Pass
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 88903fb9
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 3ff345c3
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 17223038fa99d53681ca1beabe78d1b4
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = d0e1eeef4d2a264536bb1c2c1bde7c35
+Result = Fail
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 81d587f8673fd514c23172af7fb7523d
+Result = Fail
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 500142447e535207899ab1499994daea
+Result = Fail
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = fdfdbb38bf161785114f9ee2018e892f
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 38fe9622eaa2a50152cf57e393dd3063
+Result = Fail
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = 73af4b87c167572e1400a0ee28209aff
+Result = Fail
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ace2248b9f23efa813449c82217e4a4a
+Result = Fail
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = a9bb0e469829d9cf09ad765c5b0b58bf
+Result = Fail
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = a5977f0826926ec0d32541b2bd4e2b1e
+Result = Fail
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6938fb5afec1a84e4abb062e1a943c20
+Result = Fail
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 7e3bbe0eb13988a93972f2fbcd35659e
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 48d7a15cf4f5808eb45d1ad817470554
+Result = Pass
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 97185ce68af1e6ab718c8c4b83ec04cd
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = a81bc8f5a18293ffe19505a3687ce3f3
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fe69ed84
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = db7ffc82
+Result = Fail
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 7a677329
+Result = Fail
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = d903d8f7
+Result = Fail
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 215e0bf2
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 0d38100f
+Result = Fail
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 9f8ab5f7
+Result = Fail
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7d811d50
+Result = Fail
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = c2e18439
+Result = Fail
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d8b5817b
+Result = Fail
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 28cd70ff
+Result = Fail
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 790b2624
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 9e46632d
+Result = Pass
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 39b82901
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 4c0cf71f
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 0c66a8e547ed4f8c2c9a9a1eb5d455b9
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 38757b3a61a4dc97ca3ab88bf1240695
+Result = Fail
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 11875da4445d92391d0fab5f3625497b
+Result = Fail
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 64477bcd4316e5c5789e1a678fdef943
+Result = Fail
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 87da5dbc04e39fc468f43675d4e7df33
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = bf0d53ee529d8cafc5ad7a8f2d85e7a2
+Result = Fail
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 676370637ad78c705d43fce066dc909f
+Result = Fail
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 289936db0f9f148a3c9e2d28f7d7de51
+Result = Fail
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 58a283641627669d5514f2af559b6c14
+Result = Fail
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = a6b058540ed905d6e3499a13ea1f3d83
+Result = Fail
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 7a19b3377384f09915d0e1ae93a9f16c
+Result = Fail
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = a0d047a1f9940d325e474da54aa13897
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 8a4768a2093694b6bcb7083c0bb6331c
+Result = Pass
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = a7cafd6f68dc1f15a3603da654ce27bc
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = c49845f2ea3c9981ad7e9b942f615b8d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 411986d04d6463100bff03f7d0bde7ea2c3488784378138cddc93a54
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 32b649ab56162e55d4148a1292d6a225a988eb1308298273b6889036
+Result = Fail
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = a963c3568ab413b174cd95cc1e3ca61ee181292bebdb28179b4de35f
+Result = Fail
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0396e6c8db43e5fac205f4c576fd577368adcb688cf3d7e76df9ffc5
+Result = Fail
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = b41bfba94edcafc41b4c144269b9126a6d47b19e83b15772b28c8e38
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 01e3bb938e16d0284d1d0fee049d80fb97356ae4d84127cf7336a30a
+Result = Fail
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = abd7551c5e84e9bef5fbfad3e24d13f02864410eae9177ad0c40cc72
+Result = Fail
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3b5ae49e0974f41826152432b46f1a85ab4995afefbbccddfc9fd290
+Result = Fail
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = 21fb4324de4ba1e2762b3041ce26e43a3d191458a046d489e485910b
+Result = Fail
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 99ca8f542fd06481e23719214c9892442f393d72899deea08695053f
+Result = Fail
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 5fcc05342cdc27f66b324ae7387205bfb4ab6302bfe0af09050d2054
+Result = Fail
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 0a7fe63046daf8a979935b897088c64acc1b47a5a9b86fdd6def28ab
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = daf7d7dfa512ceb1d7d3435634d9a70b3ef6c6dc38f409e068941fce
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = cdb417dff6502208775f21e35cdb8e3e1199308d1a94229051a1ec4a
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e75441093c8ccba6eac5913dc246ce96de4784a01051498298eaddaf
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = cba4b4aeb85f0492fd8d905c4a6d8233139833373ef188a8c5a5ebecf7ac8607fe412189e83d9d20
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = ca62713728b5c9d652504b0ae8fd4fee5d297ee6a8d19cb6e699f15f14d34dcaf9ba8ed4b877c97d
+Result = Fail
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 93012c0a5f6f1025b8c4a5d897d3eea0b1c77be8000c9e59f3b8899459788c58794f177cfd838f35
+Result = Fail
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = b8eb95f72f643c2c51ad74775cc203d215c86626e903eb013ad22e8fa4d2f9725ce4f212a8844855
+Result = Fail
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 71f17cf21c44267c676657db9e55bee33273787474e77b17b5eab45d7d096577643815e6d467312d
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = d6737f642260c4ee3b19cb78cc2ef1767213416b82c71e918b1a5ecca7354af824fea617b9b69031
+Result = Fail
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = cbe60d633399daa6ee66418be6d16e292ea47a93c291fce2c54c98f8007ed55a21759f5452559538
+Result = Fail
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 2a78a7beb8df4bf5d35ff0b2853bc51ce127163d2f56e00ea555aa972e1c2e3f439f85663ae25889
+Result = Fail
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = ee78ddbea9c3aede9f88af0e82464d9d1afe81de16aa18c49aeb326578fa615e86969348d9bbfb7f
+Result = Fail
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = cdf7cb74d978e7ea738e288ed79edfccf10b553c09d1856e2efbff1da769af3b72099cbda3cbf091
+Result = Fail
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 90b990a1ea254592f2c226c969b332fc7bfe5f808729c2d83291a566e6641a965ffdabe097050dc5
+Result = Fail
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 44a6aa954c3508b3c9264c20c272e80c0e95d50ddec2849084b47504dced5b70c302cc93502cc37e
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 9d4ff7a44cdb9b14f586efc3d6be02d069b425c06bec4eed37109739a3676f03adfd740dbaa4940d
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 23da95e102c7921a51b19b5733ea5776ab6c287f6057c00ec4bfacbb2f246b570efd93d98e99be49
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = 53d00d5839d0a1e695916151f9450b7311982917edcbd7c66496912db41761a1d2aecfda04fb2cfa
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 042653c674ef2a90f7fb11d30848e530ae59478f1051633a34fad277
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 1902d9769a7ba3d3268e1257395c8c2e5f98eef295dcbfa5a35df775
+Result = Fail
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = ebacb8e78c0ad9d3ed99f1821b0b0085beac351f88a79ef71faaf310
+Result = Fail
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = efc1d5b6f0a48e4ce3e821d743d34206b28c69485c410fa94d5e6103
+Result = Fail
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 3c1836e5d0f0473dab7bfd7a95ba69575f7f841970ac6c6769ac966a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 2c583e54d75a02948c7f6dcd12cba32a65e8d605fba7ec10c47e9a8e
+Result = Fail
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = a8632dee22f34315b05c40135c6dd471c63b09438da834dc1f3f537f
+Result = Fail
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 0f03ea1b2561951d79062e19a85d98293c8c2846936c724c26421940
+Result = Fail
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f9764405e54d827ac433fd624506b92e123463a5b01f21ffa3a22ac7
+Result = Fail
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = a326e0cf3f97adff3249944880ddfb8d616cd18a086e046289429246
+Result = Fail
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = f188bc1a72e81b34d75b402e4f8ef3d638d2f56a409eab064c9649b7
+Result = Fail
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 341df3a273e85cf387ab823bdf9c34a1ae2c86940cb4bfcde2e93f29
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = a0e7997fd67ea66b6274d719b84da92433fdf7d512b160da35c7081d
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = dd8fd11e1c0746e7273fdd2e7dfa1ee4fc8ad835ca3141c0f83a9ad7
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 39b0d3603f1289b5885ac244953275d28491952e7e57d93c7ff1eb5d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = a5b7d8cca2069908d1ed88e6a9fe2c9bede3131dad54671ea7ade30a07d185692ab0ebdf4c78cf7a
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 9a98617fb97a0dfe466be692272dcdaec1c5443a3b51312ef042c86363cc05afb98c66e16be8a445
+Result = Fail
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = d3068ae815c3605d7670058abb9384f4c15b75150eb7910041a8f6ac697430627826bd76b19da027
+Result = Fail
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 388a289bb85533b667b141a78d0c79acdeb9fbf72886d5ab980581017fefef92c2b50ae20b93c81c
+Result = Fail
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 71f68480a8801d4966c84807c5ff6139d83ba0a5b902bee3327f5f91763c0a0bec43264c27cd237f
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 8627bf1e3edafc69f1328c393dd8e7bd1c182d021e6d3a3652c4b7fd911ca77950ff2d035e47b7ec
+Result = Fail
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = b10ea86a384432a45f50b3c2e482595b46c81c61ca39bc0f4ffcb29bde8b9a81945d671b0f619045
+Result = Fail
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 3ace8b7e03a0c1fa9e97f46975ab0a4924446e791540e225578cc14aa558e18d5f777ab6e16dcfee
+Result = Fail
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = 8190abe4c21e320e10825e269190bb10a354691958e2436275433c4ae28757c8544c86f1f74ea6a5
+Result = Fail
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 1d7e308c34cdca7b7b222f4ebc92afd8055bff542c0b76d3d7752ebe9c5dbf00ee8ad60ac34dd7d0
+Result = Fail
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 9c2609f7af5b634a16e58f2e9cc7a9ef7812a12d209847000a4432b35d3b884e4169c28d287499ff
+Result = Fail
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 5b0b5e6690d648e1b92c12cfddb431d6d3dfe689d01db8199256ace490c2f0afb93ba32be58fd1de
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 8722fca71fdf750ec5d62fc6d7ba079aef19210da764067aefd8535dd6b7fa701c9ca8c8b635c30b
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 91ac457f5e53492301e72d9d495277ed17edb30e8c7a48d21b5d2cd4d5b6d2ef48413245a6b27b67
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = d2fe5293b7d53ed46ddf02a5618039adbae22845ce72e434fdc83ea4863c3e84a5456f7f853a1ea6
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 1d089a5f
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = 2f46022a
+Result = Fail
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 67dc4693
+Result = Fail
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 7027a849
+Result = Fail
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 5c6a4de2
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 1d855f5d
+Result = Fail
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 1b318980
+Result = Fail
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = cf871f91
+Result = Fail
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 4f0e04bc
+Result = Fail
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = fc9013df
+Result = Fail
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 5134def3
+Result = Fail
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 5814103a
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 74c75c4a
+Result = Pass
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 9884898b
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 0b1cbfb1
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 5280a2137fee3deefcfe9b63a1199fb3
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = d40a7318c5f2d82f838c0beeefe0d598
+Result = Fail
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 7551978bc9592bf9e294b4984c5862bb
+Result = Fail
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 859cf444f89225b32a55a1645bd24979
+Result = Fail
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 29e967a0245607c36cf3eaf00fdae566
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 9daa0e1c4df5f2bf507b1a57a1135b86
+Result = Fail
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 18caec79720a5d67d7457e9b7c7a153c
+Result = Fail
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 5f2c455546c56f514a0f69f05345c2c4
+Result = Fail
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = b7e4846ff30b7c3673a962a2701c0387
+Result = Fail
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 7b5fa0d42a616ab05ac2c58c904ce92f
+Result = Fail
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = c8c67f558b5844b149dd47824c8cb9d8
+Result = Fail
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 70a09aaf22ac316124a169f6b0a83ffe
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 5bc85ed5521a91b9eb42b437950f0e06
+Result = Pass
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 989ec0e7b192ea010dd61d3fb64e8de0
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 15c2dbe7fa307654d8ca7c0f8d6d2f14
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 5e0eaebd
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 71b7fc33
+Result = Fail
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 93227bd4
+Result = Fail
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = ced654e2
+Result = Fail
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = bf7a8e0c
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 840caa3e
+Result = Fail
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 1e22fc41
+Result = Fail
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 968ccbbf
+Result = Fail
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0a31cc96
+Result = Fail
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = a456c3da
+Result = Fail
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 29746eea
+Result = Fail
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = df7f63ca
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = bf0b1445
+Result = Pass
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = ae8533f5
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 9426cf89
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = d07ccf9fdc3d33aa94cda3d230da707c
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 65fe32b649dc328c9f531584897e85b3
+Result = Fail
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = ec31fb6b41c2dae87cf395fc1fe3a080
+Result = Fail
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = 33c2f2312dd5bfcadbb05f8d0a33fd4a
+Result = Fail
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = a9e81afd1030d195c679e2c837aeb736
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1db000f0e7d3a03718293fc118678427
+Result = Fail
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = ea37900f049db8fc5cbf46edb5fcac2c
+Result = Fail
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = d1097ebd7ad0a41f61ba32a44dc15305
+Result = Fail
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0979729272d8b42f2e3dc0eb181a1217
+Result = Fail
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = 4457200916a20116b096225606f1a9e2
+Result = Fail
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = cc6b51f39a3dcfb54abbb89f4df21114
+Result = Fail
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = aac09cef9697927331251f028d24c31f
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 56c00070eae0db329894a045d866bbaf
+Result = Pass
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 090016bb96aeaabbf66fd34fc97591a4
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 264407dfe796bf7f6eb1f26c1f8504ef
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 9f6ca4af9b159148c889a6584d1183ea26e2614874b0504575dea8d1
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 84d8212e9cfc2121252baa3b065b1edcf50497b9594db1ebd7965825
+Result = Fail
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 5f60a8f867a33b2077ecc69863b295c3c6aeae7d7cade7f8f7f796fe
+Result = Fail
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 1353b3fa1bb1d57ffb139017885c02e26c90231a24b5a615b8f1f2ae
+Result = Fail
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = c3116d9040e1ed4f7c9464d270fb302bd3f1561c25c5b95b8b4b53f6
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 0ca17e8f89bea67db48a8f132ef6c6df7a292914d401299af6bf3800
+Result = Fail
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 0ce543569e8187f3cec70399ff922e4903cb1d12f990f05613244cf6
+Result = Fail
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 3acdbc163a350f312791b152a41e57627b1cc8bf3e41c8aea5876de8
+Result = Fail
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 604518e436edf7a0561d5e284f3915839a6d28cb06ef792a1970ed17
+Result = Fail
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = fc79b520d67da891e63654d7927db6c8012c96985a0059d5f68d8da4
+Result = Fail
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = d86bb51a98770098d0feb39170bd979199a8f741041df13790ee4c14
+Result = Fail
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 51b6b928bdd1cc0bd0a0aed2cda302472d618ffaa60e179029c87855
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = d0abab9b8e9d6c11bb9c15bea8a486704bed32c57297055b4de8ed8d
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = 92fd519a966c0fbdd7087ff5a1bd946cd663502db378383531d69947
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f239b1916830161f3b52b7ab13542a5a0a97a17f30ca5fa30768d4d
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6aab64c4787599d8f213446beadb16e08dba60e97f56dbd14d1d980d6fe0fb44b421992662b97975
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4980b2ee49b1aaf393175f5ab9bae95ec7904557dfa206603c51d36c826f01384100886198a7f6a3
+Result = Fail
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 86a02bdd6ae733eee26f8eab898b336105978b5bbd6df781758a111aae4f735b7dd4d9802f2a8406
+Result = Fail
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 59cfab8956813c48e09332a2bb8a30dbcdf5afb2529532ab8cef14ebc2951069739d5d657d82addb
+Result = Fail
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 67d989ea935b9ce190e3a7f3b645305e1e308a7fe617f80f170a2b9c309de6c2326115a76efbdf98
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 2522a5e4d157193ef2c264cfe877db8ac75b3cc5aab08a814bcd14af0205af716f2b864f0c397f65
+Result = Fail
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 4536422bbad220079ee09e700e103efdaac832d016a20813762d5d8adafe75a191310a2618930c48
+Result = Fail
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = d6711a78adf54f4effe647d531c4618cf32e3037eb700580206f80080dfa3e66e6371c0cde6cd205
+Result = Fail
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = e44034a397778e1c6babab27f5a50fa4aac0e83d6b3eb25db1b5b2b35c8a8125efccd1f4102f3e82
+Result = Fail
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = b8e31c5910623e405f2ebf65821963e5b8814043612395feca36f53b01943f03cb8b69b5af53e505
+Result = Fail
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 4000faf8558f2f4e01e45e90796cd236e5211d1704270f31c3bfc6851049d32105fd16bd45b29f29
+Result = Fail
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 53bb608f6236798839af35888cb0fa4797b599271084cc13847b022733ca5a5e3c4d472332484b7f
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = be54551d1d2f1b3eb60ffe3b165524ff90ca09fb252bf21c1c79edbf38c50e0f240a2d70f65aa79f
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = f07c1072d8f8e077dfbb3ad86dd92d32b41f29e647dcd7e3a82cd3ebaf6c2d3e21749bdf570ad28d
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f7cf7f4d0645934cb0a5e67b4227a909aa55dba09b2c39cef93a8759845326683a0d9c22151f486
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 16e543d0e20615ff0df15acd9927ddfe40668a54bb854cccc25e9fce
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = df35b109caf690656ae278bbd8f8bba687a2ce11b105dae98ecedb3e
+Result = Fail
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 7075da2291e2cb527eb926ed08d8020c5f8f0f2d4a6a4745728da544
+Result = Fail
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 18a77a66457b53286b1aea0845304cac8e66a02d5c642e4c02a9b9bc
+Result = Fail
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = 24e1d3820101412d8f4d57118cab8f7e489d5cac78802dd5ccf8ecf0
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = b5929bc9648e24a553c5cd953ecb9d67ee508d2d4ac7b46e661181d5
+Result = Fail
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 54aa018dc7fdf8a54809e1393d18031bab4aa5ca35c201907d74517d
+Result = Fail
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 69bcc300a459862b3cd284c15dd4af53dc7e95f3067bb8254a8edd83
+Result = Fail
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5c2d2df0d8aade3e5ae0f8d8b4b4d7c565817a31b2865dc270ad39a6
+Result = Fail
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = df1b3f98b6b0060191e7eb817f5908ddc0bc6f83860349e8ae423997
+Result = Fail
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 16e59dd38395c7be7f580371edabb1e9bf21270de270aa283309108e
+Result = Fail
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 0ef8981dd37c055a3c3e14786fc662b2a11065964911d35ebcc87096
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = fc1870cfc440f74f73f40e682cf4713d027c297b9426c3efe981e935
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 9fc2c462dff1ba9756772d73de5c4e822b5ea0bc88845a323b98de4f
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 05fc586d5c780b8e06f618b5bb85f591665a54390eba4e14af3b74e1
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = c5b0b2ef17498c5570eb335df4588032958ba3d69bf6f3178464a6f7fa2b76744e8e8d95691cecb8
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = d1f0518929f4ae2f0543de2a7dfe4bb0110bb3057e524a1c06bd6dc2e6bcc3436cffb969ae900388
+Result = Fail
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 1aa7dfa3a9818142c4971cbf4f64d4cbdbd354c6958ef474bb56d90669c726d866fe2206b8828727
+Result = Fail
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 90352a5ec92d4fa52a96ae28251a57933728b2a3670e2ecd9953fec4e091b3573214e1ecac1ac00c
+Result = Fail
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = eaa995946ed91d6a08ade14b260ac752cbd1081d5a7cad90783618374f6d03df28ee57a1a5aa38d8
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 0e320c4ece6ef0305a431a07a5a34d463ec4a37fc513c4b947bb3f30d6e674d10a496806c1c8933e
+Result = Fail
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 10685888091597c50acc54b2fb65150b83a7115351d6f8bd7dd7ee3f75cfb47fa72433644f9cf62e
+Result = Fail
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = e456abf9ee83e0a68fbdb09c4a7afaba0efb0aa6d74a17c443314076072a0ebd253fe1ab4883ebea
+Result = Fail
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5adadfd296edaf4bea92c8245983dc31b11335f682fb222c16a72444f0949868f0e71907acbb29f4
+Result = Fail
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = c2bb4d5a830646b3f8bf84044851c3b676c4ec02e43dcbf1ab2025208191d73041c038cf2562bb8c
+Result = Fail
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 9589b8abcb47e54e6e8fad3e64fec7ed4f70ac435bb3e548b7e6d183efa1f51b7ff31eaa52ed59ba
+Result = Fail
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = af63f27e2a9e70f106477493dc141d16a1d059dd7a8a7810d990b642039f24755790332b3cc47c49
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = 1d2ae88c878684a0b404986252b3a7583e1a5a51163ddc606d3968fdceaae5138c411a29d0d333ee
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 30c154c616946eccc2e241d336ad33720953e449a0e6b0f0dbf8e9464909bdf337e48093c082a10b
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 0c95b692b07b39039b40c80cf52ff71608ae87c973ac9ccb88bba8f204bb98b17cb3c8644e472b1e
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt
new file mode 100644
index 0000000000..27671e1a0a
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = c98ad7f38b2c7e970c9b965ec87a08208384718f78206c6c
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 9d4b7f3b
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 80745de9
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 2f6fa823
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 3cc132c6
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = c79d5557
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 41e0eea0
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = 1f129266
+Result = Fail (1 - Adata changed)
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 41b0e4e2
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 5082e06a
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = 70587cce
+Result = Fail (1 - Adata changed)
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6aaa0acd
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 22976e42
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = f440ea1d
+Result = Pass (0)
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 88903fb9
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 3ff345c3
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 17223038fa99d53681ca1beabe78d1b4
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = d0e1eeef4d2a264536bb1c2c1bde7c35
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 81d587f8673fd514c23172af7fb7523d
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 500142447e535207899ab1499994daea
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = fdfdbb38bf161785114f9ee2018e892f
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 38fe9622eaa2a50152cf57e393dd3063
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = 73af4b87c167572e1400a0ee28209aff
+Result = Fail (1 - Adata changed)
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ace2248b9f23efa813449c82217e4a4a
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = a9bb0e469829d9cf09ad765c5b0b58bf
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = a5977f0826926ec0d32541b2bd4e2b1e
+Result = Fail (1 - Adata changed)
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6938fb5afec1a84e4abb062e1a943c20
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 7e3bbe0eb13988a93972f2fbcd35659e
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 48d7a15cf4f5808eb45d1ad817470554
+Result = Pass (0)
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 97185ce68af1e6ab718c8c4b83ec04cd
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = a81bc8f5a18293ffe19505a3687ce3f3
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fe69ed84
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = db7ffc82
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 7a677329
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = d903d8f7
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 215e0bf2
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 0d38100f
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 9f8ab5f7
+Result = Fail (1 - Adata changed)
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7d811d50
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = c2e18439
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d8b5817b
+Result = Fail (1 - Adata changed)
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 28cd70ff
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 790b2624
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 9e46632d
+Result = Pass (0)
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 39b82901
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 4c0cf71f
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 0c66a8e547ed4f8c2c9a9a1eb5d455b9
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 38757b3a61a4dc97ca3ab88bf1240695
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 11875da4445d92391d0fab5f3625497b
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 64477bcd4316e5c5789e1a678fdef943
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 87da5dbc04e39fc468f43675d4e7df33
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = bf0d53ee529d8cafc5ad7a8f2d85e7a2
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 676370637ad78c705d43fce066dc909f
+Result = Fail (1 - Adata changed)
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 289936db0f9f148a3c9e2d28f7d7de51
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 58a283641627669d5514f2af559b6c14
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = a6b058540ed905d6e3499a13ea1f3d83
+Result = Fail (1 - Adata changed)
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 7a19b3377384f09915d0e1ae93a9f16c
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = a0d047a1f9940d325e474da54aa13897
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 8a4768a2093694b6bcb7083c0bb6331c
+Result = Pass (0)
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = a7cafd6f68dc1f15a3603da654ce27bc
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = c49845f2ea3c9981ad7e9b942f615b8d
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 411986d04d6463100bff03f7d0bde7ea2c3488784378138cddc93a54
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 32b649ab56162e55d4148a1292d6a225a988eb1308298273b6889036
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = a963c3568ab413b174cd95cc1e3ca61ee181292bebdb28179b4de35f
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0396e6c8db43e5fac205f4c576fd577368adcb688cf3d7e76df9ffc5
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = b41bfba94edcafc41b4c144269b9126a6d47b19e83b15772b28c8e38
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 01e3bb938e16d0284d1d0fee049d80fb97356ae4d84127cf7336a30a
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = abd7551c5e84e9bef5fbfad3e24d13f02864410eae9177ad0c40cc72
+Result = Fail (1 - Adata changed)
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3b5ae49e0974f41826152432b46f1a85ab4995afefbbccddfc9fd290
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = 21fb4324de4ba1e2762b3041ce26e43a3d191458a046d489e485910b
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 99ca8f542fd06481e23719214c9892442f393d72899deea08695053f
+Result = Fail (1 - Adata changed)
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 5fcc05342cdc27f66b324ae7387205bfb4ab6302bfe0af09050d2054
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 0a7fe63046daf8a979935b897088c64acc1b47a5a9b86fdd6def28ab
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = daf7d7dfa512ceb1d7d3435634d9a70b3ef6c6dc38f409e068941fce
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = cdb417dff6502208775f21e35cdb8e3e1199308d1a94229051a1ec4a
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e75441093c8ccba6eac5913dc246ce96de4784a01051498298eaddaf
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = cba4b4aeb85f0492fd8d905c4a6d8233139833373ef188a8c5a5ebecf7ac8607fe412189e83d9d20
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = ca62713728b5c9d652504b0ae8fd4fee5d297ee6a8d19cb6e699f15f14d34dcaf9ba8ed4b877c97d
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 93012c0a5f6f1025b8c4a5d897d3eea0b1c77be8000c9e59f3b8899459788c58794f177cfd838f35
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = b8eb95f72f643c2c51ad74775cc203d215c86626e903eb013ad22e8fa4d2f9725ce4f212a8844855
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 71f17cf21c44267c676657db9e55bee33273787474e77b17b5eab45d7d096577643815e6d467312d
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = d6737f642260c4ee3b19cb78cc2ef1767213416b82c71e918b1a5ecca7354af824fea617b9b69031
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = cbe60d633399daa6ee66418be6d16e292ea47a93c291fce2c54c98f8007ed55a21759f5452559538
+Result = Fail (1 - Adata changed)
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 2a78a7beb8df4bf5d35ff0b2853bc51ce127163d2f56e00ea555aa972e1c2e3f439f85663ae25889
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = ee78ddbea9c3aede9f88af0e82464d9d1afe81de16aa18c49aeb326578fa615e86969348d9bbfb7f
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = cdf7cb74d978e7ea738e288ed79edfccf10b553c09d1856e2efbff1da769af3b72099cbda3cbf091
+Result = Fail (1 - Adata changed)
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 90b990a1ea254592f2c226c969b332fc7bfe5f808729c2d83291a566e6641a965ffdabe097050dc5
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 44a6aa954c3508b3c9264c20c272e80c0e95d50ddec2849084b47504dced5b70c302cc93502cc37e
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 9d4ff7a44cdb9b14f586efc3d6be02d069b425c06bec4eed37109739a3676f03adfd740dbaa4940d
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 23da95e102c7921a51b19b5733ea5776ab6c287f6057c00ec4bfacbb2f246b570efd93d98e99be49
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = 53d00d5839d0a1e695916151f9450b7311982917edcbd7c66496912db41761a1d2aecfda04fb2cfa
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 042653c674ef2a90f7fb11d30848e530ae59478f1051633a34fad277
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 1902d9769a7ba3d3268e1257395c8c2e5f98eef295dcbfa5a35df775
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = ebacb8e78c0ad9d3ed99f1821b0b0085beac351f88a79ef71faaf310
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = efc1d5b6f0a48e4ce3e821d743d34206b28c69485c410fa94d5e6103
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 3c1836e5d0f0473dab7bfd7a95ba69575f7f841970ac6c6769ac966a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 2c583e54d75a02948c7f6dcd12cba32a65e8d605fba7ec10c47e9a8e
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = a8632dee22f34315b05c40135c6dd471c63b09438da834dc1f3f537f
+Result = Fail (1 - Adata changed)
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 0f03ea1b2561951d79062e19a85d98293c8c2846936c724c26421940
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f9764405e54d827ac433fd624506b92e123463a5b01f21ffa3a22ac7
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = a326e0cf3f97adff3249944880ddfb8d616cd18a086e046289429246
+Result = Fail (1 - Adata changed)
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = f188bc1a72e81b34d75b402e4f8ef3d638d2f56a409eab064c9649b7
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 341df3a273e85cf387ab823bdf9c34a1ae2c86940cb4bfcde2e93f29
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = a0e7997fd67ea66b6274d719b84da92433fdf7d512b160da35c7081d
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = dd8fd11e1c0746e7273fdd2e7dfa1ee4fc8ad835ca3141c0f83a9ad7
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 39b0d3603f1289b5885ac244953275d28491952e7e57d93c7ff1eb5d
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = a5b7d8cca2069908d1ed88e6a9fe2c9bede3131dad54671ea7ade30a07d185692ab0ebdf4c78cf7a
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 9a98617fb97a0dfe466be692272dcdaec1c5443a3b51312ef042c86363cc05afb98c66e16be8a445
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = d3068ae815c3605d7670058abb9384f4c15b75150eb7910041a8f6ac697430627826bd76b19da027
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 388a289bb85533b667b141a78d0c79acdeb9fbf72886d5ab980581017fefef92c2b50ae20b93c81c
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 71f68480a8801d4966c84807c5ff6139d83ba0a5b902bee3327f5f91763c0a0bec43264c27cd237f
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 8627bf1e3edafc69f1328c393dd8e7bd1c182d021e6d3a3652c4b7fd911ca77950ff2d035e47b7ec
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = b10ea86a384432a45f50b3c2e482595b46c81c61ca39bc0f4ffcb29bde8b9a81945d671b0f619045
+Result = Fail (1 - Adata changed)
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 3ace8b7e03a0c1fa9e97f46975ab0a4924446e791540e225578cc14aa558e18d5f777ab6e16dcfee
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = 8190abe4c21e320e10825e269190bb10a354691958e2436275433c4ae28757c8544c86f1f74ea6a5
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 1d7e308c34cdca7b7b222f4ebc92afd8055bff542c0b76d3d7752ebe9c5dbf00ee8ad60ac34dd7d0
+Result = Fail (1 - Adata changed)
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 9c2609f7af5b634a16e58f2e9cc7a9ef7812a12d209847000a4432b35d3b884e4169c28d287499ff
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 5b0b5e6690d648e1b92c12cfddb431d6d3dfe689d01db8199256ace490c2f0afb93ba32be58fd1de
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 8722fca71fdf750ec5d62fc6d7ba079aef19210da764067aefd8535dd6b7fa701c9ca8c8b635c30b
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 91ac457f5e53492301e72d9d495277ed17edb30e8c7a48d21b5d2cd4d5b6d2ef48413245a6b27b67
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = d2fe5293b7d53ed46ddf02a5618039adbae22845ce72e434fdc83ea4863c3e84a5456f7f853a1ea6
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 1d089a5f
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = 2f46022a
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 67dc4693
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 7027a849
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 5c6a4de2
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 1d855f5d
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 1b318980
+Result = Fail (1 - Adata changed)
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = cf871f91
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 4f0e04bc
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = fc9013df
+Result = Fail (1 - Adata changed)
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 5134def3
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 5814103a
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 74c75c4a
+Result = Pass (0)
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 9884898b
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 0b1cbfb1
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 5280a2137fee3deefcfe9b63a1199fb3
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = d40a7318c5f2d82f838c0beeefe0d598
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 7551978bc9592bf9e294b4984c5862bb
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 859cf444f89225b32a55a1645bd24979
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 29e967a0245607c36cf3eaf00fdae566
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 9daa0e1c4df5f2bf507b1a57a1135b86
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 18caec79720a5d67d7457e9b7c7a153c
+Result = Fail (1 - Adata changed)
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 5f2c455546c56f514a0f69f05345c2c4
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = b7e4846ff30b7c3673a962a2701c0387
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 7b5fa0d42a616ab05ac2c58c904ce92f
+Result = Fail (1 - Adata changed)
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = c8c67f558b5844b149dd47824c8cb9d8
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 70a09aaf22ac316124a169f6b0a83ffe
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 5bc85ed5521a91b9eb42b437950f0e06
+Result = Pass (0)
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 989ec0e7b192ea010dd61d3fb64e8de0
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 15c2dbe7fa307654d8ca7c0f8d6d2f14
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 5e0eaebd
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 71b7fc33
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 93227bd4
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = ced654e2
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = bf7a8e0c
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 840caa3e
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 1e22fc41
+Result = Fail (1 - Adata changed)
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 968ccbbf
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0a31cc96
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = a456c3da
+Result = Fail (1 - Adata changed)
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 29746eea
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = df7f63ca
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = bf0b1445
+Result = Pass (0)
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = ae8533f5
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 9426cf89
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = d07ccf9fdc3d33aa94cda3d230da707c
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 65fe32b649dc328c9f531584897e85b3
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = ec31fb6b41c2dae87cf395fc1fe3a080
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = 33c2f2312dd5bfcadbb05f8d0a33fd4a
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = a9e81afd1030d195c679e2c837aeb736
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1db000f0e7d3a03718293fc118678427
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = ea37900f049db8fc5cbf46edb5fcac2c
+Result = Fail (1 - Adata changed)
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = d1097ebd7ad0a41f61ba32a44dc15305
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0979729272d8b42f2e3dc0eb181a1217
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = 4457200916a20116b096225606f1a9e2
+Result = Fail (1 - Adata changed)
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = cc6b51f39a3dcfb54abbb89f4df21114
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = aac09cef9697927331251f028d24c31f
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 56c00070eae0db329894a045d866bbaf
+Result = Pass (0)
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 090016bb96aeaabbf66fd34fc97591a4
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 264407dfe796bf7f6eb1f26c1f8504ef
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 9f6ca4af9b159148c889a6584d1183ea26e2614874b0504575dea8d1
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 84d8212e9cfc2121252baa3b065b1edcf50497b9594db1ebd7965825
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 5f60a8f867a33b2077ecc69863b295c3c6aeae7d7cade7f8f7f796fe
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 1353b3fa1bb1d57ffb139017885c02e26c90231a24b5a615b8f1f2ae
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = c3116d9040e1ed4f7c9464d270fb302bd3f1561c25c5b95b8b4b53f6
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 0ca17e8f89bea67db48a8f132ef6c6df7a292914d401299af6bf3800
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 0ce543569e8187f3cec70399ff922e4903cb1d12f990f05613244cf6
+Result = Fail (1 - Adata changed)
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 3acdbc163a350f312791b152a41e57627b1cc8bf3e41c8aea5876de8
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 604518e436edf7a0561d5e284f3915839a6d28cb06ef792a1970ed17
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = fc79b520d67da891e63654d7927db6c8012c96985a0059d5f68d8da4
+Result = Fail (1 - Adata changed)
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = d86bb51a98770098d0feb39170bd979199a8f741041df13790ee4c14
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 51b6b928bdd1cc0bd0a0aed2cda302472d618ffaa60e179029c87855
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = d0abab9b8e9d6c11bb9c15bea8a486704bed32c57297055b4de8ed8d
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = 92fd519a966c0fbdd7087ff5a1bd946cd663502db378383531d69947
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f239b1916830161f3b52b7ab13542a5a0a97a17f30ca5fa30768d4d
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6aab64c4787599d8f213446beadb16e08dba60e97f56dbd14d1d980d6fe0fb44b421992662b97975
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4980b2ee49b1aaf393175f5ab9bae95ec7904557dfa206603c51d36c826f01384100886198a7f6a3
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 86a02bdd6ae733eee26f8eab898b336105978b5bbd6df781758a111aae4f735b7dd4d9802f2a8406
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 59cfab8956813c48e09332a2bb8a30dbcdf5afb2529532ab8cef14ebc2951069739d5d657d82addb
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 67d989ea935b9ce190e3a7f3b645305e1e308a7fe617f80f170a2b9c309de6c2326115a76efbdf98
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 2522a5e4d157193ef2c264cfe877db8ac75b3cc5aab08a814bcd14af0205af716f2b864f0c397f65
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 4536422bbad220079ee09e700e103efdaac832d016a20813762d5d8adafe75a191310a2618930c48
+Result = Fail (1 - Adata changed)
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = d6711a78adf54f4effe647d531c4618cf32e3037eb700580206f80080dfa3e66e6371c0cde6cd205
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = e44034a397778e1c6babab27f5a50fa4aac0e83d6b3eb25db1b5b2b35c8a8125efccd1f4102f3e82
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = b8e31c5910623e405f2ebf65821963e5b8814043612395feca36f53b01943f03cb8b69b5af53e505
+Result = Fail (1 - Adata changed)
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 4000faf8558f2f4e01e45e90796cd236e5211d1704270f31c3bfc6851049d32105fd16bd45b29f29
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 53bb608f6236798839af35888cb0fa4797b599271084cc13847b022733ca5a5e3c4d472332484b7f
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = be54551d1d2f1b3eb60ffe3b165524ff90ca09fb252bf21c1c79edbf38c50e0f240a2d70f65aa79f
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = f07c1072d8f8e077dfbb3ad86dd92d32b41f29e647dcd7e3a82cd3ebaf6c2d3e21749bdf570ad28d
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f7cf7f4d0645934cb0a5e67b4227a909aa55dba09b2c39cef93a8759845326683a0d9c22151f486
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 16e543d0e20615ff0df15acd9927ddfe40668a54bb854cccc25e9fce
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = df35b109caf690656ae278bbd8f8bba687a2ce11b105dae98ecedb3e
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 7075da2291e2cb527eb926ed08d8020c5f8f0f2d4a6a4745728da544
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 18a77a66457b53286b1aea0845304cac8e66a02d5c642e4c02a9b9bc
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = 24e1d3820101412d8f4d57118cab8f7e489d5cac78802dd5ccf8ecf0
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = b5929bc9648e24a553c5cd953ecb9d67ee508d2d4ac7b46e661181d5
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 54aa018dc7fdf8a54809e1393d18031bab4aa5ca35c201907d74517d
+Result = Fail (1 - Adata changed)
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 69bcc300a459862b3cd284c15dd4af53dc7e95f3067bb8254a8edd83
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5c2d2df0d8aade3e5ae0f8d8b4b4d7c565817a31b2865dc270ad39a6
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = df1b3f98b6b0060191e7eb817f5908ddc0bc6f83860349e8ae423997
+Result = Fail (1 - Adata changed)
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 16e59dd38395c7be7f580371edabb1e9bf21270de270aa283309108e
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 0ef8981dd37c055a3c3e14786fc662b2a11065964911d35ebcc87096
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = fc1870cfc440f74f73f40e682cf4713d027c297b9426c3efe981e935
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 9fc2c462dff1ba9756772d73de5c4e822b5ea0bc88845a323b98de4f
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 05fc586d5c780b8e06f618b5bb85f591665a54390eba4e14af3b74e1
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = c5b0b2ef17498c5570eb335df4588032958ba3d69bf6f3178464a6f7fa2b76744e8e8d95691cecb8
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = d1f0518929f4ae2f0543de2a7dfe4bb0110bb3057e524a1c06bd6dc2e6bcc3436cffb969ae900388
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 1aa7dfa3a9818142c4971cbf4f64d4cbdbd354c6958ef474bb56d90669c726d866fe2206b8828727
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 90352a5ec92d4fa52a96ae28251a57933728b2a3670e2ecd9953fec4e091b3573214e1ecac1ac00c
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = eaa995946ed91d6a08ade14b260ac752cbd1081d5a7cad90783618374f6d03df28ee57a1a5aa38d8
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 0e320c4ece6ef0305a431a07a5a34d463ec4a37fc513c4b947bb3f30d6e674d10a496806c1c8933e
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 10685888091597c50acc54b2fb65150b83a7115351d6f8bd7dd7ee3f75cfb47fa72433644f9cf62e
+Result = Fail (1 - Adata changed)
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = e456abf9ee83e0a68fbdb09c4a7afaba0efb0aa6d74a17c443314076072a0ebd253fe1ab4883ebea
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5adadfd296edaf4bea92c8245983dc31b11335f682fb222c16a72444f0949868f0e71907acbb29f4
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = c2bb4d5a830646b3f8bf84044851c3b676c4ec02e43dcbf1ab2025208191d73041c038cf2562bb8c
+Result = Fail (1 - Adata changed)
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 9589b8abcb47e54e6e8fad3e64fec7ed4f70ac435bb3e548b7e6d183efa1f51b7ff31eaa52ed59ba
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = af63f27e2a9e70f106477493dc141d16a1d059dd7a8a7810d990b642039f24755790332b3cc47c49
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = 1d2ae88c878684a0b404986252b3a7583e1a5a51163ddc606d3968fdceaae5138c411a29d0d333ee
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 30c154c616946eccc2e241d336ad33720953e449a0e6b0f0dbf8e9464909bdf337e48093c082a10b
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 0c95b692b07b39039b40c80cf52ff71608ae87c973ac9ccb88bba8f204bb98b17cb3c8644e472b1e
+Result = Fail (2 - CT changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp
new file mode 100644
index 0000000000..b8045d8291
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:26 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = eda32f751456e33195f1f499cf2dc7c97ea127b6d488f211ccc5126fbb24afa6
+
+Count = 0
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 469c90bb
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 46a908ed
+Result = Fail
+
+Count = 2
+Nonce = e776620a3bd961
+Adata = 00
+CT = fdd35c4d
+Result = Fail
+
+Count = 3
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 869ce60e
+Result = Fail
+
+Count = 4
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = 1302d515
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = 156416ee
+Result = Fail
+
+Count = 6
+Nonce = a259c114eaac89
+Adata = 00
+CT = 4fe06e92
+Result = Pass
+Payload = 00
+
+Count = 7
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 611091aa
+Result = Fail
+
+Count = 8
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 696e9371
+Result = Fail
+
+Count = 9
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = a0e0a2cb
+Result = Fail
+
+Count = 10
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 43cc0375
+Result = Fail
+
+Count = 11
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = e5417f6b
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = fff8a068
+Result = Fail
+
+Count = 13
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = f8fa8e71
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 0bfa2d9d
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 15
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 8207eb14d33855a52acceed17dbcbf6e
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 60f8e127cb4d30db6df0622158cd931d
+Result = Fail
+
+Count = 17
+Nonce = e776620a3bd961
+Adata = 00
+CT = 4239f29871651e9a26b8b06ffc5b3748
+Result = Fail
+
+Count = 18
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 5d35364c621fe8959dfe70ab44700fbe
+Result = Fail
+
+Count = 19
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = e4dc5e03aacea691262ee69cee8ffbbe
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = c8eb7643b4ed3c796c3873e8c6624e0d
+Result = Fail
+
+Count = 21
+Nonce = a259c114eaac89
+Adata = 00
+CT = f79c53fd5e69835b7e70496ea999718b
+Result = Pass
+Payload = 00
+
+Count = 22
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 687e00723a419fa81c0923b8b8e245ae
+Result = Fail
+
+Count = 23
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 499ab350309ad6091ec4aaf6bf0cbd00
+Result = Fail
+
+Count = 24
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = c27b9f14787dc5375f59d0c561a23446
+Result = Fail
+
+Count = 25
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 655c737722c78ac96582a883d407b2bb
+Result = Fail
+
+Count = 26
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = 10d3f6fe08280d45e67e58fe41a7f036
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = b4e425e43edb92c606f7cb2de8a06932
+Result = Fail
+
+Count = 28
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = 2590df2453cb94c304ba0a2bff3f3c71
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 1f344e30dfa95b2319e274caa5780e60
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 30
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 8a19a133
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 2e317f1b
+Result = Fail
+
+Count = 32
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 979bdcfe
+Result = Fail
+
+Count = 33
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 8ef89acf
+Result = Fail
+
+Count = 34
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 154024b2
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = 8dbcc439
+Result = Fail
+
+Count = 36
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 5c349fb2
+Result = Pass
+Payload = 00
+
+Count = 37
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = 79df3e02
+Result = Fail
+
+Count = 38
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = fbc2c500
+Result = Fail
+
+Count = 39
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 2fac1bca
+Result = Fail
+
+Count = 40
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = 99948f6e
+Result = Fail
+
+Count = 41
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = c59bf14c
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = b764c393
+Result = Fail
+
+Count = 43
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 5b96f41d
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = f7e12df1
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 45
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 97e1a8dd4259ccd2e431e057b0397fcf
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 5a9596c511ea6a8671adefc4f2157d8b
+Result = Fail
+
+Count = 47
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 66f5c53efbc74fa02dedc303fd95133a
+Result = Fail
+
+Count = 48
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 2dfd3c852f68eace45acf433a6aa9c05
+Result = Fail
+
+Count = 49
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 5c8c9a5b97be8c7bc01ca8d693b809f9
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = ec093121bdcd589285f2262be8db5c4e
+Result = Fail
+
+Count = 51
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 84201662b213c7a1ff0c1b3c25e4ec45
+Result = Pass
+Payload = 00
+
+Count = 52
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = bbe746d6d31e8e9745faed4095ab8d5d
+Result = Fail
+
+Count = 53
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = 646c1258dc4aa6fc380818e70e5f4328
+Result = Fail
+
+Count = 54
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 15fa37ca7f2883a4642c1ed41b8f6293
+Result = Fail
+
+Count = 55
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = c6acf5e5ded4efb2c314370ebb9e9cde
+Result = Fail
+
+Count = 56
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = 586e728193ce6db9a926b03b2d77dd6e
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = 642a187e71feff5989e28184aded0199
+Result = Fail
+
+Count = 58
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 64864d21b6ee3fca13f07fc0486e232d
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = 58c63ce68f132d30d177c5834344cc5d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 60
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 64a1341679972dc5869fcf69b19d5c5ea50aa0b5e985f5b722aa8d59
+Result = Pass
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 61
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = c5b7f802bffc498c1626e3774f1d9f94045dfd8e1a10a20277d00a75
+Result = Fail
+
+Count = 62
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = bf432e246b7fa4aff8b3ada738432b51f6872ed92284db9d28588021
+Result = Fail
+
+Count = 63
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = 0d5760ad0e156e401120a1ebd1b139248784c88e10e3425437921120
+Result = Fail
+
+Count = 64
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 5acfbe5e488976d8b9b77e69a736e8c919053f9415551209dce2d25e
+Result = Pass
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 65
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = be8be6046ac58411a00c131dd4a72d565f98d87a2c89124b1ef530d0
+Result = Fail
+
+Count = 66
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = f00628e10e8e0115b4a4532a1212a23aade4090832c1972d750125f3
+Result = Pass
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 67
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = 9078151f674d5f7b56e2451b0316156f776459f17d277e0108aaaf93
+Result = Fail
+
+Count = 68
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 921cbecce3b06f3d655a5a0a4d212320d4f147575079fd23bd95e677
+Result = Fail
+
+Count = 69
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 8cab1ff22d474e9863c153e84680e2a66981f036051360477e2ebb1d
+Result = Fail
+
+Count = 70
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = 15f476b5aefe072548a54f59506d9c3b9ce29025340214be662f8684
+Result = Fail
+
+Count = 71
+Nonce = b672c91376f533
+Adata = 00
+CT = 758aa03dc72c362c43b5f85bfaa3db4a74860887a8c29e47d5642830
+Result = Pass
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 72
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ec645769b22161567e6a7e23aa06575bc767a34aa54d3cba01472fe1
+Result = Fail
+
+Count = 73
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 615cbeabbe163ba8bc9c073df9ad40833fcf3f424644ccc37aa999d7
+Result = Pass
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 74
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = 0ed6cc6451de57ca672d56dee45d4548a810d5c49dfe442dd27b7cf2
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 75
+Nonce = a544218dadd3c1
+Adata = 00
+CT = bc51c3925a960e7732533e4ef3a4f69ee6826de952bcb0fd374f3bb6db8377ebfc79674858c4f305
+Result = Pass
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 76
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = afa1fa8e8a70e26b02161150556d604101fdf423f332c3363275f2a4907d51b734fe7238cebbd48f
+Result = Fail
+
+Count = 77
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = 72bc8ef21a847047091b673ccf231d35ecf6f4049741703be672f1f22cbe4a5305f19aaa6967237b
+Result = Fail
+
+Count = 78
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = b719f6555fc4e5424273f5903d5672af460413110278707f400b152113c3976be63dcd9e7a84ddac
+Result = Fail
+
+Count = 79
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 4539bb13382b034ddb16a3329148f9243a4eee998fe444aff2870ce198af11f4fb698a67af6c89ad
+Result = Pass
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 80
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = 47cbb909cb12fa0a4b0f1aefd54c52d1edd1533290f76b8ccc98b3f5758972bf08ea9e88dc6e54ed
+Result = Fail
+
+Count = 81
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = 6d0f928352a17d63aca1899cbd305e1f831f1638d27c1e24432704eff9b6830476db3d30d4c103e4
+Result = Pass
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 82
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = e0e686d917f78b3b0058fed7b084976244789073a6305ff571256981db86f1e768170a104ebfb81d
+Result = Fail
+
+Count = 83
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 960c573f5d6934a4cac49d06998f827b3d665cf02c998fe55efbbae6a346863a93d52e0321cef8b2
+Result = Fail
+
+Count = 84
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 7cf8f4806848e34aa7d3bd7e2cb9f5d9ff21395ff6d34826ac2fdc3cc683f6120e405f446a10e0f3
+Result = Fail
+
+Count = 85
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = e4f6445ca36e7ee3323f11f6a5ca8ded0c85871e092aa687d254f7765b6155054a5efde28dd38750
+Result = Fail
+
+Count = 86
+Nonce = b672c91376f533
+Adata = 00
+CT = f23ac1426cb1130c9a0913b347d8efafb6ed125913aa678a9dc42d22a5436bc12eff5505edb25e19
+Result = Pass
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 87
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ac9f131389181b1023f1ee47633aa433fc5d93a87d9ece962db05feb368ab772d977fd97b35262fa
+Result = Fail
+
+Count = 88
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 773b8eea2e9830297ac11d3c1f6ea4008c96040e83d76d55789d2043179fdd8fdcbd52313b7b15cb
+Result = Pass
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 89
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = d3fae92043c419fe8ac0d7491ca8041ad089559d895103cf079a2bac0ab4bc249bbdb330181cdd16
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 90
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 63e00d30e4b08fd2a1cc8d70fab327b2368e77a93be4f4123d14fb3f
+Result = Pass
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 91
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = bb5425b3869b76856ec58e39886fb6f6f2ac13fe44cb132d8d0c0099
+Result = Fail
+
+Count = 92
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 2ca3be419d5be5ed682f8954d2c20efd9e6d360814735daeefd4365c
+Result = Fail
+
+Count = 93
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = 3d34bda62db39d6118d6fd5cd38f1a3820ca69ce584b94a2a4ccbef1
+Result = Fail
+
+Count = 94
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 377b2f1e7bd9e3d1077038e084f61950761361095f7eeebbf1a72afc
+Result = Pass
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 95
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 9cef6c889ff51666df9dd1dd2215c15f4b2078a29373c106be4f5f9a
+Result = Fail
+
+Count = 96
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = 6cab3060bf3b33b163b933c2ed0ba51406810b54d0edcf5c9d0ef4f7
+Result = Pass
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 97
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = f9543a659e9a8b7d75dd859df923817452735f5051726422c08a9e85
+Result = Fail
+
+Count = 98
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 0d20bf6a9d02da72091d94cdb38743bfea2473d3ab62dcad75dd819a
+Result = Fail
+
+Count = 99
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = 8bca01e6ebd7ebcdfe52b88e314670ffeb35882fc05394b386e205f9
+Result = Fail
+
+Count = 100
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 7061c84e2e1d9d58013543ff82666055a1f055c1296c42c8f73a8bf0
+Result = Fail
+
+Count = 101
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = c5aa500d1f7c09a590e9d15d6860c4433684e04dd6bc5c8f94f223f0
+Result = Pass
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 102
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = e3efa7971e27ba1245ee9491ebdbb28ad9b24b325da5760417af8b14
+Result = Fail
+
+Count = 103
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = 852cca903d7fdf899807bd14642057534c8a0ccacb8c7b8fb4d35d44
+Result = Pass
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 104
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e04fd4f5b60833021ed57c98de300bb68d0d892b2bf68e080bc044b1
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 105
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = f0050ad16392021a3f40207bed3521fb1e9f808f49830c423a578d179902f912f9ea1afbce1120b3
+Result = Pass
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 106
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = c408190d0fbf5034f83b24a8ed9657331a7ce141de4fae769084607b83bd06e6442eac8dacf583cc
+Result = Fail
+
+Count = 107
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 52b3d31d02d1b92b38cbae8c510204dde6bf9588e994296c9002a46cfb734290924a15e9c3d99924
+Result = Fail
+
+Count = 108
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = f80190470212ce1e64bf4c64ca0133d90469abf87a8233c2b238e316c3f9adccce95e8c8b9c7e8d2
+Result = Fail
+
+Count = 109
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 254b847d4175bbb44a82b4e805514fa444c224710933f3ec8aaa3f0133234c0cd91609982adc034b
+Result = Pass
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 110
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 7a5c7bc02aa69efc5a159d653f3993399f69e20752c3b00633255731cd88345860da913bc696fdc1
+Result = Fail
+
+Count = 111
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = c3618c991b15de641d291419ff6957e8b9ae5046dd8c6f08fafb76adf12f36740347e3edae62bca4
+Result = Pass
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 112
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = 240927bfd671a92aef0311395ad55ae42233ecee53873da4066f55f23d4e55bcbbbf2312ea2d8071
+Result = Fail
+
+Count = 113
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 4731a7e690c77cd47582ce54a1cec23d94c856b93a9fc767004753689cc84810b8414f1464c0c5b9
+Result = Fail
+
+Count = 114
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = f0ea12eaff20c3a50674aa1546aaae3bd5c9249108535b21504da83478ede24026ec91fb12769e4b
+Result = Fail
+
+Count = 115
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 5b164d9752ad6c497a7ab2d0bf8be68fea084ea5839b07b7c9fcf9b9fd5e99767a7b1679b57ea961
+Result = Fail
+
+Count = 116
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = bd37326da18e5ac79a1a9512f724bb539530868576b79c67acb5a51d10a58d6584fbe73f1063c31b
+Result = Pass
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 117
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = 0455b4dd1069281e10531c0dc180ced9a5ef5d3fe0007470ce54cd7623a80a176f29a01b3abb642e
+Result = Fail
+
+Count = 118
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = ecd337640022635ce1ed273756d02b7feeb2515614c1fadc95c66d3f411b478853886afd177d88c3
+Result = Pass
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 119
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e25d7c9fb388596b13a13b885d5b24e31579a3494ad256da830b2b6317716b3975e2b101aebdd920
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 120
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 92d00fbe
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = 9143e5c4
+Result = Fail
+
+Count = 122
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 54337466
+Result = Fail
+
+Count = 123
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = bf0bf84c
+Result = Fail
+
+Count = 124
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = 11250056
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 13de5339
+Result = Fail
+
+Count = 126
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = 4eed80fd
+Result = Pass
+Payload = 00
+
+Count = 127
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = 4bc2e450
+Result = Fail
+
+Count = 128
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = b30e6bbd
+Result = Fail
+
+Count = 129
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = f7c11fe2
+Result = Fail
+
+Count = 130
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 76673751
+Result = Fail
+
+Count = 131
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 9a5382c3
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9e632f56
+Result = Fail
+
+Count = 133
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = e1842c46
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 9f644671
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 135
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 93af11a08379eb37a16aa2837f09d69d
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = d19b0c14ec686a7961ca7c386d125a65
+Result = Fail
+
+Count = 137
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 02ea916d60e2ceec6d9dc9b1185569b3
+Result = Fail
+
+Count = 138
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = fabd2d0c422b47d363ea9936ff4a311b
+Result = Fail
+
+Count = 139
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = b3884b69d117146cfa5529901753ddc0
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 7162026b6306e74fe32ece8433801bc2
+Result = Fail
+
+Count = 141
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = b53d93cbfd3d5cf3720cef5080bc7224
+Result = Pass
+Payload = 00
+
+Count = 142
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = c8bbecf69ecf8d10f0863bb4b7cbed51
+Result = Fail
+
+Count = 143
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = 6037145cc23a175760ae4b573907c80c
+Result = Fail
+
+Count = 144
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = df7ea77425d631f652ffe096a8157f71
+Result = Fail
+
+Count = 145
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 7182b25ef5b113c13fa8f6769e74f1e2
+Result = Fail
+
+Count = 146
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 0a5d1bc02c5fe096a8b9d94d1267c49a
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9eb6d9757ec7c56cc8c79461e0017486
+Result = Fail
+
+Count = 148
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = 1eda43bf07f2bf003107f3a0ba3a4c18
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 5287cc160c5dd3a0f9c1986aac2a621c
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 150
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 866d4227
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 94cb1127
+Result = Fail
+
+Count = 152
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = 82c2b67a
+Result = Fail
+
+Count = 153
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 8c8283f9
+Result = Fail
+
+Count = 154
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = c4ac0952
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = c59aa931
+Result = Fail
+
+Count = 156
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = 27c3953d
+Result = Pass
+Payload = 00
+
+Count = 157
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = cb1ac8eb
+Result = Fail
+
+Count = 158
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4dcc55cc
+Result = Fail
+
+Count = 159
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 727d8f5e
+Result = Fail
+
+Count = 160
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 5aa56a54
+Result = Fail
+
+Count = 161
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = c38fbdff
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 6be30c42
+Result = Fail
+
+Count = 163
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = d34e90bb
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = 4a5d14bc
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 165
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 867b0d87cf6e0f718200a97b4f6d5ad5
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 677a040d46ee3f2b7838273bdad14f16
+Result = Fail
+
+Count = 167
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = f650d46ade2cbabbc68ead6df1ea0c37
+Result = Fail
+
+Count = 168
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 11b8fe8c139ee38f77fd8fa552cbff67
+Result = Fail
+
+Count = 169
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = ad879c64425e6c1ec4841bbb0f99aa8b
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = 3c64f8731930ae000162c10654531066
+Result = Fail
+
+Count = 171
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = e2751f153fc76c0dec5e0cf2d30c1a28
+Result = Pass
+Payload = 00
+
+Count = 172
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = 76127bf891141e73854752ed10c02bd0
+Result = Fail
+
+Count = 173
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4bd833f9da0496e5f6a08a05d02df385
+Result = Fail
+
+Count = 174
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 05f166328a67a8c58b10a7348f3df612
+Result = Fail
+
+Count = 175
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 42499bcd949a5163855a9794f11f917e
+Result = Fail
+
+Count = 176
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = fc85464a81fe372c12c9e4f0f3bf9c37
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 8c7501f423647dee77668858c5e350bb
+Result = Fail
+
+Count = 178
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = b1c09b093788da19e33c5a6e82ed9627
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = d2231ee1455b0bc337c4f8173fb8647c
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 180
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = c2fe12658139f5d0dd22cadf2e901695b579302a72fc56083ebc7720
+Result = Pass
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 181
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = 94748ba81229e53c38583a8564b23ebbafc6f6efdf4c2a81c44db2c9
+Result = Fail
+
+Count = 182
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 1d670ccf3e9ba59186c48da2e5bd0ab21973eee2ea2985bf83a09067
+Result = Fail
+
+Count = 183
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 2c8c80ff10fac1bf6c9c83533c1514ee032c0983730b0657392ae25d
+Result = Fail
+
+Count = 184
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = e1b4ec4279bb62902c12521e6b874171695c5da46c647cc03b91ff03
+Result = Pass
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 185
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = b5dda89fe879d6a665b99285b6d937fd5877ebef4de049fb64b837fb
+Result = Fail
+
+Count = 186
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = 224db21beb8cd0069007660e783c3f85706b014128368aab2a4e56a7
+Result = Pass
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 187
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = ba1ce3a799e1173178b6788723005566f9269d5828c85d28e960a769
+Result = Fail
+
+Count = 188
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 79d59e4bb251988c019c4eaaee2a2513f9cb0521334018fded14a5a5
+Result = Fail
+
+Count = 189
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = af4350795f24087aa05070d6d5f55ebb12d7ad3141066866d7d6c61d
+Result = Fail
+
+Count = 190
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 22d2da531be1f0d1da4bc21f984d29bf56bed2e92da6bf42d0605b84
+Result = Fail
+
+Count = 191
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = 61b46c9024eed3989064a52df90349c18e14e4b552779d3f8f9d6814
+Result = Pass
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 192
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 539799c2b22a33dd648fc4497d12f9455beaf932f1eaaff4d930f5ce
+Result = Fail
+
+Count = 193
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 52f8205534447d722be2b9377f7395938cc88af081a11ccb0d83fa19
+Result = Pass
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 194
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = d11c892ae155098f5e4b5fe60c7afd74fb2dbcc4db956556f243e273
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 195
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 3341168eb8c48468c414347fb08f71d2086f7c2d1bd581ce1ac68bd42f5ec7fa7e068cc0ecd79c2a
+Result = Pass
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 196
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = d543acda712b898cbb27b8f598b2e4438ce587a836e2785147c3338a2400809e739b63ba8227d2f9
+Result = Fail
+
+Count = 197
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 39a8af5c976b995ea8049e55b68bc65503592ab00915638646288ce9dd1c7088c752e35947fdca98
+Result = Fail
+
+Count = 198
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 950fbf6445f6ffb68178f52f5079d0c6081a48ae1f267a0b7fd89caef9388fbb82361b8d53d9edc6
+Result = Fail
+
+Count = 199
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = fbfed2c94f50ca10466da9903ef85833ad48ca00556e66d14d8b30df941f3536ffb42083ef0e1c30
+Result = Pass
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 200
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = 2ebfeb7a843618b37025352df3538526517ed320adfb486c04cf3426e8f975125a7eed00e5f33b6c
+Result = Fail
+
+Count = 201
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = dae13e6967c8b1ee0dd2d5ba1dd1de69f22c95da39528f9ef78e9e5e9faa058112af57f4ac78db2c
+Result = Pass
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 202
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = e683040a0bcf04c1748e7746400d6ef0f7cd8e77a29517790c63959ce534a0f87fb42a9b000dec84
+Result = Fail
+
+Count = 203
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 829e50e8c09e727a58287e6eb7d38edeb8ab39db279c06397d1a2111dc21aec79ef73193b306d31f
+Result = Fail
+
+Count = 204
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = 873c91e76dca0062ae66325aefb84ece3e98928f8dbc5fee7c516d2d1a8318893923f398ca249401
+Result = Fail
+
+Count = 205
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 343f6c86f2b852ac388a096faec4472107a924aba56d0cb88055e777bb57eb49497cd2e233ee06fd
+Result = Fail
+
+Count = 206
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = a654238fb8b05e293dba07f9d68d75a7f0fbf40fe20edaeba1586bf922412e73ce338e372615c3bc
+Result = Pass
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 207
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 4846816923ed9f0254bdd0be01028f75061d3594ad3a45bd03538d108df6ecd6f39acfe076ba5fb8
+Result = Fail
+
+Count = 208
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 765067ef768908d91ee4c3923943e0c7be70e2e06db99a4b3e3f51ee37fdcc5d81dd85d9e9d4f44e
+Result = Pass
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 209
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = e58ea6c1522e5a3e93a85edd05ae80d6cf5c4dd6d604a8f8d8a906488f79ad5d2234d72458dcfcd4
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 210
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = c0ea400b599561e7905b99262b4565d5c3dc49fad84d7c69ef891339
+Result = Pass
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 211
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 60871e03ea0eb968536c99f926ea24ef43d41272ad9fb7f63d488623
+Result = Fail
+
+Count = 212
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 81d7859dcbe51dcc94fe2591cd3b0540003d49a8c4dccbf4527e5ed0
+Result = Fail
+
+Count = 213
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = bef380ad725b65fb5fceeabf09c665bc35089f434ec831494d20d5fa
+Result = Fail
+
+Count = 214
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = fabe11c9629e598228f5209f3dbcc641fe4b1a22cadb0821d2898c3b
+Result = Pass
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 215
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = b7eb87f84951640de731d4093f1a4ed5f831138a27465d3941e92090
+Result = Fail
+
+Count = 216
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = d88f8fcd772125212ce09c2a6e5b5693dd35073f992004f0d18fc889
+Result = Pass
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 217
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = d2d7d52b11304fc1d15b8c20e296ba7c63d99f4ce86cc8ae0f39ecea
+Result = Fail
+
+Count = 218
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = ae1d9f82efb464d5dc2018cffa309634c09b34d1122c4bd994b1d516
+Result = Fail
+
+Count = 219
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 477c985d92ad1b69d22315235a29e3d3a5991487cbdc8d11d394d047
+Result = Fail
+
+Count = 220
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = d1c085c75d808dc6db493b8a0b4d884e0700d2844a1b4b46bd3d22eb
+Result = Fail
+
+Count = 221
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = 76bdd9a7b34bf14ae121a87fdfa144f71b848744af6a2f0b1c0d067c
+Result = Pass
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 222
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 413e2e8df9d65b4e5d3b63a738258aaee643f364be9a01b974192744
+Result = Fail
+
+Count = 223
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 617d8036e2039d516709062379e0550cbd71ebb90fea967c79018ad5
+Result = Pass
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 224
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 40e609c739e409750a6c41d9c6ea64ce36f70711b4ca3e365c916f91
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+
+Count = 225
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 8d34cdca37ce77be68f65baf3382e31efa693e63f914a781367f30f2eaad8c063ca50795acd90203
+Result = Pass
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 226
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 516c0095cc3d85fd55e48da17c592e0c7014b9daafb82bdc4b41096dfdbe9cc1ab610f8f3e038d16
+Result = Fail
+
+Count = 227
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 0293eae9f8d8bd7ad45357f733fc7b5d990d894783e18501d81ec96df41b8fa8262ed2db880b5e85
+Result = Fail
+
+Count = 228
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = 256bad8295e67d8d450f5ecc8276920ec23b1156c57be7c96ee80f60f72db2cbf25b2f8c6af8749c
+Result = Fail
+
+Count = 229
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = 6df09613ea986c2d91a57a45a0942cbf20e0dfca12fbda8c945ee6db24aea5f5098952f1203339ce
+Result = Pass
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 230
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = c5b64577d3c34e50f7da5072db5bda1d1d2c6db1a4f1183e2cc4c90ac3f798957cb09a05868a8ad5
+Result = Fail
+
+Count = 231
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = 2bfe51f1f43b982d47f76ea8206ddbf585d6f30cec0d4ef16b1556631d3b52bf24154afec1448ef6
+Result = Pass
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 232
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = 1622ae109073f44a4596722d9943fea774dfc2a1f939fc0914f42ec81e3af71c9a5de7e0ac16ca69
+Result = Fail
+
+Count = 233
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = 4c0b361a766d366d983c41e793d75635e17f6eab2eadcf9743d67d90850c4c76a43df1f95170b29b
+Result = Fail
+
+Count = 234
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 5b02347f30213df7f1506d7dca41b838c92aea0f190c5dba7bd5d5c8c098299394333b34fae9a110
+Result = Fail
+
+Count = 235
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = c77283ca15484d82469ce7249d1fb8e5f4c3bc8245fb4d97e26149d4a9711be81b4f69aa9fabd7f6
+Result = Fail
+
+Count = 236
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = bf0d219bb50fcc1d51f654bb0fd8b44efa25aef39e2f11afe47d00f2eebb544e6ba7559ac2f34edb
+Result = Pass
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 237
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 1609f8de59da4f50ce034977d132d4f9881a9b85ffa5bb886fa3fddc87690a359fe55f8fa12ba749
+Result = Fail
+
+Count = 238
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881567a6b4426f1667136bed4a5e32a2bc1
+Result = Pass
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 239
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 27c575be0b99af9b106f53f471c31cac4d54ea0bcb602a33fb67bb6092cd579f722ae9b680da083d
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt
new file mode 100644
index 0000000000..6d9a3eadcb
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:26 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = eda32f751456e33195f1f499cf2dc7c97ea127b6d488f211ccc5126fbb24afa6
+
+Count = 0
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 469c90bb
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 46a908ed
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = e776620a3bd961
+Adata = 00
+CT = fdd35c4d
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 869ce60e
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = 1302d515
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = 156416ee
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = a259c114eaac89
+Adata = 00
+CT = 4fe06e92
+Result = Pass (0)
+Payload = 00
+
+Count = 7
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 611091aa
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 696e9371
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = a0e0a2cb
+Result = Fail (2 - CT changed)
+
+Count = 10
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 43cc0375
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = e5417f6b
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = fff8a068
+Result = Fail (1 - Adata changed)
+
+Count = 13
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = f8fa8e71
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 0bfa2d9d
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 15
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 8207eb14d33855a52acceed17dbcbf6e
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 60f8e127cb4d30db6df0622158cd931d
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = e776620a3bd961
+Adata = 00
+CT = 4239f29871651e9a26b8b06ffc5b3748
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 5d35364c621fe8959dfe70ab44700fbe
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = e4dc5e03aacea691262ee69cee8ffbbe
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = c8eb7643b4ed3c796c3873e8c6624e0d
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = a259c114eaac89
+Adata = 00
+CT = f79c53fd5e69835b7e70496ea999718b
+Result = Pass (0)
+Payload = 00
+
+Count = 22
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 687e00723a419fa81c0923b8b8e245ae
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 499ab350309ad6091ec4aaf6bf0cbd00
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = c27b9f14787dc5375f59d0c561a23446
+Result = Fail (2 - CT changed)
+
+Count = 25
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 655c737722c78ac96582a883d407b2bb
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = 10d3f6fe08280d45e67e58fe41a7f036
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = b4e425e43edb92c606f7cb2de8a06932
+Result = Fail (1 - Adata changed)
+
+Count = 28
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = 2590df2453cb94c304ba0a2bff3f3c71
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 1f344e30dfa95b2319e274caa5780e60
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 30
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 8a19a133
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 2e317f1b
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 979bdcfe
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 8ef89acf
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 154024b2
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = 8dbcc439
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 5c349fb2
+Result = Pass (0)
+Payload = 00
+
+Count = 37
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = 79df3e02
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = fbc2c500
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 2fac1bca
+Result = Fail (2 - CT changed)
+
+Count = 40
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = 99948f6e
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = c59bf14c
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = b764c393
+Result = Fail (1 - Adata changed)
+
+Count = 43
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 5b96f41d
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = f7e12df1
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 45
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 97e1a8dd4259ccd2e431e057b0397fcf
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 5a9596c511ea6a8671adefc4f2157d8b
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 66f5c53efbc74fa02dedc303fd95133a
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 2dfd3c852f68eace45acf433a6aa9c05
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 5c8c9a5b97be8c7bc01ca8d693b809f9
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = ec093121bdcd589285f2262be8db5c4e
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 84201662b213c7a1ff0c1b3c25e4ec45
+Result = Pass (0)
+Payload = 00
+
+Count = 52
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = bbe746d6d31e8e9745faed4095ab8d5d
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = 646c1258dc4aa6fc380818e70e5f4328
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 15fa37ca7f2883a4642c1ed41b8f6293
+Result = Fail (2 - CT changed)
+
+Count = 55
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = c6acf5e5ded4efb2c314370ebb9e9cde
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = 586e728193ce6db9a926b03b2d77dd6e
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = 642a187e71feff5989e28184aded0199
+Result = Fail (1 - Adata changed)
+
+Count = 58
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 64864d21b6ee3fca13f07fc0486e232d
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = 58c63ce68f132d30d177c5834344cc5d
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 60
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 64a1341679972dc5869fcf69b19d5c5ea50aa0b5e985f5b722aa8d59
+Result = Pass (0)
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 61
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = c5b7f802bffc498c1626e3774f1d9f94045dfd8e1a10a20277d00a75
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = bf432e246b7fa4aff8b3ada738432b51f6872ed92284db9d28588021
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = 0d5760ad0e156e401120a1ebd1b139248784c88e10e3425437921120
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 5acfbe5e488976d8b9b77e69a736e8c919053f9415551209dce2d25e
+Result = Pass (0)
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 65
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = be8be6046ac58411a00c131dd4a72d565f98d87a2c89124b1ef530d0
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = f00628e10e8e0115b4a4532a1212a23aade4090832c1972d750125f3
+Result = Pass (0)
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 67
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = 9078151f674d5f7b56e2451b0316156f776459f17d277e0108aaaf93
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 921cbecce3b06f3d655a5a0a4d212320d4f147575079fd23bd95e677
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 8cab1ff22d474e9863c153e84680e2a66981f036051360477e2ebb1d
+Result = Fail (2 - CT changed)
+
+Count = 70
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = 15f476b5aefe072548a54f59506d9c3b9ce29025340214be662f8684
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = b672c91376f533
+Adata = 00
+CT = 758aa03dc72c362c43b5f85bfaa3db4a74860887a8c29e47d5642830
+Result = Pass (0)
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 72
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ec645769b22161567e6a7e23aa06575bc767a34aa54d3cba01472fe1
+Result = Fail (1 - Adata changed)
+
+Count = 73
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 615cbeabbe163ba8bc9c073df9ad40833fcf3f424644ccc37aa999d7
+Result = Pass (0)
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 74
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = 0ed6cc6451de57ca672d56dee45d4548a810d5c49dfe442dd27b7cf2
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 75
+Nonce = a544218dadd3c1
+Adata = 00
+CT = bc51c3925a960e7732533e4ef3a4f69ee6826de952bcb0fd374f3bb6db8377ebfc79674858c4f305
+Result = Pass (0)
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 76
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = afa1fa8e8a70e26b02161150556d604101fdf423f332c3363275f2a4907d51b734fe7238cebbd48f
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = 72bc8ef21a847047091b673ccf231d35ecf6f4049741703be672f1f22cbe4a5305f19aaa6967237b
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = b719f6555fc4e5424273f5903d5672af460413110278707f400b152113c3976be63dcd9e7a84ddac
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 4539bb13382b034ddb16a3329148f9243a4eee998fe444aff2870ce198af11f4fb698a67af6c89ad
+Result = Pass (0)
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 80
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = 47cbb909cb12fa0a4b0f1aefd54c52d1edd1533290f76b8ccc98b3f5758972bf08ea9e88dc6e54ed
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = 6d0f928352a17d63aca1899cbd305e1f831f1638d27c1e24432704eff9b6830476db3d30d4c103e4
+Result = Pass (0)
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 82
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = e0e686d917f78b3b0058fed7b084976244789073a6305ff571256981db86f1e768170a104ebfb81d
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 960c573f5d6934a4cac49d06998f827b3d665cf02c998fe55efbbae6a346863a93d52e0321cef8b2
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 7cf8f4806848e34aa7d3bd7e2cb9f5d9ff21395ff6d34826ac2fdc3cc683f6120e405f446a10e0f3
+Result = Fail (2 - CT changed)
+
+Count = 85
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = e4f6445ca36e7ee3323f11f6a5ca8ded0c85871e092aa687d254f7765b6155054a5efde28dd38750
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = b672c91376f533
+Adata = 00
+CT = f23ac1426cb1130c9a0913b347d8efafb6ed125913aa678a9dc42d22a5436bc12eff5505edb25e19
+Result = Pass (0)
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 87
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ac9f131389181b1023f1ee47633aa433fc5d93a87d9ece962db05feb368ab772d977fd97b35262fa
+Result = Fail (1 - Adata changed)
+
+Count = 88
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 773b8eea2e9830297ac11d3c1f6ea4008c96040e83d76d55789d2043179fdd8fdcbd52313b7b15cb
+Result = Pass (0)
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 89
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = d3fae92043c419fe8ac0d7491ca8041ad089559d895103cf079a2bac0ab4bc249bbdb330181cdd16
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 90
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 63e00d30e4b08fd2a1cc8d70fab327b2368e77a93be4f4123d14fb3f
+Result = Pass (0)
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 91
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = bb5425b3869b76856ec58e39886fb6f6f2ac13fe44cb132d8d0c0099
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 2ca3be419d5be5ed682f8954d2c20efd9e6d360814735daeefd4365c
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = 3d34bda62db39d6118d6fd5cd38f1a3820ca69ce584b94a2a4ccbef1
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 377b2f1e7bd9e3d1077038e084f61950761361095f7eeebbf1a72afc
+Result = Pass (0)
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 95
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 9cef6c889ff51666df9dd1dd2215c15f4b2078a29373c106be4f5f9a
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = 6cab3060bf3b33b163b933c2ed0ba51406810b54d0edcf5c9d0ef4f7
+Result = Pass (0)
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 97
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = f9543a659e9a8b7d75dd859df923817452735f5051726422c08a9e85
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 0d20bf6a9d02da72091d94cdb38743bfea2473d3ab62dcad75dd819a
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = 8bca01e6ebd7ebcdfe52b88e314670ffeb35882fc05394b386e205f9
+Result = Fail (2 - CT changed)
+
+Count = 100
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 7061c84e2e1d9d58013543ff82666055a1f055c1296c42c8f73a8bf0
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = c5aa500d1f7c09a590e9d15d6860c4433684e04dd6bc5c8f94f223f0
+Result = Pass (0)
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 102
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = e3efa7971e27ba1245ee9491ebdbb28ad9b24b325da5760417af8b14
+Result = Fail (1 - Adata changed)
+
+Count = 103
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = 852cca903d7fdf899807bd14642057534c8a0ccacb8c7b8fb4d35d44
+Result = Pass (0)
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 104
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e04fd4f5b60833021ed57c98de300bb68d0d892b2bf68e080bc044b1
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 105
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = f0050ad16392021a3f40207bed3521fb1e9f808f49830c423a578d179902f912f9ea1afbce1120b3
+Result = Pass (0)
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 106
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = c408190d0fbf5034f83b24a8ed9657331a7ce141de4fae769084607b83bd06e6442eac8dacf583cc
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 52b3d31d02d1b92b38cbae8c510204dde6bf9588e994296c9002a46cfb734290924a15e9c3d99924
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = f80190470212ce1e64bf4c64ca0133d90469abf87a8233c2b238e316c3f9adccce95e8c8b9c7e8d2
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 254b847d4175bbb44a82b4e805514fa444c224710933f3ec8aaa3f0133234c0cd91609982adc034b
+Result = Pass (0)
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 110
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 7a5c7bc02aa69efc5a159d653f3993399f69e20752c3b00633255731cd88345860da913bc696fdc1
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = c3618c991b15de641d291419ff6957e8b9ae5046dd8c6f08fafb76adf12f36740347e3edae62bca4
+Result = Pass (0)
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 112
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = 240927bfd671a92aef0311395ad55ae42233ecee53873da4066f55f23d4e55bcbbbf2312ea2d8071
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 4731a7e690c77cd47582ce54a1cec23d94c856b93a9fc767004753689cc84810b8414f1464c0c5b9
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = f0ea12eaff20c3a50674aa1546aaae3bd5c9249108535b21504da83478ede24026ec91fb12769e4b
+Result = Fail (2 - CT changed)
+
+Count = 115
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 5b164d9752ad6c497a7ab2d0bf8be68fea084ea5839b07b7c9fcf9b9fd5e99767a7b1679b57ea961
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = bd37326da18e5ac79a1a9512f724bb539530868576b79c67acb5a51d10a58d6584fbe73f1063c31b
+Result = Pass (0)
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 117
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = 0455b4dd1069281e10531c0dc180ced9a5ef5d3fe0007470ce54cd7623a80a176f29a01b3abb642e
+Result = Fail (1 - Adata changed)
+
+Count = 118
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = ecd337640022635ce1ed273756d02b7feeb2515614c1fadc95c66d3f411b478853886afd177d88c3
+Result = Pass (0)
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 119
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e25d7c9fb388596b13a13b885d5b24e31579a3494ad256da830b2b6317716b3975e2b101aebdd920
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 120
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 92d00fbe
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = 9143e5c4
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 54337466
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = bf0bf84c
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = 11250056
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 13de5339
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = 4eed80fd
+Result = Pass (0)
+Payload = 00
+
+Count = 127
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = 4bc2e450
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = b30e6bbd
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = f7c11fe2
+Result = Fail (2 - CT changed)
+
+Count = 130
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 76673751
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 9a5382c3
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9e632f56
+Result = Fail (1 - Adata changed)
+
+Count = 133
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = e1842c46
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 9f644671
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 135
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 93af11a08379eb37a16aa2837f09d69d
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = d19b0c14ec686a7961ca7c386d125a65
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 02ea916d60e2ceec6d9dc9b1185569b3
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = fabd2d0c422b47d363ea9936ff4a311b
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = b3884b69d117146cfa5529901753ddc0
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 7162026b6306e74fe32ece8433801bc2
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = b53d93cbfd3d5cf3720cef5080bc7224
+Result = Pass (0)
+Payload = 00
+
+Count = 142
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = c8bbecf69ecf8d10f0863bb4b7cbed51
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = 6037145cc23a175760ae4b573907c80c
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = df7ea77425d631f652ffe096a8157f71
+Result = Fail (2 - CT changed)
+
+Count = 145
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 7182b25ef5b113c13fa8f6769e74f1e2
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 0a5d1bc02c5fe096a8b9d94d1267c49a
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9eb6d9757ec7c56cc8c79461e0017486
+Result = Fail (1 - Adata changed)
+
+Count = 148
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = 1eda43bf07f2bf003107f3a0ba3a4c18
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 5287cc160c5dd3a0f9c1986aac2a621c
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 150
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 866d4227
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 94cb1127
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = 82c2b67a
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 8c8283f9
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = c4ac0952
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = c59aa931
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = 27c3953d
+Result = Pass (0)
+Payload = 00
+
+Count = 157
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = cb1ac8eb
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4dcc55cc
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 727d8f5e
+Result = Fail (2 - CT changed)
+
+Count = 160
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 5aa56a54
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = c38fbdff
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 6be30c42
+Result = Fail (1 - Adata changed)
+
+Count = 163
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = d34e90bb
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = 4a5d14bc
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 165
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 867b0d87cf6e0f718200a97b4f6d5ad5
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 677a040d46ee3f2b7838273bdad14f16
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = f650d46ade2cbabbc68ead6df1ea0c37
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 11b8fe8c139ee38f77fd8fa552cbff67
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = ad879c64425e6c1ec4841bbb0f99aa8b
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = 3c64f8731930ae000162c10654531066
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = e2751f153fc76c0dec5e0cf2d30c1a28
+Result = Pass (0)
+Payload = 00
+
+Count = 172
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = 76127bf891141e73854752ed10c02bd0
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4bd833f9da0496e5f6a08a05d02df385
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 05f166328a67a8c58b10a7348f3df612
+Result = Fail (2 - CT changed)
+
+Count = 175
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 42499bcd949a5163855a9794f11f917e
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = fc85464a81fe372c12c9e4f0f3bf9c37
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 8c7501f423647dee77668858c5e350bb
+Result = Fail (1 - Adata changed)
+
+Count = 178
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = b1c09b093788da19e33c5a6e82ed9627
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = d2231ee1455b0bc337c4f8173fb8647c
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 180
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = c2fe12658139f5d0dd22cadf2e901695b579302a72fc56083ebc7720
+Result = Pass (0)
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 181
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = 94748ba81229e53c38583a8564b23ebbafc6f6efdf4c2a81c44db2c9
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 1d670ccf3e9ba59186c48da2e5bd0ab21973eee2ea2985bf83a09067
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 2c8c80ff10fac1bf6c9c83533c1514ee032c0983730b0657392ae25d
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = e1b4ec4279bb62902c12521e6b874171695c5da46c647cc03b91ff03
+Result = Pass (0)
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 185
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = b5dda89fe879d6a665b99285b6d937fd5877ebef4de049fb64b837fb
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = 224db21beb8cd0069007660e783c3f85706b014128368aab2a4e56a7
+Result = Pass (0)
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 187
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = ba1ce3a799e1173178b6788723005566f9269d5828c85d28e960a769
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 79d59e4bb251988c019c4eaaee2a2513f9cb0521334018fded14a5a5
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = af4350795f24087aa05070d6d5f55ebb12d7ad3141066866d7d6c61d
+Result = Fail (2 - CT changed)
+
+Count = 190
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 22d2da531be1f0d1da4bc21f984d29bf56bed2e92da6bf42d0605b84
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = 61b46c9024eed3989064a52df90349c18e14e4b552779d3f8f9d6814
+Result = Pass (0)
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 192
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 539799c2b22a33dd648fc4497d12f9455beaf932f1eaaff4d930f5ce
+Result = Fail (1 - Adata changed)
+
+Count = 193
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 52f8205534447d722be2b9377f7395938cc88af081a11ccb0d83fa19
+Result = Pass (0)
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 194
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = d11c892ae155098f5e4b5fe60c7afd74fb2dbcc4db956556f243e273
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 195
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 3341168eb8c48468c414347fb08f71d2086f7c2d1bd581ce1ac68bd42f5ec7fa7e068cc0ecd79c2a
+Result = Pass (0)
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 196
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = d543acda712b898cbb27b8f598b2e4438ce587a836e2785147c3338a2400809e739b63ba8227d2f9
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 39a8af5c976b995ea8049e55b68bc65503592ab00915638646288ce9dd1c7088c752e35947fdca98
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 950fbf6445f6ffb68178f52f5079d0c6081a48ae1f267a0b7fd89caef9388fbb82361b8d53d9edc6
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = fbfed2c94f50ca10466da9903ef85833ad48ca00556e66d14d8b30df941f3536ffb42083ef0e1c30
+Result = Pass (0)
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 200
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = 2ebfeb7a843618b37025352df3538526517ed320adfb486c04cf3426e8f975125a7eed00e5f33b6c
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = dae13e6967c8b1ee0dd2d5ba1dd1de69f22c95da39528f9ef78e9e5e9faa058112af57f4ac78db2c
+Result = Pass (0)
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 202
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = e683040a0bcf04c1748e7746400d6ef0f7cd8e77a29517790c63959ce534a0f87fb42a9b000dec84
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 829e50e8c09e727a58287e6eb7d38edeb8ab39db279c06397d1a2111dc21aec79ef73193b306d31f
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = 873c91e76dca0062ae66325aefb84ece3e98928f8dbc5fee7c516d2d1a8318893923f398ca249401
+Result = Fail (2 - CT changed)
+
+Count = 205
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 343f6c86f2b852ac388a096faec4472107a924aba56d0cb88055e777bb57eb49497cd2e233ee06fd
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = a654238fb8b05e293dba07f9d68d75a7f0fbf40fe20edaeba1586bf922412e73ce338e372615c3bc
+Result = Pass (0)
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 207
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 4846816923ed9f0254bdd0be01028f75061d3594ad3a45bd03538d108df6ecd6f39acfe076ba5fb8
+Result = Fail (1 - Adata changed)
+
+Count = 208
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 765067ef768908d91ee4c3923943e0c7be70e2e06db99a4b3e3f51ee37fdcc5d81dd85d9e9d4f44e
+Result = Pass (0)
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 209
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = e58ea6c1522e5a3e93a85edd05ae80d6cf5c4dd6d604a8f8d8a906488f79ad5d2234d72458dcfcd4
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 210
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = c0ea400b599561e7905b99262b4565d5c3dc49fad84d7c69ef891339
+Result = Pass (0)
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 211
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 60871e03ea0eb968536c99f926ea24ef43d41272ad9fb7f63d488623
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 81d7859dcbe51dcc94fe2591cd3b0540003d49a8c4dccbf4527e5ed0
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = bef380ad725b65fb5fceeabf09c665bc35089f434ec831494d20d5fa
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = fabe11c9629e598228f5209f3dbcc641fe4b1a22cadb0821d2898c3b
+Result = Pass (0)
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 215
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = b7eb87f84951640de731d4093f1a4ed5f831138a27465d3941e92090
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = d88f8fcd772125212ce09c2a6e5b5693dd35073f992004f0d18fc889
+Result = Pass (0)
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 217
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = d2d7d52b11304fc1d15b8c20e296ba7c63d99f4ce86cc8ae0f39ecea
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = ae1d9f82efb464d5dc2018cffa309634c09b34d1122c4bd994b1d516
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 477c985d92ad1b69d22315235a29e3d3a5991487cbdc8d11d394d047
+Result = Fail (2 - CT changed)
+
+Count = 220
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = d1c085c75d808dc6db493b8a0b4d884e0700d2844a1b4b46bd3d22eb
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = 76bdd9a7b34bf14ae121a87fdfa144f71b848744af6a2f0b1c0d067c
+Result = Pass (0)
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 222
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 413e2e8df9d65b4e5d3b63a738258aaee643f364be9a01b974192744
+Result = Fail (1 - Adata changed)
+
+Count = 223
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 617d8036e2039d516709062379e0550cbd71ebb90fea967c79018ad5
+Result = Pass (0)
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 224
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 40e609c739e409750a6c41d9c6ea64ce36f70711b4ca3e365c916f91
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+
+Count = 225
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 8d34cdca37ce77be68f65baf3382e31efa693e63f914a781367f30f2eaad8c063ca50795acd90203
+Result = Pass (0)
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 226
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 516c0095cc3d85fd55e48da17c592e0c7014b9daafb82bdc4b41096dfdbe9cc1ab610f8f3e038d16
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 0293eae9f8d8bd7ad45357f733fc7b5d990d894783e18501d81ec96df41b8fa8262ed2db880b5e85
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = 256bad8295e67d8d450f5ecc8276920ec23b1156c57be7c96ee80f60f72db2cbf25b2f8c6af8749c
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = 6df09613ea986c2d91a57a45a0942cbf20e0dfca12fbda8c945ee6db24aea5f5098952f1203339ce
+Result = Pass (0)
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 230
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = c5b64577d3c34e50f7da5072db5bda1d1d2c6db1a4f1183e2cc4c90ac3f798957cb09a05868a8ad5
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = 2bfe51f1f43b982d47f76ea8206ddbf585d6f30cec0d4ef16b1556631d3b52bf24154afec1448ef6
+Result = Pass (0)
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 232
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = 1622ae109073f44a4596722d9943fea774dfc2a1f939fc0914f42ec81e3af71c9a5de7e0ac16ca69
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = 4c0b361a766d366d983c41e793d75635e17f6eab2eadcf9743d67d90850c4c76a43df1f95170b29b
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 5b02347f30213df7f1506d7dca41b838c92aea0f190c5dba7bd5d5c8c098299394333b34fae9a110
+Result = Fail (2 - CT changed)
+
+Count = 235
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = c77283ca15484d82469ce7249d1fb8e5f4c3bc8245fb4d97e26149d4a9711be81b4f69aa9fabd7f6
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = bf0d219bb50fcc1d51f654bb0fd8b44efa25aef39e2f11afe47d00f2eebb544e6ba7559ac2f34edb
+Result = Pass (0)
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 237
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 1609f8de59da4f50ce034977d132d4f9881a9b85ffa5bb886fa3fddc87690a359fe55f8fa12ba749
+Result = Fail (1 - Adata changed)
+
+Count = 238
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881567a6b4426f1667136bed4a5e32a2bc1
+Result = Pass (0)
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 239
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 27c575be0b99af9b106f53f471c31cac4d54ea0bcb602a33fb67bb6092cd579f722ae9b680da083d
+Result = Fail (1 - Adata changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt
new file mode 100644
index 0000000000..88bdc95fd0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt
@@ -0,0 +1,9 @@
+There are two sets of CCM example files:
+
+1. The response (.rsp) files contain properly formatted CAVS response files.
+
+2. The three DVPT{128/192/256}.txt files contain the same values as the
+ DVPT{128/192/256}.rsp files but have additional information. For the cases
+ that fail, the reason for failure is in parentheses following the result:
+ e.g., Result = Fail (2 - CT changed)
+ This additional information is not in properly formatted response files.
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp
new file mode 100644
index 0000000000..a4fe9130a0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = d24a3d3dde8c84830280cb87abad0bb3
+Nonce = f1100035bb24a8d26004e0e24b
+
+Count = 0
+Adata = 00
+Payload = 7c86135ed9c2a515aaae0e9a208133897269220f30870006
+CT = 1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab1123301219c70599b7c373ad4b3ad67b
+
+Count = 1
+Adata = 00
+Payload = 48df73208cdc63d716752df7794807b1b2a80794a2433455
+CT = 2bf7d09079bc0b904c711a0b0e4a70ca8ea892d9566f03f8b77a140819f39ef045103e785e1df8c2
+
+Count = 2
+Adata = 00
+Payload = b99de8168e8c13ea4aef66bdb93133dff5d57e9837ff6ccb
+CT = dab54ba67bec7bad10eb5141ce3344a4c9d5ebd5c3d35b664b01098842a618390619b86e00850b2e
+
+Count = 3
+Adata = 00
+Payload = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce
+CT = 6ad4821cbf7f2b9973662b5084aff39b69c6276d8636c0638bd518724ab84fb814fe7b5570769f7f
+
+Count = 4
+Adata = 00
+Payload = cb43320d7488dfd6eed9efd88f440ea3f6f77a0df09d0727
+CT = a86b91bd81e8b791b4ddd824f84679d8caf7ef4004b1308a7229cbcecef221570cee8345b38cd6ec
+
+Count = 5
+Adata = 00
+Payload = a350ed58c04473e113b9088b1fb9dad92807f6b63b0d690c
+CT = c0784ee835241ba649bd3f7768bbada2140763fbcf215ea1fee47fec27d7764e5e2819c850088bac
+
+Count = 6
+Adata = 00
+Payload = 0709e691faf41383fab5d1848a8eee77101d1c99e526a264
+CT = 642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d610bc1ab4bc9a8a28c7306f7c539e
+
+Count = 7
+Adata = 00
+Payload = e7b913c2f0630562eb1c16b3b1ed84090c011a15c09e5471
+CT = 8491b07205036d25b118214fc6eff37230018f5834b263dc2e31657ecc51f5ec8590482fc053230d
+
+Count = 8
+Adata = 00
+Payload = 6b909697074900d41ce8c7d559b229af11fb3cec334784d4
+CT = 08b83527f229689346ecf0292eb05ed42dfba9a1c76bb379d500827f2081b00397102f90fc9ccd88
+
+Count = 9
+Adata = 00
+Payload = 495ff03335bcb39a317b9ea3f8bb6306fa771f3c55adebce
+CT = 2a775383c0dcdbdd6b7fa95f8fb9147dc6778a71a181dc63e2e7997803029476598c0e8d4fc63857
+
+[Alen = 1]
+
+Key = 08b0da255d2083808a1b4d367090bacc
+Nonce = 777828b13679a9e2ca89568233
+
+Count = 10
+Adata = dd
+Payload = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0
+CT = e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6282283e16602331bcca9d51ce76
+
+Count = 11
+Adata = c5
+Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
+CT = f0828917020651c085e42459c544ec52e99372005362baf308ebeed45f67ef8733737c9c6f82daad
+
+Count = 12
+Adata = 68
+Payload = 9c4cd65b92070bc382fd18146611defb4204acddfdf6b276
+CT = 6fe1b1d12ffd9676197322ab732e80b1183032b65be00628f9b477e3a23bfdfdb619c7bc531fbcce
+
+Count = 13
+Adata = be
+Payload = 2ff93ef2fc5fe2c297ace05f3f7585aed75ef90ade3acf89
+CT = dc54597841a57f770c22dae02a4adbe48d6a6761782c7bd7aa82130f5a86c0cd0433585e5c208cf7
+
+Count = 14
+Adata = 7a
+Payload = 62766e9acd41285eeed9b4007340dbb611699624274ad117
+CT = 91db091070bbb5eb75578ebf667f85fc4b5d084f815c65499d60012a2f25463e036ceecea57b3c97
+
+Count = 15
+Adata = 13
+Payload = ea689c268a04912d0527b16d9d9406df38302fb11cb64a99
+CT = 19c5fbac37fe0c989ea98bd288ab58956204b1dabaa0fec7e337897c90eb260729a729aed1c8a244
+
+Count = 16
+Adata = e5
+Payload = f31e35953beb211efcce487ba8c0cd1a8446343d5851b9fd
+CT = 00b3521f8611bcab674072c4bdff9350de72aa56fe470da373dc2911c75b37cd995481d42b04524a
+
+Count = 17
+Adata = e3
+Payload = c4ac3c645387584c2a95b1f16b8317730592924dd831a388
+CT = 37015beeee7dc5f9b11b8b4e7ebc49395fa60c267e2717d684f76ecf3dc5f3307ce982f185321248
+
+Count = 18
+Adata = d5
+Payload = 81af394c2ea3a85e1ea954596e3772f01635d007794c0b19
+CT = 72025ec6935935eb85276ee67b082cba4c014e6cdf5abf472c38d0fe4e4eba054c1420c39a3dcc61
+
+Count = 19
+Adata = ed
+Payload = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304
+CT = 13bec5676842f61e167bf32b183552cc1e4c5fc6e470375a7cfa6c9945f5aee3c799eee37b0605db
+
+[Alen = 2]
+
+Key = 1538cc03b60880bf3e7d388e29f27739
+Nonce = 9e734de325026b5d7128193973
+
+Count = 20
+Adata = c93c
+Payload = e7b819a853ffe79baaa72097ff0d04f02640ae62bcfd3da5
+CT = 1d8f42f9730424fa27240bd6277f4882604f440324b11b003ca01d874439b4e1f79a26d8c6dc433a
+
+Count = 21
+Adata = 4cf9
+Payload = dc6cf325ed6d968efba9f57e48a58f4578cc3540fe121ba2
+CT = 265ba874cd9655ef762ade3f90d7c3373ec3df21665e3d07b40653cd23afc7cc7a31fa13ba8f4e49
+
+Count = 22
+Adata = b469
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = d89c315c8f6ef204502b4f8d3699345c6153e166b2a1f421c8c10aaf90b1116be216f912c82ca96a
+
+Count = 23
+Adata = cf6b
+Payload = a35f62a431fee63468dc02fdf7bef78d3a5937de56151939
+CT = 596839f511052555e55f29bc2fccbbff7c56ddbfce593f9c2f568ef41324189fb3644edcd76dc19c
+
+Count = 24
+Adata = af7c
+Payload = 548840cb0400824af809fb68447500b77e977128200d3b81
+CT = aebf1b9a24fb412b758ad0299c074cc538989b49b8411d242548c244a875d3681d715db3da19962f
+
+Count = 25
+Adata = 61dc
+Payload = 440b6095c77495e73fff54c785b7ceb5eb358731c213ffcd
+CT = be3c3bc4e78f5686b27c7f865dc582c7ad3a6d505a5fd968b599bc8927ad8d43067807f4b858f854
+
+Count = 26
+Adata = b97e
+Payload = 50c59ca54eb64575b82b13c6dac96488af369e9f5f86cdf2
+CT = aaf2c7f46e4d861435a8388702bb28fae93974fec7caeb577454774ee78f76e555cf743df340381e
+
+Count = 27
+Adata = 57ab
+Payload = 21b8eb1f0bda26ca36167ce7bc2e796818bf11fc8c192885
+CT = db8fb04e2b21e5abbb9557a6645c351a5eb0fb9d14550e20e0a22a5ee031978271c7dd2a0d4e7018
+
+Count = 28
+Adata = 5f9c
+Payload = b4d84fb1e81e18c89391a7a59fc05fedaf160e0d0d027a7c
+CT = 4eef14e0c8e5dba91e128ce447b2139fe919e46c954e5cd99a242ebae5c6da57ee38e5c227c46b32
+
+Count = 29
+Adata = e0c4
+Payload = 54dc5a0e1b67577cda4e7dbd48b769c120c1d13dd567cfad
+CT = aeeb015f3b9c941d57cd56fc90c525b366ce3b5c4d2be908a5f8a92f4201c4658289307167cee810
+
+[Alen = 3]
+
+Key = f149e41d848f59276cfddd743bafa9a9
+Nonce = 14b756d66fc51134e203d1c6f9
+
+Count = 30
+Adata = f5827e
+Payload = 9759e6f21f5a588010f57e6d6eae178d8b20ab59cda66f42
+CT = f634bf00f1f9f1f93f41049d7f3797b05e805f0b14850f4e78e2a23411147a6187da6818506232ee
+
+Count = 31
+Adata = e9699b
+Payload = 1555bc87d6c688fd221a2c75cd1e4dd1c1693207ac421d24
+CT = 7438e575386521840dae5685dc87cdec14c9c65575617d28f10835db9897b7528e3204fe3a81424f
+
+Count = 32
+Adata = 972896
+Payload = b72b2a080d92f3f3bb7d96222982de82a28c9eebaddba247
+CT = d64673fae3315a8a94c9ecd2381b5ebf772c6ab974f8c24b3efa05ba4a73ec2234461d459f54acd2
+
+Count = 33
+Adata = 3053f3
+Payload = b5417ed6933ffe2b57ea601d77e97eb12fa1fb8fdc06c86f
+CT = d42c27247d9c5752785e1aed6670fe8cfa010fdd0525a863b557537c6525e827750917a1ed49602f
+
+Count = 34
+Adata = 24db75
+Payload = 4e7f42666035a00e62783283c54b027603917685d27326bc
+CT = 2f121b948e9609774dcc4873d4d2824bd63182d70b5046b0dfd06b037e9094f120eb3d8649d48918
+
+Count = 35
+Adata = ff27a4
+Payload = 7bf180699c294421ad9565cacc27227a4b3a7cf9637290c6
+CT = 1a9cd99b728aed5882211f3addbea2479e9a88abba51f0cabfa8cfabbd79b3e3210482e6f3822fee
+
+Count = 36
+Adata = 77ec24
+Payload = 3d47071c13f994cb42fb2887e5c6e53a542be7ddad9779e0
+CT = 5c2a5eeefd5a3db26d4f5277f45f6507818b138f74b419ec3b9575e347051e98d0c8646ad46318e6
+
+Count = 37
+Adata = 6d7748
+Payload = 317d5da0a2ec12c3b96c83dd61cc955242a9c1c640e2b92f
+CT = 501004524c4fbbba96d8f92d7055156f9709359499c1d92378e7af65eb0388ae7a52f58f6ba32109
+
+Count = 38
+Adata = 029674
+Payload = c9bb21306ee1b4a6c4fa5443af2e181716993cbb374e177c
+CT = a8d678c280421ddfeb4e2eb3beb7982ac339c8e9ee6d77708019fa97ff70d4d21c0bd83caa434b3a
+
+Count = 39
+Adata = 60dfe8
+Payload = 44eb7edd6bee501ad97873aa7ecbf7ed8b613760d7c95e15
+CT = 2586272f854df963f6cc095a6f5277d05ec1c3320eea3e191814ed48a21d97ea02e86d7e6e8834cb
+
+[Alen = 4]
+
+Key = 9a57a22c7f26feff8ca6cceff214e4c2
+Nonce = 88f30fd2b04fb8ddbce8fc26e6
+
+Count = 40
+Adata = a95bdff6
+Payload = 035c516776c706a7dd5f181fa6aa891b04dd423042ea0667
+CT = b92f7ec2ebecebdbd2977b3874e61bf496a382153b2529fc9b6443a35f329b2068916fb6ab8227eb
+
+Count = 41
+Adata = d2672cbb
+Payload = 3ba306bcec94615c347f990b62841a16df7b321f113f1714
+CT = 81d0291971bf8c203bb7fa2cb0c888f94d05f23a68f0388f19e2aa492ce9ddfb6de0ab7a447f5351
+
+Count = 42
+Adata = 737f4d00
+Payload = 68313a29ace3efe521c3ca1e5bac8e98d6b4434c80a7dc74
+CT = d242158c31c802992e0ba93989e01c7744ca8369f968f3ef2bf683b1209f104e82ba39f7c62cd666
+
+Count = 43
+Adata = 3610b1ae
+Payload = 963bfe556138317bebe3936b18a2c1dd100dc73be6fde556
+CT = 2c48d1f0fc13dc07e42bf04ccaee53328273071e9f32cacd4fc7d5cac043f182edbe5c2658f73092
+
+Count = 44
+Adata = f1aa7f72
+Payload = 52d5c53ee4f23cb050a95db54112b44033c34ac31de96be8
+CT = e8a6ea9b79d9d1cc5f613e92935e26afa1bd8ae664264473b8234f3fbaca3dc2c497418219151b05
+
+Count = 45
+Adata = 6b1013aa
+Payload = a302aebc0f8fd61badc8371991beacf5933de46effacb8ce
+CT = 1971811992a43b67a200543e43f23e1a0143244b866397558fa5f9539e0500f139016e4a4337d86b
+
+Count = 46
+Adata = 33028129
+Payload = f7d653c23254875625b20e1ef60ae92847046d84bb4ce857
+CT = 4da57c67af7f6a2a2a7a6d3924467bc7d57aada1c283c7ccfa2379fde155e64b5b84e336056445c3
+
+Count = 47
+Adata = 2cab4a09
+Payload = 872a3f7230e626abff519e5aeecc93897249405daeaffc98
+CT = 3d5910d7adcdcbd7f099fd7d3c800166e0378078d760d30358208335cb81e4fb10923fca4ddb9ff9
+
+Count = 48
+Adata = 73142ba7
+Payload = 766f94e7d9b1ce74bbaf2c99d215350f060122767fc1953f
+CT = cc1cbb42449a2308b4674fbe0059a7e0947fe253060ebaa42d6ecfb49ac8983415503efef1e21950
+
+Count = 49
+Adata = bc9f967e
+Payload = 5f089ed9267363bc23c6c7b8f73208a36f61fa8ea8084ff7
+CT = e57bb17cbb588ec02c0ea49f257e9a4cfd1f3aabd1c7606c1978a62d15430fc20b87940292b49641
+
+[Alen = 5]
+
+Key = 54caf96ef6d448734700aadab50faf7a
+Nonce = a3803e752ae849c910d8da36af
+
+Count = 50
+Adata = 5f476348dd
+Payload = c69f7c5a50f3e72123371bbfd6bdf532b99ef78500508dfe
+CT = 20c43ad83610880249f1632dd418ec9a5ed333b50e996d1a4e5a32fbe7961b832b722bc07a18595b
+
+Count = 51
+Adata = 07db8aada5
+Payload = 9cf8b638f2b295b85cf782fabab11153dc091b4afcd761a9
+CT = 7aa3f0ba9451fa9b3631fa68b81408fb3b44df7af21e814d401a2222443696021b5faa520129b563
+
+Count = 52
+Adata = 31ef6561ff
+Payload = 62b8263dc015ef873cd16272e4da89799b910f2b04204420
+CT = 84e360bfa6f680a456171ae0e67f90d17cdccb1b0ae9a4c4f842681d2e90da5718234ed893197662
+
+Count = 53
+Adata = e97dfcbafb
+Payload = 810bed3a2bc0f9d75389155b7a39d9d014c08646814f9718
+CT = 6750abb84d2396f4394f6dc9789cc078f38d42768f8677fc33a08eb30ee154f71279682ab02eff27
+
+Count = 54
+Adata = 4981c51fcc
+Payload = 063d23fc3ec344c1ba3486802e01e55617455d5cfbfb5279
+CT = e066657e58202be2d0f2fe122ca4fcfef008996cf532b29d8d3071c79f0cf86fe4148cb5e8ace0ce
+
+Count = 55
+Adata = c8437dba76
+Payload = 41db5b245ea0fab985b93e7fc0a00cd3cca5bdbb642b7ebf
+CT = a7801da63843959aef7f46edc205157b2be8798b6ae29e5b842700619dc1599603f3f3f6cfdf5e0b
+
+Count = 56
+Adata = 6f65a24344
+Payload = b0e36734b2ba871d59df0b029c7f32af68e003a689ac4911
+CT = 56b821b6d459e83e331973909eda2b078fadc7968765a9f539a0cd8d8bbf211b907f34411f868c79
+
+Count = 57
+Adata = cd62d6d203
+Payload = 747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2
+CT = 922515644109d2c3a7b1af1f1972391642553c92f9a7b746c4a90e5fc11266bab77eea1d24fbdbb9
+
+Count = 58
+Adata = 9663b3c8e6
+Payload = c70c92ec4c518802662fa4c41a6a33a22599f79f8f7264b3
+CT = 2157d46e2ab2e7210ce9dc5618cf2a0ac2d433af81bb8457b3c1246f7dd6462ce757db82db45f36e
+
+Count = 59
+Adata = 35c4720d3c
+Payload = a26835605b66fc08abdbb5dc77e39783d60b8e8f2314e95f
+CT = 443373e23d85932bc11dcd4e75468e2b31464abf2ddd09bbd472c06a5f4c04f97d06ec401d3e7fd9
+
+[Alen = 6]
+
+Key = cc0c084d7de011e2f031616a302e7a31
+Nonce = f0b4522847f6f8336fe534a4e7
+
+Count = 60
+Adata = da853a27aee2
+Payload = 15b369889699b6de1fa3ee73e5fe19814e46f129074c965b
+CT = f39755d160a64611368a8eccf6fcbc45ef7f1f56240eb19a2e3ca4ec3c776ab58843f617d605fd72
+
+Count = 61
+Adata = d4ed4584678e
+Payload = a18c0460b56a5bcd5bf6842cec6ed44d90b2bfa968a6a7e7
+CT = 47a838394355ab0272dfe493ff6c7189318b51d64be48026327804c44c8f17a4446a3d5ba85f9c7f
+
+Count = 62
+Adata = 590a27721a36
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = a7eadcb559a39501de6924b5e07bf12be89c6b08be689c0bbcd00e9cb726d75e4283820ee81d933a
+
+Count = 63
+Adata = 58830fb0b1f3
+Payload = dce983e4e3734a9bd8848dba0d744d07bbeba602f4006025
+CT = 3acdbfbd154cba54f1aded051e76e8c31ad2487dd74247e4d5d71a1f0f1b6518c35f0632a30931fd
+
+Count = 64
+Adata = eedd0d767a25
+Payload = 4653b3e879ab18b65c5c3706a5139698262cb830a22d943b
+CT = a0778fb18f94e879757557b9b611335c8715564f816fb3fa3ad112899e9ba442660eb5dfe33b2f96
+
+Count = 65
+Adata = 618bcf2e3e79
+Payload = 8586383281925363ac15fb19c26d64c639c75920c792dc2c
+CT = 63a2046b77ada3ac853c9ba6d16fc10298feb75fe4d0fbed54fba446028919342b2fe86ee67efcc7
+
+Count = 66
+Adata = 549c9b84c7f7
+Payload = 95c25ae4445cd8c4d267df82687484667e309992fcf1e737
+CT = 73e666bdb263280bfb4ebf3d7b7621a2df0977eddfb3c0f69fc23013142f62881ccfa3037067e1ef
+
+Count = 67
+Adata = 92d7fa6a8135
+Payload = e58034bbb0e6f5e724e32ee56896dadae25c2a3efb8c6f2f
+CT = 03a408e246d905280dca4e5a7b947f1e4365c441d8ce48ee8263568d56fae8bf35b2f2cdecbffe0a
+
+Count = 68
+Adata = f43e126c0f83
+Payload = d98f0dddfe9cb3cae1336970d5efb55316a65e2c51e316f4
+CT = 3fab318408a34305c81a09cfc6ed1097b79fb05372a13135de2c2fbfdddc7dd6672714af174c5121
+
+Count = 69
+Adata = f02074812dde
+Payload = 548747b1669c6383b793054d93957f9e99d605761c6c23b5
+CT = b2a37be890a3934c9eba65f28097da5a38efeb093f2e04743704560ff23ce0000fba8812c45940ad
+
+[Alen = 7]
+
+Key = d7572ed0e37261efa02f8c83e695efdc
+Nonce = f4f96d7b4384a3930b3d830f82
+
+Count = 70
+Adata = 922340ec94861f
+Payload = 1edef80c57d17f969f8bde10ab38a1a8811a124de72c526e
+CT = de14558cc686e1836f1f121ea1b941a9ebd4f0fb916dc870fd541b988a801cb5751c7faaf5b0c164
+
+Count = 71
+Adata = 4eb379f21b1531
+Payload = ddd5282a207c1dcb03c1c3bbc9eb12a7bd28534118db2735
+CT = 1d1f85aab12b83def3550fb5c36af2a6d7e6b1f76e9abd2bc068bd1b1c309dfbd52d9a24be07c630
+
+Count = 72
+Adata = 7fa89e9d6e3fec
+Payload = c5b7c462eb166f48bb59c8102ee7b3dc67a28e5de7570c51
+CT = 057d69e27a41f15d4bcd041e246653dd0d6c6ceb9116964f2d114d6ab082738d05d60acca8e8ccfb
+
+Count = 73
+Adata = fda8665f87c618
+Payload = af793815e147e3180f5146aa6a582e343dc479f26b4226b2
+CT = 6fb3959570107d0dffc58aa460d9ce35570a9b441d03bcac1cc84bd77fe00e1a13433f2c10e3b799
+
+Count = 74
+Adata = 46bde207491ebd
+Payload = 47c76a0bbd5b1616b278089d41a050c509c7a1c280574bf7
+CT = 870dc78b2c0c880342ecc4934b21b0c463094374f616d1e9990c81f1bae32c953bf02ddbde047632
+
+Count = 75
+Adata = a799f5f895fd7a
+Payload = d554806ffc3900a0952a3c094c745808950697a6e5d62c1d
+CT = 159e2def6d6e9eb565bef00746f5b809ffc875109397b6031af19f1f080dd1dd2da799059755e49f
+
+Count = 76
+Adata = 20225831a9ee06
+Payload = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b
+CT = 7a8f4c050fad7d7754decd18abcfa88ac9a738da00820b2523d3b9a0060834ac4860dae0eac570ef
+
+Count = 77
+Adata = 785360916464eb
+Payload = 57bc338946ff78cf76adf5021e2e44e34e687fb68ad703f3
+CT = 97769e09d7a8e6da8639390c14afa4e224a69d00fc9699edff96e7cf841a66c50bbb6fb2bac7ef51
+
+Count = 78
+Adata = 57b946369226db
+Payload = 9ac5be9929c4fe5a9992749a38dc69874866db3d4747da97
+CT = 5a0f1319b893604f6906b894325d898622a8398b3106408986e1c33a45f9d52755c374650635bef6
+
+Count = 79
+Adata = 73e4da8973c1e3
+Payload = 5a05410aa3a71f5f1a253b8576eba269c06a4c30591144cc
+CT = 9acfec8a32f0814aeab1f78b7c6a4268aaa4ae862f50ded2d78592c2d89c15edc5bb7486aa93f896
+
+[Alen = 8]
+
+Key = 98a42d7a0c5917deaf3b4de3f0cbe0a1
+Nonce = 03d33ab0c2df7bfce88b5ee4c4
+
+Count = 80
+Adata = 2d5438b728b950d9
+Payload = 9aa9c8358117564371366beeec923051ef433252197aaad5
+CT = 9ff942baa60f440c17a78e9581216b9a947a67f04d54911feecfff971fdfaa856310b014aa59c978
+
+Count = 81
+Adata = 6e430b497a16e7f5
+Payload = 5758a500978c71a9b90f6e5beae9d96ef05a41486b10ea2e
+CT = 52082f8fb09463e6df9e8b20875a82a58b6314ea3f3ed1e46a4d7b4b4df6c831ee32116ee4dad98c
+
+Count = 82
+Adata = e12f98507d6514c3
+Payload = 49efe18c76a8355127d914a3a830c1c6ff2a163d728526e1
+CT = 4cbf6b0351b0271e4148f1d8c5839a0d8413439f26ab1d2b3243fc75cd1624e152f451678edcac87
+
+Count = 83
+Adata = eecf8d641ee0bee9
+Payload = 49ae2309fbe6ce4e9421516b8f79ae64b1316cb849eaf638
+CT = 4cfea986dcfedc01f2b0b410e2caf5afca08391a1dc4cdf2dd6d8ca57da1880e1baff43736b3da34
+
+Count = 84
+Adata = 9066367c784de0a4
+Payload = b1bda5fa4242aa6aad0f5a5b1d31d86b8d4a97588b3e315d
+CT = b4ed2f75655ab825cb9ebf20708283a0f673c2fadf100a97f05439a661001513a96b896de46b7081
+
+Count = 85
+Adata = edf848b2510f7803
+Payload = eaa8608f6763d968576a7e89056b9828a1686c8441b06377
+CT = eff8ea00407bcb2731fb9bf268d8c3e3da513926159e58bdcf20709b2dc2ff9946094190b5ea09d1
+
+Count = 86
+Adata = 0f49cae81c8628d2
+Payload = f32029cf51609f0df9832ad1b283ea94a5356f70112c1328
+CT = f670a34076788d429f12cfaadf30b15fde0c3ad2450228e2a5bb6b4f87b9b198665203e4fdf9e7f7
+
+Count = 87
+Adata = b0c47e9cce46a276
+Payload = 7a550ef9254a8da6e4fee290a76ea838ffb61d3533d4d31f
+CT = 7f05847602529fe9826f07ebcaddf3f3848f489767fae8d529f416f89f1a34bbbf2ce40d943c6d8b
+
+Count = 88
+Adata = a6fe7c9ce2d49f85
+Payload = e67c486dd7ba9a9061844b9354f55890321ae626efaa28cc
+CT = e32cc2e2f0a288df0715aee83946035b4923b384bb8413067eb95550b91b955d5c2d72d5c189b704
+
+Count = 89
+Adata = eb1d11cc4876f58f
+Payload = 35f2c810091e930a52e4a3f28c9c8184967f1554c2675eb5
+CT = 30a2429f2e06814534754689e12fda4fed4640f69649657f0e8e8a5a7e0ea6860bab4a4320f03ae5
+
+[Alen = 9]
+
+Key = 2a68e3fe746f593c1b97cb637079c3e5
+Nonce = cd62d0f27b7f4864dc7c343acd
+
+Count = 90
+Adata = abe4f1d3812bfe3ccf
+Payload = 13b4a874888db0e5d8fd814b5e7e04f7fdfbc1601ccc02bc
+CT = 032835a3dbf688d09cf2a32a92b101959d33ff47500f92f4fd49840440f866d1a22b0854996111d8
+
+Count = 91
+Adata = 2e21f466814d3d6340
+Payload = 08b5c773364cded74d7b308984313c17ff90eed496a27a2b
+CT = 18295aa46537e6e2097412e848fe39759f58d0f3da61ea63de2f5c335df537fbbc6ae59cd562732f
+
+Count = 92
+Adata = dba22aabcea0e694fc
+Payload = bbac1790abb7aafe272ec472c897e6363e335b3c4126c762
+CT = ab308a47f8cc92cb6321e6130458e3545efb651b0de5572acc5ed6e4a907ff4742ab6c835a427f92
+
+Count = 93
+Adata = 97e9d16bd757395ec1
+Payload = 7249612dc09809bbca9dd311e720f7da2cb54ce33e3eb9c3
+CT = 62d5fcfa93e3318e8e92f1702beff2b84c7d72c472fd298b1714b5a3df454f3bc35869da75adc882
+
+Count = 94
+Adata = 866cf710470cac74d3
+Payload = 060ae0ab9857324a3b2ac79f3b6e6f90f5de884ce9c7b930
+CT = 16967d7ccb2c0a7f7f25e5fef7a16af29516b66ba5042978aa33dffe2596832f98a9c8413bd898b9
+
+Count = 95
+Adata = 2dd7a7f832b29ccce2
+Payload = f77a9fd5363836deefd34e1bea0882484a7ab746b4495d59
+CT = e7e6020265430eebabdc6c7a26c7872a2ab28961f88acd11dd5049f7c53d6a7fe5d7f959689ee960
+
+Count = 96
+Adata = 502349a60e897356b5
+Payload = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34
+CT = 868d1068b64f0cedead7a50869faee6eeb9077fbed0b8c7ced9c3a0d0de8788471c5f6c2f9638b7c
+
+Count = 97
+Adata = debed45c9acf129268
+Payload = df5a47d3eb5c0b6cabb6711a45400602d205b82ecae9e849
+CT = cfc6da04b8273359efb9537b898f0360b2cd8609862a7801d49b4b9bead1b7de2021cff280d6f93b
+
+Count = 98
+Adata = 2726702dd62a6e5344
+Payload = 5a7649cb001fbb6f653cbca17756c5c1a078c2e240d92085
+CT = 4aead41c5364835a21339ec0bb99c0a3c0b0fcc50c1ab0cd69df31aba209d87ee22bd6a1dcadb168
+
+Count = 99
+Adata = e8006cfb0536696ac7
+Payload = 95186d41f927cdbef42157f21d966e88061b6558b5ec932f
+CT = 8584f096aa5cf58bb02e7593d1596bea66d35b7ff92f03677cc5b60c881fe834a789d28447d8fb54
+
+[Alen = 10]
+
+Key = 46b067cf9b1a28cf187002e90b14e130
+Nonce = bad8c03292bf01cfd8d34f860c
+
+Count = 100
+Adata = 8d65880eddb9fd96d276
+Payload = cc0915194218d4536e467433cd6d79ff1d9eb9ff160ab684
+CT = bd56edc015692c6ab9bec493a9893863598414a3d11a6a0f27ecdcb257d0d30491e5bf1aa8f90958
+
+Count = 101
+Adata = 8a65cde13149d9d54a5b
+Payload = 28257133b1d8b0b2be4faecd6e819ac783707a5c5f50c302
+CT = 597a89eae6a9488b69b71e6d0a65db5bc76ad70098401f89b10f9fc201e4128696dcd899dd2e24ea
+
+Count = 102
+Adata = e999ec3e1bfb25b5877c
+Payload = 96ab0cfc204bafc4f5851d6c682d631d0c5ad03ac925a943
+CT = e7f4f425773a57fd227dadcc0cc9228148407d660e3575c8c522e5ba5adbc6a639cbd06f103ebc9e
+
+Count = 103
+Adata = a8554441e073d6065dce
+Payload = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+CT = 21cda08aff3bcbc6eed9e44483d3ae5dc9d564d38a42e922e1a4e0f7ebc3cff3915d27971cce7e91
+
+Count = 104
+Adata = 838f0be8d04d28d77549
+Payload = d0700658d5f4010ff21091f3d119c99645e339198029c3a9
+CT = a12ffe818285f93625e82153b5fd880a01f9944547391f22c215c88d80bffc881aff10ba40f11976
+
+Count = 105
+Adata = 20f014d928d5b25fbaf4
+Payload = 4bdf28748a0c281dd49c7294ae8e55fe7a52d45ff6384db3
+CT = 3a80d0addd7dd0240364c234ca6a14623e487903312891382cc9391bc06aa6ca9d486a4e2a218c54
+
+Count = 106
+Adata = 56c026b8a71974ff7ecd
+Payload = f75db057f0276fff85014f54ecdec8f90b96a2a982db14cb
+CT = 8602488ea75697c652f9fff4883a89654f8c0ff545cbc840778b05c6c582a0bb7d1d9dcf6a46b9f6
+
+Count = 107
+Adata = 75c3b9e52648a4f9aca9
+Payload = c15c554169dbb9b08494afaa44819a10dc9ddad54199ab54
+CT = b003ad983eaa4189536c1f0a2065db8c98877789868977dff47d9ebbd3cff14623b10cecc94b53d6
+
+Count = 108
+Adata = 1c76c3014a14b7fa1ca8
+Payload = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032
+CT = 68b10e2ecf8d9031bd55ac7a099d37518bfc15f3b3495cb9d2b74b84dc170c00dce85b56e346a976
+
+Count = 109
+Adata = a4eb60d4eb7ead1bd0e6
+Payload = e06e5dba5ac35cfd07949e5cc12ad70507d4a86a952ecca3
+CT = 9131a5630db2a4c4d06c2efca5ce969943ce0536523e1028d92e19fd8b5c1fcbff36adaa5e47ae84
+
+[Alen = 11]
+
+Key = e94dac9c90984790a7c0c867536615ff
+Nonce = c19f06f91e645d4199365f18c0
+
+Count = 110
+Adata = 537038b5357e358a930bd6
+Payload = 4d64461c55eb16bf7b9120f22be349598f2f394da8460dc6
+CT = e9fc5004c2359724e1e4411ae6f834ef6bea046d549753c88790c1648f461a31c84e62ea8592a074
+
+Count = 111
+Adata = 7e3d7b3eada988668f3784
+Payload = eab7d5dbd91d4cbbac8d79fadd70b5dcb3baadac5cb713a3
+CT = 4e2fc3c34ec3cd2036f81812106bc86a577f908ca0664dadacb1d1c9231d2c22ecfeed622792dfd0
+
+Count = 112
+Adata = 78b107b29c4878ff18f749
+Payload = 3c6ae2e2578875a1f5611582528e058aece2ddc33a4dde3d
+CT = 98f2f4fac056f43a6f14746a9f95783c0827e0e3c69c8033fffe60299768f048e7098033cde046b0
+
+Count = 113
+Adata = d293908bb516c5f3a411b9
+Payload = d7a46e726ed43f1580eb52141a93390982cc809dc833e3f0
+CT = 733c786af90abe8e1a9e33fcd78844bf6609bdbd34e2bdfe4ee6ebc0d90a0de05b428495c93e1801
+
+Count = 114
+Adata = 33ef208faad4d2948c9e67
+Payload = b1fe5d9d34157193fc0608cd8ecb872e17720f5f6814a466
+CT = 15664b85a3cbf0086673692543d0fa98f3b7327f94c5fa687e7e64cc0fcd6a92c79ceb6ce2abd8ee
+
+Count = 115
+Adata = b7f7ed9ccac3c2b4fbfee0
+Payload = de6bb539fb7a9c87414f62a7cf25a4cfca176509e991af41
+CT = 7af3a3216ca41d1cdb3a034f023ed9792ed258291540f14fb02b53bc779e0976b634b0d1b88fc0a9
+
+Count = 116
+Adata = a6e287383927f76e4927af
+Payload = 8719d20c20c8959068b8adcd65e6f6bc7b3693828f0735a0
+CT = 2381c414b716140bf2cdcc25a8fd8b0a9ff3aea273d66bae3c37fa936243b393f07fcccb0fc13e41
+
+Count = 117
+Adata = 70828be6dd93954f4e7b6b
+Payload = 30b39426831f61c8ba5f2ef5b71f0c4b2f916e3b5a578110
+CT = 942b823e14c1e053202a4f1d7a0471fdcb54531ba686df1e0d7534a489e6d242966ebea4455f8f79
+
+Count = 118
+Adata = 506015fc2831df293f4da0
+Payload = 818d5d810f678629f078723f5c6c3657271077533bfb7c29
+CT = 25154b9998b907b26a0d13d791774be1c3d54a73c72a2227ccbf64f04e95b180d09e843847d22104
+
+Count = 119
+Adata = e9394b0245b379e68e3dea
+Payload = f0613205a7a0822849df9e8a3cf6caf281f3adfa966c5507
+CT = 54f9241d307e03b3d3aaff62f1edb744653690da6abd0b0927b546ef8cd717073832584fb25a0645
+
+[Alen = 12]
+
+Key = f6bb5d59b0fa9de0828b115303bf94aa
+Nonce = 05358f33e1fc6a53ab5a5c98ce
+
+Count = 120
+Adata = 040b25771239cc2a39446e3c
+Payload = 011fc50329bfd63a85ebd4f7693363602f1a4147371270b7
+CT = 4432d7eb42980734d34f19c50cf8abf71ac1b19ed75a727854e5d050a405f755047d09cb0f49546a
+
+Count = 121
+Adata = 50a1d37fa2f3462bd304631b
+Payload = c90e40540d372ab1eb00ea5d5b8de5bf7c94ce4e376d6949
+CT = 8c2352bc6610fbbfbda4276f3e462d28494f3e97d7256b862abee8547ee3f24cfa677468ecc1d121
+
+Count = 122
+Adata = ac3bb872a41df35e415d2b0c
+Payload = 9e7be78c0ab9e6a4c6c257e77c63681bea35d951f168b0c5
+CT = db56f564619e37aa90669ad519a8a08cdfee29881120b20a61cef865ce4080e7c7abfc43f62c03a3
+
+Count = 123
+Adata = e3106ae6456153dd922640a1
+Payload = 00df0c5a5d3eceb2bd293066529799544f846672a9a1d31b
+CT = 45f21eb236191fbceb8dfd54375c51c37a5f96ab49e9d1d4e1d19c321a1e0852adba939b447220ab
+
+Count = 124
+Adata = 297b4498bf5427e6341aa927
+Payload = 14967a0476dbaea03b07fa8d40d344eabaf479be2443243a
+CT = 51bb68ec1dfc7fae6da337bf25188c7d8f2f8967c40b26f579ea5fb65018abdcde1a39f6859ecb56
+
+Count = 125
+Adata = 5de60dc0e3b5bda0b33a9520
+Payload = 2da3716d76d10b6766a1f9cbf9f420316fd5f396e7b9a2ba
+CT = 688e63851df6da69300534f99c3fe8a65a0e034f07f1a075c2629ff871ee15745fd8c1ddbdae4c29
+
+Count = 126
+Adata = 1c9b8541943ad50b4243c179
+Payload = 8c1b3ba18d1f5cff74a457aadd6b3e7d093d06ad2622e6a0
+CT = c9362949e6388df122009a98b8a0f6ea3ce6f674c66ae46f04e198ad16ad1106d3ba6172f4a13a8f
+
+Count = 127
+Adata = 51e926d2542ac8faef61465a
+Payload = 88936e97db070c0ec2aa58d1c6f5b34df3d32ddf7db34a8b
+CT = cdbe7c7fb020dd00940e95e3a33e7bdac608dd069dfb484475981131e3934ec6d41e00d502729799
+
+Count = 128
+Adata = ebefbac97b363e6f32526aac
+Payload = c20742e4b410c5b661da373a905fb0ed55b20e0e879eff5c
+CT = 872a500cdf3714b8377efa08f594787a6069fed767d6fd93e2c005b5bebe07ff578b1b4bc51971cd
+
+Count = 129
+Adata = 1ef059ac7d648e9e32d9b1f2
+Payload = 65c55ca21a89a8325365bf2be861d700559de2eabb41b37f
+CT = 20e84e4a71ae793c05c172198daa1f97604612335b09b1b021a25f15b5b4229a872a9199972c85b3
+
+[Alen = 13]
+
+Key = d1da2e961e78063af8de41865b226873
+Nonce = 03739f5474857006340cce554d
+
+Count = 130
+Adata = e3afd091d2b588465872a6300f
+Payload = 8e5fa1a6662a8378cda15697e926841594f2f394fa5a34ab
+CT = ca0d95e3ff186ad6b88d45fc4079e6b7b4a615e7e8dd5f4742d522cc9dc19c47a4fa0b1528069cf8
+
+Count = 131
+Adata = ce3186bb737753b59ee76b748c
+Payload = 311ebc5ff2f625944562ea699b2690df3e6e64a17c62bd3a
+CT = 754c881a6bc4cc3a304ef9023279f27d1e3a82d26ee5d6d659b26510b8f25610799e011d7c850ecd
+
+Count = 132
+Adata = bfd636989dfbcb0edc9f014cc8
+Payload = c96cee5ba7b799f16254a17b1870cdb85fe0ef3f42110c13
+CT = 8d3eda1e3e85705f1778b210b12faf1a7fb4094c509667ff52942aa0d39649f3d9ed535bebc2b603
+
+Count = 133
+Adata = 4812b092aa59d57451bfd812c3
+Payload = 13b1b4404dc5735655139414fcbd02c5327ae9fb148bd324
+CT = 57e38005d4f79af8203f877f55e26067122e0f88060cb8c8c1e61efb9c1d84ddac2d24f43531f569
+
+Count = 134
+Adata = f6ef9ac4f4c9ce1e4309c64fa8
+Payload = 6c5b59319e2710f5d63407f85b424d1860425ef8ce0cfe53
+CT = 28096d740715f95ba3181493f21d2fba4016b88bdc8b95bf13350de0ef34df12fb945b0ae0a0d9bd
+
+Count = 135
+Adata = 9bf12168bb3d79ebd25262f2b4
+Payload = 968e1d78008da78611e82985c4028e86770858cfe61c3723
+CT = d2dc293d99bf4e2864c43aee6d5dec24575cbebcf49b5ccfa0734563638598d8c4bf1fcd94009925
+
+Count = 136
+Adata = 7d870d7e52d3053c65eefad477
+Payload = 6a1306d911434cc7400d2f9a95e36aedceddca2b3d583f51
+CT = 2e41329c8871a56935213cf13cbc084fee892c582fdf54bda1f5fc53b08aca82bccfba6fbcb27e69
+
+Count = 137
+Adata = e95099f04371e445e5eaa1d80e
+Payload = b9197eb50c8168d16b8a12bd261d553ffcc521d979b26fee
+CT = fd4b4af095b3817f1ea601d68f42379ddc91c7aa6b3504027d1a922953facbd630d7fea6b63594ec
+
+Count = 138
+Adata = 3e80eb03db6545204ef4241ad6
+Payload = 95f59e36eac8eb3b51709d635b07fa2da0976ea20e25807f
+CT = d1a7aa7373fa0295245c8e08f258988f80c388d11ca2eb9383fa000d10078256b71249d9d1f1846c
+
+Count = 139
+Adata = 9748798c0f3cc766795c8ce0e4
+Payload = a48db9add9ecdeb49e51d3ab7bb2075202ed2aa50c0195b1
+CT = e0df8de840de371aeb7dc0c0d2ed65f022b9ccd61e86fe5d2773c2f55b752477c489facee812c614
+
+[Alen = 14]
+
+Key = 1eee667267ef10b03624cf9c341e3f75
+Nonce = 0630a3eae27e505c61c56e6560
+
+Count = 140
+Adata = d24651ef0561282d3e20e834960c
+Payload = 798e31cce0a83702a95171fb1162a17b9ce00ec3592ce262
+CT = f3c3e52f1a1ff528a8d3783ee4e75f114e3e6416334815d2d9236d5c5c9319092078411b72c51ba8
+
+Count = 141
+Adata = c527d309ab29ee91c5fc53117e71
+Payload = d79cd4c8891ec4ce2c51136712d23b32266b2b73768aeb1e
+CT = 5dd1002b73a906e42dd31aa2e757c558f4b541a61cee1caed8ad2a48cb734e3f93e602c15c7c775e
+
+Count = 142
+Adata = a93dfc3944514ddfc5acdd89fab7
+Payload = d7fa81c949f1f2af29dbd56529b307e3b348e996d0936455
+CT = 5db7552ab34630852859dca0dc36f98961968343baf793e5f34b297f3f106a9cdae255f7634fbd0f
+
+Count = 143
+Adata = e502abe21c7b22120693a08ef3e6
+Payload = 6330caaeddf0473d564d175b9408c6f12e6d3cd4ee2c423f
+CT = e97d1e4d2747851757cf1e9e618d389bfcb356018448b58f4f5d9c3dbfe3e2fe03a002e55039ebe6
+
+Count = 144
+Adata = a49b34dfad43333fb2ffd701a2d6
+Payload = 45671482c390e65f75de15ca91b93596e9bf3d6fc9178bcb
+CT = cf2ac06139272475745c1c0f643ccbfc3b6157baa3737c7b6f7bb0749c99d75740f2d193fef36c60
+
+Count = 145
+Adata = 9e4d8aa3dbdc4d4b4b8d72734f52
+Payload = c8f34bea8bdc403a48d8ed9268429141cd03c29558050ef4
+CT = 42be9f09716b8210495ae4579dc76f2b1fdda8403261f944ceec82fc674da9efa6926e8641729ed8
+
+Count = 146
+Adata = 052327ad59cc791259817fd0ed96
+Payload = d8d1c57b16c23894b66023c29f8648ce4a6074647e1f5f69
+CT = 529c1198ec75fabeb7e22a076a03b6a498be1eb1147ba8d92ff19e93f60c8f3a511300fddc38ee59
+
+Count = 147
+Adata = 14bc3c44c001ccb261a2a0526523
+Payload = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b78
+CT = fb8c9e93cbb4ff9b5a7c2a72aa6863c55a58b7c4534efcc87fa00fb244eda0d77cf6c05c8fd590af
+
+Count = 148
+Adata = 3477384c396a9e9efb3e169722cb
+Payload = afa795f836763a1210bb36fef167864f73ba3b6abc593537
+CT = 25ea411bccc1f83811393f3b04e27825a16451bfd63dc287bae19612657c87d3bb73cfb8cee7c8a8
+
+Count = 149
+Adata = 0c3b9a6924ad506038cb2d6590c9
+Payload = ca4a186f116a179579e3d327aec3f5be358bc7094f853bc3
+CT = 4007cc8cebddd5bf7861dae25b460bd4e755addc25e1cc733d9713d2e916c23ac3039de34c295fc4
+
+[Alen = 15]
+
+Key = dbbd26f5d9e970e4e384b2273961be5a
+Nonce = 0b1eabe504ef4822542e397fec
+
+Count = 150
+Adata = 477937301c83ba02d50760b603e0ea
+Payload = 553714e17a208a2eceb847a4a2d95088388b1ac8d8ca43e0
+CT = 1c80213268bad5402c4dc9b5d836ab7499810d0d8a974716df9a0e986ab2890736423bb3772cec3e
+
+Count = 151
+Adata = c91eb5a07ff19c044023e5cf339203
+Payload = c94d0b9e728413c58202cb3f6b82dba7aa9e3ca0a72c40c7
+CT = 80fa3e4d601e4cab60f7452e116d205b0b942b65f571443139f907a92cb01215e3cda84ae13af48b
+
+Count = 152
+Adata = 38c71a8e9b279c605c7f0418a0afc1
+Payload = b4e8c4fd5ad98a1be8b5a11677c57ca1c1694e3528092aa9
+CT = fd5ff12e4843d5750a402f070d2a875d606359f07a542e5f3dbd8dbf7485106cdf9ea0e7088a5650
+
+Count = 153
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe8
+Payload = 578ce26cdb5ba2e8798e23588e5cd04ef782820b80e49a42
+CT = 1e3bd7bfc9c1fd869b7bad49f4b32bb2568895ced2b99eb4853fde6f4dca88ff11bbce20ed9e5012
+
+Count = 154
+Adata = 36004342dd74e7966692a848b2c11e
+Payload = 78733c635d4d4e8b0729732f1e174dfcec4e020a7ac3870d
+CT = 31c409b04fd711e5e5dcfd3e64f8b6004d4415cf289e83fbd94e979108fcecbd32f6bdf72f0ccb4d
+
+Count = 155
+Adata = db92bc3fe5d4141aeb39baea6f114c
+Payload = c7aafe7760945e45703c1e19f1032dfd56ddc216c3b03826
+CT = 8e1dcba4720e012b92c990088becd601f7d7d5d391ed3cd0229c8f9d4e39fc16cbdb44236ef125c7
+
+Count = 156
+Adata = 34ec2d5b6f0d950509b47a0637d74c
+Payload = 2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3
+CT = 6af2d6b9712454163d6068187d28765c4584762254d8a5051c9ab7cb0a779c3fa78c9ee12603802b
+
+Count = 157
+Adata = 6ab658d177c2dd87c9b8787cd70182
+Payload = b0725f735543eb0c0ec88ae69b140f5787d28ef4a2e36d57
+CT = f9c56aa047d9b462ec3d04f7e1fbf4ab26d89931f0be69a1648c6307ec5ea304045a7cdc93f36b9d
+
+Count = 158
+Adata = 483f135c61250fa610b4d14b99ecf0
+Payload = 315a947bf5291278d446d332ee5ca0def7655d5c957a8fb4
+CT = 78eda1a8e7b34d1636b35d2394b35b22566f4a99c7278b42364ff3b1ad915347b1c7f062b10d3da4
+
+Count = 159
+Adata = bb022aed60819ef84ae83ce27db9d0
+Payload = f78d00755bcb45e6822121fe7cb03c8e627c9f548ccd7e7c
+CT = be3a35a649511a8860d4afef065fc772c3768891de907a8a7569808dab58d42181543b2e2d05992c
+
+[Alen = 16]
+
+Key = 10a7720f2e18f739c26924925af6b670
+Nonce = 8c4e7813ab9bce9dafee01c628
+
+Count = 160
+Adata = a209941fab710fda38d11c68b13d930f
+Payload = e59782a9aea45f467b90e51a0fdf166baba05663def2d8b6
+CT = e357b1ccdaca6f3506dc45279c2e4c59f5307a5fd6a99cd72341ea8c0785569973f90ee9ee645acc
+
+Count = 161
+Adata = 2e2f6f9755a492ee54df77b2ecab9808
+Payload = 042a072f6ebf11f79fcb4f5a64f7946dc837d9d2355785ea
+CT = 02ea344a1ad12184e287ef67f706ce5f96a7f5ee3d0cc18b703eb81224cdb1fd2e1cfb2fbfe1e402
+
+Count = 162
+Adata = 99e98c9983c85d1f49ae43ebad67a652
+Payload = 5db6bda27910e7b8b61ac476c6532570b71b3932bd6a698c
+CT = 5b768ec70d7ed7cbcb56644b55a27f42e98b150eb5312ded64c4aea7f17f18f068897557c93ffaaa
+
+Count = 163
+Adata = 37a837d73fa15793f6f823fb99c2ea74
+Payload = 8cac261a461c3ddd2642b8e4e5c3389e491fcb2ff8356412
+CT = 8a6c157f32720dae5b0e18d9763262ac178fe713f06e20736f3b2e70e6e2dc7acc74a823a7f49722
+
+Count = 164
+Adata = 11119a4e779cfb64c736d425e4ff554d
+Payload = 3429f9b088b501d7944c462694d0799568282e7ce07d3e61
+CT = 32e9cad5fcdb31a4e900e61b072123a736b80240e8267a000dc3b57096f0df1d4eb5328c416921bc
+
+Count = 165
+Adata = 962d7d4305f23d1692747b504960c0a4
+Payload = a46ae4c71d4c9eb72fabfa76b8074aa02e07653eca10eef5
+CT = a2aad7a26922aec452e75a4b2bf6109270974902c24baa94f62ed804e9f2ac0f7001d0f35ea9f3c1
+
+Count = 166
+Adata = bbb1fdfefcf3657ba6cd93ff341a04e1
+Payload = 92f5e3083f57c77ac9553a2024a66489698bd2261f05d415
+CT = 9435d06d4b39f709b4199a1db7573ebb371bfe1a175e9074907dcd7ac1e0bb248d46c3036c39fb02
+
+Count = 167
+Adata = 74be126f7c596642dafa8fe3da904e69
+Payload = 41ecc3aae5cfebfad7921a47a0684601ffe73816380f8716
+CT = 472cf0cf91a1db89aadeba7a33991c33a177142a3054c37787cbb80fd21127feca7e76fd6947d5b7
+
+Count = 168
+Adata = d72cc521c90a468522af8966c24799f3
+Payload = 8850bdda4bd0271e333db344a47b837183eb48269c3dc0b6
+CT = 8e908ebf3fbe176d4e711379378ad943dd7b641a946684d7cdb5d1243b6e73b8e380d8ca041647db
+
+Count = 169
+Adata = 28f427fba8d0bb0380bbe5072ccfa519
+Payload = fdd3ca2f193f93f5a349b50357d26748b767cde6ab5cbfe7
+CT = fb13f94a6d51a386de05153ec4233d7ae9f7e1daa307fb864a0ae8604b103f882f17db893ed5c576
+
+[Alen = 17]
+
+Key = 6bffab1f4f4c1ff66b4a669b515b2f8d
+Nonce = ddb34d5e0140fb96d690e1a2b7
+
+Count = 170
+Adata = 5cbba9ea778e01af00afb2a934f28c7211
+Payload = d91b12e8655dd92b1332fc1d71c391c96a17111562d90ba3
+CT = d302e5b2d5d90433186b804cd7717e2db2f22cdc34fb2942ab30780a2c4f12af8f35350d65284c59
+
+Count = 171
+Adata = 1583138aa307401dddc40804ac0f414d33
+Payload = eeafb08d4a4819f5682a01d44371e34cc5729079e74e73a6
+CT = e4b647d7faccc4ed63737d85e5c30ca81d97adb0b16c514746577901b7f6feb88b8e2b8562f9cb5f
+
+Count = 172
+Adata = 23931c258c84086500c6a3b6eda457e6b5
+Payload = b8737d5bbfc976c2d8d9786148dea664dd83cee98df537b5
+CT = b26a8a010f4dabdad3800430ee6c49800566f320dbd715548735a59390ba7a892741694f3a89b0bf
+
+Count = 173
+Adata = e12f98507d6514c3b551d240595346bc9e
+Payload = eb021b63c61c0b194bd44870608d7ef0b932b6104412d7a9
+CT = e11bec397698d601408d3421c63f911461d78bd91230f548f4f81ed18cc1820375a7bec2318cde1e
+
+Count = 174
+Adata = e14b87d49d231c0199eec627fd7f1b5332
+Payload = 93b42584c4956078359d77e80aef52281b9228a1f66aa36b
+CT = 99add2de7411bd603ec40bb9ac5dbdccc3771568a048818a187b430caa60d98dc3e2aeefe6249b44
+
+Count = 175
+Adata = ca095aec96a8b093e62b10f0950ce35ce7
+Payload = 6a788d8238c7b313b8eba27b210a71c36819d719115b9b76
+CT = 60617ad888436e0bb3b2de2a87b89e27b0fcead04779b9970a77372b727408e1bf5a70790b9eba3a
+
+Count = 176
+Adata = d1cac02b34ad33c0e77a5bda2c3baf5e5d
+Payload = 3bc1ee54d0094603dfc68eee118e547d031fb36e464e776d
+CT = 31d8190e608d9b1bd49ff2bfb73cbb99dbfa8ea7106c558cdc1f5cb4d4fa2204e82eedcb3784443d
+
+Count = 177
+Adata = 065c06b49a49898e20bb679e35edbb1f76
+Payload = 8a12adb8b746216baa8a418725e608e4377f13816a036a10
+CT = 800b5ae207c2fc73a1d33dd68354e700ef9a2e483c2148f12413f9496592a75a1d6e42ee3a258607
+
+Count = 178
+Adata = 98a42d7a0c5917deaf3b4de3f0cbe0a191
+Payload = 30a226c07401d0ae24c73d682e3a6e7e377ec1613bafba17
+CT = 3abbd19ac4850db62f9e41398888819aef9bfca86d8d98f6b571a3150887df1ac5f813676b2eb24f
+
+Count = 179
+Adata = e245a7528931841b52a5f59d861d98d7b7
+Payload = 3d17bcdf30445ebd8a9b6aa2fe11d443c1161bb1ee69ced0
+CT = 370e4b8580c083a581c216f358a33ba719f32678b84bec3131aa5e4657c92e31c69ab18d447d3578
+
+[Alen = 18]
+
+Key = ae6136df9ab43631ef143515dacedbe7
+Nonce = c5c445792208a50c8e93d64aa3
+
+Count = 180
+Adata = e04006b68c83a5dd4ceac3cde238e48895ae
+Payload = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731
+CT = c7584c0203c2535c5702c6ae93b7cbfb066f4a055c627a180d6d676d11fce907b5c93fa1ed7bff2b
+
+Count = 181
+Adata = 5da64e368f45153ea5b7ddca966b6c5b699a
+Payload = 15e0c672c6764f3699d9d3e7120f8ce5daab166f08fdd074
+CT = b8f1b62e36c280a68fdacefb6a8ea6fb67012bca0351ad5d2cd45f211b1a1364c91ad07959bf0ee5
+
+Count = 182
+Adata = 1b315d024bb5d1e03d7510e61f37d8adb10a
+Payload = de907d58cd8f5a72acaa1d329b937dfbbfed65a4e45eb029
+CT = 73810d043d3b95e2baa9002ee31257e502475801eff2cd0018f021a98b2edfb0b7500363099c2a1a
+
+Count = 183
+Adata = 8691ba4f9232ca86f919fe72ddb39c91d707
+Payload = c7fa314d27be79f9d3e2d1e188c1785b0c970f91b8ed4290
+CT = 6aeb4111d70ab669c5e1ccfdf0405245b13d3234b3413fb92ac9aeb018c48f3902276ac759710b6d
+
+Count = 184
+Adata = ff0baf1cbb5884a9290ea7b5ee49915efb4b
+Payload = 33b05b20f3c849fac091a5028cbfa0bc9a1c32514136fee3
+CT = 9ea12b7c037c866ad692b81ef43e8aa227b60ff44a9a83ca7dac49f606dadb9f7034e0a1860d519b
+
+Count = 185
+Adata = 2d118cda20700bc2748ea1753fbca6f74933
+Payload = f43832e420e2eccd5d80502bea2ba1804e17d4433318fc86
+CT = 592942b8d056235d4b834d3792aa8b9ef3bde9e638b481af623ccbab19c1442806e21c5a820945da
+
+Count = 186
+Adata = 0c7a5fd2010c999a8a0efa81f89ff5bfefe0
+Payload = ceb203c842a962183f22e602644fc66e4290b3d5be445fb4
+CT = 63a37394b21dad882921fb1e1cceec70ff3a8e70b5e8229ddbcd18947ac1800856c9c92eb0388c70
+
+Count = 187
+Adata = 73fdddb9e0a64f5671fd70c4ea8443507789
+Payload = d6015b6bd5f5eabb2a649129f8f727c06a3ad59499f21caf
+CT = 7b102b372541252b3c678c3580760dded790e831925e618639c29ea73b0c5aa130d8b14f7b9926a9
+
+Count = 188
+Adata = 82c4484e3a6e18b6bbfd78b69b00c40b30c5
+Payload = c288b810fb533441bd549d02c0b28d5b834293683eaacda2
+CT = 6f99c84c0be7fbd1ab57801eb833a7453ee8aecd3506b08bf0a0f148ae138c2ea02538c8fd7ac76c
+
+Count = 189
+Adata = 267d8385b14721eded743cffd69e4d595f7e
+Payload = 667cc47d13c34923be2441300066a6c150b24d66c947ca7b
+CT = cb6db421e37786b3a8275c2c78e78cdfed1870c3c2ebb75285eb537e7583f04e040a0ddc41106213
+
+[Alen = 19]
+
+Key = f1908328edf2996ebfc9655472ca5ad0
+Nonce = 4c693364546930b6c5250e2699
+
+Count = 190
+Adata = 4a3634e5028df97fbe00eb016e8ea4f1918faa
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 90c850790b0b380f5aeb2488fdf43c9d5ef1759861e86f6e52570e769629dcc2e568737ba53a1195
+
+Count = 191
+Adata = 041b93e3fc059fa44aa755e88df277b9b6e499
+Payload = e61ca7310172eec16745a73e34516f65844eecd0dbc5566a
+CT = 980af6f885e3e6f2e2ba4a2bb3e020d1a87976ba1bf63feff1d82ec19a2e3ec43bbdb34e10999d90
+
+Count = 192
+Adata = d1be393376cb5d23cf8139da0fd92f3d520ae9
+Payload = ea887edee68ad5fa6bae928aa480dda898037f820700ec52
+CT = 949e2f17621bddc9ee517f9f2331921cb434e5e8c73385d7f2abb0ce4de9eeb5e8af9cdf3391d3cc
+
+Count = 193
+Adata = f3e551b34d2db1286a9f41085e4dda95ec3f75
+Payload = 71fe1ba5d299495d2a56039c64032ec6263d437f55e3f5be
+CT = 0fe84a6c5608416eafa9ee89e3b261720a0ad91595d09c3b239c73b01ba49a8498b5ff4833851069
+
+Count = 194
+Adata = a69ddc66e63a3415f21009d53adcf26bc1a9a5
+Payload = bd04d854216740a6ceb9827cbddd83761d19feb2a21d78ef
+CT = c312899da5f648954b466f693a6cccc2312e64d8622e116a2248dacd3903c26a2dc5ae649566ad67
+
+Count = 195
+Adata = 5735d6f5882d8f27155eb4cc285a65138ad64a
+Payload = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda
+CT = 4da219ba2330ed8378449366c0d371fb8dfb435d3e81065fd4156cf7d97b2e744351b6960a807cf8
+
+Count = 196
+Adata = 5d94ed976ab2063512690ae704c3b115519742
+Payload = d3909d577a4e89642227cc6fc146b61bc18392175e342898
+CT = ad86cc9efedf8157a7d8217a46f7f9afedb4087d9e07411d5a50086b6711ac72533c3c5717f6892c
+
+Count = 197
+Adata = db20b384620ab8691aed2fed14a745188d94c0
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c56699029
+CT = c41147fcdb6eb0dc1182c7006ce978ee33c69226965af9ac54fb74ecb9a5163b01b9dbf97ff2f999
+
+Count = 198
+Adata = 94897cdd04e0c8480b2ef7b5201dda37558ba9
+Payload = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9cc
+CT = 215d1e5e323b409e36cc81509d1d78cbf27d452d494cb049d2a81702f665ff5c54f586defd268c94
+
+Count = 199
+Adata = 95c44e1e5ad256b3ce1cc1d87137a1e09f1fd4
+Payload = 598e91d39c414496fd5e69f2cf80826b4e7d59ba28e0a0d8
+CT = 2798c01a18d04ca578a184e74831cddf624ac3d0e8d3c95dfa641889723e163825ab65727e8a5343
+
+[Alen = 20]
+
+Key = 61cb8eb792e95d099a1455fb789d8d16
+Nonce = 1f37b3e59137f2a60dc09d16ac
+
+Count = 200
+Adata = 09db3efac9473f713da630ae92c2c8604c61c51e
+Payload = 6ad541695a37c32d73ff6d5f870abd5b0f362a8968c4fce0
+CT = e65fcc975865c1499b088b58ba163283085d8ca68dc3b235d89756e5d78753ef22c012ae34b39a20
+
+Count = 201
+Adata = b6d07035aed9c141c713cc3bce60f7ba8ac2545f
+Payload = 9cce4c82fe9d38ef64ac8abdf0619f201a25ce6903675627
+CT = 1044c17cfccf3a8b8c5b6cbacd7d10f81d4e6846e66018f2fc78ebae9c143a7283b0641e1f83f5a0
+
+Count = 202
+Adata = 80a5ab693378af29cd5a33555cb3579f9ae540aa
+Payload = 7295a7aed3e987baef19ad68c33ba5a5dcbff27875ff5236
+CT = fe1f2a50d1bb85de07ee4b6ffe272a7ddbd4545790f81ce35a7e44348d2b3085348f787128a4e96a
+
+Count = 203
+Adata = 220817144a15a0a654fc1beaabce60270aa72df8
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 67ab73defe1d9021c3d1f8ab3067ffd9681fcf803af0ed2024dfc096cd8a09d2d81f6146fb54082a
+
+Count = 204
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01
+Payload = 23bf80f51dfd83f63986910e69d54a315c2bfb43f432b7de
+CT = af350d0b1faf8192d171770954c9c5e95b405d6c1135f90b5da82204f4dd8f535cb2fec2f133d882
+
+Count = 205
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe88436fdc216
+Payload = fc3a50cc8a68778327923ea697f5388da4c814381e29c5e4
+CT = 70b0dd32883a75e7cf65d8a1aae9b755a3a3b217fb2e8b31108630135498ba409f4b6c8caee8a85b
+
+Count = 206
+Adata = b40c8c1d2cee490653105ca2443356cdb63e4fd0
+Payload = 465e41c69928d08c33e063ea119595a04d0de6bffd17bba5
+CT = cad4cc389b7ad2e8db1785ed2c891a784a6640901810f570f89c515837d129ba41f9c24b0229ddcf
+
+Count = 207
+Adata = 6ebfa1e8f80b3cdb1bedf2e3c7e74f30f55c38e1
+Payload = 3f98ee3922f8f1086e3135ae66c5465426b13c8794954880
+CT = b31263c720aaf36c86c6d3a95bd9c98c21da9aa871920655a352fa6b9c4e40733ddcd3fcdaf9ae63
+
+Count = 208
+Adata = 6d0159861031c1a5f01aab35927fe2ab28154d19
+Payload = 5b43067a5ab3a9f9e633fdc084c44ffa7f11edd12ea5873d
+CT = d7c98b8458e1ab9d0ec41bc7b9d8c022787a4bfecba2c9e82c1aa13f062c0f1f5008e27ff2191942
+
+Count = 209
+Adata = 15e5ade017b30ab41878a2747e93aa91c61c2908
+Payload = e40b7e9e46e339e64891526e730b3bf6562fa37acefce307
+CT = 6881f36044b13b82a066b4694e17b42e514405552bfbadd2e149dd02bc7face0c4dfe4e501c2ac2a
+
+[Alen = 21]
+
+Key = be1ed49e2cb0caf6b6a0940c58453b93
+Nonce = b78ad129457681fa7346435b97
+
+Count = 210
+Adata = 161d92c7df1ebb0924719e066e08b95eb4914a5eda
+Payload = a9eec383f63892521e4616fcbadc5485942ffaf4669c43a7
+CT = 949be340720c4fdc4adc05cb777dd81a2549628d33fba07e62d2b338a7b34ebd9d85c244c952d681
+
+Count = 211
+Adata = 6b1d94bc0c6e45fc905c509ea667853e4b2c5a8848
+Payload = 7b44a093162bfc8b4d65f1031d890a6b08a3705b142c0c26
+CT = 46318050921f210519ffe234d02886f4b9c5e822414befff8a4defafeb3d61dad8c007b68d8fb9b3
+
+Count = 212
+Adata = 868dd3e241f60f097a7a2fe571307ee5eb961218ca
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447cad9d5
+CT = 15b1f61dba183895d001006a515cbc1b41858d2d12ad3a0c57cbab553b511d68a4f41db211d0a2fc
+
+Count = 213
+Adata = 3776f37fbf8803bdfd246ffaff2e59658a6c3f0ebb
+Payload = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+CT = 2ba665a3ee05875c14f0a8fc8e6c0034582e8802f3b699ab0290fd7dbf0afa3e597274e3c9fe170b
+
+Count = 214
+Adata = d0f2769eba9b8e618f00eed6b34c261c59322a253b
+Payload = fcbbcdd9599a86e7c8ccb9347065789a9728ca1220fa51ca
+CT = c1ceed1addae5b699c56aa03bdc4f405264e526b759db2139c7dec3960e6aba3174d793b4e08f449
+
+Count = 215
+Adata = 2be180892faed0bb75887668d187807666d3c66c68
+Payload = 8d145b1f792cc31a2e5b86216609bb018e7aea3012ff70a5
+CT = b0617bdcfd181e947ac19516aba8379e3f1c72494798937c7057b9e2d844e86ee5c3ecfb3270804e
+
+Count = 216
+Adata = 52859849a5b7c1d432c3bfb35271cd8141db2ec774
+Payload = 741db990b43ef34993c33d1c4953b67b128b9299dfe86d74
+CT = 49689953300a2ec7c7592e2b84f23ae4a3ed0ae08a8f8ead1150fa899152eef7a30ae0f20986818e
+
+Count = 217
+Adata = aa192759625f4e42d1d1fa73dc0f62199142155615
+Payload = 51dca5c0f8e5d49596f32d3eb87437bcae866640310ce1e3
+CT = 6ca985037cd1091bc2693e0975d5bb231fe0fe39646b023aba7ff9203608089558698ec29472dda7
+
+Count = 218
+Adata = 6de564226884188ec7bea3894535a875cff2a42fdb
+Payload = dfaa7aa8b28626210d5c24e2ddfe516189be05aabe26f3b2
+CT = e2df5a6b36b2fbaf59c637d5105fddfe38d89dd3eb41106b85bd0a5074ef852575baf5f12c22663e
+
+Count = 219
+Adata = f245f2ee23755df863dee55d7ef0c3c09a0b6f0b0c
+Payload = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc57
+CT = d3aa206931d9325331d3c04919e2d47ead3e145da4263f8e9eb617436bae012331daf020fce24e47
+
+[Alen = 22]
+
+Key = 34ab6fd7f54a2e0276fcb7cf1e203aba
+Nonce = 6091afb62c1a8eed4da5624dd7
+
+Count = 220
+Adata = 1ab5cc3d7b01dc74e6cf838bb565fea3187d33d552a2
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 0d30ab07153b5153637969e6bd3539448c541e42b3d432fd7ef14622a9b621d1721b944c60f7fd67
+
+Count = 221
+Adata = 1f1ac4674b272bc7a4ee9f4eae33e969b16fa90a69ba
+Payload = 14e99a2ef0de650adbd785c692342cdb765e6d20d5fca09a
+CT = 94cf7e706b44755193be855740cdcde455605601adf35bb6dfa4ec2c92671c64ee07946527be67f0
+
+Count = 222
+Adata = 43ee77f12ea42e82a02275a68aa95cbd1bb440442bcf
+Payload = 383242c709fe5f2ce782bf8c83b645d171f2bd238abc655d
+CT = b814a69992644f77afebbf1d514fa4ee52cc8602f2b39e71173572fbf3d9495760aae4347397b110
+
+Count = 223
+Adata = ae2ff288199be25bf640811541394ad7e1dd0dc0d24d
+Payload = 9c16a5b638c35c97c5c981c1b8dbcba11aec30e72e45a936
+CT = 1c3041e8a3594ccc8da081506a222a9e39d20bc6564a521a4d2327956e030b9df753e063b5b71201
+
+Count = 224
+Adata = 4ccfb4281852b5ca7e787723d689384a68ff9437db31
+Payload = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878
+CT = 6cbb6a8169cc55094068b67903b3cefc92ade051adea1354e4dac0c9130f5641afd035dd884b6271
+
+Count = 225
+Adata = d3a2fffc798fd9cc2f409471faf18caa2ff3dcf4e652
+Payload = 0db33eda4188a9165147e24e40f79fee1985eb68d5162728
+CT = 8d95da84da12b94d192ee2df920e7ed13abbd049ad19dc0448807dd50a9cf41651083c49c7493ceb
+
+Count = 226
+Adata = 7b5121aa4d1e314f209ffe3e92cd26ee4f74d91e27f2
+Payload = e0d3ea4308376423c4322503f56e427a64e2e6d8b4f5e668
+CT = 60f50e1d93ad74788c5b25922797a34547dcddf9ccfa1d448ea0da53046733f522ded40a09c6d7a6
+
+Count = 227
+Adata = 6e12c112720ef346bbbe7d1c19483721b1c52c438dad
+Payload = 491f2bca585d6b5fdf38d18890e4d1bc923fe26930b3d2f1
+CT = c939cf94c3c77b049751d119421d3083b101d94848bc29dd345cb5a968f39654b994686699d532c2
+
+Count = 228
+Adata = 20433402a2d869c95ac4a070c7a3da838c928a385f89
+Payload = f45908d691ddaf89c0bc129ffada94c3ceda5f47d63ef76a
+CT = 747fec880a47bfd288d5120e282375fcede46466ae310c46cce85eb55339b886b7121b306fccc0b2
+
+Count = 229
+Adata = 42f944c21cc221beaacb288115ac628346b8a1d94bd5
+Payload = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b
+CT = 63261824c00c9038caaa5a64603b09dd40bc4e3a210ef667a37ca5ce12aa6f0659467642deb8bfcd
+
+[Alen = 23]
+
+Key = ea96f90fbae12a857f5c97e0cba57943
+Nonce = 21cc46d9ced1539b0ad946e600
+
+Count = 230
+Adata = 105258d2f25f62675aee975cfdb668aff833f05b61eb2a
+Payload = 49db80f22bc267a70e5636dfbc8a21c83d9691fe4b9c3051
+CT = d2fcc8b7809b5fc07e44083e437d8180157f1782a9ce9f65c7fa9ee2e7cdc1b755258f2212a8a8f4
+
+Count = 231
+Adata = 0f5938540651fa4ca03867e67518eb2b73f60dd8750fa0
+Payload = 26618e21099a79d6c517335389551323065ad89c8848ea12
+CT = bd46c664a2c341b1b5050db276a2b36b2eb35ee06a1a4526bfdb9bfcd3b969fb2e41221eb92b0147
+
+Count = 232
+Adata = d6b228960fcbcf07c7bede616139db62b3808718a5b511
+Payload = 4de1d6d57144896ddea1c30f49afecd27bdf4840ed9928b5
+CT = d6c69e90da1db10aaeb3fdeeb6584c9a5336ce3c0fcb8781f8beea22cba93203c912209c78c03aa1
+
+Count = 233
+Adata = 75f8f071e229355e286882917ce5dd4f1db591fee51b6c
+Payload = 785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8
+CT = e37411f4772c72796b7fb9d042da3134cb00937ba241bfdc69a2e3ea4a40f7c491912c1a0778ebde
+
+Count = 234
+Adata = 4afb62aa8648ac7474dd16fcc376f8909c69e1ce36e6d1
+Payload = ab627aac1496d011ed2edcb2fc6b2afbcc394654f56124f6
+CT = 304532e9bfcfe8769d3ce253039c8ab3e4d0c02817338bc2a75c7ba2a769c27903e99b72639b0841
+
+Count = 235
+Adata = 736fdf94db820a2efe89e7fc9dcfe7c23d5754ac2bcc7c
+Payload = 40722cffb37f1455c2618408e777ed0f4b1bd039952730cc
+CT = db5564ba18262c32b273bae918804d4763f2564577759ff8f84f4ca4a69fde75d7207e50494819b6
+
+Count = 236
+Adata = 8a9a0367137c28db4c4e78d9cd9a68cde0d1b4583532ae
+Payload = dcaabf7a061502618541c09ea59dbbbd52b2692fd0064747
+CT = 478df73fad4c3a06f553fe7f5a6a1bf57a5bef533254e873a0c34a24d3ee0946034c71fba4dbb333
+
+Count = 237
+Adata = 34dbbff560ef04ea731b8979aef2ae50972f4db3efe14a
+Payload = dd641a893b16e0e173ea2eda20638bb01849ac11e64e8ddb
+CT = 464352cc904fd88603f8103bdf942bf830a02a6d041c22ef0f5e24a435a39a716c39f43dabdc4281
+
+Count = 238
+Adata = f3d1fcd912252431db9d8ccfc3e203d5b34d537468b4c6
+Payload = 9aa3e8ad92777dfeb121a646ce2e918d1e12b30754bc0947
+CT = 0184a0e8392e4599c13398a731d931c536fb357bb6eea673f623d59f66764d859a772bb50ec91fc3
+
+Count = 239
+Adata = 513b4cdc551c203ed5f1e659813584862023911590b672
+Payload = c8f44ae4b02fffdbce0df773c24075f877945fc7a86be460
+CT = 53d302a11b76c7bcbe1fc9923db7d5b05f7dd9bb4a394b543b6549eb16fba96318afb3df51f4675f
+
+[Alen = 24]
+
+Key = 35b403a15212097085d6e2b77ec3d4f2
+Nonce = daa423bf9256c3fcc347a293aa
+
+Count = 240
+Adata = d3c0ed74e5f25e4c1e479e1a51182bb018698ec267269149
+Payload = 7dd7396db6613eb80909a3b8c0029b624912aabedda0659b
+CT = 5b00cf8a66baa7fe22502ed6f4861af71fa64b550d643f95eee82c19ecba34280604b58d92dacd3f
+
+Count = 241
+Adata = 62f4fe53e99a9b0c51e9561d910d7e2ffe19a5176c9dec06
+Payload = 897f0dfd90213f64a9277a0eda4f134f303fa89f56ca54fb
+CT = afa8fb1a40faa622827ef760eecb92da668b4974860e0ef5ab4999e9689d52b8afeb87923efa3b48
+
+Count = 242
+Adata = 191c4dfa653c20292657f7694c6b6a4a410c49a879abd217
+Payload = 2b7cf9e6e2d6abcd7775f8a6eb6294e822041c4c45f09c3c
+CT = 0dab0f01320d328b5c2c75c8dfe6157d74b0fda79534c632cdc71e556c34fd4e1b5ebc50d38da8b3
+
+Count = 243
+Adata = ba34741f8edb51470eb20f891869aabeab562d92571ac943
+Payload = dccb9a4625512496b372a2b8b768f75741d8c2e30e57d638
+CT = fa1c6ca1f58abdd0982b2fd683ec76c2176c2308de938c3646223d381090661c2ee2370d29a572a9
+
+Count = 244
+Adata = 8b922aca6125722ec490b134a45864397f4e2c281d6e2089
+Payload = e0e452c990665465160b02cad6367ca89723613488d8efbf
+CT = c633a42e40bdcd233d528fa4e2b2fd3dc19780df581cb5b1f78af50466646b7c7e652f787afe5357
+
+Count = 245
+Adata = afb9fd78e3f8eaf4e8c91da62b2da534508e54f7dfa214fc
+Payload = b536fdb8839f87080ae65ec35da347e792622ffe18a61d46
+CT = 93e10b5f53441e4e21bfd3ad6927c672c4d6ce15c8624748cc9d9a1270f78648a6b66cb8c0f2471b
+
+Count = 246
+Adata = ecf942ccee7396cb3ee177eadd4d96a4af1d90afdce97376
+Payload = c81233826e5125e1f31fe275184ccba8f1a743e58e146e4d
+CT = eec5c565be8abca7d8466f1b2cc84a3da713a20e5ed03443b17d3d6f1fc4f530841b749d9f3a0a7a
+
+Count = 247
+Adata = 16fea92ffcaad563792aa924bffe7ef690edc90ea4e29cc0
+Payload = 24ab253b5b06552665c3c810254c0ed15e68a783180d7eee
+CT = 027cd3dc8bddcc604e9a457e11c88f4408dc4668c8c924e05852ed48cf88d9ab2326aa46b6541b60
+
+Count = 248
+Adata = 76f110eecd369d79e21fb208058359d3a2f37581d1f7f691
+Payload = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4a
+CT = 598e9d2078ce4845c6c6e0aa1c328fe7f8192a7852088444c62dff6bcade5ac2edb8ec9797ce433e
+
+Count = 249
+Adata = 8834c776a3237f060ae0ab9857324a3b2ac79f3b6e6f90f5
+Payload = 11cbfb3d348c7abef99f562607e289de34a2bb379a5dfe50
+CT = 371c0ddae457e3f8d2c6db483366084b62165adc4a99a45eb936ac4764575f85352c24ab23209d42
+
+[Alen = 25]
+
+Key = 7a459aadb48f1a528edae71fcf698b84
+Nonce = fa4616b715ea898772b0e89dd4
+
+Count = 250
+Adata = 0c0b4a45df5c3919c1e1669c5af5d398d9545e44307d95c481
+Payload = 0b3d947de8632dc8ff752f619ba7c84716fac7a23e101641
+CT = 7db9f3f7dc26fc2adf58d4525d26d5601e977de5a7c33911a1138cff7b624f9908b5b4d7e90a824a
+
+Count = 251
+Adata = aa27a28a36b5a2cee57ffeca0233feb4bdd4eacb2cae28e98f
+Payload = e6dedce2c278c44e5678d13e7d5b5d3501d61bb0bb6b5558
+CT = 905abb68f63d15ac76552a0dbbda401209bba1f722b87a08e23f92b598f7a248a894e6b8f5691bee
+
+Count = 252
+Adata = 66220aa9b40a1772caba7749a544bff938e804dbc6e556498f
+Payload = a276b0922fbd5094bf89b9329d07341e039d6204397b81c0
+CT = d4f2d7181bf881769fa442015b8629390bf0d843a0a8ae90e94043c0d80fd651469232fe9d47a81f
+
+Count = 253
+Adata = 3d765d20e03a4cebfda50316c4b7d8b6c55078d5b3e9cbc567
+Payload = b99afbc2dbb377350cc58d4bfe8e954cef25d7b27b82fad4
+CT = cf1e9c48eff6a6d72ce87678380f886be7486df5e251d58425088b522fc0731097e729448236b317
+
+Count = 254
+Adata = e91b6265879153e1692b00a112b4205111c8eb1a7b7f2c6898
+Payload = 56114cc783b80ca2dd2881387b6d92a59a237dfc8e976d8b
+CT = 20952b4db7fddd40fd057a0bbdec8f82924ec7bb174442db2208cf07574cc4f3f83ed6301b904404
+
+Count = 255
+Adata = 340b16f352817babb4fb70e9e6e18784b3e67bdd449872158c
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 9da599aac80a43a70b0be59fcbfa6d266719d3e846248ca514b0a900068e55cd24c92bbb78c521ad
+
+Count = 256
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01445be684dc
+Payload = b15083a73607c9d7e197a8cc884ad3be98ac343f6493df67
+CT = c7d4e42d02421835c1ba53ff4ecbce9990c18e78fd40f0373f8ba66d74321c80c057f010078d2f28
+
+Count = 257
+Adata = 5fe8bb27a59a5f4e370adbba96484c2365fc0d8c6e58d7d3e6
+Payload = 07542d18e8f2d3e199fca0f90cabb78b169525fdce81666a
+CT = 71d04a92dcb70203b9d15bcaca2aaaac1ef89fba5752493a0a189319e4f06d53c1405d37b06cc8eb
+
+Count = 258
+Adata = 23e5422e8d7560a9e65642b5e723a47536c16791f3a0cf918d
+Payload = cd574ed56bdfd1408f7831e0b24b4345ee979ac906a7aa22
+CT = bbd3295f5f9a00a2af55cad374ca5e62e6fa208e9f748572dd72f48ae03670249d74f8460b63b1ae
+
+Count = 259
+Adata = fcc9422ba5023a9997baa9c4ee6cb196ffe96e08eb9c2b8a75
+Payload = 8c9abe94beed4c9bd46adb1d04fbfe7016dd50d324525abb
+CT = fa1ed91e8aa89d79f447202ec27ae3571eb0ea94bd8175eb1717c00c93d36a77141b723d573c8c65
+
+[Alen = 26]
+
+Key = ca748225057f735f712ecc64791367f0
+Nonce = 1341a6998eb1f50d4b710a13ac
+
+Count = 260
+Adata = 5fb96b045f494808c02014f06074bd45b8a8ad12b4cb448ec162
+Payload = e92cd0cb97afe4fb00c4f12e9b9abe1d08db98f49a27f461
+CT = 82b666694232e86e82295beae66ae67d56aceb5d6b1484ceb4a6843ec16078038c10afedc41f5362
+
+Count = 261
+Adata = 87db0d9d69bc0cf69cabeb92570e482bbc8ff3e1ba72f12f3225
+Payload = a6dbad96ad23ff61479df39b99f0673a09f2a7eaebbd34b9
+CT = cd411b3478bef3f4c570595fe4003f5a5785d4431a8e4416a7c6566d0b8ff97f946d7c7773a845f2
+
+Count = 262
+Adata = a061a09024f1e03b223695d4703ee202e90e07156b95859a22e3
+Payload = b1dd81cc3b2b0efe540a3194d6fe304cd2de53db7929ebe1
+CT = da47376eeeb6026bd6e79b50ab0e682c8ca92072881a9b4ee1d66a4728b67b42602e23c8500b0115
+
+Count = 263
+Adata = 0dd513c5d8d62b723ab8b0a3aaa477e843d9149dc8a2f878e585
+Payload = fb30c2e98f3d7e4ed7431da285711d3d287884db13a474e7
+CT = 90aa744b5aa072db55aeb766f881455d760ff772e297044803c51e8c59ed13b3e5d9b489d4ea2ccf
+
+Count = 264
+Adata = 3ff59c40bd796048e586eccc23a82e4d09fc5e779f38eb4afbed
+Payload = 886f9f91a6566ceb99c39462ab675a3ae3be98f68787626f
+CT = e3f5293373cb607e1b2e3ea6d697025abdc9eb5f76b412c0f1ec270b43fc5a9811b56ccf033789c6
+
+Count = 265
+Adata = 0df7ef91f7124da867e992bcbc6fb38232ff6d5205f38768da72
+Payload = ed370d1c2d6dc03e4fae4deb9343a7d4339562cffd427587
+CT = 86adbbbef8f0ccabcd43e72feeb3ffb46de211660c710528bb4ed25940d58cba64271fe1d2e8013d
+
+Count = 266
+Adata = 6777de159c34d005b94f67c33ae4a35ebab09d9cb9c56b4c9c81
+Payload = 2f77c2eb07db14bd713c5af10c0760ea3a6ca5ff8d046d36
+CT = 44ed7449d2461828f3d1f03571f7388a641bd6567c371d99392636a5e373c1354ea9b969abb4932a
+
+Count = 267
+Adata = 75559898f4ba03c55afc25ea91aa61a93c2f8270a5fa51b6f6dc
+Payload = 360fb89429dc9b48358097d930c8561b2bd18dc0a470d1d6
+CT = 5d950e36fc4197ddb76d3d1d4d380e7b75a6fe695543a17959a7e8bc0570f19159f91fc14ac6532a
+
+Count = 268
+Adata = 5e03fc430473c5de96d68907fa506f9da353ae48a965445e1f24
+Payload = f2d8d67b9f291c3edc264893922622b2693f3e7231137eba
+CT = 994260d94ab410ab5ecbe257efd67ad237484ddbc0200e1507e559568c27a30b5676f98cc66f57d6
+
+Count = 269
+Adata = 7eee4869e77f6db12c91d1f647cad2340d33a3defaeb362d311d
+Payload = 7fd6fb81c36e44b150af10e04683b1ec9b5dda87c71ff939
+CT = 144c4d2316f34824d242ba243b73e98cc52aa92e362c89964910615920f6f3c3421a9c2bec1bec7e
+
+[Alen = 27]
+
+Key = fdf2b2c7fcb3789b4e90abe607dca2af
+Nonce = a69ddc66e63a3415f21009d53a
+
+Count = 270
+Adata = c76846da496ed87b9c0f65c6266c9a822224acde9775efb186a4a5
+Payload = d7aa4efa5d75195a400018bd38f7d8cd53fdffe88df1837f
+CT = 150d9a8b78d9c04239d66207a1f95021bbb1b7c70d7c354825d05e5a2e76a90f6fe489fd74cab2a3
+
+Count = 271
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d
+Payload = 5f94a2e48d348a1d56c55a659306e319c3d2ad78b9fe43a7
+CT = 9d337695a89853052f1320df0a086bf52b9ee5573973f590be6af49ce97d5e0e77c7fd5d9cc6d932
+
+Count = 272
+Adata = 7631cf7822a545daefa16a5ec43c877d475a82d5aa2d51cec7fbb4
+Payload = a44b010fc1c659eac9241a58b11a73d7ce33156ddfc54c3c
+CT = 66ecd57ee46a80f2b0f260e22814fb3b267f5d425f48fa0b924b268cab915f999aea3e1cc3a88ccd
+
+Count = 273
+Adata = e4da34663edc44370bfd8aa8315945471a893a1cc069628a071ee0
+Payload = 28d157f5741f1be057d5219711414c0638b47d165a905a6a
+CT = ea76838451b3c2f82e035b2d884fc4ead0f83539da1dec5dc368f5af8e311e67209e02dfa2613377
+
+Count = 274
+Adata = 077509eae1dc367540f87832c5780f6c5b29e180bc6c1fee38e826
+Payload = ba7432a8e34bfaa91b35c8dfd822d86850be39e63150257f
+CT = 78d3e6d9c6e723b162e3b265412c5084b8f271c9b1dd9348ad175fcad35d29396380b79a28784cff
+
+Count = 275
+Adata = a513d750ca1e8bf6cb7b8cea5204e064c15c2dc40d742b31cf5459
+Payload = 3f5830b0ce8849a660af7d58a60c19a9824a3033bb5fed43
+CT = fdffe4c1eb2490be197907e23f0291456a06781c3bd25b7493b4b3e33d325359c9c651290ce73bed
+
+Count = 276
+Adata = e439db829c1291df49fc42c2fa1a92118c2665f11e13f28dc6f11a
+Payload = e69b2a243340df5dc70b2cb05be12e5992ee36f7d9f4ca84
+CT = 243cfe5516ec0645bedd560ac2efa6b57aa27ed859797cb371f88ca5857c6d801e726a01c621a0c3
+
+Count = 277
+Adata = a12c690568114fd7a677f49d74e84fc1a6b7f7d2a08693266c0a91
+Payload = 9de35b840a69a84701ffae1b1d2bf13c34b42a57d14c524d
+CT = 5f448ff52fc5715f7829d4a1842579d0dcf8627851c1e47a0592d360fc6a46aa18c4ce5d74fa4532
+
+Count = 278
+Adata = 1813bf176a1127f4d508d7663ae750f9c4bcb84a6e26811ac60d46
+Payload = 9e2fa20bf76768a5a1467d90a048bb503a2c33bbbaa71653
+CT = 5c88767ad2cbb1bdd890072a394633bcd2607b943a2aa0648b772cef893495cf0a94e8ebf06e920b
+
+Count = 279
+Adata = cc6e9cc2699d3ba0e624e715599480d6b7dbc6eeea0d12a9236444
+Payload = 6681b1cbeceea57a828324831407280b00f4917ed52a10df
+CT = a42665bac9427c62fb555e398d09a0e7e8b8d95155a7a6e8b1851d571a1ef8aed565b784dcaaac4e
+
+[Alen = 28]
+
+Key = 7d870d7e52d3053c65eefad47764cfeb
+Nonce = 37d888f4aa452d7bf217f5a529
+
+Count = 280
+Adata = 9610949f6d23d5b1f3989b2f4e524fab4f297a5bec8ddad4f16cb616
+Payload = 109317556c21c969eda65a94176d7a11462c9ae18a865b6d
+CT = 4e6b967b1571c6d7b9e118b112b7ac949a4a175650316a242dd579cb0d201d22c86bbc7fbe47bd0d
+
+Count = 281
+Adata = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34626ac9b9
+Payload = 3e6c914a196e175079315b1c92b2b8a844deb472e249e3d3
+CT = 60941064603e18ee2d76193997686e2d98b839c538fed29af0dd7aef4a609f3587652173446ebd82
+
+Count = 282
+Adata = 21fc96f73975298207f818909088295d6d6861677130ca258c2174f6
+Payload = e0014147d5771b4380dc0192d45f36f7d60776d1ba47374d
+CT = bef9c069ac2714fdd49b43b7d185e0720a61fb6660f0060463e4405d45caf4836467edbf35089d87
+
+Count = 283
+Adata = 72a5151abcb55933ff7c9314f3235eba2a400121454144c2670e8359
+Payload = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a
+CT = 51e4ecd194f980c441d8dee31dfa69374576555d7eac44537441c813e90fac775eddb7290df059d9
+
+Count = 284
+Adata = dbbf192914b1ad73666e9f5e9c22c08ca398f7524af62b1046a863bd
+Payload = c1ddd14e380cc91324cf2a381df1da1ccffd90ae436a373a
+CT = 9f255060415cc6ad7088681d182b0c99139b1d1999dd067334d9316f1f1c3142c1c9b26e5c220a32
+
+Count = 285
+Adata = 28e4b88fbf04e9897057ff5bfde7eb04fa480256817a50fa281030b4
+Payload = d4dae9c4cae92afb80f9a5c99383ff16e23a2ec942eed4d2
+CT = 8a2268eab3b92545d4bee7ec965929933e5ca37e9859e59bc0b188e33bfab29b237d6c6920ce3418
+
+Count = 286
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d7
+Payload = 8a188d40a6e6fbb06a9f06304349a7a808b092cc2fc10b9e
+CT = d4e00c6edfb6f40e3ed844154693712dd4d61f7bf5763ad7fdde04d21b876468bd9184101b5f32d0
+
+Count = 287
+Adata = 34ad69f192ae4dcab771aeeacf01bbd32609bcbbea8ff9df31ded719
+Payload = 590c1aac30ab166b1caff748452fc146765c372e226ffc26
+CT = 07f49b8249fb19d548e8b56d40f517c3aa3aba99f8d8cd6f068c65e9d0e5f1b81c86393900e64c19
+
+Count = 288
+Adata = f5e50ce1f99ed5e9f2baa54b96ae7039234b1131e734ec190695d28d
+Payload = 16d0522b2e691e42bd80ce95e00c8a7a1fc738169e904bdb
+CT = 4828d305573911fce9c78cb0e5d65cffc3a1b5a144277a9206ab3b72c56c8df4a12dba89a2f21276
+
+Count = 289
+Adata = 9b1e7e52ea1a12444d884866e11dcf367b70b816460936fdaebba36d
+Payload = 0bddf342121b82f906368b0d7b04df1c682ecd4c2b2b43df
+CT = 5525726c6b4b8d475271c9287ede0999b44840fbf19c72960170ca7b16d23537eeb3034105334699
+
+[Alen = 29]
+
+Key = 8fcac40527c0e7ca8eaff265ca12c053
+Nonce = ae9f012fd9af60a400e20b1690
+
+Count = 290
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154
+Payload = 78d1e96af8cebdcc7e7e2a4ddcfa34f6cf9a24fb85672ad7
+CT = 9adb9a95a9379ad795d8d3ffd4e37a045160d6d727f974a6cb3b5151f327e65447e52c7525562c91
+
+Count = 291
+Adata = e7c78ef4c4b959ee00cb1a09d71221a43892ef8ad705edd27ed85d03a3
+Payload = bc59f18c8473941abc681a92741ab5ee13679829f542b8f4
+CT = 5e538273d58ab30157cee3207c03fb1c8d9d6a0557dce68534e5b08e27d8f5eeef0f064ff620652a
+
+Count = 292
+Adata = f1bce6f2a4bdd3a07ebf5f8d47f931d27e7e63389d70e1059f701216be
+Payload = 5575d950312c14c89ac609dfb0b2fd1af732bb6aae5e8651
+CT = b77faaaf60d533d37160f06db8abb3e869c849460cc0d82044c0a96baae318f4714f0206812516b5
+
+Count = 293
+Adata = 3da3bb091016e54477dae88af1c84c1a51b59c1bb49a05deb6f32064e6
+Payload = df5947d8c6094ccc25816639ec42214b28731bfd7b8312dc
+CT = 3d53342797f06bd7ce279f8be45b6fb9b689e9d1d91d4cad4e7bdce2dc6aae24178aab6984f31028
+
+Count = 294
+Adata = c4cd183071c37a8157c6930a7d4d530cf4b7eb021682327810bd48209e
+Payload = 2fbb6dc235761875411ef59ae06110df8f15f66b721b0fd6
+CT = cdb11e3d648f3f6eaab80c28e8785e2d11ef0447d08551a7f18ece8260bd56ecdee768022d0dd8d1
+
+Count = 295
+Adata = 0e0fece7b6b659b642668e8ba3dca330523e70279155f485f3f6f8041e
+Payload = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e
+CT = 2f1eeee88a5ecb4bebad75e198c85a9be155443c87ae413f6f0fb3b7440b84ddc3cc53819c2e93be
+
+Count = 296
+Adata = a35c6f70f637a9a5e6f215c694fdf65b6fd85f794ed3eaa1bc19abe592
+Payload = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa00
+CT = e109e352e48bd5a6c1ccbde6f5716d9e4f2e977be1b6f47129ca778c51f9320f121dd803ece8d5da
+
+Count = 297
+Adata = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f904398afbec
+Payload = f2d9cf953c8d3a051d9b3eae4307a3cb4fffaa2435b49586
+CT = 10d3bc6a6d741d1ef63dc71c4b1eed39d1055808972acbf79c223a5ad65120bfca4a5992e5ebc6fc
+
+Count = 298
+Adata = c023763a285ea934bc5bc7ddfc2aefe2b3f9eafe7b87c61383dcc07990
+Payload = 4b92e8d2ffaa4af8f3e0ac037a900bd18e195f490a3d71e1
+CT = a9989b2dae536de3184655b17289452310e3ad65a8a32f905c3bc4f618ffb3a159f4e2d0622cea6e
+
+Count = 299
+Adata = 0a39ec0163c7aeb1b4fbe7cb4fa5b0592fade70f430e23730a23ed4160
+Payload = 7c0e6a0d35f8ac854c7245ebc73693731bbbc3e6fab64446
+CT = 9e0419f264018b9ea7d4bc59cf2fdd81854131ca58281a376f099dce6e18435fba4d26c1e93bda0c
+
+[Alen = 30]
+
+Key = ddf9f150cc3f1c15e8e773663c5b061c
+Nonce = 98c5036b7d54da9a1177105600
+
+Count = 300
+Adata = 20c5ab290e6d97f53c74121951f39ba865b3acc465fa3f0fb8a591622277
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d00d29396ffa9e691290d746527777bf96a851f306d4da0b1816df1e0e82bb7bc8105930ad6a2232
+
+Count = 301
+Adata = 0e205a4dc5d5ead0d9ff7f182dc140fc49511c01b0fdbc7e6d6cb5fdf027
+Payload = 88b2572fbe7cf2b46df04db476ffedb41778ae2eb3c3aae4
+CT = 2167fa0c69b415af3383c4e8ae35d41e00b8232e3dbc3cd2df823c8ccd466807f2bd1c4032f0cfeb
+
+Count = 302
+Adata = 48043560d60381e83c11d4bc9d997d3ee2add6b0524b779c62dfaa73ce0a
+Payload = d44bf28b010e076b45db1b053af03db718b60748da51db1f
+CT = 7d9e5fa8d6c6e0701ba89259e23a041d0f768a48542e4d2931f5be8c9965345c760c72cc1b7908d1
+
+Count = 303
+Adata = f0729a8a2fd073699ab87b521cbe0420b43529556a505f5f87874d1a053c
+Payload = eab8cffb512eabe267cd64353552513defe97c2d10f35503
+CT = 436d62d886e64cf939beed69ed986897f829f12d9e8cc335381d94a828a95872ebdfda8a4c6a196b
+
+Count = 304
+Adata = fc2cd69bb61223f713e33a5071d09bf2783640c307c22d836dd94952dd37
+Payload = 001056926546c261fbbdf92b94498e038c2bcfd0b6345497
+CT = a9c5fbb1b28e257aa5ce70774c83b7a99beb42d0384bc2a163931808533f4f70d7a78242ced110eb
+
+Count = 305
+Adata = 8f653c5c003c807d16d17f833eebb97c9c2f0e5aae3780a52ce53a6c33f7
+Payload = 29ffaef9415fd300127ffd26ef324083a9d90e0f60e2ab4f
+CT = 802a03da9697341b4c0c747a37f87929be19830fee9d3d79f34553198f8e40fde6473f9cf04f1de6
+
+Count = 306
+Adata = 8d05e7d3077151c6d9378cb08e049e4d7c28a908f7f7c079c46ff92cd01b
+Payload = 9874dc5ca1b541f7b21c7b3860fa6b0c3ab1b712ab0fca98
+CT = 31a1717f767da6ecec6ff264b83052a62d713a1225705cae0fac20e8d45d2b0771d140b5e4a47c87
+
+Count = 307
+Adata = d4feb3ea76ac2945651f557406f3f38a2d7e9232ed55ff4eaf1201dd8255
+Payload = 1e01c7128c821fb9c971a27fc7c6f9bb902fa735de583b8a
+CT = b7d46a315b4af8a297022b231f0cc01187ef2a355027adbcd3cacfe4281e52d79e60eeb38319bc3a
+
+Count = 308
+Adata = 7cbb4ae995a3367a256cafd11cd6c6cab5bf3252fa97f27a8a1434ca9a27
+Payload = 51cd306fac7d20e3c7043eae3a6dfec046c5c24a666a0723
+CT = f8189d4c7bb5c7f89977b7f2e2a7c76a51054f4ae81591158f0d7646a799b14288bb2f354b5d8847
+
+Count = 309
+Adata = bd40b06a4beded2be3d176266b10772c7fa2949f0a9b20d613af90c2daf5
+Payload = fc5b26befc633a3e8ace011aa7a42bd0258a9f3dc14fc1c8
+CT = 558e8b9d2babdd25d4bd88467f6e127a324a123d4f3057fefd7f95e1d331e700aa9ef83f09b689fd
+
+[Alen = 31]
+
+Key = b1dc81d116d94f5eced526b37c004b95
+Nonce = 97c8f69fb91b17299461fd8d63
+
+Count = 310
+Adata = f8b08aa83bed09ca342249b2cf9e2b45a89dcfb8711a120395e455921af481
+Payload = 54390715b6e7c7bd51a234db059a51ba030cf22ee00b7277
+CT = cb629994c3418a662a8cde1b5f4d99aa7df66e24c53dc6df11297930fd44c63675b7cca70671ef4d
+
+Count = 311
+Adata = 0351c969dd38eeaa4b9b0000e346eeb1a2cd462033c59d9e6e3331822045cd
+Payload = 65b5e856a8cf35dffd42c5ba105cba4c434aa1c2a0390352
+CT = faee76d7dd697804866c2f7a4a8b725c3db03dc8850fb7fa7e77f5566ca2fd9293835bceb461dbaa
+
+Count = 312
+Adata = 5db8b6bc16740680f78fba917733a6899cdba5e4c10a8058963d1265681eaa
+Payload = 9a7685e3daac43ccf22cad0df900ba8acddc5d420846118d
+CT = 052d1b62af0a0e17890247cda3d7729ab326c1482d70a525ec2cf9f5d35521c1c000685e49d2ed42
+
+Count = 313
+Adata = e7d6024611210da0cfb90a9955195aa0a0539280a3a7c792a1540930daae2d
+Payload = c18d9e7971e2ae5fc128777086338fbe194443324e2d2cd1
+CT = 5ed600f80444e384ba069db0dce447ae67bedf386b1b987966f33dfb44ae413283b238616c6b99fb
+
+Count = 314
+Adata = 77a878c9c76f3e6a4ddd330d1d8828949d08e0fedffe0d8e2e557b29e7c78c
+Payload = fcf8982f7342f1b953658453cd5ea413700eff00f1ee7d6f
+CT = 63a306ae06e4bc62284b6e9397896c030ef4630ad4d8c9c731df6fc6b4cf0b6332936ed7cfe9455e
+
+Count = 315
+Adata = aa540554ee80dbffa475f702d862d6b60e0a4090792420a26d02926517723e
+Payload = 0d5690d2a7083ad6daf22b308314b8f5363aca77ca72835e
+CT = 920d0e53d2ae770da1dcc1f0d9c370e548c0567def4437f67c8162a815f2809601ad02595e2e0ff4
+
+Count = 316
+Adata = fae86f95dd06fb7fbae63a646615555aec8153dc328bdf79da5d4cc9677ed6
+Payload = f6e313cc35e8f8812b10a44f8ad00b6893f8084d942effe0
+CT = 69b88d4d404eb55a503e4e8fd007c378ed029447b1184b487fcaa11bdeab86f60f9cd0a2b45cee1a
+
+Count = 317
+Adata = fd525302d2fb246a47cf4e3a27808bda89d8488cf450f1a1c7df6eedd810ee
+Payload = 91e961ea2eb750577c5137c609602dbfcc4c07955ba429ec
+CT = 0eb2ff6b5b111d8c077fdd0653b7e5afb2b69b9f7e929d440a86a810881bd969744ad80f579400f1
+
+Count = 318
+Adata = 767b1bdf9793a512d3a84e99ef77b43011a3bcb8de4cd375dfe47a79293e01
+Payload = 98438c4411bead6f30c89ead762a12bf39391d3652b78b7a
+CT = 071812c56418e0b44be6746d2cfddaaf47c3813c77813fd2250ca00d3231819ecdf501ad39c864f3
+
+Count = 319
+Adata = aac7014f606df6feec415a75e29015891007f07518c955875fbf5619262ff2
+Payload = 540cb00c0eface3d1b2d632d80a642f53c78ff672a1ff6ff
+CT = cb572e8d7b5c83e6600389edda718ae54282636d0f2942571224d1d0294d46981d7dc39114a693d2
+
+[Alen = 32]
+
+Key = 5a33980e71e7d67fd6cf171454dc96e5
+Nonce = 33ae68ebb8010c6b3da6b9cb29
+
+Count = 320
+Adata = eca622a37570df619e10ebb18bebadb2f2b49c4d2b2ff715873bb672e30fc0ff
+Payload = a34dfa24847c365291ce1b54bcf8d9a75d861e5133cc3a74
+CT = 7a60fa7ee8859e283cce378fb6b95522ab8b70efcdb0265f7c4b4fa597666b86dd1353e400f28864
+
+Count = 321
+Adata = 55a62968c222a8501d1ae56a9a815667f8a9554607b7c56e6753f8fa92a4d054
+Payload = 764dbefb42644d18d23e5e4568685d14dbacfa418d36c4ef
+CT = af60bea12e9de5627f3e729e6229d1912da194ff734ad8c4423862a715dda2f63a4197f894515803
+
+Count = 322
+Adata = f8436e35b7a1c810ac6aabe8e2d48a3678d19e1e96337dada514ee5fc075fce4
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 17e3f2110e9ec22c8ebef633023a178021ef45ff5f31cefec200f190bd700f6108f9959f6d12f0f0
+
+Count = 323
+Adata = 548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f
+Payload = 53c164a4990c6e0637267ff2556c1542712fc584f6ff7458
+CT = 8aec64fef5f5c67c9a2653295f2d99c78722ab3a088368733a66ebc4e0777a6fc140a51e04a10f86
+
+Count = 324
+Adata = d100f1d08ef1e3eda4aef22cd970c2b785c4ff9b523c401b4064324aecf7f2d9
+Payload = 15681d2121ac56a63b9d0a38b9c4eccf84fdb746d32c14b4
+CT = cc451d7b4d55fedc969d26e3b385604a72f0d9f82d50089fb810cdc08db0a9966dffeb43ba26446e
+
+Count = 325
+Adata = eece934a807c9f21487cd810f15fd55d7bb4421882333ff2c43b0353de7fc5a6
+Payload = 412a8ef924ca156de860f147575e5731825f0a3759688928
+CT = 98078ea34833bd174560dd9c5d1fdbb474526489a7149503cfc5b397578f8d02a0b936ffac29b99a
+
+Count = 326
+Adata = 86311ff444d9be90459b6ee3652e1705ed0b5cdac3d27293ddea3378fb686ee5
+Payload = 54ba8a020d0876fa369dc32e8627f565ba3dda862ea0bcfe
+CT = 8d978a5861f1de809b9deff58c6679e04c30b438d0dca0d52c3fcd6d618c260d51724126f257534a
+
+Count = 327
+Adata = ab6efbc44a8906d5c067eaed71af467e130aaf170827a58beb03c55069674125
+Payload = 7a15506fd1dae444d77b2a3ae7b57a8d5b4f10e25a9f78e2
+CT = a3385035bd234c3e7a7b06e1edf4f608ad427e5ca4e364c9bf8b2821920640b992b00cd1c9618025
+
+Count = 328
+Adata = ddb640923d083725587aced81ae1d7409983d1f1e3ccc8dcf94376dc1bbcae8b
+Payload = b18a61a89cd698f32e059b7a2a9f62a46be2c248790a9915
+CT = 68a761f2f02f30898305b7a120deee219defacf68776853e4cd52d41a968284af8907ccbb4588cc0
+
+Count = 329
+Adata = d95ec4a6f594be1ba39fa1aa933dc0a5dafff5ce44509577ebb3a3e8084c4401
+Payload = 16ee3bc9ec8b4448e292b8973618e02a99da1c348539d5c7
+CT = cfc33b938072ec324f92944c3c596caf6fd7728a7b45c9ec47449a5cb4943ff2846c589b7c98ef49
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp
new file mode 100644
index 0000000000..1a7a5875fe
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+Nonce = 15b369889699b6de1fa3ee73e5
+
+Count = 0
+Adata = 00
+Payload = 39f08a2af1d8da6212550639b91fb2573e39a8eb5d801de8
+CT = 6342b8700edec97a960eb16e7cb1eb4412fb4e263ddd2206b090155d34a76c8324e5550c3ef426ed
+
+Count = 1
+Adata = 00
+Payload = 296fbda0017351491c2187273fbde2c3a427170e430a703c
+CT = 73dd8ffafe754251987a3070fa13bbd088e5f1c323574fd2167ee33e75d05023a7d63c770cfef2ea
+
+Count = 2
+Adata = 00
+Payload = eb61c284fe009921039ef6a9ce50e702823e44b35357923f
+CT = b1d3f0de01068a3987c541fe0bfebe11aefca27e330aadd170647420f79c0d91cbbd69b806fe96a5
+
+Count = 3
+Adata = 00
+Payload = ffeccc6460d23fdcc387c697e75dbb959b78013a8282eaa4
+CT = a55efe3e9fd42cc447dc71c022f3e286b7bae7f7e2dfd54a8a3ef2324754539ac774872282534386
+
+Count = 4
+Adata = 00
+Payload = 90958d7f458d98c48cbb464c74bf495a49846dd468c514e9
+CT = ca27bf25ba8b8bdc08e0f11bb111104965468b1908982b07e292cd0e32535a848e327bc53cdae94c
+
+Count = 5
+Adata = 00
+Payload = a4fad5205d38206e25097075687ca86032b95b3fe7e82a07
+CT = fe48e77aa23e3376a152c722add2f1731e7bbdf287b515e9bb21701af36936be5f62d02b84df87c3
+
+Count = 6
+Adata = 00
+Payload = b37114c65372b052cbeecf83d05a5da44f7b5bbff7d986b5
+CT = e9c3269cac74a34a4fb578d415f404b763b9bd729784b95b7da7f975367be24341e4af51b8bb156a
+
+Count = 7
+Adata = 00
+Payload = 9c0f0426f171ff18b2a4392f61fb4ee4a44c476fe03dc930
+CT = c6bd367c0e77ec0036ff8e78a45517f7888ea1a28060f6de360c6d50a96f316eda0b216cbb6380ef
+
+Count = 8
+Adata = 00
+Payload = 7b6e0a480a40585545b0e940e8d97c9ec987bd3c0e9c16a8
+CT = 21dc3812f5464b4dc1eb5e172d77258de5455bf16ec1294634cd1bd98e8137b578a174e39efe09b8
+
+Count = 9
+Adata = 00
+Payload = 34dac6dbc28be62332a6935efc122e37b26ee100eb4033f8
+CT = 6e68f4813d8df53bb6fd240939bc77249eac07cd8b1d0c16909a895a3b08b63d7a2a1e75d25e7861
+
+[Alen = 1]
+
+Key = 9748798c0f3cc766795c8ce0e4c979c1930dfe7faefea84a
+Nonce = cdf4ba655acfe8e2134fa0542f
+
+Count = 10
+Adata = 67
+Payload = 100fa71462277d76ca81f2cfdb3d39d3894b0ca28074a0f0
+CT = 36e2415b4f888a6072f260d7e786d803be16f8b9cbee112d7ff74e3b05b7d7c13284573bd3e7e481
+
+Count = 11
+Adata = 17
+Payload = 0217eb6778691f8dfe2d0e5241f05fcbcf97b9171f4de3f0
+CT = 24fa0d2855c6e89b465e9c4a7d4bbe1bf8ca4d0c54d7522d3ee7ce845f85dfc770d96dee9ca54ccd
+
+Count = 12
+Adata = dc
+Payload = a78b7bc6c1a7250c5fc236f2a8343725a9a7bd3ca81b53e4
+CT = 81669d89ec08d21ae7b1a4ea948fd6f59efa4927e381e239dc14ddd8ae0aa5d810040a8d1d4da1e9
+
+Count = 13
+Adata = 0c
+Payload = 390c808d998582793bb10ee60568eb8d975c51d68b4e4da9
+CT = 1fe166c2b42a756f83c29cfe39d30a5da001a5cdc0d4fc746b40dec7e647720f1f5e8474bf570c2f
+
+Count = 14
+Adata = 3e
+Payload = bcd9747fb54184b61b2e9e049caa75e22006e250f3722c0e
+CT = 9a34923098ee73a0a35d0c1ca0119432175b164bb8e89dd3c10c4aac45d90119cce490cc8681a49f
+
+Count = 15
+Adata = 7e
+Payload = d0342e3cd2c1142b642da7297ee3b9978cec405e6810f12f
+CT = f6d9c873ff6ee33ddc5e353142585847bbb1b445238a40f2f9a95091d2cab7d3d9fa3e10d3e67ac9
+
+Count = 16
+Adata = e3
+Payload = 7fab91d1aa072947d22f0dc322355a022fe7f0747f4a184b
+CT = 5946779e87a8de516a5c9fdb1e8ebbd218ba046f34d0a996180f7818c373e89f7ff3003f53260060
+
+Count = 17
+Adata = 3e
+Payload = e487143dc4d98dcc6a2dfe6ee0f85d565d1f46bb0fafe62a
+CT = c26af272e9767adad25e6c76dc43bc866a42b2a0443557f71905f581585e59e3c8c038b5bf966559
+
+Count = 18
+Adata = 3b
+Payload = 976b489244ed6789a34251500057d1d4a3229367a42b9066
+CT = b186aedd6942909f1b31c3483cec3004947f677cefb121bbea56569c34f8d9eea23e85fec18cfc51
+
+Count = 19
+Adata = a5
+Payload = 71efa75961dfd60ad533082a8cfe111214eb02573adc4591
+CT = 570241164c70211c6d409a32b045f0c223b6f64c7146f44c212da23548f2ca4e9a8a07962be6422c
+
+[Alen = 2]
+
+Key = 393dcac5a28d77297946d7ab471ae03bd303ba3499e2ce26
+Nonce = fe7329f343f6e726a90b11ae37
+
+Count = 20
+Adata = 1c8b
+Payload = 262f4ac988812500cb437f52f0c182148e85a0bec67a2736
+CT = e6d43f822ad168aa9c2e29c07f4592d7bbeb0203f418f3020ecdbc200be353112faf20e2be711908
+
+Count = 21
+Adata = 9db5
+Payload = d5982c462ad40458660cd7b120ce07fce9afe812caedcebd
+CT = 1563590d888449f231618123af4a173fdcc14aaff88f1a89015e5cd97b7dd3d981321ae0b2d99e1a
+
+Count = 22
+Adata = 69cf
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = da6e85202048347568befac0731db702e687d5ef51d50402bf3e75863c7acd2699caba3cc301f4b2
+
+Count = 23
+Adata = 6c6e
+Payload = 373c157e59b934a1afb57d4c5dd9ca7fb736b206a6210bef
+CT = f7c76035fbe9790bf8d82bded25ddabc825810bb9443dfdb5d6a8f7a9f52a8038aa9dc1bdc9ed876
+
+Count = 24
+Adata = dafa
+Payload = 26e10a2ed8cc883a6552aee162c5542ff8bb8e758a1975f8
+CT = e61a7f657a9cc590323ff873ed4144eccdd52cc8b87ba1cc8a15603f10cbfdb041f8b2b12cc8f037
+
+Count = 25
+Adata = c8b1
+Payload = dd235b05c15479dfe0326ba206ac784eca50038bbeb35d32
+CT = 1dd82e4e63043475b75f3d308928688dff3ea1368cd189061278bf62ba6a4819513d49fdcdb45480
+
+Count = 26
+Adata = af48
+Payload = a0818342a5cae4a90ef281d3d1289d83f273f418a545fcbf
+CT = 607af609079aa903599fd7415eac8d40c71d56a59727288b8b4d00309b50f9ea72f8105c94475b52
+
+Count = 27
+Adata = b1cd
+Payload = 33c0d06b6583bb4d15b4a07364c4be70ac6e72795c3dae0f
+CT = f33ba520c7d3f6e742d9f6e1eb40aeb39900d0c46e5f7a3b220ba58e97936612c4183ba86705b2f9
+
+Count = 28
+Adata = 649a
+Payload = 3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863bde9
+CT = fb5a67c9744faec46fa7e127d646ed5f8be555566a0169dd87d602dc85bb260fb3df1221e2fbd10c
+
+Count = 29
+Adata = 593c
+Payload = a97faefcae36732fcfe47736c2334ea7d411bf7638b0c019
+CT = 6984dbb70c663e85988921a44db75e64e17f1dcb0ad2142deb3835b7eecad6dac9785ad1d370ede4
+
+[Alen = 3]
+
+Key = a74abc4347e4be0acb0a73bb8f7d25c35bae13b77f80233a
+Nonce = 6a850e94940da8781159ba97ef
+
+Count = 30
+Adata = a4490e
+Payload = 6372824bf416cd072a7ad0ae5f9f596c6127520c1b688ab4
+CT = b14a07bdc119d87611342c4c6935c5786ff1f9ae2eb49e6191c88a3cb4fbafcb8a4a157d587d7e39
+
+Count = 31
+Adata = 5cad2e
+Payload = 295f4f3417a77fcf0bbda17b0fd629ad57a6086573c87eb1
+CT = fb67cac222a86abe30f35d99397cb5b95970a3c746146a64235c34d1390bba5b008c3fb29c2df958
+
+Count = 32
+Adata = ebdf4c
+Payload = 86f354a505de941d34cd98e3af3706d56a938ab9a2797182
+CT = 54cbd15330d1816c0f836401999d9ac16445211b97a565575a733bba0a6992d0664dc77d2b5d194c
+
+Count = 33
+Adata = 7c0d70
+Payload = 88c3bfb546abe2f6bfc92a7c56c627e24ab92a8a87a6b43c
+CT = 5afb3a4373a4f7878487d69e606cbbf6446f8128b27aa0e90902a31b15eed99c2dc4ed1bf11cad96
+
+Count = 34
+Adata = 8fa501
+Payload = 75d4216bad77943bfe82be216157843b0da0fd16eeee8471
+CT = a7eca49d9878814ac5cc42c357fd182f037656b4db3290a42f25595ae00103d4eb20288158132e7d
+
+Count = 35
+Adata = b7aca7
+Payload = bf1401e8dcf6f681ed6dd74c7e23b7e54b384608b0e5ec52
+CT = 6d2c841ee9f9e3f0d6232bae48892bf145eeedaa8539f88760e67693b509ea4795b7da32c5c5d17f
+
+Count = 36
+Adata = 1f283f
+Payload = 7e623e7ef7d0a678b5d22a8402d89220f4f1bf759e3084dd
+CT = ac5abb88c2dfb3098e9cd66634720e34fa2714d7abec900880ef8ea380a1a0a38b2c20288e637a9f
+
+Count = 37
+Adata = e93f31
+Payload = 14f80e7a6298d85d31fb80376a394a8f88b0ae47f00450c7
+CT = c6c08b8c5797cd2c0ab57cd55c93d69b866605e5c5d84412d553aafe8536385d34c412c14d3a1563
+
+Count = 38
+Adata = 27e9a5
+Payload = 3330df12249639961f562a74b34f60b0a8bc7c783f6572fd
+CT = e1085ae411992ce72418d69685e5fca4a66ad7da0ab96628f594d366c8fc826ce58309e9053c27f7
+
+Count = 39
+Adata = 72d566
+Payload = 1a1860ac8c11c5d262f8141738cae8ff91ca05906dc98bb4
+CT = c820e55ab91ed0a359b6e8f50e6074eb9f1cae3258159f61cdd6ac6c42cd3d11e0344a9c1001e253
+
+[Alen = 4]
+
+Key = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb0
+Nonce = ba356d392c3f700f4f2706a4ca
+
+Count = 40
+Adata = 8ffc0e3d
+Payload = e8c1a89228d8212f75c136bab7923a89f9fea18e781cb836
+CT = 66b5d782323925e1bd0a8413a9a5a881356453d5df2cbeb199b2e1e803550dcdde55fd66ecb45edd
+
+Count = 41
+Adata = 2b4f9cfc
+Payload = a12c6324e022affd61b7e0d8cccbeb23e2e6c65355c1d586
+CT = 2f581c34fac3ab33a97c5271d2fc792b2e7c3408f2f1d3019e8fbc507244ba234a0581dc69962a66
+
+Count = 42
+Adata = b4de3039
+Payload = 7cccb26f1dd227bc77458b99fd9e00f8e801adaece7bfcd1
+CT = f2b8cd7f07332372bf8e3930e3a992f0249b5ff5694bfa5628a2857099af20a4ae08e687bdb02c75
+
+Count = 43
+Adata = bc59f18c
+Payload = 692b53c1355475c71ceff0b0952a8b3541b2938270247d44
+CT = e75f2cd12fb57109d42442198b1d193d8d2861d9d7147bc3e33a6416e387d9e571a1954471ec9cc7
+
+Count = 44
+Adata = 4fd9fd39
+Payload = 7e3e755e25bbe78d4a7770f9356ab9f4ff1bbfdba46383f5
+CT = f04a0a4e3f5ae34382bcc2502b5d2bfc33814d8003538572180f9735f994c8335e593f30b331a920
+
+Count = 45
+Adata = 296cd04c
+Payload = 997b712cd9295dc43cc19b40679f218c27af3e8c638d2e5d
+CT = 170f0e3cc3c8590af40a29e979a8b384eb35ccd7c4bd28da91990fa537d2657d01f66872ba9af22f
+
+Count = 46
+Adata = 88037d3e
+Payload = 577981ccb6c893dfe6405075fcb41507de7f9bfda860791f
+CT = d90dfedcac2997112e8be2dce283870f12e569a60f507f984915cb93e84028c7aedce1a2dadbb6bb
+
+Count = 47
+Adata = fc4bb852
+Payload = 37ba9f57ec230675ce060ba3d388095adf15907aa0b0673d
+CT = b9cee047f6c202bb06cdb90acdbf9b52138f6221078061ba25baa6385af8d7b807a2d2ab19aa4999
+
+Count = 48
+Adata = f40ec14f
+Payload = 401e0cdc132a9e4a9b5ceeed3c181f67e5203ea69508deff
+CT = ce6a73cc09cb9a8453975c44222f8d6f29baccfd3238d8786adcdb44870e1105b7318d8bad0af957
+
+Count = 49
+Adata = 90e2c63b
+Payload = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+CT = 8c40a5f5a79be2a2af34beb3212d8b12c1e13ceff68c2dfa8b079fb71d45bd985bffd343c3362653
+
+[Alen = 5]
+
+Key = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+Nonce = d4ef3e9e04f1b7f20ffc5a022e
+
+Count = 50
+Adata = a468f08d07
+Payload = d3bef460223c81e4579c9d1d463ac5e0881685de1420a411
+CT = abb85db49a9b1c8724ecbc734cc8373bd20083cfa4007b1cfe4d3a3bb25f89f692884be230c6035c
+
+Count = 51
+Adata = 4497649a54
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326461ee1
+CT = f9ab96ecd34a5695258f723269aaffc4ddf5c1329666c1ecd05ae56511a230627e02d066c52a919e
+
+Count = 52
+Adata = c30ddd994e
+Payload = 84b88264afec06b370dfcebf5e1d3e2c1f005faf248b3215
+CT = fcbe2bb0174b9bd003afefd154efccf7451659be94abed188ef92fc17dca026f1ac1eaf78a05017c
+
+Count = 53
+Adata = 9573270f7e
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a040
+CT = e64a237d0d2d13c8b62849fcffa6e2dbee2911c810717f4d38eddff1e60e2d9ae74a936364b8df21
+
+Count = 54
+Adata = 40336790fc
+Payload = 260f67122dfbe03365bc9e35e9d4ac4b2eb150eddb30857d
+CT = 5e09cec6955c7d5016ccbf5be3265e9074a756fc6b105a70aa3d464ad89cae59b474d019a5a7605c
+
+Count = 55
+Adata = 0b310c8529
+Payload = 1d55e7352bd895c4ef77389a7225c664f72b38c8de778d57
+CT = 65534ee1937f08a79c0719f478d734bfad3d3ed96e57525abeab0c520e64939c6950c0fa406eafb1
+
+Count = 56
+Adata = 5756b2c681
+Payload = fbd315e1f5bd0f0e60ee6684c88f3543452c62ea0701d11d
+CT = 83d5bc354d1a926d139e47eac27dc7981f3a64fbb7210e10d22d339c382343bf39c239fd64c2a64f
+
+Count = 57
+Adata = 3b919e3665
+Payload = d68d6556c5a5b1f5a123389b3ce966d5837cb8fcf5accfff
+CT = ae8bcc827d022c96d25319f5361b940ed96abeed458c10f2fcd6b562a1b6aa10be92a81f99ed540c
+
+Count = 58
+Adata = 58749b643f
+Payload = 062cb6962fa5b3a6239b95f3a51b478a1f32b081dc538a80
+CT = 7e2a1f4297022ec550ebb49dafe9b5514524b6906c73558d4b853022237d94d253b375bf2150e699
+
+Count = 59
+Adata = a5d50c008b
+Payload = 08c62ff9bd7bcf189f530d5065f8764532d2692f69858483
+CT = 70c0862d05dc527bec232c3e6f0a849e68c46f3ed9a55b8ee7aee0d403b2cf6f8b993eebd6b93615
+
+[Alen = 6]
+
+Key = 1c476cfd7dd300d961fd3f24a6fe0e80742b00851676ca63
+Nonce = e300fc7a5b96806382c35af5b2
+
+Count = 60
+Adata = 28130f938c45
+Payload = 6f3938932b5c1280311e892280d8a822a828a0be7fdb1bcd
+CT = df48662fe134e75a85abc2cece2c3b6236c88a70fa792e9beadc9601adf9fbdf4e3e94b395b0a332
+
+Count = 61
+Adata = f600024a7bf9
+Payload = 0af7345e71f4e8886503395ade0b0296a5856e086638b06a
+CT = ba866ae2bb9c1d52d1b672b690ff91d63b6544c6e39a853c0692a40a6aba8d7c5addae21de90fea9
+
+Count = 62
+Adata = 4eef510d1f48
+Payload = 37f57772f056f45a5ce9f46d27be1858980c8935b9c839b7
+CT = 878429ce3a3e0180e85cbf81694a8b1806eca3fb3c6a0ce122f64becb581070411957e632e19bb8f
+
+Count = 63
+Adata = 4c9c76b6fad5
+Payload = 8bb10c82bcabb7fb2b169252ab443b01df217cf908b8c241
+CT = 3bc0523e76c342219fa3d9bee5b0a84141c156378d1af71708c59f83aa97d069b6d83d9387051f43
+
+Count = 64
+Adata = 5572ecfc7e53
+Payload = d1ccb4654a22b1afe32f3d3035fdccd87e9cbed83c679007
+CT = 61bdead9804a4475579a76dc7b095f98e07c9416b9c5a551f04686ee1d7b985d903f1de6cf78f8f4
+
+Count = 65
+Adata = bffdf9d20d74
+Payload = f990a8f6ba14065d48665db36eb470c49f38e2b6376a9bde
+CT = 49e1f64a707cf387fcd3165f2040e38401d8c878b2c8ae88f8118f1b9f39b51965ae9ef1bdb40111
+
+Count = 66
+Adata = 3f27e678c580
+Payload = f8c7d89639ab742a8bcfffe776e868d671e1fbdd55807a8a
+CT = 48b6862af3c381f03f7ab40b381cfb96ef01d113d0224fdca3236d02f33f49759f281315e449bfef
+
+Count = 67
+Adata = 1294cb9db5f5
+Payload = 8601cfd7d935e8a8487b9c39d55ca27096255f2eb9e009e3
+CT = 3670916b135d1d72fcced7d59ba8313008c575e03c423cb5e74770a07c242c3854ceb242dadc1976
+
+Count = 68
+Adata = cec271332b75
+Payload = 77c85b8022f58337b364142a2474fe5cfddb31cfca48af46
+CT = c7b9053ce89d76ed07d15fc66a806d1c633b1b014fea9a10d6c65f19175cfa49898655ccdddb864a
+
+Count = 69
+Adata = da06bd140502
+Payload = b0f2db802475fa70af02057373844f637a3244cda4b4f93d
+CT = 0083853cee1d0faa1bb74e9f3d70dc23e4d26e032116cc6b458822e49e69031431b3eea872a72eb7
+
+[Alen = 7]
+
+Key = 79d1e38a70df1cf239be168833dcd0570bc8f37b3aa26c37
+Nonce = 8229d6d7e9e21fdc789bff5dcf
+
+Count = 70
+Adata = 076887d2abe900
+Payload = 83c24f3a77b83b4ef45277ba90225f3ba1722312f52b1a07
+CT = 19d880f1d959a68f162de243d4a45747ace704613359b27218d1531a066de60a95d2924a6910e990
+
+Count = 71
+Adata = 7535bcc6fbd1a0
+Payload = 24f85ef683cc521387f484bc0b2ad9172f61884c09a9718c
+CT = bee2913d2d2dcfd2658b11454facd16b22f4af3fcfdbd9f96dbf58406020e6df7b312b6825127f9a
+
+Count = 72
+Adata = f4f96d7b4384a3
+Payload = 212bedfa06b5e1a2c3a2f31f6f791dd9df8ef26077821c0a
+CT = bb312231a8547c6321dd66e62bff15a5d21bd513b1f0b47f64dd755177efc87f8b1daf1fd88e51a6
+
+Count = 73
+Adata = 3b7e3d9c1a7fa2
+Payload = 8b9036914bb0f440c8dbcfde9b9547be5e5ef1f56492c75e
+CT = 118af95ae55169812aa45a27df134fc253cbd686a2e06f2b0be31cab31f1a20805d5c07dc516d707
+
+Count = 74
+Adata = a8c35fae8912d6
+Payload = 50f3f3a91bf6fd9573d5ef54b9bb5805205b2f9865d81fd7
+CT = cae93c62b517605491aa7aadfd3d50792dce08eba3aab7a2399df9a45ad153c0dfb3fec3b9d6f7c5
+
+Count = 75
+Adata = db636541f2429d
+Payload = 6fbda8d435555e735443f1e6bc09e96065092efd89edd64a
+CT = f5a7671f9bb4c3b2b63c641ff88fe11c689c098e4f9f7e3fe20b7da94eac8c7ef8478671165e0d82
+
+Count = 76
+Adata = a8de55170c6dc0
+Payload = 640ef4c246a2c6e16ddc49072a5aeef70319149ffba071ef
+CT = fe143b09e8435b208fa3dcfe6edce68b0e8c33ec3dd2d99a4979c35bdbf9538666b6fa57f0f915d8
+
+Count = 77
+Adata = f8d64ce2aa66e6
+Payload = a14e3910766f31594a28ad2c3678c31d0c3aee88484ca6d6
+CT = 3b54f6dbd88eac98a85738d572fecb6101afc9fb8e3e0ea3752824a691da2e99374ae6c031d74ffb
+
+Count = 78
+Adata = b3c340afdc53a8
+Payload = 1b8e0a09e6364020b4cac704dc19bfa79455295604cf9c9a
+CT = 8194c5c248d7dde156b552fd989fb7db99c00e25c2bd34ef04159a68706faa2e8c3376b4dbeb423a
+
+Count = 79
+Adata = 73824034001519
+Payload = 52c84a0735eea6c5c230644075ebfc5db0c3128056e7a8f4
+CT = c8d285cc9b0f3b04204ff1b9316df421bd5635f390950081e5adc7564721ead2af75cb98e61148b4
+
+[Alen = 8]
+
+Key = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+Nonce = 3820db475c7cb04a0f74d8e449
+
+Count = 80
+Adata = f427c47e10c45bb3
+Payload = 54bc7e3c227df4e83252a5848fea12dfdb2d14b9e67c1629
+CT = 91e7baff2b42af63e26c87ce6991af22422c1f82906858b1721961de5c768f4d19bd3034f44f08d2
+
+Count = 81
+Adata = ca25504f3f5559aa
+Payload = ff4493fea916f49fbb3cae2838bc84e293531092cc0904ab
+CT = 3a1f573da029af146b028c62dec7391f0a521ba9ba1d4a3342968c638ecb8a2b358e8eaefd931efb
+
+Count = 82
+Adata = 8215753d9efc5132
+Payload = af16ab8558269a93d8e8c9e38f12a8768947d8b69be0e259
+CT = 6a4d6f465119c11808d6eba96969158b1046d38dedf4acc1f8ac11752fe51e354f3f8a68815539aa
+
+Count = 83
+Adata = 9e7cdbc6202e6492
+Payload = 744a167ae31a8ca20df82290766429de9ef0b7dfe199a78d
+CT = b111d2b9ea25d729ddc600da901f942307f1bce4978de915489de8e241dcab16bdcbf1a1ff4d8d10
+
+Count = 84
+Adata = b8d511d0ab86a07f
+Payload = eeb39de1fe21b5aba654da45fe1481decb22365fa4cbe49d
+CT = 2be85922f71eee20766af80f186f3c2352233d64d2dfaa053fab212a1b6dc7b953e2bc211be194ae
+
+Count = 85
+Adata = c74a5d4265f9f3d5
+Payload = e95c20e80153bae3fde3c3d82b6b33b35fc1959fa31a5d11
+CT = 2c07e42b086ce1682ddde192cd108e4ec6c09ea4d50e138973918ab70fe048d6c5b63a01725eddfb
+
+Count = 86
+Adata = fd849d3ada03181a
+Payload = 6d00606c72cea3deaea5b51ae09e61924355e167058ef42c
+CT = a85ba4af7bf1f8557e9b975006e5dc6fda54ea5c739abab487089bc20867f474c1127aa1320f0000
+
+Count = 87
+Adata = 56825a68681f498c
+Payload = c47705d897a6c7e7aed710b96e2d8532c23b82090e21b114
+CT = 012cc11b9e999c6c7ee932f3885638cf5b3a89327835ff8c34a23b0b6ac4d297dd7832a5e2102272
+
+Count = 88
+Adata = 72e4da839913a26e
+Payload = c822a1ee581cf85b0482c821473385bd3f28528e5e5760d9
+CT = 0d79652d5123a3d0d4bcea6ba1483840a62959b528432e41dd665766c7af21ff890bd40178f1c660
+
+Count = 89
+Adata = 138457571ee8dafd
+Payload = 3ffb82a83308da66e95ac63ae92931b09ffe0e42afbb4979
+CT = faa0466b3a3781ed3964e4700f528c4d06ff0579d9af07e16a6a58bb772c79481dc26861ffbd68c6
+
+[Alen = 9]
+
+Key = 39c03a0c8634047b1635348f284d3dc1e752ab40548eb337
+Nonce = 9e2ea8eb7f56087ee506925648
+
+Count = 90
+Adata = 28d157f09a71da80dd
+Payload = 0662e63c88e963d3e0cf2c4653515ae4474a2c78ab0394c0
+CT = 01dcd4dd3b8c1369518136ce45e8bb9df565b0ad231a887b02ada34addf0aa2f4744ed2e07995491
+
+Count = 91
+Adata = c17d311362c41d442b
+Payload = d6df8b60c697093987b3d89a3667b36504b6ddddf12b0900
+CT = d161b98175f2798336fdc21220de521cb6994108793215bb38a27466b8741bffce44ef04b23af321
+
+Count = 92
+Adata = 006669ef1a11b65b1d
+Payload = 49ad29ef5e82b08752ac5a50dd982e4bcb700005454ade6c
+CT = 4e131b0eede7c03de3e240d8cb21cf32795f9cd0cd53c2d77d11372fb0dab1c99b159e5fe9f91118
+
+Count = 93
+Adata = 8eafce9ba466fd53eb
+Payload = 385f9fb139dbf88561b7a500b0c7b835fe57e2698c6d9f76
+CT = 3fe1ad508abe883fd0f9bf88a67e594c4c787ebc047483cd09e4898a4046f6ec9f40e412915007e4
+
+Count = 94
+Adata = 796e55fbe7bed46d02
+Payload = 4ebb149b01cbacba32d11168ca61928ea149dcf2ee2c1001
+CT = 4905267ab2aedc00839f0be0dcd873f71366402766350cba5d40a9902481bfac7ff33d08fb4b3d31
+
+Count = 95
+Adata = 8f958d796be0566512
+Payload = 0d974e5621caa1d86eaaee689ccbca57843373fcf20db407
+CT = 0a297cb792afd162dfe4f4e08a722b2e361cef297a14a8bcd972d09a17172161eb68a30b593b1bd6
+
+Count = 96
+Adata = cc879ff2d583a7288c
+Payload = f8e0dac6a691dfb231411b5c5f70a0daff83cc637b0c7bb3
+CT = ff5ee82715f4af08800f01d449c941a34dac50b6f3156708119cc26a80c152c253fbc36cb886e0fc
+
+Count = 97
+Adata = 4765d696d19dec58bc
+Payload = 096a36396ccfa260f28fb0919157a5076b53506c51a2a4ef
+CT = 0ed404d8dfaad2da43c1aa1987ee447ed97cccb9d9bbb8549de06cc5c3bc4ad75076c774576843fb
+
+Count = 98
+Adata = a004f283afc3309c31
+Payload = 5b943269be41e2758a4ea6a3cc621b711a8ba6002783aa72
+CT = 5c2a00880d2492cf3b00bc2bdadbfa08a8a43ad5af9ab6c9135493b44f79a5774df6b2943b0bec67
+
+Count = 99
+Adata = cdd5d8aefe49a315ad
+Payload = 5f27867109e74862ce0dbc9ba73c420b93067bdede17ae51
+CT = 5899b490ba8238d87f43a613b185a3722129e70b560eb2ea7a5da4a29a9012d78b6de6f1b3e8c9ed
+
+[Alen = 10]
+
+Key = e2a92ffbb0b5eb68cb82687f12449fae5167d375131b0b10
+Nonce = 441ad5e1382e083a95224f395d
+
+Count = 100
+Adata = 2352648299b0413cb2ce
+Payload = 048c9ba4597c3bb595bfd5048e5e9a1296f30e5c0118b177
+CT = 25247a258e4ac0a988d8def60cc174a9d4578cd5346fb5150c96e8ab8774baa421f39c64a386c418
+
+Count = 101
+Adata = ce003c836a6f5f066053
+Payload = 02ea8e7e488c863584f828df13dfeb68433294d11d9ca9d7
+CT = 23426fff9fba7d29999f232d914005d30196165828ebadb5d453036cdc6bad0c5e770a6249a52e74
+
+Count = 102
+Adata = d11be73a104ccc6346d5
+Payload = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024
+CT = 4cfd9248f0ae6ccbcc072678175fa50e889b2fa48bfea4464627ad75bbfe17f3f5ddfd3dbc1045f3
+
+Count = 103
+Adata = 6a7b80b6738ff0a23ad5
+Payload = 97a813e75d95d25c2edb1c705c4ffe4d7c08c756761fbc0b
+CT = b600f2668aa3294033bc1782ded010f63eac45df4368b869af8943f74706cc3394a170fd49f7011a
+
+Count = 104
+Adata = a391acdb3a06dae4a671
+Payload = a78981ac244307451e4d3fd7f654b70cc4e6518aa47a3c18
+CT = 8621602df375fc59032a342574cb59b78642d303910d387af22597f63074ca3533bb5e107860481f
+
+Count = 105
+Adata = 0b9f28f2d3215785f569
+Payload = 5d649d79ff0e304e164a383c74f13d7ffab145d00cb0ec2c
+CT = 7ccc7cf82838cb520b2d33cef66ed3c4b815c75939c7e84e905b5609f593c6ea9281f66cd2e646dd
+
+Count = 106
+Adata = 7928b1091cbfb2eef0fe
+Payload = 83a273687dced7b94d569f81d75508595cde668f06406183
+CT = a20a92e9aaf82ca55031947355cae6e21e7ae406333765e1428195355618ea0cf87260ad20b6d7b9
+
+Count = 107
+Adata = 3b74afb81f54a93c79d5
+Payload = b4dc3c059cf7b47dd0bb7f165a63fc80b5c6b5f3ca7eeb73
+CT = 9574dd844bc14f61cddc74e4d8fc123bf762377aff09ef1155019659f41a5f0430695b4ada9d8b8d
+
+Count = 108
+Adata = a46ae4c71d4c9eb72fab
+Payload = 7e919581c5105d98717d0613e1ca869c6516506ea482d5c2
+CT = 5f3974001226a6846c1a0de16355682727b2d2e791f5d1a01514b252f33dc870c42260e48c4fa9fd
+
+Count = 109
+Adata = a1ace61711f0a09ac17d
+Payload = 3a4558b55214f21cbd2ae2eda5a2321cfc2f102e059b744a
+CT = 1bedb93485220900a04de91f273ddca7be8b92a730ec7028c263c667d7ed58907452c092905d0b31
+
+[Alen = 11]
+
+Key = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Nonce = 8e7d8a44244daa7df2b340993e
+
+Count = 110
+Adata = 521583c25eb4a3b2e46120
+Payload = 9f580cc6c62a05ce125c6bec109a48ca527ee26a64b14b68
+CT = ff0ff95bcb0bccd5e4aadd77ac6770f5013654eb3c6386fded2c87135861b43a99f258b6938f66e3
+
+Count = 111
+Adata = 31adb39e947f8883fa4b69
+Payload = f16bba081bddda83546eabc9a55c81a439720dd8562ce964
+CT = 913c4f9516fc1398a2981d5219a1b99b6a3abb590efe24f132b87476d66a1bd405f484ef9ac8ab7e
+
+Count = 112
+Adata = f05f39eb0a3d6460076aa8
+Payload = 6baf784f63cf45a1836fa8f3609fff7870ce8cbd1e91268c
+CT = 0bf88dd26eee8cba75991e68dc62c74723863a3c4643eb19a120b455b366cb104fd8b6dc2c80471e
+
+Count = 113
+Adata = 74c7a633ff73ff507009c5
+Payload = d8176a6de1c15a14c8b8b58725c179dc84c9308268d718d5
+CT = b8409ff0ece0930f3e4e031c993c41e3d78186033005d5400c8ca09f4bf06b1c27e75abf15112e49
+
+Count = 114
+Adata = ab322a88cf44b9ca774415
+Payload = 3706e4d8ff748574f382e5f9b0a3b6258f1f360fd87001b0
+CT = 57511145f2554c6f057453620c5e8e1adc57808e80a2cc25b3159274a7de3550baf759f7fae53dbc
+
+Count = 115
+Adata = d6fe6e17221d4e06ed3ab9
+Payload = e02217394772deffe218c405e40f2a3a56ca01d55d6d3330
+CT = 8075e2a44a5317e414ee729e58f212050582b75405bffea516fba8d193e133e6f78daa39681cb262
+
+Count = 116
+Adata = 2739d2cdfcbe7d5cd7d28c
+Payload = bb713f74a884bd1a994adba87561d637853c6181290ef5e8
+CT = db26cae9a5a574016fbc6d33c99cee08d674d70071dc387d65f92db3b3d1c2de04c69c5d06b0e001
+
+Count = 117
+Adata = 5841571299cd064a6262b7
+Payload = 9641dedd50d80ac0abf7591436065fa2e23e4687abbb86e4
+CT = f6162b405df9c3db5d01ef8f8afb679db176f006f3694b716e4d20ab5ffad6f71155f6839dfdbb25
+
+Count = 118
+Adata = dc5d7fd97bb3243ba585fa
+Payload = aefda8501193edacb8abb94fff875529a537a462c4b9b69c
+CT = ceaa5dcd1cb224b74e5d0fd4437a6d16f67f12e39c6b7b090ebc3af2de52b8bee3d130fa973f716b
+
+Count = 119
+Adata = 8789e0b3e0dc13d9725b37
+Payload = 65e53f549b62aca03f21ab2a494b93805e02cfecf4f12aa4
+CT = 05b2cac9964365bbc9d71db1f5b6abbf0d4a796dac23e731b5cd5a004a0ef28e30383bdaed8f93c7
+
+[Alen = 12]
+
+Key = 44cba20b7204ed85327c9c71c6fea00b47ce7bdde9dea490
+Nonce = f3329154d8908f4e4a5b079992
+
+Count = 120
+Adata = f1e0af185180d2eb63e50e37
+Payload = 6333bde218b784ccd8370492f7c8c722f8ef143af66d71d7
+CT = b9401a4927b34dc15e9193db00212f85f0c319781ec90e3b4484d93cb422cb564acc63d3d18e169c
+
+Count = 121
+Adata = ea74231e49e667ca1c21d46d
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+CT = e67d8fbeec794d42fc64d7f36a87d2ac22aafa440021ea72c4c151d9927e6a9f19d47ff7d79ca6f6
+
+Count = 122
+Adata = 7f5871a8300471dc325f8289
+Payload = c642c9722d84d708682350dc70bdaa9a1181a415a9e72b93
+CT = 1c316ed912801e05ee85c7958754423d19ada9574143547f959eee29be1415ab03444de0fa42707d
+
+Count = 123
+Adata = ee7e6075ba52846de5d62549
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = f8f50646e284ba77f4ea3e08d69777a53aab062ec784ad70ce97c1c8aea70de04580d7b37f8c014d
+
+Count = 124
+Adata = a30f2fd445820cdf80014554
+Payload = 92577d5db20391110309d490f52acecdfc18382f368bbe42
+CT = 4824daf68d07581c85af43d902c3266af434356dde2fc1ae23b536f993381e525a14599dd5c02e80
+
+Count = 125
+Adata = 0cfec933831644b468724e80
+Payload = 6803dc3f7c06568ca78ee5aa2e9b1b354a4f1e067ff6a25b
+CT = b2707b9443029f81212872e3d972f392426313449752ddb7d6ea722fdd82ede2c7b8832dde3cbe80
+
+Count = 126
+Adata = 6bd14e3bf91dc7fd6be07647
+Payload = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adba
+CT = 8ff3c0856dae0290f7eca38aebda1485163fe5bbe0edd2565c2994b2b469ad977564d83db1ebfe38
+
+Count = 127
+Adata = 6c6ad35e97d023217018162f
+Payload = 1bd1bcc6766d251144376d91ff93ef83033d0e0ee546266f
+CT = c1a21b6d4969ec1cc291fad8087a07240b11034c0de25983ac31ebf9e255eecf3c69ddf198760556
+
+Count = 128
+Adata = 52c35db85cc34b6efed180ee
+Payload = 28f71a2fe498f89203a5d23e8f8fa64b124aea6459fe721d
+CT = f284bd84db9c319f8503457778664eec1a66e726b15a0df13424079e3de87fa59c3d10fd62380a90
+
+Count = 129
+Adata = a96e4776270683ee7d0c9b6e
+Payload = 5be078ead1926074afca81f9a97dc93dcb954c955e4343e4
+CT = 8193df41ee96a979296c16b05e94219ac3b941d7b6e73c082258e1f3fc3eb7e976c86c8a21bd6569
+
+[Alen = 13]
+
+Key = b5f43f3ae38a6165f0f990abe9ee50cd9ad7e847a0a51731
+Nonce = 13501aebda19a9bf1b5ffaa42a
+
+Count = 130
+Adata = ead4c45ff9db54f9902a6de181
+Payload = 3726c1aaf85ee8099a7ebd3268700e07d4b3f292c65bba34
+CT = fd80e88f07dad09eed5569a4f9bb65c42ef426dda40450119503d811701642143013f28ce384d912
+
+Count = 131
+Adata = e63b89e95df8338ecdcc885c3b
+Payload = 37f86aa62b1e31e9ded3e1a38a7e1a8a638d619ac109694f
+CT = fd5e4383d49a097ea9f835351bb5714999cab5d5a356836ac6d3f9c7b9f25e09ce164a11370b8b05
+
+Count = 132
+Adata = a2161536e263459e0b0a29a225
+Payload = 1749f5977197359a5d318d5fea38aba95b3603f1d7011e66
+CT = ddefdcb28e130d0d2a1a59c97bf3c06aa171d7beb55ef443e02b848b006c28803303fd97bdc35476
+
+Count = 133
+Adata = 8ac95a6ae0bce0fb07f85368ab
+Payload = 0842bfb8b38283257c2ea58b29c8350775f1dbf15f73c905
+CT = c2e4969d4c06bbb20b05711db8035ec48fb60fbe3d2c2320431de2bc45b2b726bfda92939a11f68b
+
+Count = 134
+Adata = 44cc9b2510680c4d73f1938c77
+Payload = 68d09fce5e89e4ef6d453b8ee326090cedb97b75b886c7b3
+CT = a276b6eba10ddc781a6eef1872ed62cf17feaf3adad92d96786add8c2619f0782ca12312a1d64266
+
+Count = 135
+Adata = d8a662ab8449bd037da0346a24
+Payload = 45245de4ac6a6196a0b15b77c622a21bb50627379ddb4256
+CT = 8f8274c153ee5901d79a8fe157e9c9d84f41f378ff84a873b6bd4a09f9b4aa2864d39ff1a03e0ff7
+
+Count = 136
+Adata = 8ed39da1d9179e77156eb909f3
+Payload = e928e37dbe8389a53c650edc86f83cd3589a53dc8e45adfd
+CT = 238eca584107b1324b4eda4a17335710a2dd8793ec1a47d819b6935778ffbc0953974de0a9d87a31
+
+Count = 137
+Adata = 423515f7bd592d6a7a2408661a
+Payload = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b1
+CT = 869df54479ad40017e50e6012b5bd71d829b5ed19c64329400a3da0d3ce34a272b51582a998f461e
+
+Count = 138
+Adata = 5a6bc2cd6890a473d478a582b4
+Payload = 1c5ebaeb7b926a39b8aaf65a4c484b113d6f2caafadc33ea
+CT = d6f893ce841652aecf8122ccdd8320d2c728f8e59883d9cf4ef28c338f497a40f550f2945734ad1a
+
+Count = 139
+Adata = 7bdc26b5b4df58af539d91eb2e
+Payload = be5c9fee6babf569c66e6a0d0f3c4dc314f40c0aeca493f7
+CT = 74fab6cb942fcdfeb145be9b9ef72600eeb3d8458efb79d2e07f1998e57ba9b611568632dc5cb9fe
+
+[Alen = 14]
+
+Key = 13f179aa2a23bc90a85660306394940e9bb226ce3885ec01
+Nonce = aaa52c63ca1f74a203d08c2078
+
+Count = 140
+Adata = 5cc924222692979a8e28ab1e0018
+Payload = d3b36c6289ad6ae7c5d885fe83d62a76270689ce05fa3b48
+CT = bc4fcef401c2e1d1c335734ff23ea52c3474d2e6f31648a7f58649400ac9e825b038d67f0c2a6f1c
+
+Count = 141
+Adata = 21fb9cdd9b110bbbc6832275dfa7
+Payload = a7742dd9c3e8bbad08157fbd01ebfb94e1639117c4b4eb5d
+CT = c8888f4f4b87309b0ef8890c700374cef211ca3f325898b23fa5ad4142e0b4650fa5cc8f7ef70d62
+
+Count = 142
+Adata = 9919ddb6ee6c330646cd15953d39
+Payload = 297b4498bf5427e6341aa9275c1f62e3b0c9b150a195ae72
+CT = 4687e60e373bacd032f75f962df7edb9a3bbea785779dd9dfec551d11b8647432cc4320173939600
+
+Count = 143
+Adata = f94cfd1f8c7902a57784c10b9a5a
+Payload = 2218868033e17220655f0196dab6193c58293ca105d467d9
+CT = 4de42416bb8ef91663b2f727ab5e96664b5b6789f3381436a79a075ec2cacee1482b8328b697a3b2
+
+Count = 144
+Adata = 63f3fe58c348dc6bcbb44c3c370f
+Payload = 4a9bc26fb10000a57b9e73a8a3d30f66ef9de8782201ffa8
+CT = 256760f9396f8b937d738519d23b803cfcefb350d4ed8c4739cbe17b4edd64a3dcd2b8ae3352c04a
+
+Count = 145
+Adata = dec0ce763833305aa9c9efdc2c65
+Payload = 1b61b3ff3e4847a17f55f7565826b0e2ccc1368f4de32022
+CT = 749d1169b627cc9779b801e729ce3fb8dfb36da7bb0f53cdf54665c476d0741164685b0d81caca31
+
+Count = 146
+Adata = 592ef6784ee839a049e0d96257fa
+Payload = 32e5998b37987a38800f5bfe3132979ca1447314570aaef7
+CT = 5d193b1dbff7f10e86e2ad4f40da18c6b236283ca1e6dd18500d93b11fecc8b4560320878ba53550
+
+Count = 147
+Adata = 4a47a82b999a2a739959f153a091
+Payload = 84acfb6cf10b301558e5acbf41bbbe0b145dc66dc600f4df
+CT = eb5059fa7964bb235e085a0e30533151072f9d4530ec87303c2a41443578adaf31483bbb6b9f10b0
+
+Count = 148
+Adata = 4ceba98cc0ff5de1a7d580cf23d2
+Payload = d7c73d77a286df38aad116843620911c92e11486be5fcb0c
+CT = b83b9fe12ae9540eac3ce03547c81e4681934fae48b3b8e32232a856c07999e99a4701988b486ef2
+
+Count = 149
+Adata = 15e3b3c5794fececd703ac58ccb2
+Payload = 140882c5d3534bb0861e7ba9423e67439a02ee6f0b0b00f3
+CT = 7bf420535b3cc08680f38d1833d6e8198970b547fde7731cb3a6d50a92f3183c0c5090edc3c7f822
+
+[Alen = 15]
+
+Key = c1dfc48273d406a3a7b9176f80b2dc4e9a7f68134bab66d2
+Nonce = 1ac53ba965cdaeeef7326a37e4
+
+Count = 150
+Adata = 39ba54a410a58a5d11615a2163cc3b
+Payload = 67d9728a88f1fac3af43ed6d634ba902896bd226858697d9
+CT = 360f0fc714994e3b59448b50cdd61d511b4f09e0e5fb5ac826a51fe5b9b598a17eb3da10f936813b
+
+Count = 151
+Adata = 38b0cca09d69320105d24ee3f96684
+Payload = a8365ba9fcfff060b28895f7a2d786c5991a8f7758962caa
+CT = f9e026e460974498448ff3ca0c4a32960b3e54b138ebe1bbba673a94f4280e84724f4a2510165e9a
+
+Count = 152
+Adata = 76718dfb9c68acdd82592d96def39a
+Payload = 497be597dd695cb159d8a64f44049c3b549ac927837b1b90
+CT = 18ad98da4101e849afdfc072ea992868c6be12e1e306d68118865ab37be6f015316e0d177b6c2e91
+
+Count = 153
+Adata = dd719ba1710916a546233c1494a7a7
+Payload = ca452c21383ebc3fb584f0d59a227374854983f243a3f460
+CT = 9b93516ca45608c7438396e834bfc727176d583423de39713d903f67ad0d72fb8ffea2035216b769
+
+Count = 154
+Adata = d893fa2bd7c70e21a5934dc2e99037
+Payload = 3dd118ed65453d3d7844d8de78d7a43587ac5e9305b11464
+CT = 6c0765a0f92d89c58e43bee3d64a10661588855565ccd9750b885e3e054f519d0355db1bd589bb35
+
+Count = 155
+Adata = 97c60265a3a6993b97ac1b375a79b8
+Payload = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117
+CT = f6e126eebe391bf9cebaf9e55248de2fd18ff76fc781cc064a950e4bed4137e38787839e39924821
+
+Count = 156
+Adata = acfdf302ed116ac4755069d1704423
+Payload = d39d188f28521e4fb0a0c5e48e6d6efe4383c95b2535ea8d
+CT = 824b65c2b43aaab746a7a3d920f0daadd1a7129d4548279cca94dd97fd2a5d50eb7dd6234b40c525
+
+Count = 157
+Adata = d449f97164aae9a3046624e98810bc
+Payload = 758102470e221e30d87d2807b5f8b793a7a56c83eecf32a4
+CT = 24577f0a924aaac82e7a4e3a1b6503c03581b7458eb2ffb596f11450d5d2ba55ffb4a6cf7eab847a
+
+Count = 158
+Adata = 3e6c914a196e175079315b1c92b2b8
+Payload = 1db875c4b4f9dd4926dfb5604d6c4d21aba7d905aed9d1b0
+CT = 4c6e0889289169b1d0d8d35de3f1f972398302c3cea41ca164894e9218ecacd143fb62df69a13d33
+
+Count = 159
+Adata = e2b7b00d0cfbdfcc24f1819ae1869f
+Payload = d7a75bc621addccbbe162b86d536d69c887c278384af54e7
+CT = 8671268bbdc5683348114dbb7bab62cf1a58fc45e4d299f685a7c19bc9c2f8e36ed95015ebb679ae
+
+[Alen = 16]
+
+Key = d8a662ab8449bd037da0346a24565683a3bbbbd1800e3c1c
+Nonce = 166fb8d0e110124c09013e0568
+
+Count = 160
+Adata = 1c1c082eeb5b8548283d50cc2ace1c35
+Payload = 61fdd10938557080191d13dd6c3002dd445d9af988029199
+CT = 23c05927502a4ee6e61e4e10552d49b020643eab476eeacc867601fe79a122a7817819655183283e
+
+Count = 161
+Adata = cae884fa25adedd883ef4e7c855def19
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = ce476aedad7cd761d26d59297533ece2b6703002fa0bda63160bb976ab072aec8fcea8eab3dc5aff
+
+Count = 162
+Adata = a350ed58c04473e113b9088b1fb9dad9
+Payload = 863f9a26182f131c594972398b52b3a01a9d314fd9390bf4
+CT = c402120870502d7aa64a2ff4b24ff8cd7ea4951d165570a1291b2c13a3f5e49ce35b9047ee1e8627
+
+Count = 163
+Adata = cb7090f7a465782f680fd44cbc558107
+Payload = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402
+CT = ffa941830a2cfc3b3b14a5b6574fab5b45f550e17099cf57fdd9fd1d469a9042b80e6458d25292b4
+
+Count = 164
+Adata = 914cf55a3fc739b5f87ac7518cc4171b
+Payload = c313bd213dc29c00691e25ce028884192e21a820003aece4
+CT = 812e350f55bda266961d78033b95cf744a180c72cf5697b1a8b8e82175ff30c69ea71d2cfb814ada
+
+Count = 165
+Adata = adc8b69d84ef7ae62f9ca9f371d3488e
+Payload = 85e4e053b976e06a64dfa8523130cdd802d3e7c3d6d797c2
+CT = c7d9687dd109de0c9bdcf59f082d86b566ea439119bbec9776fa36db27b2f84d1b8ab55e2fc89ab8
+
+Count = 166
+Adata = 29ed477994dd231d3a71157eb56d219d
+Payload = c77aae5fd09dc9bceee7428e0734d4b0556528396a58f909
+CT = 85472671b8e2f7da11e41f433e299fdd315c8c6ba534825c0e32058ea939036805a735198934a072
+
+Count = 167
+Adata = 494c8f931029a4919e2dcbc16512a8bf
+Payload = 1f47273103f265f963e498878361c06c01a5ffcfb630a161
+CT = 5d7aaf1f6b8d5b9f9ce7c54aba7c8b01659c5b9d795cda3437098c81475f8a1d8f3b0e63d499d387
+
+Count = 168
+Adata = 53200bc5d1f1fb0eeff02d2bc42f7d54
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = e1bfb9812822f9d1f38ee14181532085c4e58ac732b057bd9d7317973878957e8fc1fa57a025a3e9
+
+Count = 169
+Adata = 61e0e28bf344a9a1b04b15156e06498e
+Payload = a0d3a94ba6bb3bedf38220d1cba7e91273ad19f9a1c436c0
+CT = e2ee2165cec4058b0c817d1cf2baa27f1794bdab6ea84d95b0aa1befae96e71b9d221673844b1cb7
+
+[Alen = 17]
+
+Key = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5
+Nonce = 924322a3ef0c64412f460a91b2
+
+Count = 170
+Adata = 03c2d22a3bb08bbb96b2811ce4b1110a83
+Payload = 1bd3b5db392402790be16e8d0a715453928f17f3384c13a7
+CT = ad736402626df0f9393fe4491eb812725ad39d6facf20b5b2f9340b0d48a17ae1cc71d7515e61ee9
+
+Count = 171
+Adata = f390387610741d560325b5d2010d8cd4a0
+Payload = c93aaa04279e451b6880ed7b7fdb3ca9e80ab76180434937
+CT = 7f9a7bdd7cd7b79b5a5e67bf6b127a8820563dfd14fd51cb717bae4c040561bcfcf80fd842ae8dd8
+
+Count = 172
+Adata = 891d7988a56415a7b433f463b1e80eaa62
+Payload = 2611612ccb5ffefaa73195509bb52c641472bca0dfd09d49
+CT = 90b1b0f590160c7a95ef1f948f7c6a45dc2e363c4b6e85b5bc9fb15d874feccb6b5f581fa470734f
+
+Count = 173
+Adata = 831c0fed5e600dd82d7d55669262a9a17d
+Payload = 08136e946e306cde0544ddc2f3f4a529c89c7b77a5e635c1
+CT = beb3bf4d35799e5e379a5706e73de30800c0f1eb31582d3da72589ee50d23f925f7998ab3ccac37f
+
+Count = 174
+Adata = 32ca9d412d4ef0e89928496e96c9de7f2e
+Payload = 695aaac402942de7d899cc3f741c7fb2b2d8247a7676cf29
+CT = dffa7b1d59dddf67ea4746fb60d539937a84aee6e2c8d7d555c0b608f331dca47c65f5c879f2d532
+
+Count = 175
+Adata = 0746b2e6149c7f55854e9ca3e6861bf0e9
+Payload = 8f958d796be0566512f0512dcebd2e12f3160b05b72ae955
+CT = 39355ca030a9a4e5202edbe9da7468333b4a81992394f1a9b039bd916e923e2fc1f7c60eb59916fd
+
+Count = 176
+Adata = 0e4cbd1c574d656112bf6e70a8f23347f0
+Payload = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364
+CT = 80de1cc22a964beab63cbc5b3cb91bdb23ac4da247e34b98ac07f2c0847069fe5be26e623033f532
+
+Count = 177
+Adata = 1a05ff12412bf728497536534c234901ce
+Payload = a9ccee975feb10f635d548a8502f7c8b6adbd2be74117257
+CT = 1f6c3f4e04a2e276070bc26c44e63aaaa2875822e0af6aabf4e66a2b210e5a03bb10ff2926ed8a48
+
+Count = 178
+Adata = 3bd063a51c71fab5aeb47e7f8f958d796b
+Payload = 7df6220599d6235eb450989b6f0cd6c96db62b0d13afc4f4
+CT = cb56f3dcc29fd1de868e125f7bc590e8a5eaa1918711dc08ec90169d0c5c11fff8f255fedb13a99a
+
+Count = 179
+Adata = f0d334e0a27c3d00d56b15c2ee426e6347
+Payload = 6f65a24344c32debaf9f8c3fa426fe0b139e8ad1c8b1fbbb
+CT = d9c5739a1f8adf6b9d4106fbb0efb82adbc2004d5c0fe347170141cf3f207c4f0fc1b0238477cfad
+
+[Alen = 18]
+
+Key = e67f3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863
+Nonce = a727ed373886dd872859b92ccd
+
+Count = 180
+Adata = 68d199e8fced02b7aeba31aa94068a25d27a
+Payload = d7a954dae563b93385c02c82e0143b6c17ce3067d8b54120
+CT = c6cfaa1f54d041089bd81f89197e57a53b2880cefc3f9d877e30b2bcc3f1ea9ec2b8f28bf0af4ecf
+
+Count = 181
+Adata = fc4bbe329a86089ebe2a2f3320dad55a9bda
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd2
+CT = b3605f2ec11a2a70abff1c3ab717fd172ba9e9ac72d961753a6e6844102d6bb86986c030765d3393
+
+Count = 182
+Adata = d8741e540330692d83cc806a8ac1c4742be6
+Payload = 56ef76dbec6b8b46f5b7b4e311c0baaa6fcf54c69c0b9c3b
+CT = 4789881e5dd8737debaf87e8e8aad6634329e46fb881409c3f92a80b1d82f8c1dc32bfe64adca12a
+
+Count = 183
+Adata = c8b1992dfba55b4ab86b480546c861655e1a
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 364f9da4a34153d9d97696eed355ec79d464405a927d14a12fb48ad162b0c0678674d79d26a6b5ef
+
+Count = 184
+Adata = 347e12eec56e95aafcc7d25bf10fc756b4e4
+Payload = dd433eb7422c7c4dccee57a1679633ced3b5f08df763d457
+CT = cc25c072f39f8476d2f664aa9efc5f07ff534024d3e908f081c7cd81c974d985bf24b7fe9542141a
+
+Count = 185
+Adata = 45b35a04d6e2645e9a5aef206ed4e36199c9
+Payload = 70523bc397417e09d791a4976960e02636ca7144a5681cf7
+CT = 6134c50626f28632c989979c900a8cef1a2cc1ed81e2c050a7f6a5c04e59896074e1594706ab27e9
+
+Count = 186
+Adata = 378b48531fe34f55125b2f14f59715dd6ef0
+Payload = 514cb462dd4b117f26cac22062fcbeb353650c71649a7b3d
+CT = 402a4aa76cf8e94438d2f12b9b96d27a7f83bcd84010a79aa9d16c3ab79276cff345444511940a9d
+
+Count = 187
+Adata = 73ed686d6fecdc031cd97653137f269d6537
+Payload = 7f0c2b261db3f3de0ce3a733f4b8c446c374567d96d00379
+CT = 6e6ad5e3ac000be512fb94380dd2a88fef92e6d4b25adfdef92bf8aa6facbe6f9607ea02b54a1bf0
+
+Count = 188
+Adata = 5b0441107e5560be94f030a41cedbdb116d9
+Payload = ebb3e2ad7803508ba46e81e220b1cff33ea8381504110e9f
+CT = fad51c68c9b0a8b0ba76b2e9d9dba33a124e88bc209bd238e4936ee93b5c7a302913292df33c1700
+
+Count = 189
+Adata = feedcc5f8524fe7d49bcd178415b9f4c450a
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = 237022260902363567fc3cf433ad446235fc1a5a3d53ad7493426b6193afe765a76b3dec00266e69
+
+[Alen = 19]
+
+Key = e0a29a2c7840cf9b41de49780b9ee92d646a4bfc5b9da74a
+Nonce = fc9fd876b1edded09f70b18824
+
+Count = 190
+Adata = 36e15baafa0002efbb4bb26503b7e3b79f6c68
+Payload = 344dc8b6bd66a1fbbe330a95af5dd2a8783dc264d6a9267d
+CT = 43b3b96aa5a54378f3bb573ffda3e154aa7f425fc3008175b60a77b9d38740356b544b1c0f259086
+
+Count = 191
+Adata = 712b788f0276e2b5a58be80f9114a12ab2a268
+Payload = 6d0546d4e95d1cfcb37a8f88a62064f5d95791311511535b
+CT = 1afb3708f19efe7ffef2d222f4de57090b15110a00b8f4535f750bb4cd42db3038e2c1622b72cea8
+
+Count = 192
+Adata = 07f77f114d7264a122a7e9db4fc8d091334a03
+Payload = 05024ce13b9057dd2c509db7dbcbd5585e4e64a1e2e380ff
+CT = 72fc3d3d2353b55e61d8c01d8935e6a48c0ce49af74a27f761e77b59ef7eeeae35bb53bb9543b64a
+
+Count = 193
+Adata = 899b036138cee77cd28382ba27984d858a6351
+Payload = 77b8e735b13b10e45e411ab94c6fe1a9eb89f0a7af40ff1a
+CT = 004696e9a9f8f26713c947131e91d25539cb709cbae9581244a60fdb473098a11b2176d37b2c4643
+
+Count = 194
+Adata = 4b000440a8484a5201cd54aec058919769772e
+Payload = 6b21800ae599a15254bb33f0bb080788fb6e9fa054bfd8b2
+CT = 1cdff1d6fd5a43d119336e5ae9f63474292c1f9b41167fba58d4afc30a7f672ea34e05ec1843d848
+
+Count = 195
+Adata = 73a222e681ed1ca47d92a6dd90625d895fbf29
+Payload = bfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028
+CT = c857a87376dcd0352fe24172c9e201ade919d09a987317204ef270e0f3b5e3ca0b8440af65c76e85
+
+Count = 196
+Adata = 7109a3a36b286059bc1a1abb2767c92f884e3f
+Payload = c68b1bc0050e19780ab53efbea175634f70a7245d966966e
+CT = b1756a1c1dcdfbfb473d6351b8e965c82548f27ecccf3166ffb66991b38a0345fbbff5f2362f87de
+
+Count = 197
+Adata = cd15973753b94b77bb4b778de8b3b0cabbde85
+Payload = 4256f1c9b64390fe2120df9fd38e497c2903c2ca5679ab75
+CT = 35a88015ae80727d6ca8823581707a80fb4142f143d00c7dd033a087c44c2e44adbeb333aa9ded10
+
+Count = 198
+Adata = 6e5e0793855f7145e13a5872f563e5ec61cfd2
+Payload = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192e
+CT = ccfe476f53cfc28a00bb072626088022766c6cf454ecbe26ff9c8713422fe38d5bbf2dedccbffe10
+
+Count = 199
+Adata = f844684f5404e7d8eedfa20394b40b4f5d910a
+Payload = 86afa9cdd743916563ebfd3adbdd56e015ea3a4ebc61cfe2
+CT = f151d811cf8073e62e63a0908923651cc7a8ba75a9c868eae75de56eabcf8e02c1a27705adef2732
+
+[Alen = 20]
+
+Key = 26d0a3a8509d97f81379d21981fe1a02c579121ab7356ca0
+Nonce = 8015c0f07a7acd4b1cbdd21b54
+
+Count = 200
+Adata = 093ed26ada5628cfb8cfc1391526b3bcc4af97d9
+Payload = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711
+CT = a3a60b422eb070b499cf6da0a404b13a05cedda549c6b93e6ca0e07e04674f21a46df2659a5905fb
+
+Count = 201
+Adata = 7df13c9d2247aa40af7bbe2da98bd366d8b47b43
+Payload = 93925579b6367ff592ecbd59495fdeccb50f31ea4fa390bc
+CT = 079f7430e3ef9b6373c1c0cb11d884507d02a31d83cd9e93836597806f5da1d176c745d95c4fa46a
+
+Count = 202
+Adata = 7f369bbc99b6f08049eeb43566269a174829d4dd
+Payload = 8363aef9c7c34e1f8149de46c97d5ac79d38c6ed31ab1d12
+CT = 176e8fb0921aaa896064a3d491fa005b5535541afdc5133df826dda99111691993027628c70ff6ae
+
+Count = 203
+Adata = 04aa8442179f62babad0c006e36af0c21105f27a
+Payload = 17281acb525b13653000ab45d86e70106c10a93c99b18f76
+CT = 83253b820782f7f3d12dd6d780e92a8ca41d3bcb55df8159d074b018143a7ea1b5369b7f80eae20d
+
+Count = 204
+Adata = 997e646014f19a53beab8877ca6022bef23016f1
+Payload = 5d48a71557608736eded309027a80349a18e9ce5dee2bc6a
+CT = c945865c02b963a00cc04d027f2f59d569830e12128cb2455db17d3f75214c3cf39858617cfee57a
+
+Count = 205
+Adata = 60ffcb23d6b88e485b920af81d1083f6291d06ac
+Payload = 6c9d11cfb64d96bfab61c04a25d9e19294fb7330fb4847c8
+CT = f8903086e39472294a4cbdd87d5ebb0e5cf6e1c7372649e79550998376e61e11a5a69e9f8fe1c329
+
+Count = 206
+Adata = d574632658bf456dfbb11c2653602ed0f4dae777
+Payload = 7d41688c86d5e3bc53966810f2299fdd732e3471fb0a88f9
+CT = e94c49c5d30c072ab2bb1582aaaec541bb23a686376486d6a1b0d05a7ebc657c3235479893bf7e5d
+
+Count = 207
+Adata = d896ed60128f4bb0277d3af94c5138cf91697aa9
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = 1877c38a90da0d91cc43797614a9fd131a4406a7f909af1980c98c8959c158ce209aebcbd554f250
+
+Count = 208
+Adata = a350ed58c04473e113b9088b1fb9dad92807f6b6
+Payload = 49bc9d3bcf3c22daa8cf55c1b59d4bffddc2412d60518e98
+CT = ddb1bc729ae5c64c49e22853ed1a116315cfd3daac3f80b7573175f9105cd16ee384465ebb232200
+
+Count = 209
+Adata = 1db5887001204194e8b5dcee92c8af8fa5f7321f
+Payload = 25f3788e0d3dd8f5821faa4e45a9d6b3995fd881f927135c
+CT = b1fe59c758e43c636332d7dc1d2e8c2f51524a7635491d732b67e993384f2e7229d1838efd040d99
+
+[Alen = 21]
+
+Key = aac60835c309d837aacc635931af95702a4784c214283ebb
+Nonce = 0e20602d4dc38baa1ebf94ded5
+
+Count = 210
+Adata = 796e55fbe7bed46d025599c258964a99574c523f6a
+Payload = e8610756528f75607b83926597ef515f4b32a8386437e6d4
+CT = e0a3d5f43e688ce104f4ae1a4fcd85500aa6b8fdbcd1b8d3003c0c3b7369e79339433e1754c0937f
+
+Count = 211
+Adata = 5170836711fcb1a350b087907d8a17c7637aa1595b
+Payload = c61b0c1845fa9b2e0013b3fa9a8cb4f4fbbc6846f63ed180
+CT = ced9deba291d62af7f648f8542ae60fbba2878832ed88f87120a7f18d021833b167bf330c4858239
+
+Count = 212
+Adata = 2a68e3fe746f593c1b97cb637079c3e5ee352c107a
+Payload = 10c654c78a9e3c0628f004b061e28c39a3c23e7250f53615
+CT = 18048665e679c587578738cfb9c05836e2562eb788136812ca9698d9a88e892c364e57dd35c2f17a
+
+Count = 213
+Adata = bf38ca0e89b8f5ccd29387f7f193ab5a967caa715b
+Payload = fa3a959fdff853c39f76da626094a1ea6dbc78bd2f091a79
+CT = f2f8473db31faa42e001e61db8b675e52c286878f7ef447ef3839d6f7e20a2e343f4c4da9eb9be13
+
+Count = 214
+Adata = bee00f2f75a4415ce993d2d14a6d8e01d1d59a48f6
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f6d
+CT = 7e13fc9e20ba608a8a14fa757cbb4a5dd81998ba4fa1216a6630bfb7a2a2441e020efdf36274b72f
+
+Count = 215
+Adata = d5b614e4e8f72a5d8b1ec2b375da5dac64c2cc30b1
+Payload = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b634
+CT = 61fd7cd894ad5a168fc586d10191139a7ee1f78794afe833866bcee343ec5aae61f9effa19b99d3b
+
+Count = 216
+Adata = 33f11aa36d8ab0fc53486839a576b31ee915dbd769
+Payload = 56ce9a09f38127b14dbbdcaa59f363c92a3b9843ad20e2b7
+CT = 5e0c48ab9f66de3032cce0d581d1b7c66baf888675c6bcb00331b60eb252f744a06b4a95aa9f4e7c
+
+Count = 217
+Adata = f40bce1a6817b29b9e8b56f214fcca7dfde17e7ee6
+Payload = 5cd8986e974d09ede34ba68fd81d6109a64092e7fbbaf87d
+CT = 541a4accfbaaf06c9c3c9af0003fb506e7d48222235ca67a4153778a644cb2469cef3ad125e257bc
+
+Count = 218
+Adata = 53c457d8d4d4ab95ba116c28b82c16743cb09de9fe
+Payload = 9c3c610f204d98702dd91ea28e0cc14830b26bb5e2ee0349
+CT = 94feb3ad4caa61f152ae22dd562e154771267b703a085d4e7013e1c34dbc5efc7bcd4f8e52797644
+
+Count = 219
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c
+Payload = 90c5dd9db0316dac89db18f70491bdf0a06a6a7f72b77d9a
+CT = 98070f3fdcd6942df6ac2488dcb369ffe1fe7abaaa51239d66aed667c761b7dea44822e30cff671f
+
+[Alen = 22]
+
+Key = 671544bf2988056f7f9ccd526861391a27233793a23f811f
+Nonce = 0a259148a1d081e0df381ecd0c
+
+Count = 220
+Adata = 61dafc237cb52f83ab773ba8a885462b6f77d4924611
+Payload = 576b069ae2713f53d2924c1fd68f786cb2eec68892f9e1be
+CT = ce06b3d09b02921f290544032a081a7766612940048867281bb089af0245792c16e6320cf5ffa19e
+
+Count = 221
+Adata = 87e49b8164e7052becfa0c966991637b38df833fc5f7
+Payload = d7eb0d7dd737805cd3b8dbf451aeea2fa1f6a96eb58cb428
+CT = 4e86b837ae442d10282fd3e8ad298834757946a623fd32be3cec29bd5df92363d6bb75456f5cd32b
+
+Count = 222
+Adata = d302a518d7c625756d3e4c8cc2b1d973a19107c945fc
+Payload = 77d8c9e6321314524afd05b7ad599c29f4eedda9e9f0763f
+CT = eeb57cac4b60b91eb16a0dab51defe32206132617f81f0a901ca82cddb78a2fe3904d1d8bf6fe5b2
+
+Count = 223
+Adata = 6566bb616a94bb03df5c26b722bcd38d516285c5f6c1
+Payload = abbf28b3ae164051648293d0b94e11f5af8468450005c7c0
+CT = 32d29df9d765ed1d9f159bcc45c973ee7b0b878d96744156d095ad121f0f76f07b715cad996def52
+
+Count = 224
+Adata = 141be3601e38185a9fa1596d2ee406415c9673af32f5
+Payload = b67d50110f844b36a00d352123012a1123c7c3cba959dc48
+CT = 2f10e55b76f7e67a5b9a3d3ddf86480af7482c033f285ade8529ec8f477462dc2409482c3479756d
+
+Count = 225
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732b
+Payload = 2a63f7b09b43fee65738e8115bd8419b3ef3e8f86eca707f
+CT = b30e42fae23053aaacafe00da75f2380ea7c0730f8bbf6e9b14fe8dbb3c361ea61d7b44e689a1c48
+
+Count = 226
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc
+Payload = 59dad755af92c29522da4348ab9b3037fe87004f5fa1394a
+CT = c0b7621fd6e16fd9d94d4b54571c522c2a08ef87c9d0bfdc54f0659fae291f943f2f3b33688602cb
+
+Count = 227
+Adata = 5d895fb949344e603ce5de029842b20d2bb614ecbbb8
+Payload = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f
+CT = fdb508761d1cdb90977f95f3288015e5c3be88e1745a2f993af4e3a7a20390a8da264299712a34e3
+
+Count = 228
+Adata = 74cc8da150b0bacdefa8943900b4ea047611d96be70a
+Payload = 0c3c9a634a000f00be003846eac7482e303a5bef3a70fe75
+CT = 95512f293373a24c4597305a16402a35e4b5b427ac0178e3a7f79d2b5a9bde5bd453bc8a03e971d8
+
+Count = 229
+Adata = 65f6adbaaa803dbad5ba9cb6d231314d55147cc61399
+Payload = 712c788928c8a1562bc1f3f0eb1286e15c3405f6a6fa0443
+CT = e841cdc351bb0c1ad056fbec1795e4fa88bbea3e308b82d5ffccebfb8c833833db40e98a1950fb70
+
+[Alen = 23]
+
+Key = 90e2c63b6e5394b1aeec03f95a9d13a01a7d4e9d58610786
+Nonce = dada5465eb9b7229807a39e557
+
+Count = 230
+Adata = f5629ca0eea589f6cf963d875a7d2efb656983f2dd2231
+Payload = 44dd098b1f869d670a8a841900c4bef023a1946a0c278354
+CT = 6b38ca85450e05e7b9362ed7e6e291a130ff233b5a561cdef7ec84dd992fdf98514f845dac8f656e
+
+Count = 231
+Adata = d43d7753530a7280b76221906dca85d396b6cf05125018
+Payload = cea19562328bd1fea889f575db6a28a14b7d06fb9f9c98bb
+CT = e144566c6803497e1b355fbb3d4c07f05823b1aac9ed07313613ed15d527d9dc58ab6893e723db58
+
+Count = 232
+Adata = 75650ce366757618af20205b69af7e5d4e82c398c00101
+Payload = f0641f595b791edd860977fcf699688587a354e053e9c7fe
+CT = df81dc5701f1865d35b5dd3210bf47d494fde3b105985874ef8728d1bf3a2d93db3266bafadb7c26
+
+Count = 233
+Adata = c00f1b8066677c63e898fddfb8a1b482b536963da0628d
+Payload = c7486a084f8475e6f5138e8d6e9f42a1de90f05aa88a362d
+CT = e8ada906150ced6646af244388b96df0cdce470bfefba9a7a5bce94d7564d297fe87730f1a36acf4
+
+Count = 234
+Adata = 5a89ab6b26b2ca78f98a8f8409fe8008b97ba9ef185d41
+Payload = 091ef698e16dc43a11d3ea005d5a5cdb7f1bdb5665a6c81e
+CT = 26fb3596bbe55cbaa26f40cebb7c738a6c456c0733d75794cd971b07fc14c512b8df6dd964b129d0
+
+Count = 235
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d3
+Payload = 62f204394b367c4410746001e02dfd171858396568fdd43b
+CT = 4d17c73711bee4c4a3c8cacf060bd2460b068e343e8c4bb1a192b781dc94448d4a0f6a439a716339
+
+Count = 236
+Adata = 4a47a82b999a2a739959f153a091a65c4d7387646da66b
+Payload = ac1cd5ba4997af91dbd74aee7730f9ee92cf8a360ca96a8a
+CT = 83f916b4131f3711686be0209116d6bf81913d675ad8f500cade9533b272e0a3edeba68362b057b4
+
+Count = 237
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab
+Payload = d0a249a97b5f1486721a50d4c4ab3f5d674a0e29925d5bf2
+CT = ff478aa721d78c06c1a6fa1a228d100c7414b978c42cc4785d68df8ff28345be4d83541a72071059
+
+Count = 238
+Adata = 720a9dc3e33ac080775a06f67f4a6591c37d0e101944a0
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664caa7ec8892be6a18458c663665495035
+
+Count = 239
+Adata = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664862fda880e45e891a3a50da7e14344c8
+
+[Alen = 24]
+
+Key = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903e6
+Nonce = f97b532259babac5322e9d9a79
+
+Count = 240
+Adata = ad6622279832502839a82348486d42e9b38626e8f06317c4
+Payload = d7c837971b973f5f651102bf8d032e7dcd10e306739a0d6c
+CT = 4709600418f2839841e6d126359f6982bdb53acc7ff209635623d15b24184481eadc63bb8c878fc4
+
+Count = 241
+Adata = ad4833aa53218949cfd724814a43889a74a2114bbef4cf37
+Payload = 7d672bccd0fb01ce79320ed61779146aa432038daa13cb41
+CT = eda67c5fd39ebd095dc5dd4fafe55395d497da47a67bcf4e614c3e546273f0aeef207bd3f4d32fca
+
+Count = 242
+Adata = 54a723826086c7175e8fdc854b62d780de6ac1f90b57dd3a
+Payload = 0e1b73df74982f535a5fb08bc13d22515ee10969efe033bb
+CT = 9eda244c77fd93947ea8631279a165ae2e44d0a3e38837b413c6395ce9aee2e22ac0606beb140185
+
+Count = 243
+Adata = bec02d7df4cc3deefdd7e7d3ea82d381c870ad46bc06d64f
+Payload = 9a55aff269b180118ff0ea99e851c7474d19d23e641f16a9
+CT = 0a94f8616ad43cd6ab07390050cd80b83dbc0bf4687712a661e4f02150bedd86dfa49f52b214239d
+
+Count = 244
+Adata = 1b8090d712e0ec95a01bc3aeb6f5230c67c355e0ed68043a
+Payload = ff19294e8faed8353dbcab0b146e2ef928dd2680833424bd
+CT = 6fd87edd8ccb64f2194b7892acf269065878ff4a8f5c20b2f0e82b9f04bfc0cc0ba432b5135450c2
+
+Count = 245
+Adata = 5ed0b9f25d07b26717cdcb2507bef9d681ecd9389831ac15
+Payload = db1eba6ac4a79aa1d97838d263c7c4ffa7d354770e762805
+CT = 4bdfedf9c7c22666fd8feb4bdb5b8300d7768dbd021e2c0a2e64c82b60880c5c7506321a1060a481
+
+Count = 246
+Adata = 55f16fefaf2168aebc61b5e01d9e1f7bfe215eaaef118974
+Payload = 012d45168505ca9fde5aed123875639a207d473b993dc7b8
+CT = 91ec128586607658faad3e8b80e9246550d89ef19555c3b77152f64dc993b36ad9d5d12bb52b1ad5
+
+Count = 247
+Adata = 9893bf14fd3a86c418a35c5667e642d5998507e396596c50
+Payload = b205f26d6c8a8d6085ab28d595703cae046f96d82093082b
+CT = 22c4a5fe6fef31a7a15cfb4c2dec7b5174ca4f122cfb0c243e5c69256b6326ebb7ee6e677d396765
+
+Count = 248
+Adata = 244b840085bda9576c8424bb05a925a6b09cad2d0528ab8d
+Payload = 549ba26a299391538b56ce4bd71dbbfd96995836f8915ca5
+CT = c45af5f92af62d94afa11dd26f81fc02e63c81fcf4f958aa2083dac565c7a63908f0022e2867bb68
+
+Count = 249
+Adata = 9e8d492c304cf6ad59102bca0e0b23620338c15fc9ecd1e9
+Payload = 9e9dbd78a1066800ae33253be6104015158a0187e4f38116
+CT = 0e5ceaeba263d4c78ac4f6a25e8c07ea652fd84de89b851968242fe32958ea32e670ae1b3543974f
+
+[Alen = 25]
+
+Key = 90851933d4d3257137984cdb9cba2ca737322dac4dbd64bc
+Nonce = be02df3a840322df8d448c600c
+
+Count = 250
+Adata = 69a9dd9ac8be489c3a3f7f070bdaca10699171f66ab3da9351
+Payload = ba1785a149cb8b69a4e011c11a3ff06f6d7218f525ac81b5
+CT = 89ab2efefa8406336d9e2245199fbc9454f0ef650b9ed0f446c7246bd3130803bf8d703ef5bdf15c
+
+Count = 251
+Adata = 0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0
+Payload = 263dc4fb5cd8798ce0f183a816e51fafba167533dde1bf96
+CT = 15816fa4ef97f4d6298fb02c15455354839482a3f3d3eed7096a6a4422e582c5d02973952ac80e5f
+
+Count = 252
+Adata = 911d9f5c4c34c2f4b69be1e253d43fe729e2ab2622130394b1
+Payload = 7b5da2c283116713f3d80c7907114270964541e03ab80d50
+CT = 48e1099d305eea493aa63ffd04b10e8bafc7b670148a5c115965f6df4332fe7a2cdc4d1b80e28a34
+
+Count = 253
+Adata = 8a961df9c23f6d5ecdafa94c61164a22f460a1bf7415258d39
+Payload = 541a2b3ee25022c92fdc6783a6cbde90680ad3dc41868e5f
+CT = 67a68061511faf93e6a25407a56b926b5188244c6fb4df1e18bed174081b2170ffc6ab53b54c9ddb
+
+Count = 254
+Adata = cac7a248a4d4e96a9733627e247234995d6aa57e491498118a
+Payload = ebb2e893da9f32c363f98bc76fd14eda59e7cc620070f6d3
+CT = d80e43cc69d0bf99aa87b8436c71022160653bf22e42a792bac3d3a2b9ef6d4c8715f9a5c6fe8245
+
+Count = 255
+Adata = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eebd9
+Payload = 199cca0d0e1c70ec405d6816cbddc69f8ada624f2c168891
+CT = 2a206152bd53fdb689235b92c87d8a64b35895df0224d9d07f9610c82fe9a7c78e8f1980e886b446
+
+Count = 256
+Adata = 78b6ed20ed85337c969618bd41917cd85c37e7c35c3a12e25f
+Payload = ca481f557306f9ce386edd0cfde375a550cb5b574be524f7
+CT = f9f4b40ac0497494f110ee88fe43395e6949acc765d775b6aab366637ec41d0bf557f578be424a8b
+
+Count = 257
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc93e7cf
+Payload = 6f1b4ff66d3aec7b0c0d9e202acc52722e15bca0983291e0
+CT = 5ca7e4a9de756121c573ada4296c1e8917974b30b600c0a1e57a5b3ae26469d229425f887ad5a2a1
+
+Count = 258
+Adata = 7f19ac3e53a629a2df1cb56d68fde0c80a46be40a996830e2a
+Payload = 7533c88ce55c2243b64b6c5bd01aed4dd6ac8bb9fd333e06
+CT = 468f63d35613af197f355fdfd3baa1b6ef2e7c29d3016f476ce4fe492062f74bff4c3c0e9ea849a4
+
+Count = 259
+Adata = 0516a69bfd8785ad001367b51e5410b75c11b761be08b9eea5
+Payload = 19ea09a9bfd10db2a74e398859d8f4831fa5749767773acf
+CT = 2a56a2f60c9e80e86e300a0c5a78b8782627830749456b8ead47ffc17b871f530f62b9f9aec98509
+
+[Alen = 26]
+
+Key = 5c5d02c93faa74a848e5046fc52f236049e28cd8096dcac6
+Nonce = 54cbf2889437673b8875a0f567
+
+Count = 260
+Adata = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce33bb
+Payload = b4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7
+CT = d40725397229021a18f3481e3a85f70445557bb2a85e4ae8101a34c777e918e16186fda05a386572
+
+Count = 261
+Adata = 10f0c45d06a138a964fb11b2d450620a2977bcd2952afe371cad
+Payload = 7b628930d44e22907277db057395601b82b65479fbd59613
+CT = 1bbfefe258f4b63ce5c21ae0e193eb7717e5678a9556085cc1e79234882846d916dabae40b1bd055
+
+Count = 262
+Adata = 64dbb170a037b36beed28a2637c87830e2b23f8eea6cd9a7331c
+Payload = 9db30b669fc5d25f05e0dc708d597da6ddce2dacc85ae99c
+CT = fd6e6db4137f46f392551d951f5ff6ca489d1e5fa6d977d3e35499e3c09dc384eb41344ee8be3769
+
+Count = 263
+Adata = c47de6608546a02c6eebd6628c9123f6936c0154d3df52a367e5
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 02de0a6c5fdcf929f5f8fc2c53f2bc29dec98633526340ddd605189608ce40b237dde7bed6fde487
+
+Count = 264
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb7
+Payload = 5c9bc739f6b6fe4214f3c6aad307d1f208892d79de010e37
+CT = 3c46a1eb7a0c6aee8346074f41015a9e9dda1e8ab0829078c31f69c847440be20bd08cfef330002f
+
+Count = 265
+Adata = 8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df9
+Payload = 0df109298083d3896214b84ff6edb11e9cfdbd88f5702839
+CT = 6d2c6ffb0c394725f5a179aa64eb3a7209ae8e7b9bf3b676ca83622b127fa50fc9637998c0ddd44d
+
+Count = 266
+Adata = 2d52447d1244d2ebc28650e7b05654bad35b3a68eedc7f851530
+Payload = 518f651f6d82f670b63767ad8476ed8fc24df12a45110611
+CT = 315203cde13862dc2182a648167066e3571ec2d92b92985e81e738b9e4b0dc7b7a39eb7d03adc64a
+
+Count = 267
+Adata = 3cba0fd2bb16ae1d997cbe659a2dd101885c97f2322b0172b5d6
+Payload = e91a694bea2d351928b6098660d49f382c087f6777de159c
+CT = 89c70f996697a1b5bf03c863f2d21454b95b4c94195d8bd3d298c05b1d2e597f44f8621ecd11ed16
+
+Count = 268
+Adata = c7f93152016bba584dadc6002ec493a46305726068886d2340da
+Payload = 2d14792ed349a878b2b879e7fa5f438a50e36947ce827e73
+CT = 4dc91ffc5ff33cd4250db8026859c8e6c5b05ab4a001e03c5fd5221fceecbf0dc7211a1aec06793a
+
+Count = 269
+Adata = 799cac048eaccded37ca6a70dd89595e1ee04606212da5572679
+Payload = 315b8d95938d304015bbc94ea03c21f6dc25c90f991ba680
+CT = 5186eb471f37a4ec820e08ab323aaa9a4976fafcf79838cf5c25f00b862b49fcfe8447949f39787c
+
+[Alen = 27]
+
+Key = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+Nonce = 16d345606a315ad2406abbcb43
+
+Count = 270
+Adata = c37fdf7449fd7e943595d75e977089c623be0a3926e63fdbbfdf4a
+Payload = 0f960a89a7e806f8709047cb7a2e7c4211ad724692c88a05
+CT = 3907880d25f910eab12dd14e704d1b33ea7c453634d54da2a461f44dac1112ae3f9c65671a931d3e
+
+Count = 271
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb99
+Payload = ab40a4baa39b0e568bf2193fecbc36b84c76bb50523b2912
+CT = 9dd1263e218a18444a4f8fbae6df51c9b7a78c20f426eeb5ed15db6e142ee07b59eb5b0ad3a59194
+
+Count = 272
+Adata = 79ae14843b2e7ccf0fd85218184f7844fbb35e934476841b056b3a
+Payload = b74c06d9077c568762796d5be14f3563e7205a6e9bc65bcb
+CT = 81dd845d856d4095a3c4fbdeeb2c52121cf16d1e3ddb9c6c203f11f66b74366caeca8dbded2bf17a
+
+Count = 273
+Adata = 542d86fd7ff591f97e6926a090553538bc3b8a6bcd45f2e29c7d9f
+Payload = f2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12b
+CT = c486196fd424b0ca69899c4baa9ca835d334e963a0b5068ced925fb9a4cf6b6bf17f72ab044653d1
+
+Count = 274
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a4
+Payload = d1a9e4593bc3d02c407e84a1736e587c1819c72195a07d57
+CT = e73866ddb9d2c63e81c31224790d3f0de3c8f05133bdbaf0d1f677deca1bfda83c1b9223aaaedbfc
+
+Count = 275
+Adata = 966954582e78e99ba68d6ffaf794b55a82325834ec4f373b2bd227
+Payload = 15b94910853a8f23dfb8b31c0262b8461f777075cc0937e9
+CT = 2328cb94072b99311e0525990801df37e4a647056a14f04e12937871932a7ca3e1e27a90a7f73694
+
+Count = 276
+Adata = b7aca715dcc402565cb711b001f21e8e95ec54c4afab2e2dcc8a2f
+Payload = fd1681cc306518bf77766f55226afac3eb21e31ed897075c
+CT = cb870348b2740eadb6cbf9d028099db210f0d46e7e8ac0fba0464ff4ddeccbd523a5ed3b32337f7c
+
+Count = 277
+Adata = 290a36f7daeeeafca4431446b396dbec0bea0a1f6f081418811656
+Payload = 0804fa48fc76f98bb021e3501bef8875b64a3b508adf8594
+CT = 3e9578cc7e67ef99719c75d5118cef044d9b0c202cc242332f68ed5e44a71c5ba8bade07b7bf5495
+
+Count = 278
+Adata = f0739a855422310a21ed863376bce9d75dc7c687b9b535cb7a05cc
+Payload = 4f5c6d80a3955f12f4d2594e02a045c42fabb11d90817fff
+CT = 79cdef0421844900356fcfcb08c322b5d47a866d369cb8583b5dc1fbe32743e257b7c1c9d624adc8
+
+Count = 279
+Adata = ffac0edb0b62977bb5040e4128a48deaf711f5e6a84d8f677341f3
+Payload = 5c29c458212d010a0d9c5a547aba1138eb4ce94742fef01e
+CT = 6ab846dca33c1718cc21ccd170d97649109dde37e4e337b9e53b654de1976294897cae0476ac6248
+
+[Alen = 28]
+
+Key = 6351a67fd6daabd2fd49ee944dd41dd37301f958dd17fcc3
+Nonce = b8d517b033754058128d13d11a
+
+Count = 280
+Adata = 511c6924fa96db716f6b053b7a48aebdc1504145a56cd02d6be2590d
+Payload = 0c0663dd69ccbffbbd0c8c2e9473d0354451ae7a20fa3695
+CT = 19f2745df5007619c79c84d174e4521b942776478a0601d982c560fede4741e2fd3b54b3a48f3e38
+
+Count = 281
+Adata = d9ccd93317441e9d6ccc358f31e7e2ccef8c921b23d742993eff9d53
+Payload = 34a882834172924d39d2df5d637d9d273a99a9222971701c
+CT = 215c9503ddbe5baf4342d7a283ea1f09eaef711f838d4750ee82d927a2aa678e792acdeb615409f8
+
+Count = 282
+Adata = c268d65f7a7b30d3d198b2045fc8d1db7adda56604fa567d8855d1a5
+Payload = 5b7450b73d68de079e92bba56c7860f11126b8fdedd3334d
+CT = 4e804737a1a417e5e402b35a8cefe2dfc15060c0472f04017a48226389d24ed3ec3da2da1a9bdf7c
+
+Count = 283
+Adata = 4c2b6815156f0643b4573825e28b9f2a668a4976e3342884f48bc310
+Payload = 140c6933248f052e05bd4a36aec185ee86730108cc2989b6
+CT = 01f87eb3b843cccc7f2d42c94e5607c05605d93566d5befa16fe6bd83993ccbdd50e1ca061f4845f
+
+Count = 284
+Adata = f11c873354b3c0cff2c8f8010e9e364582b9c05c62efdefbdcc2e1c0
+Payload = 2a083de317380d94dd991349a7b8761c7c98013b1b0227e0
+CT = 3ffc2a638bf4c476a7091bb6472ff432aceed906b1fe10ac577c5893cb3896400012e48f5b190b73
+
+Count = 285
+Adata = d0a056754098d7f7ef2f639d61ea3d2b9cc936c48a1b2c5a9e96d169
+Payload = 02769283d5a06c363c2cc66c09b1ac954134e3ec7df773f2
+CT = 17828503496ca5d446bcce93e9262ebb91423bd1d70b44be80c80101fdfe6dc4cfce080bf921582e
+
+Count = 286
+Adata = 56de0e55653b9a04a3ded71c31f8807c3c8dd96bc82892e4acccef30
+Payload = 4890404bc5b24822b4cf7a2fe28abc52fbefb919ae0629ec
+CT = 5d6457cb597e81c0ce5f72d0021d3e7c2b99612404fa1ea0122dfc20e3088dcd33b6706a0c1fdfa8
+
+Count = 287
+Adata = 794a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b425
+Payload = 161f8501f59338f72026815c77cad6d8d581859192cd5644
+CT = 03eb9281695ff1155ab689a3975d54f605f75dac3831610828f0a78ce798448529afe26eec875aa6
+
+Count = 288
+Adata = b1eafc03ea2fa3e9e3842a09a225e83055de8a1f412badd6fc9ead12
+Payload = b3f38aedbf08dd7ead9d402c5aaa1ec9279c7e4bfd4a2967
+CT = a6079d6d23c4149cd70d48d3ba3d9ce7f7eaa67657b61e2ba48856a266c0d404474316f418f8f4e4
+
+Count = 289
+Adata = 8fec99f1be0e69267620c0b934bf984d60c1437f74c6ac19610fe188
+Payload = 5c09e2a6a055fe9c21e06e5519cf56b8e2e7fb44094e79f9
+CT = 49fdf5263c99377e5b7066aaf958d49632912379a3b24eb56412292d8015285efaa6f1154580eb57
+
+[Alen = 29]
+
+Key = 9a5a9560baed3b8e0e90b92655d4e5f33889e5d7253d9f6c
+Nonce = c0049382cdd8646756d4e6bff5
+
+Count = 290
+Adata = c95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe3
+Payload = 5bbe9c1fb2563e3e82999fe097b28da4dc6ff2e020f3b4f3
+CT = 6d5401db42b5c48b79203b6ad82806d7460ac4c82ad0809b811020480e834f6fe55900a162a4e61a
+
+Count = 291
+Adata = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193dfa755a5943
+Payload = 8a85a9b32a323c6af156a3fa2f1448b6387cc3660aa8a0f4
+CT = bc6f3477dad1c6df0aef0770608ec3c5a219f54e008b949cba9827513c7f1de970d316b6f81c109d
+
+Count = 292
+Adata = c834096e059ea73ddc90b0c982f9a3a31bfc6b1b81a03f9d41c9c741e7
+Payload = 1e02c13104937fe084b18eba1ea8951dcc5e75b692937dea
+CT = 28e85cf5f47085557f082a3051321e6e563b439e98b04982c9d79dd3255a8323f8229ac1c6d76ae4
+
+Count = 293
+Adata = 9249022bdead3d86ef5bd03acf053132d08663ba1f2426e19c126b22e9
+Payload = 3225570fb15ae13a13c71e364ae9a9fef03d1c9a7fa5dfa0
+CT = 04cfcacb41b91b8fe87ebabc0573228d6a582ab27586ebc8425dc81f93257ae8399fc2d48b4a7685
+
+Count = 294
+Adata = 3c3a92c4ece49fb9f84243d7c1bc91f595fce118305a758c83985c34b4
+Payload = fa0a458174537ddba25708b8d0c22d5517d57b122517b0c9
+CT = cce0d84584b0876e59eeac329f58a6268db04d3a2f3484a1b595003c58e69600c2a3b9ec45c0e15a
+
+Count = 295
+Adata = b49b845ccf76acf508f9db8543c73375d530d91f3b0e4ed70decfd2c2d
+Payload = b7fbdaeaa3ee1d0bbf5ec47898b069ec4ba6a140a3e83996
+CT = 8111472e530de7be44e760f2d72ae29fd1c39768a9cb0dfe0da009261c43c6640303696655e2981f
+
+Count = 296
+Adata = 3aabdf589eeb1709bb3d60b08bc71eaa3ffeba4e2903a5dbd8339aae85
+Payload = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7e
+CT = ac001b7d0b3a47f0ff578aaf4ad3c9c0a759edf04836ef16dfdcdbd4ad711c493d3176f032a02af0
+
+Count = 297
+Adata = 6a79879cd62bd1dbf9609897d2ebf2dc4dda43cc15fcb241aaa0deb4b3
+Payload = 3a861638ccd6591e51e2a525be59447e4a28bab32e36a5f3
+CT = 0c6c8bfc3c35a3abaa5b01aff1c3cf0dd04d8c9b2415919bfd59b45c05873c670f5f8bb47732d59f
+
+Count = 298
+Adata = c5b6ca474eb251817ae4d2f47c0632c381e222aae3b6f585a0dcae120a
+Payload = c7da4e9ba6e5758be726e6e227d7bddb0332228f7e3ecb6b
+CT = f130d35f56068f3e1c9f4268684d36a8995714a7741dff031572a24bc00b40a6b4b172b3648142e7
+
+Count = 299
+Adata = 64a96d191f1d5f95f5fed6259e33e7206adc07b0279e16cb453a9c6438
+Payload = 2b9347d3e195152dce22afdb92acd179eb484872285704c3
+CT = 1d79da171176ef98359b0b51dd365a0a712d7e5a227430ab828bc33396179ac39ce0027a1d62e0fe
+
+[Alen = 30]
+
+Key = 3e61094c80df0053e86d43fccf4e1d3ee2cdb862d3237b0a
+Nonce = 63f00b2488809fdc49ca5f05d5
+
+Count = 300
+Adata = a08763ca936abdeece06467bef8c3c47c3a473636a039d4db540c867d3e3
+Payload = 1fada8f4c7daea0d1c370184c169485b80a278708ed41451
+CT = 680dd22f16a1290bde42c9792dfa997aed24d5bd2265b6e095aa6b99d3f894d3790c2aa2dae1ba2c
+
+Count = 301
+Adata = 19508a6c83b992c660a1a28597e07c729ea2ed39401aadbf9d7586b5720d
+Payload = e9f1f2cf0b8d563e2d20f39f9f464a808b136dba364a6446
+CT = 9e518814daf69538ef553b6273d59ba1e695c0779afbc6f72d9d77109f4597e9c4c8cf7023dc5f3b
+
+Count = 302
+Adata = e5929c3b5d68a4c9fcf1168ea35bf8c0bf3043cb1ed54ff301578b3b7266
+Payload = 07a74c3b874849ecbf013713b80a84337c90b690cea0b837
+CT = 700736e056338aea7d74ffee5499551211161b5d62111a86b2544ecc3c7d5accd22ac075e7b44d5a
+
+Count = 303
+Adata = caa5cc5d0d87680eafc29429bac55c9e33167d485789c7c124b5c57a1ba8
+Payload = 4255f2cf90f0d15e9bead4be799165c57f7225980713d609
+CT = 35f58814418b1258599f1c439502b4e412f48855aba274b8f1a8a1db25de0fab7cabb11a18497584
+
+Count = 304
+Adata = f61cf7ae23a66777bd3fabc3d542feed2b00c6d4f46a772fda11b5214551
+Payload = 70b1e2e4cf260b108f5a52d0d8234838ffd6ffe7b4acd78d
+CT = 0711983f1e5dc8164d2f9a2d34b099199250522a181d753c5a9718ed0257a50e38de86154054fc3a
+
+Count = 305
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb993e86f4
+Payload = af4be10b3a59ea99dadc75fbe5651f6f7630852bb556aa39
+CT = d8eb9bd0eb22299f18a9bd0609f6ce4e1bb628e619e70888550d1acca34c28ba8a3b890bb0542b23
+
+Count = 306
+Adata = 296cd04c4d9ab493def7aeb6841a45309e777028868efe45166235c56b2d
+Payload = 72d5663727592f1bfc9c65be83f4d3508126fecc4e34ae72
+CT = 05751cecf622ec1d3ee9ad436f670271eca05301e2850cc3a268dc1596a7855639c63fa76ad8479b
+
+Count = 307
+Adata = f380ca0a26a94adcf2c1ce26d226d3bf520268c72412e58a71acd9a66d00
+Payload = 3e2ccce03c10ce1527ef8e002adb265edba5779fbd4fcaf6
+CT = 498cb63bed6b0d13e59a46fdc648f77fb623da5211fe6847e3416c75fc28924a21cc123e62a7894c
+
+Count = 308
+Adata = 8825532a31680cb3b5bdb027802d2d8718755e135367e0c8c88e21288311
+Payload = a18dfe7f2d7bbaf316366f67445170afcbe18e2a1de1e947
+CT = d62d84a4fc0079f5d443a79aa8c2a18ea66723e7b1504bf6ff1a47f23d08485951aab18b393584ef
+
+Count = 309
+Adata = f768375589b687fb17c56673af4263626da69eb991007d94d4f5a163fd05
+Payload = 17ca72a440c944fefd6c08ecc3a8ecb54d96b9cad9d2aa4c
+CT = 606a087f91b287f83f19c0112f3b3d9420101407756308fd7d024456bcb69a4f77008773a3f48805
+
+[Alen = 31]
+
+Key = b5664dd6ed435df006052f6ded74bb7ce9482ca9229886f7
+Nonce = 7a1649896f3e030c18f0205599
+
+Count = 310
+Adata = c5f1a26351e53e6509c8bbbed03c42c23ad81c65fccec7ffa1cb494c7f1fc4
+Payload = 0b6de49b530703affc94010c2b793ddc6de0c44d48037ff2
+CT = 56b02fea595cc24e798691ae905be3d466ca68ca744005dba260b5ea3b047020b73b5bafa17e5084
+
+Count = 311
+Adata = 89899be18b4c389afa769b11ecd22e9fad8f38fd614ea5f8eb7a066c0ed8d8
+Payload = 2f1821aa57e5278ffd33c17d46615b77363149dbc9847041
+CT = 72c5eadb5dbee66e782151dffd43857f3d1be55cf5c70a685e4bd97b9dc83134867c00c2acea0aaf
+
+Count = 312
+Adata = d43b841f174335f1347834590b0984a2cb35f7a00a0ee993157d2d4f848748
+Payload = c7da4e95cb38342c6d5bf0c381d5a192adc3bfc1cda3a1d7
+CT = 9a0785e4c163f5cde84960613af77f9aa6e91346f1e0dbfe55202ba34bb9918fe915776de65947c0
+
+Count = 313
+Adata = c1093518efd80245e3c42371f220b21f2034e6738fe02ef43e828190f01aef
+Payload = 414a70aba5a219dbd41cdc46b84812b28cc4f7399218004d
+CT = 1c97bbdaaff9d83a510e4ce4036accba87ee5bbeae5b7a642fdf807b5a6880f2d4c36d558b40eb90
+
+Count = 314
+Adata = 90f627d5b939625bc76fe1bd4643b39edc11d3dc7f4bfe16e61bc26c3d49d8
+Payload = 58b260d3f645a35bad7a3842440bc03608248bd46e725e60
+CT = 056faba2fc1e62ba2868a8e0ff291e3e030e2753523124495a9307ca4239380a45bb7f87e41c4cf7
+
+Count = 315
+Adata = 2f360a4715074e942244ab7f9b6db127b0442df9af2efa2e78db1a94312905
+Payload = 5505caa97218957e90247fde60275bdafce4b16bcb36c263
+CT = 08d801d87843549f1536ef7cdb0585d2f7ce1decf775b84af3aeadff9dd60468aef2a8e2c56dda7d
+
+Count = 316
+Adata = 7db564811f14bc5c2098d5635655c3671fbd8288ea14944af925eaec653408
+Payload = b93e40f556a786e39126b8834a6ecacd2dc9f0f528bab135
+CT = e4e38b845cfc470214342821f14c14c526e35c7214f9cb1c8335f2e31a0468b830c5009cd02dbd5f
+
+Count = 317
+Adata = 36be91854d3d02a5d62503bb9047ef4354280510f7576c4272fd757240b621
+Payload = 543a070fdb3a855dd7d83fbc5f983671ad9e905f307148e4
+CT = 09e7cc7ed16144bc52caaf1ee4bae879a6b43cd80c3232cd5d772a599e91504e022b9dbfb124b71a
+
+Count = 318
+Adata = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb8813ccc2f2dd96
+Payload = 86ef67572cb339c6706eb5909b96848aba5246a196972a1e
+CT = db32ac2626e8f827f57c253220b45a82b178ea26aad450379846cd12430f7adc910d1f0c51d80636
+
+Count = 319
+Adata = 3a64414c3588d7c26871d7d054ac6c8420d4917e3baad4a343685916265321
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 9313393a683cabb7a6ac4a4ab359450ddcc887c69d0ea8fcd9ee65ac3a8fae1b00a4f1dfe2577293
+
+[Alen = 32]
+
+Key = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+Nonce = 809343e986f6ff47f54d4cac22
+
+Count = 320
+Adata = d70aef3532bdc5293a3ebb11589ac1f801c9f93ea0d656e1d04068facf9f768b
+Payload = 718f061e8b972a3adcf465d66c5b28e8661f080127f6722f
+CT = bad3b0e6772e9c4c9c631c095e259d99692292932efb72b8966e91a19617bb748f3495aa433585bb
+
+Count = 321
+Adata = 1ee0eb409398bc252175cb460ef9a2da4c9beab2ef6d8206e4fcce74df785246
+Payload = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+CT = b9ba78455331962a0ee33b5956c2b80fbb55e0b52b1ab75dc8f70aa565a12ca3545e68110968040f
+
+Count = 322
+Adata = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698b0ed5c8cb09a8c96
+Payload = d959dd38a458039e2400d21d27b9a2faee8fe23683330cb5
+CT = 12056bc058e1b5e86497abc215c7178be1b278a48a3e0c22daf38076c810e14a7843444a02f010e0
+
+Count = 323
+Adata = f555216840a1f40b411d44128e567617e2694caf16216ea74c604a8d6ec01e72
+Payload = 337f12e8ebc0544b82fcdd3c4a0dab0e5e75c9f433a27d66
+CT = f823a4101779e23dc26ba4e378731e7f514853663aaf7df1594aebf9b8318877bdec2900a22df858
+
+Count = 324
+Adata = 2311a6fe1feeda3a1f16310d635496c0dd662024f0b0f1de79325e030cb850e5
+Payload = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb4
+CT = 8d60d302875518204538f90eccb4ec7651d51698b6ca2c231d9872d1c10a6594b5c349b84f710d64
+
+Count = 325
+Adata = b2c633e3181ae5fe7828707ed5b70e0460088a84465eadeecdbcfa0e9ff19bb1
+Payload = 23c1732959c4bf85bc707e45cc964b6227acd3a8fc73e675
+CT = e89dc5d1a57d09f3fce7079afee8fe132891493af57ee6e2a9db7c4bcaf6087e158c1a5d4eb1c2cc
+
+Count = 326
+Adata = 791f23252094b9b99fafe7fac1d8ff3ba09305c476041e75afb245ac438b4069
+Payload = 02f60f967e7fbcf957313619882407ea8a03fc943062296c
+CT = c9aab96e82c60a8f17a64fc6ba5ab29b853e6606396f29fb5e1c87d9e1c1f3b7d30fdc2f0ccac783
+
+Count = 327
+Adata = 22197f9ad14591e7a6d5f8b18c969a553de9a85309757fa5d319cc505c24f438
+Payload = 6c1aa088d1a6086d0e72636744a6840c80ab8223409c61b7
+CT = a74616702d1fbe1b4ee51ab876d8317d8f9618b1499161201514b449a741e07f9287f7e9090fa54b
+
+Count = 328
+Adata = 0bb18f7280a30767cd769cb5ffd3edd1c18914b92d1b2192e27ac88f57135616
+Payload = 57275bc3b4d63b9b01b0b0760235c9785d45761cace23f1e
+CT = 9c7bed3b486f8ded4127c9a9304b7c095278ec8ea5ef3f892c889b610157e16e9f31558c669298a7
+
+Count = 329
+Adata = 3e5f0f32e27be18ca6f84de11e6e9c25fc0c4cb0cf83633eea1f033aa1373f3c
+Payload = eba27a27f0d4604a5296a41b3fe995c50c66bcba302d0447
+CT = 20feccdf0c6dd63c1201ddc40d9720b4035b2628392004d0fbe19321dc22c748a17aa5eda29d8cf3
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp
new file mode 100644
index 0000000000..af4f5c1df7
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886df3ba3e6da3a1389
+Nonce = 72a60f345a1978fb40f28a2fa4
+
+Count = 0
+Adata = 00
+Payload = 30d56ff2a25b83fee791110fcaea48e41db7c7f098a81000
+CT = 55f068c0bbba8b598013dd1841fd740fda2902322148ab5e935753e601b79db4ae730b6ae3500731
+
+Count = 1
+Adata = 00
+Payload = e44b4307234281209bd41f89dbe2cc3fbf68e14df2f7fce4
+CT = 816e44353aa38987fc56d39e50f5f0d478f6248f4b1747ba003abc6a4b020625adc8b6cd7bafbd42
+
+Count = 2
+Adata = 00
+Payload = 8db7a73856bcb4007346bb3e00096f69e75e97c0bb960f3b
+CT = e892a00a4f5dbca714c477298b1e538220c052020276b465e7cfa7a208a8b3e6b6377236045df17d
+
+Count = 3
+Adata = 00
+Payload = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e676d44
+CT = 2dd6c9e8563298008cba3be237c67ffb68f59f97c787d61a81b39a0c55822e32042b4f8981021090
+
+Count = 4
+Adata = 00
+Payload = 7cdb2c9b167b3ae811289acf7dc1814bbe241f553447699f
+CT = 19fe2ba90f9a324f76aa56d8f6d6bda079bada978da7d2c1091117e2ad77db510d902038743b5a98
+
+Count = 5
+Adata = 00
+Payload = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eeb
+CT = 24cfc842c9bb65abbc5ff4e61cb2156c19663821c6d395b5ac7379b8e51592b98e4874f4592278a8
+
+Count = 6
+Adata = 00
+Payload = bde9e3eb9f0c57302c9185b1cb912ef76d88f2f9c3b51e9a
+CT = d8cce4d986ed5f974b1349a64086121caa16373b7a55a5c4d08c1c902c4c2f078452dd6943b85028
+
+Count = 7
+Adata = 00
+Payload = 6f9ccc033c6bfbdfad4719ad033c927e2175727a9a021dc6
+CT = 0ab9cb31258af378cac5d5ba882bae95e6ebb7b823e2a69832fefb87445f1ca42811899acc0cdf68
+
+Count = 8
+Adata = 00
+Payload = cc67bc3b7afd625b2610226d3b30e111e6aa47a3254f711a
+CT = a942bb09631c6afc4192ee7ab027ddfa213482619cafca4481d605a1019c8e9778b8928b4636053e
+
+Count = 9
+Adata = 00
+Payload = a10c81725f49ab9075fbf4d96be030a2d881d8501b115d61
+CT = c429864046a8a337127938cee0f70c491f1f1d92a2f1e63f96a82e8411e5b04426dc608298c6408d
+
+[Alen = 1]
+
+Key = a4490ed6ab51dbfccd6f3702a857575dad44da3a27eaf31178abc97da60d1e4b
+Nonce = 26ceaf6e3b28190a17c4f0c378
+
+Count = 10
+Adata = 9e
+Payload = 1b5cc6b1651dec4bbbf5130343852e971c7ff1774100d9be
+CT = 789bce069a725a96c484e64a9e54dcb7a7c268c85df47815a462ff2dd8ba44a381e1f6edab12b5a9
+
+Count = 11
+Adata = 4e
+Payload = e7ab98901c0cb1d7d76e125d8ac8e86edf6f469fa937bc10
+CT = 846c9027e363070aa81fe71457191a4e64d2df20b5c31dbb6b0789c5866b7e3312ad992e228d6d20
+
+Count = 12
+Adata = cc
+Payload = 53bc7e3648d0b389b887b065e9e8f79685beb2eb36e2eb95
+CT = 307b7681b7bf0554c7f6452c343905b63e032b542a164a3e39b1b1a480fdd268c1c75b131cde798b
+
+Count = 13
+Adata = 45
+Payload = 6d7262476da95db63b322c5193ea05030923c3cbf0f8e8b1
+CT = 0eb56af092c6eb6b4443d9184e3bf723b29e5a74ec0c491a32060fea35c3e9528fd18994fae9fce8
+
+Count = 14
+Adata = 2c
+Payload = 8246bf7b81b287411777df7ecb53a1795e54b150ff3dd584
+CT = e181b7cc7edd319c68062a3716825359e5e928efe3c9742fb4e0a604ab30a764e8c98a9cafbca8d4
+
+Count = 15
+Adata = a9
+Payload = 2596ca8772bc69b50bcbf33088c6efbab614b691ed836f92
+CT = 4651c2308dd3df6874ba067955171d9a0da92f2ef177ce397ca72f1acf6dfd078b6f4eb82fa01e9b
+
+Count = 16
+Adata = 85
+Payload = 703065d701f4fcadee20d64300b3082c0c76490eb2dc4ba7
+CT = 13f76d60fe9b4a709151230add62fa0cb7cbd0b1ae28ea0c2a85c9252ee62612dc29cffa7289b2ca
+
+Count = 17
+Adata = dc
+Payload = a1aeda4b4cb8dd2943675181561bac48ba07e8de5b327837
+CT = c269d2fcb3d76bf43c16a4c88bca5e6801ba716147c6d99c9fbdac729413152c089d3939e30b8602
+
+Count = 18
+Adata = ce
+Payload = aa17341f4cead054d41c171dd34c459f7052da225c6c365d
+CT = c9d03ca8b3856689ab6de2540e9db7bfcbef439d409897f6f86266c273f8184e901b50c04845b8ab
+
+Count = 19
+Adata = a6
+Payload = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f
+CT = 274bd52b4497d536191e2f7f65f40159339a43830fbdc0b4ddd02d5c9ae2bbac47a7a076edb1d207
+
+[Alen = 2]
+
+Key = df594db94ef8eca56a417afe946085eaed444c7cc648d07d58132e6cb5bc2bc3
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+
+Count = 20
+Adata = c0c3
+Payload = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259
+CT = bea778540a90033b2c0d087e3cc447711ea25f7eea96855506ec97f23bd6ea97834f92f7263c3195
+
+Count = 21
+Adata = 34b9
+Payload = f6c043c70136585d012ae0df6f42b25584e374649d0116c5
+CT = bcb0ac1ca69079500eeb5d1a4b21c21820cb45216b0581c9f3230df0b52b5cb7ac907dcadcb662ca
+
+Count = 22
+Adata = d4ab
+Payload = dec0c896b04490816409da1783478ef2510231d0a28c5b39
+CT = 94b0274d17e2b18c6bc867d2a724febff52a00955488cc35a99c3165ce83102891ef3885088ed6eb
+
+Count = 23
+Adata = 2a3a
+Payload = cbfd94fc31785d30214271dab2264134805fee6e52aa0b5c
+CT = 818d7b2796de7c3d2e83cc1f964531792477df2ba4ae9c50c9d8078607994ae5dff0de6526fb53d1
+
+Count = 24
+Adata = 4eb1
+Payload = 134d2d9726400d09dd3521326f96fbef993ddc0c40887700
+CT = 593dc24c81e62c04d2f49cf74bf58ba23d15ed49b68ce00c7e84da7d2564533e7ad55390ec3a6ff9
+
+Count = 25
+Adata = 0a79
+Payload = 1ccdcf789d42caba80d7893feaf26d3853fbcaf7d964df0b
+CT = 56bd20a33ae4ebb78f1634face911d75f7d3fbb22f604807520849295a56191367a696999ffef8e9
+
+Count = 26
+Adata = 865f
+Payload = 4042dbe148db3e6dc542b25d57a5787af535d38e8c34c71b
+CT = 0a32343aef7d1f60ca830f9873c60837511de2cb7a305017bc4aceed1a10309b6402b9e9420b33a3
+
+Count = 27
+Adata = f4ae
+Payload = 85b6894fec36294aa934cdc3523fd95c90ad56cbd18545dd
+CT = cfc666944b900847a6f57006765ca9113485678e2781d2d176c180d2e299ccf0b8781ba6de8a72ce
+
+Count = 28
+Adata = 10bf
+Payload = 0f27f4fc8538a676a763b3e5db845a1bfb20d5fab340dee3
+CT = 45571b27229e877ba8a20e20ffe72a565f08e4bf454449ef98d91c68d94873a5d6557611a5402a0a
+
+Count = 29
+Adata = b92e
+Payload = 1b5ec0cb03810a12fc6a0a1ff565afb001405d2a45a1f18a
+CT = 512e2f10a4272b1ff3abb7dad106dffda5686c6fb3a566865321cedf1122354636e130acbd69718b
+
+[Alen = 3]
+
+Key = d98193ab2a465e3fcd85651aaeca18b8e91489b73b7c7e93b518c4b5b81fc6ac
+Nonce = 2247dc7e2674e9e0a63fe70613
+
+Count = 30
+Adata = 4dc2f4
+Payload = edba7d6312144e90ec9eaace7576045a46e553dcb8ee5a98
+CT = 44b9ea727c847336fd739ad11f4b906b292edb810462f06ef59626ad5cdac2e4d4cb07b538a1fd8f
+
+Count = 31
+Adata = 2f3bf0
+Payload = 52a9626f5279c11e17e96f5dc5e1c1f58c1e913020d8499b
+CT = fbaaf57e3ce9fcb806045f42afdc55c4e3d5196d9c54e36ded0d53402253453e494ad350994ca77a
+
+Count = 32
+Adata = 95d2cf
+Payload = 87b6447d97a74d0b315031078aa06fffc7b9f246bfa5f147
+CT = 2eb5d36cf93770ad20bd0118e09dfbcea8727a1b03295bb196dbc3bff865a1d94b164df23d708e8e
+
+Count = 33
+Adata = 0caba9
+Payload = 1852848046706f2e274ba381a2bee1422df4f61d93219af7
+CT = b151139128e0528836a6939ec8837573423f7e402fad3001791b4469fe50d45f8efb81217cd68580
+
+Count = 34
+Adata = f8d459
+Payload = 99aac82fa66a15e4f76b76cf4590150999d5cf8468df7f42
+CT = 30a95f3ec8fa2842e68646d02fad8138f61e47d9d453d5b4587106da25012f92f01cc2db8d11ac29
+
+Count = 35
+Adata = e883dd
+Payload = 4e2f0f91990b855a00d27fbb2e8db7184cd82909de361b52
+CT = e72c9880f79bb8fc113f4fa444b023292313a15462bab1a464148536847290e4fdda7966fe6d5e3b
+
+Count = 36
+Adata = e45da4
+Payload = e558be3fd246170b294d18ffa708842242681890baf8bed9
+CT = 4c5b292ebcd62aad38a028e0cd3510132da390cd0674142fcc4cb33472825363940e2b26424b7802
+
+Count = 37
+Adata = 3b6fc8
+Payload = f8b284c2d851289275973fcd807fac5d8e5e3b6a75ba2ace
+CT = 51b113d3b6c11534647a0fd2ea42386ce195b337c9368038a99dd8dbe89b3ecf663eda1b0f92be7f
+
+Count = 38
+Adata = 043d68
+Payload = 8edf1eb90f0ad33be8a7c6446899e06addc10b3badc4ea25
+CT = 27dc89a8619aee9df94af65b02a4745bb20a8366114840d3dc4894c8fa0a1e1aa760acf9360042f5
+
+Count = 39
+Adata = e89257
+Payload = 8fe9a6bd82462c97f436d382d1ff971c95406b1a6c847d81
+CT = 26ea31acecd61131e5dbe39dbbc2032dfa8be347d008d777cdad1590fd8bf2d7ea919e60d0316566
+
+[Alen = 4]
+
+Key = 45c8afd7373cb0f6b092af3a633d9fd97c4ca378e19d75f9b74d089429726c29
+Nonce = fdb1fa230ae0b172ff98fc7496
+
+Count = 40
+Adata = 270981af
+Payload = 0b92adbb251dc29a67f0bb97f8e7160862b6c4e843d07fd9
+CT = 274e2faea3271ea6fa0494c1951f115b5491a893056c3ee4c76fc350e585277e373e9119bf9595cb
+
+Count = 41
+Adata = 633f3efa
+Payload = 1f88dfd4f5c52c22b1db47f9f4fb6e2f8bcd78d593061369
+CT = 33545dc173fff01e2c2f68af9903697cbdea14aed5ba52540fa7e55dc54e80488a05ee7f1fc96e9d
+
+Count = 42
+Adata = aad86fb5
+Payload = b2b4cb5e90ebf4bd265093b7f5efd4d62dc60e29737aa496
+CT = 9e68494b16d12881bba4bce19817d3851be1625235c6e5ab18151c17d9e3f97244000a3b2d3c2f95
+
+Count = 43
+Adata = ed42941a
+Payload = f312b47d05f8eb5a29943b41347cb1983c75cb7a458a3868
+CT = dfce366883c23766b46014175984b6cb0a52a7010336795562d521c4b5c7a6f2c5ac65f2fd15b066
+
+Count = 44
+Adata = e5b085d8
+Payload = e9fb86938ea7f04cc230296859e7c96fcc352f968c9473e4
+CT = c5270486089d2c705fc4063e341fce3cfa1243edca2832d9e491a31218f688744098851672a09a64
+
+Count = 45
+Adata = 3776f37f
+Payload = 8af6b7540f997954812e38dbd99ccfaedd5c69963c353a4e
+CT = a62a354189a3a5681cda178db464c8fdeb7b05ed7a897b730ece28347d7ebf8291d7eb66b7651b4e
+
+Count = 46
+Adata = 4eb08c9e
+Payload = b90cfd9dd58e320d98510483b1d939bdb5f3b81666ecee59
+CT = 95d07f8853b4ee3105a52bd5dc213eee83d4d46d2050af64cbd25fb40480d15c039878b5d2f25afb
+
+Count = 47
+Adata = c7f93152
+Payload = 02caabc6ed0641681e7148c10cf3159fe35e44013252071e
+CT = 2e1629d36b3c9d5483856797610b12ccd579287a74ee4623fbfd98c8567b78d4b9c3a49a4641908e
+
+Count = 48
+Adata = 57957630
+Payload = 2f29882fdf1418d04f0b9d44272995a56973c4369c687a99
+CT = 03f50a3a592ec4ecd2ffb2124ad192f65f54a84ddad43ba4655c1abcb3ed1a175f12721a407c5d00
+
+Count = 49
+Adata = 19da955d
+Payload = 4e427130be9e94639320529ec135715e65da1117b5ba3c76
+CT = 629ef32538a4485f0ed47dc8accd760d53fd7d6cf3067d4b90621a5e5683df421a0dc52341485d1b
+
+[Alen = 5]
+
+Key = a2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd
+Nonce = 693cbb46bc8366086ec7cd7776
+
+Count = 50
+Adata = 3ba11282d6
+Payload = d822f84b023f12ea9e3ce16b904278e4aaab5e11c2c23f3f
+CT = 9f91fd2f6472e33b02b1eabb9d6655729d44c44dad6b3883fe0667bcc5806b225224b04ade8b21c1
+
+Count = 51
+Adata = 3f3a4718ea
+Payload = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12
+CT = e834b623d3d3c675b88d41d09d59e6595dbad43bed00b9aea6750fffa5a487540ce65770cd836e99
+
+Count = 52
+Adata = ff79ca8965
+Payload = 82b7cd168b6a82cb2d837f41ceda0c27adc5f5b28030454b
+CT = c504c872ed27731ab10e7491c3fe21b19a2a6feeef9942f7e7cfafe32bd71ea9813607c5df446c9d
+
+Count = 53
+Adata = 0021be18ed
+Payload = 1c1a0f144df76781e7c85ab178ed9b1ce8c6dc3f15c59149
+CT = 5ba90a702bba96507b45516175c9b68adf2946637a6c96f576716fe674c33ad3b9d3e54cc86bfccf
+
+Count = 54
+Adata = 9ae7996547
+Payload = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841
+CT = 9e0874c9f658dc8d867e53185d3b85088aa48de3205d3ffdab55dbee34f1bab555bbb196095fb5fd
+
+Count = 55
+Adata = fa292d1958
+Payload = fc7d028a1aa05c74b7ffe333ba6f676913b0f9f1ffa050b8
+CT = bbce07ee7cedada52b72e8e3b74b4aff245f63ad9009570476a4e9e759d5bb79c187a157099e3d12
+
+Count = 56
+Adata = 88800df7b6
+Payload = c9ea772e61742a6706da3ab3e81df14b31506ae58b063ece
+CT = 8e59724a0739dbb69a573163e539dcdd06bff0b9e4af39729f0f3699c9743ad6c9f09dc00ea10487
+
+Count = 57
+Adata = 715041afd4
+Payload = 70d2b8d64121ceccf1961444e8d33b7b7f998aeb58d3d270
+CT = 3761bdb2276c3f1d6d1b1f94e5f716ed487610b7377ad5cc560d78cba6d9f50e9c2677a710f92155
+
+Count = 58
+Adata = 14682301a9
+Payload = 1013946815001a2c08acca4196e0d6668ffbb3883cf111e7
+CT = 57a0910c734debfd9421c1919bc4fbf0b81429d45358165b95ffb6e29172a283d47e4478e2e1f7c4
+
+Count = 59
+Adata = e44c3c21c1
+Payload = f40dc834067bd163e0004d0ec5dd4b96e2a1ea31ea431c98
+CT = b3becd50603620b27c8d46dec8f96600d54e706d85ea1b24ccf233caf0bad9f68f71d78ee58512ec
+
+[Alen = 6]
+
+Key = c5a850167a5bfdf56636ce9e56e2952855504e35cc4f5d24ee5e168853be82d8
+Nonce = c45b165477e8bfa9ca3a1cd3ca
+
+Count = 60
+Adata = 4759557e9bab
+Payload = e758796d7db73bccb1697c42df691ac57974b40ca9186a43
+CT = 93ad58bd5f4f77ac4f92b0ae16c62489e4074c7f152e2ed8a88179e0d32f4928eff13b4ce2873338
+
+Count = 61
+Adata = 2ea07d393a0a
+Payload = ce60ddbe40b70bd55a9147036ad079dec1558ef4c2c625b3
+CT = ba95fc6e624f47b5a46a8befa37f47925c2676877ef06128b7d812c4d69f1f53ee9158382e56625b
+
+Count = 62
+Adata = aa6667faedc1
+Payload = 89eb3056770a6157f06921bc153834447c4b6d862d10d185
+CT = fd1e118655f22d370e92ed50dc970a08e13895f59126951e26fdbed62b228db008a1b14bd7942e12
+
+Count = 63
+Adata = 9e2127d92311
+Payload = 132f3e19e12f462a7463226b716c41a05a59c76f0e1a2f72
+CT = 67da1fc9c3d70a4a8a98ee87b8c37fecc72a3f1cb22c6be9124e1eb78de01b8af83b684baf3e43ad
+
+Count = 64
+Adata = 2f191bc9cff6
+Payload = b8611cbb9a3667b9458ca57eb636eb1dc580e7dbb5701692
+CT = cc943d6bb8ce2bd9bb7769927f99d55158f31fa809465209cb0f79736d1a810d06a776094f9fb67f
+
+Count = 65
+Adata = ad739d5f4736
+Payload = 112f89ccbdadc2433008d3ede2290f9ce81e5c736abf42a8
+CT = 65daa81c9f558e23cef31f012b8631d0756da400d6890633bfba2348f629471c232c9ff7e5f6f85a
+
+Count = 66
+Adata = 01acc909b7d3
+Payload = d47f2ff745de39a9055ad002de6334971fde480bef268b33
+CT = a08a0e27672675c9fba11cee17cc0adb82adb0785310cfa8c0f694d03ffed043787343827ea2603f
+
+Count = 67
+Adata = ce003c836a6f
+Payload = 13be365884b8a91a284ca24f70011e48794b51be275153b9
+CT = 674b1788a640e57ad6b76ea3b9ae2004e438a9cd9b671722279b553998a6fee0a86e177a448573a4
+
+Count = 68
+Adata = 6a759a4efd00
+Payload = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e
+CT = a13d5db4b781965f9dd065b0790f42dedde61cce68d673f54eeb434cca3ea719827417e94d6ed564
+
+Count = 69
+Adata = 02b84a26c773
+Payload = b7bc1580c68fd5d06c1bf75c31dad7a3e26d636d7eee20b9
+CT = c3493450e47799b092e03bb0f875e9ef7f1e9b1ec2d86422a74b5e4e2edb91fbbe722bfaf1500db4
+
+[Alen = 7]
+
+Key = ae8f93c3efe38e2af07e256961dd33028faa0716e5320a7ab319a10d2f4c5548
+Nonce = 6333bde218b784ccd8370492f7
+
+Count = 70
+Adata = 0b1fabdf2a4107
+Payload = bc9ca92a9c9919e39095d3e53fb148694620ae61227e0069
+CT = 45811b0c8f754bf03950e520cd4afc81c2e3eb8a11f4fd386d5a6e4b1fbee15d35939c721004502e
+
+Count = 71
+Adata = 2fc7f5c0ce052f
+Payload = f25a4ca20bbf4969bed6b93c1c77e3d7415f60fe3784216b
+CT = 0b47fe8418531b7a17138ff9ee8c573fc59c2515040edc3a24a68f98716190fb55f743a8bf62a085
+
+Count = 72
+Adata = 8a74412da3034b
+Payload = 3237bf953989d17c65a0fafd2bb1e32c237f98f55389e8f8
+CT = cb2a0db32a65836fcc65cc38d94a57c4a7bcdd1e600315a923afef7b4955d7d1e8f1abef9933bf9f
+
+Count = 73
+Adata = 7139f3c1d6cc36
+Payload = 55d86dc0423cfc2616ef996a3316e776707f8d25c985884a
+CT = acc5dfe651d0ae35bf2aafafc1ed539ef4bcc8cefa0f751b8e824c62632dff5cbc103d3060fbd174
+
+Count = 74
+Adata = af7a380f079aa1
+Payload = ac48398adb10292314973946f261ec39397442ca09b98dd8
+CT = 55558bacc8fc7b30bd520f83009a58d1bdb707213a33708980202d518ca871c9544f4a8c55fd8d20
+
+Count = 75
+Adata = e602abe8f72964
+Payload = 2fb78654e4395df8c37f260d74def234a3a4e3d2b1fe8614
+CT = d6aa3472f7d50feb6aba10c8862546dc2767a63982747b454b33ea6e4344033f74f513d1e41b82ae
+
+Count = 76
+Adata = 82741c5fd6e1df
+Payload = d488bdda400932de56a9f105f0e74ee79c2ed869faaadc31
+CT = 2d950ffc53e560cdff6cc7c0021cfa0f18ed9d82c920216073ccf18c7ea7dce79d0be1204c593234
+
+Count = 77
+Adata = 78f0cc22535402
+Payload = b22aba8d3e9f4b4bf006e26062de15daf94597731a600912
+CT = 4b3708ab2d73195859c3d4a59025a1327d86d29829eaf443b81b8af57b85093778690266e20e2fbb
+
+Count = 78
+Adata = 18e468139dd16f
+Payload = bd864f7b8efd6ed2b068f425482d449bf53a203ea88e1ca1
+CT = 449bfd5d9d113cc119adc2e0bad6f07371f965d59b04e1f09b94a857e7a0423ef6c9cbebde1f9c40
+
+Count = 79
+Adata = a6dab47c0fbfe1
+Payload = 47d9d18b6addc5f88986f0457b666faae59aba4fa3a02abb
+CT = bec463ad793197eb2043c680899ddb426159ffa4902ad7ea64718820065a739fbd3ba560a416895c
+
+[Alen = 8]
+
+Key = 548c2d1eb7d91e003633d4d9ff199e4a8447180edd89ac7867d25a1db288b5ce
+Nonce = 23b205bd6ff8ed0bab0c98999c
+
+Count = 80
+Adata = a6601111cd92c943
+Payload = 49fd5cbe4aff89dc3b8718f9ce545d612cbbebb289ecbf42
+CT = 3cfc6211e359ae322802fc9566f377b0dfe17d1dfe0878ebf2a9047e37cc0be1fab0006af8db8dc4
+
+Count = 81
+Adata = 96f0b7cd7439721d
+Payload = 94a95e945f660d1571b4d7d22709b000b45ff98b2129a4ae
+CT = e1a8603bf6c02afb623133be8fae9ad147056f2456cd6307106a430b04938e97f2e4cda81108ad3e
+
+Count = 82
+Adata = 2ee135dc2ddd9501
+Payload = aeed3aea01755c912213c8c276a2b75dad24f888a611efa3
+CT = dbec0445a8d37b7f31962caede059d8c5e7e6e27d1f5280ab2ab219c6c4952d52505cd9f904b0e04
+
+Count = 83
+Adata = 10c361934fd6ff77
+Payload = be1fcebea4c22a1d71e08047b028d7f4ccab0a6b8085d344
+CT = cb1ef0110d640df36265642b188ffd253ff19cc4f76114edfc1f7b2fe314faea28ab0dae349feb9c
+
+Count = 84
+Adata = 3f6c8a69917f7776
+Payload = 87680ac26fe1511e0f1f745aa4c2a5b9f6c0117dcf08feaa
+CT = f269346dc64776f01c9a90360c658f68059a87d2b8ec390308e529d64e786a29661cccddc0366f3b
+
+Count = 85
+Adata = 0f7a1426ff3b5ee1
+Payload = 9e004b072a27b085e59ca201c157c7d3c906a2c3b455c56e
+CT = eb0175a88381976bf619466d69f0ed023a5c346cc3b102c797c6510b85dfd097f3eac276aff00ba2
+
+Count = 86
+Adata = faa5bed84dcf168e
+Payload = a1bf47b15cd66e43daff420edf014a14b11994b97ada4030
+CT = d4be791ef57049adc97aa66277a660c5424302160d3e87998e522b6f13f99ecb553b6de845940907
+
+Count = 87
+Adata = 2851dae3cb3fcb1c
+Payload = 2d15734871adc63ff32d7002ab40c4a235a4d5fad223953f
+CT = 58144de7d80be1d1e0a8946e03e7ee73c6fe4355a5c752967a9ca39566189ee96c86462bfea78af5
+
+Count = 88
+Adata = 35a29c1bcbe2182f
+Payload = 5a84c4fdd47510fb7aebc0f79d7b625ccd0a96575740b8e6
+CT = 2f85fa527dd33715696e249b35dc488d3e5000f820a47f4fa613b5fbbe73a2df6c630a00ff4b1b92
+
+Count = 89
+Adata = 45820ae66c3e8e77
+Payload = 2052a94e1392dc1db0e89be19ea8f7379ee4cb607a914c89
+CT = 555397e1ba34fbf3a36d7f8d360fdde66dbe5dcf0d758b20d19feb067e9f6225376da21b4899d296
+
+[Alen = 9]
+
+Key = aab793e377a12484dbdd74c9b3a85c74c286e1cc498663fbd7c718b5633bb91a
+Nonce = 10022cddb323e88b3c08f95a0f
+
+Count = 90
+Adata = 82b8c736037ce2f2e8
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1044250f58857c69f72b5d3454d43949e5c02b3822970b280de1a3f7fc5d06cc30f06075f5504ed7
+
+Count = 91
+Adata = 8f2777ec4930f7e349
+Payload = bd845561f099500a6ff3fd09964dc3820f7ab48ba4ed04d5
+CT = d1c8f9ebee44ff231485207e684b0e65a033db29b082ac45835840df6fa96f5c972ac09d94148cbc
+
+Count = 92
+Adata = 5cab3b846870709569
+Payload = a6e09404fe60badfc63dc228057485e6f563ba82acdabd7c
+CT = caac388ee0bd15f6bd4b1f5ffb7248015a2ad520b8b515ec2f83ef84b299cfdb61d2b5039d536c3f
+
+Count = 93
+Adata = 0938f2e2ebb64f8af8
+Payload = 33404d7e0e620c1030b91020e33619c5f53d8b210fa86489
+CT = 5f0ce1f410bfa3394bcfcd571d30d4225a74e4831bc7cc19db04e655cbe22b9ea508d2a03757b97c
+
+Count = 94
+Adata = 82f78ca0e0da2b2d3a
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb9f087a50bf50
+CT = 0d34c4248f2aaaefcef5688a80188d610ef2f0aa6e3f17c04bd88dc6985f819004c2b634c5303ed8
+
+Count = 95
+Adata = 401191aa3fd34abe87
+Payload = 949cdd7c2973d7519e7bca98b2c5947e6d8e91c90e632319
+CT = f8d071f637ae7878e50d17ef4cc35999c2c7fe6b1a0c8b894ff3572e4ebf78473760d8cb4b0366b4
+
+Count = 96
+Adata = 4df4377596d8987671
+Payload = f6720a0bd8705c70e0f923338965e810b3ea939bad652327
+CT = 9a3ea681c6adf3599b8ffe44776325f71ca3fc39b90a8bb7de95ec3eee17753e60fb3c0661bdd098
+
+Count = 97
+Adata = 6593194b9970545c5a
+Payload = de9b0556661e726f3e6e34515ff7196420fe61b4f38419f2
+CT = b2d7a9dc78c3dd464518e926a1f1d4838fb70e16e7ebb162b8590ff04f967e51fbd1be84f01b4dcb
+
+Count = 98
+Adata = ab2d432058b540ac72
+Payload = 6cad7f3b9f196839bbc5a7f755c09aa8e17c83d9cb8b3954
+CT = 00e1d3b181c4c710c0b37a80abc6574f4e35ec7bdfe491c471d67b75b2da855a12ffb24ddd64a048
+
+Count = 99
+Adata = 5dc631eeeacb5a0b0b
+Payload = 70a55aec1144357377612fd0bbc2c817f33465a656219957
+CT = 1ce9f6660f999a5a0c17f2a745c405f05c7d0a04424e31c71fc798dd16c1fadef607a9297cbfbfef
+
+[Alen = 10]
+
+Key = 06ac39896073a44283611a66ccab067e2dd2faa8da82ff9a45bb29e54d2e6e77
+Nonce = 6c7942c9819cf69b817bfcdb0a
+
+Count = 100
+Adata = 215e2a6c24325340fdec
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = c5b3b50ed8a7b7b96b02ba9464b6a2ff80e90548605699a63d70e6dffb31a376a1eb7f94526dca48
+
+Count = 101
+Adata = e0a29a2c7840cf9b41de
+Payload = 7e5e5710a693ebfa36335cf7965574740880acdddd13fb1a
+CT = 89fb3efdc685924d24d5e99c3824fe2091730366a49c136fcbf516608fe20e06bbff931e84683545
+
+Count = 102
+Adata = b8026fbada6339d84802
+Payload = 08c342a50aa23362622934dfab55d9b22c22c249ad08138c
+CT = ff662b486ab44ad570cf81b4052453e6b5d16df2d487fbf9d70eb14f3fa0229906b9e0360be3d3f9
+
+Count = 103
+Adata = 65f4b3a00c1c1ef39445
+Payload = e085aba85882c75d5e41559167731496cf17d3907894352a
+CT = 1720c2453894beea4ca7e0fac9029ec256e47c2b011bdd5f4184771199a427861bf17cd8401e794e
+
+Count = 104
+Adata = 96118dbfe53434d8aed8
+Payload = 710f890be2b8da77c1eff429ede9cc931d50f059748cbcb6
+CT = 86aae0e682aea3c0d3094142439846c784a35fe20d0354c34e20b2db52fde68f88bfb886fdcb2c47
+
+Count = 105
+Adata = cdf4b485d2e04709cf8f
+Payload = cda96efee4e188ab3048bc1904ac2c36ab018f2ab7602682
+CT = 3a0c071384f7f11c22ae0972aadda66232f22091ceefcef782ee3df38ddea8e269eb47e39900345e
+
+Count = 106
+Adata = 50e57e57cf8e49e3a4e6
+Payload = 3dc596d52e520779a50bcba3049388b340dbf6d0f2eb94cf
+CT = ca60ff384e447eceb7ed7ec8aae202e7d928596b8b647cba44aaac4ed86f687cfc031f22827725f1
+
+Count = 107
+Adata = 48c670f11ff7f74e7003
+Payload = a33105c0dccf8e3b687212a870af9f710462756705fe09b3
+CT = 54946c2dbcd9f78c7a94a7c3dede15259d91dadc7c71e1c6d75255006ac037d6a4d048f1fc338012
+
+Count = 108
+Adata = 465e3be6113a2fb2ee20
+Payload = 573ac2436158eb7dd9be981e3cfbe75d3a188ea9cf2b1ee2
+CT = a09fabae014e92cacb582d75928a6d09a3eb2112b6a4f6976c1da33a80bc8157cece1acf9400b2bb
+
+Count = 109
+Adata = ee4e10574faeae85e9b6
+Payload = ca35bdb54e73eac5a5200a296b3aba5f37c87349746102d4
+CT = 3d90d4582e659372b7c6bf42c54b300bae3bdcf20deeeaa165c1cb98da4a1a920ca1ed9a7b6ec514
+
+[Alen = 11]
+
+Key = 50412c6444bcf9829506ab019e98234af1541061557412740bc120b456052763
+Nonce = 85684f94c3702c5d870310166d
+
+Count = 110
+Adata = f706a3e09df95d3e21d2e0
+Payload = 6cdbd63f6d591f59776f828533b28e2453a214d1d0dd8a39
+CT = 8c8b4ae854a5d5c265b25e3b54bded9444cc454b3e0e6a24d6c05eaf406a5ebd578e19edd5227380
+
+Count = 111
+Adata = e46b25b9a41a858e87900a
+Payload = 100132c315bfc9c4fb93023f5d3500d7208a68acb4d2c630
+CT = f051ae142c43035fe94ede813a3a636737e439365a01262d5088446e42591c0ede68e82334d97cfa
+
+Count = 112
+Adata = 28d34b29afe6586fd9bf0e
+Payload = d5460c1db0d24dedc63c4c78ce6d1f0b2d46f3b01934525c
+CT = 351690ca892e8776d4e190c6a9627cbb3a28a22af7e7b2413eaaef2823f5ac3f313f560bd774d10e
+
+Count = 113
+Adata = 2852d4fd68a3e9e47d44a7
+Payload = d2d73b62e3b1c9ab75f3544ff8616741e0adbae84b8cf9d0
+CT = 3287a7b5da4d0330672e88f19f6e04f1f7c3eb72a55f19cd62d30d99bb7dadec34e2891c156a1f5d
+
+Count = 114
+Adata = ec1c17b2ab13d7c8ac874f
+Payload = 74796d78d6ad03634ed80800af530212baa7e5093651cedf
+CT = 9429f1afef51c9f85c05d4bec85c61a2adc9b493d8822ec241c9a05ebf9ed27792bbced83b5dc582
+
+Count = 115
+Adata = 4f1ab5ddb1c199e9a5daab
+Payload = fb432488b5d08d576a90f085181ad883407a6ce9ea29950a
+CT = 1b13b85f8c2c47cc784d2c3b7f15bb3357143d7304fa75171ffc24020e86b1314724104e6b57b3ce
+
+Count = 116
+Adata = 864e0e728aea856fae6c6d
+Payload = 2b82d96ed1778412378abe4e09c633acf3359b9709ae3dcb
+CT = cbd245b9e88b4e89255762f06ec9501ce45bca0de77dddd6539bbb0af8ecf77b4508533247b3501a
+
+Count = 117
+Adata = 21ee21a5ed0d75d0380a28
+Payload = 85143071241bb65261fe7afcc102416e59b9e46ee0c90073
+CT = 6544aca61de77cc97323a642a60d22de4ed7b5f40e1ae06ef8981ec6ce7c4687b178f2103fa8c8be
+
+Count = 118
+Adata = 2b63f7b676f13f45d103dd
+Payload = 185577b48237acbdaa3590b8057fe374f875ce829b62c98f
+CT = f805eb63bbcb6626b8e84c06627080c4ef1b9f1875b1299265d9d899c6b71c0ab3049ea1dbfaf6a9
+
+Count = 119
+Adata = a33e86d813c2c4ff3bab20
+Payload = f051beb936e60fd4f3bca31964f1ad3e6fa16dd27b65a6db
+CT = 1001226e0f1ac54fe1617fa703fece8e78cf3c4895b646c6b246474c4e79822f5fd55f2fb0067a40
+
+[Alen = 12]
+
+Key = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0cb00b1abade1b5ce0ed
+Nonce = d80210b9f9776ea36dc0e0a787
+
+Count = 120
+Adata = e4296d1c8cf4ffc4b2635135
+Payload = c825952293e434ea866db558aaf486ef09a92bf366988f71
+CT = b8b3b15fdf6a4a0b5abc313afc769e4e8413bd887552583ede3ed995d1b70561c8e28a7b1a7e3dc8
+
+Count = 121
+Adata = d18bfcc1584eeb8695388ebe
+Payload = a1e0248355bfd1d881fb1a4798cda2f6f6ad513c69c5f9b4
+CT = d17600fe1931af395d2a9e25ce4fba577b17c7477a0f2efb561575f6743c5759494be59afa0c3e11
+
+Count = 122
+Adata = 14682301a99bf680805d1ffe
+Payload = ded135fcbf62219bfba2cba40c2d2cbe4815ddaac1342231
+CT = ae471181f3ec5f7a27734fc65aaf341fc5af4bd1d2fef57e34f689367228cbaf3cd76fb407109cf6
+
+Count = 123
+Adata = 8853aa2dfea9c4d370678bb6
+Payload = 12d3900c6c01968b8344762e0e883e5e219f42b052dc6215
+CT = 6245b471208fe86a5f95f24c580a26ffac25d4cb4116b55a2cacb7fc3856abcf759feb8dc0998ab1
+
+Count = 124
+Adata = c5d3b9c593c3185fe4b6d1bc
+Payload = 8c3c1193fe1a1ebad7e01a1eed1a32c08a0091b1c948e184
+CT = fcaa35eeb294605b0b319e7cbb982a6107ba07cada8236cb42a740cd3262424a2c3d77849ead6149
+
+Count = 125
+Adata = dfb9e8149b51f89b1ec00a8e
+Payload = 8219618b7728ac89237705ecf84012cc7c80293c4cf171d8
+CT = f28f45f63ba6d268ffa6818eaec20a6df13abf475f3ba69747d4dbe0f9415d40843070e1e93059eb
+
+Count = 126
+Adata = 08a4590d262e4dbcb7e23ffc
+Payload = b344b7dc239617fa51b9ea10a349e940c3163779f5284c9c
+CT = c3d293a16f18691b8d686e72f5cbf1e14eaca102e6e29bd31215b3dccba4ca5de64be7fab8a7a22c
+
+Count = 127
+Adata = 74aab7b5b96238710637c6e5
+Payload = 740d4b25ca7221d0826057701a6bfd66c50a82f010a57be8
+CT = 049b6f5886fc5f315eb1d3124ce9e5c748b0148b036faca734e09945ee44c95c7923d8b9249ade7b
+
+Count = 128
+Adata = 420aac47a3f212fffca40549
+Payload = 5d9000489186abdf4f0a2794f0222fcaa156fe6309c10f79
+CT = 2d062435dd08d53e93dba3f6a6a0376b2cec68181a0bd8360a568dd779526a0058d522af1dafde30
+
+Count = 129
+Adata = 6e80dd7f1badf3a1c9ab25c7
+Payload = ac2c44263363810bec3a309aa618b303e05099dfdbeb5c16
+CT = dcba605b7fedffea30ebb4f8f09aaba26dea0fa4c8218b59279442c88d612ed1a39ae0005f88155d
+
+[Alen = 13]
+
+Key = a4cc7e1c90f8684e6a5f95e6898ab4e3c194cb46e196d8228062b9f3fa744930
+Nonce = cdc2712e51c7f333d6bad78eee
+
+Count = 130
+Adata = 569c56b27268d3db54e728aac0
+Payload = 10d4cff95ef490923c9e0906880729d4d05412e7675cce76
+CT = be3ce3e9dc72499839a98ae52abb17415e8547687e8a3c7b8aaaac20d4c9276f2851cbba2b04d185
+
+Count = 131
+Adata = d75635b6450e43285fba966835
+Payload = c9db03e2efbab713b0b640421018d3971ffe2abd70fe8fa1
+CT = 67332ff26d3c6e19b581c3a1b2a4ed02912f7f3269287dacc121ff83891335dd1214ea6fc25f6a68
+
+Count = 132
+Adata = 70750acea6a05f8b7b425d262b
+Payload = add631ce5846ce71434aad4998f8e429aed430e7d38bdbb2
+CT = 033e1ddedac0177b467d2eaa3a44dabc20056568ca5d29bf549e71ec517cd65150f42b3cb53f936e
+
+Count = 133
+Adata = 2a567c7ec7edaa5a438ae3bb35
+Payload = a514d170422feb1d87bb7725a9e77cc6fc8afb45c2af6d90
+CT = 0bfcfd60c0a93217828cf4c60b5b4253725baecadb799f9d0e432ec394ddbb65205dc40a5a8e90a4
+
+Count = 134
+Adata = 0f8795385b805246a0a2573afc
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d730a80a3ab4a07849d4ddf9280170800fb9897c917dbe30926b0d977107a3918717f79b63f36b0a
+
+Count = 135
+Adata = 111d224c102b136159fbeb44a7
+Payload = 2edd498e54b23aab6f4fd7b3f22c4c787e3a4f1fb06c9ec7
+CT = 8035659ed634e3a16a785450509072edf0eb1a90a9ba6ccac2cd61599bb93db3dd3dabc12aa90932
+
+Count = 136
+Adata = df0821c9ea6ab329c626d11b4b
+Payload = 6e3e25db29da2c787bb37755ee770e2402fb8208da23389d
+CT = c0d609cbab5cf5727e84f4b64ccb30b18c2ad787c3f5ca90bd027ecd00cc6dc5ffd5d746d92281e9
+
+Count = 137
+Adata = aacaf4839c35338d6e2b47ac45
+Payload = d4ed4584678e982ace8664e77d0e55be356be558cead3755
+CT = 7a056994e5084120cbb1e704dfb26b2bbbbab0d7d77bc5583c01354a450eda2588be7578530e38c0
+
+Count = 138
+Adata = dc6eed3f8bd1b5563c1eeb9afa
+Payload = 4ebf00eadaf70711f630f5badf0214d8518a200afb0e5765
+CT = e0572cfa5871de1bf30776597dbe2a4ddf5b7585e2d8a5688d7a1d546e25ba026cd46556eb2c4b7e
+
+Count = 139
+Adata = fbfe7e910f242a78dd6e69a2ec
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 89c14f71907472e8c25926068883be257653a57caf213a0b0e951aee790239e7067ef37f497b4bf4
+
+[Alen = 14]
+
+Key = 347e12eec56e95aafcc7d25bf10fc756b4e42bc2e43da7f97df24331f27f1f5c
+Nonce = b8d517b033754058128d13d11a
+
+Count = 140
+Adata = 511c6924fa96db716f6b053b7a48
+Payload = ca88dddfc876a12f45f19562bc9ca250f43267ab251a7f34
+CT = eeedcfa8f5b5b48c1d7e277526eecb7294213b9f5785167ae949b93003dfe63c95c1d49edfb4de3f
+
+Count = 141
+Adata = 10c26d5939618189a9503623f55f
+Payload = de0c0d17c3950e7f8985b56d60623cbd010cd765da4df5ab
+CT = fa691f60fe561bdcd10a077afa10559f611f8b51a8d29ce585c32a90d77fed97eb0ac164ed616e1c
+
+Count = 142
+Adata = bc09c59d20e55a9e184d70af2c7c
+Payload = 2f35102d78a32fcde1cfb563ea8d310ecb83c146ab8de362
+CT = 0b50025a45603a6eb940077470ff582cab909d72d9128a2c180fdf5f63045f326057cf74fd4cee6b
+
+Count = 143
+Adata = b75887f13d6e8c4b35b27b965693
+Payload = a3fcce3420effdd6edb37271735a0d30c10c65233aee173f
+CT = 8799dc431d2ce875b53cc066e9286412a11f391748717e7134959a180fc2cf2ba99af21cc1bc8e5c
+
+Count = 144
+Adata = 603401a9b8ecde4d5c86b6107363
+Payload = 4ac918727e41b8c536484e3781c403e260c278712853508d
+CT = 6eac0a054382ad666ec7fc201bb66ac000d124455acc39c32ca2e5195dbd44f0a119538c95788510
+
+Count = 145
+Adata = 7206b06f306124ca3a302e84c5a6
+Payload = 97d770cbb2c42a552e450cc4e35e5668b2ff89cec735cc91
+CT = b3b262bc8f073ff676cabed3792c3f4ad2ecd5fab5aaa5df74a4e1198878a76291594b9826d4b563
+
+Count = 146
+Adata = b15efed90a5d1d62f545ac22af6e
+Payload = 86bb2ae50e36c72936240a74502172625cbca210cf285077
+CT = a2de389233f5d28a6eabb863ca531b403caffe24bdb73939ff5f993dcfbd048274da7439c0f9ef5a
+
+Count = 147
+Adata = c9eb714ed9858a8dc11a26ee3f00
+Payload = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17
+CT = 29a28be439bcc3447e851e5a1e0db26f765b631cc3a436590e87710559a375ece6ef2953b6aa2542
+
+Count = 148
+Adata = 07ca22271e95cb48a872046822b7
+Payload = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a1
+CT = dd35fb1a58664b58636c174a35892b389ac289562cab29ef998035c81716e2d1ed4b4d56ff18af5d
+
+Count = 149
+Adata = b65f6773516124317cfb4b1fcdf5
+Payload = e160e28e601a49d16db18f25410756b330b036c42e615fd6
+CT = c505f0f95dd95c72353e3d32db753f9150a36af05cfe36981ae73a9b6896d8fc1b8c0d772d632983
+
+[Alen = 15]
+
+Key = 520902aa27c16dee112812b2e685aa203aeb8b8633bd1bfc99728a482d96c1fe
+Nonce = ddf50502f414c1bf24888f1328
+
+Count = 150
+Adata = 22b4f8f1aac02a9b2ef785d0ff6f93
+Payload = 533fee7d2c7740db55770e48cb1b541d990ea3f8f08ed1a6
+CT = fc867b319e0e4ab45ec518a1b5dcec4f29982173f3abfd4d8a8f8d14d2bdac84c3737cfbd75b7c0b
+
+Count = 151
+Adata = d0a43de391d492746ecf322acd6e5b
+Payload = cced20b59a6b2c3c45ea6c87802440c9c47b1015e83d86c3
+CT = 6354b5f9281226534e587a6efee3f89b74ed929eeb18aa28fce59f5e6e3cee284b4cc747ff5ee13f
+
+Count = 152
+Adata = 3a789c06f87f05933c34a1cf9834a8
+Payload = 90939a4530181ad6900664f66bfc2ce0289432a0afe9babe
+CT = 3f2a0f09826110b99bb4721f153b94b29802b02baccc9655ddaef56d8255125f7c316c6c59ce779f
+
+Count = 153
+Adata = 785260973f112c56d9f891160c4c11
+Payload = 86cd926b9565b76a88fde73c31e9ac908ffd1e6ca30b59ce
+CT = 29740727271cbd05834ff1d54f2e14c23f6b9ce7a02e752555810cbcdf48f05d0a7808673c82d08d
+
+Count = 154
+Adata = bf6a144591c0ea7b10274fbd3345a1
+Payload = 6ecd1c1acc6290672f9cf639ed0cebcb21ed0c56f35a5ce3
+CT = c17489567e1b9a08242ee0d093cb5399917b8eddf07f700849e41e5d34a698ae1d96f16bc68da944
+
+Count = 155
+Adata = 7d9488b500d89a27f367f34a448a87
+Payload = b01e3f4fb5ee7501e8c2f4ccefb542ae20d7fd61a2c41c8b
+CT = 1fa7aa0307977f6ee370e2259172fafc90417feaa1e130601bc54e546d1a6fcf6187169feb1ea533
+
+Count = 156
+Adata = 060fc718e994edc7bac9962ca7f28d
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = 8d12ff411dec3b0ad61a7225902cc07c97ca898c29c8fe6ff2eb6c0ab42acf42985c721bfd576e71
+
+Count = 157
+Adata = cb6f96dd06015967279ade310a7401
+Payload = f96ed20b23c784015ff58f5f040798ca75e3b98045deca8e
+CT = 56d7474791be8e6e544799b67ac02098c5753b0b46fbe665ac502b8e65cc1329b6895afdd354f5db
+
+Count = 158
+Adata = 9aa6d501455019b4ef4c7fb789d22f
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = cb3311cd8ed070804105f7aa90ee14ebf6ae04ebf2ab9a9a87e5f8a8148f21adf721477c36bd99ca
+
+Count = 159
+Adata = ebd1d12bbd14176a0d4080aa1edb89
+Payload = 32d71e59634126ac6c6156a80a0dfa0175b29e9f40a31696
+CT = 9d6e8b15d1382cc367d3404174ca4253c5241c1443863a7dda9ea0427522dbeaa509a11755434760
+
+[Alen = 16]
+
+Key = 57da1c2704219ed59abfdf04743a9a93c87a63d471818de0f1564b2db6421562
+Nonce = 4b60a47b7e90f622fa0bf803e1
+
+Count = 160
+Adata = 0ae8c012ff39753510df3ee80707e4e2
+Payload = ddc3c1aa73fb6de92bb4db138e26f3c2e0543ab4f5924871
+CT = daa8256d4753fdf9cfef876295badaba89b45cc497f54d220ec2c6fb687753bca4580adc6aa2f296
+
+Count = 161
+Adata = d5b22e7697ba70e00c7ef32709563f01
+Payload = 34270576724083e9989764d08a0d5c1b4738f34927a1e436
+CT = 334ce1b146e813f97ccc38a1919175632ed8953945c6e1658f30b9c8e380c98bb939a4e8a85af758
+
+Count = 162
+Adata = 6b4edef415763aabcef01863e8197aec
+Payload = 904fe88e7a8e76447a64b488ef84184d0f1ab1b67f0c5a7d
+CT = 97240c494e26e6549e3fe8f9f418313566fad7c61d6b5f2e53e80d8ccc687fd303f4cdef44b6e8b9
+
+Count = 163
+Adata = 4c099809061024c010a77e9621fc2bcf
+Payload = 51fe7bac8f3255f17f64fb9322210fb7d8da8e762498b233
+CT = 56959f6bbb9ac5e19b3fa7e239bd26cfb13ae80646ffb7600c635dac5b70338dac3f33ce16a99145
+
+Count = 164
+Adata = 9d329439588164d5a96675a85c07a039
+Payload = eab6dbc13bb92df36b1882df2b8f34c3cefa41f95717fbd7
+CT = eddd3f060f11bde38f43deae30131dbba71a27893570fe84f996e8163affb1494bb3c12eeadf16b6
+
+Count = 165
+Adata = b768fc3daf29ff9e8bd575072d986e99
+Payload = c44c9c287d3eac7c30570d9c4adf2e4857c598f7c54cd126
+CT = c32778ef49963c6cd40c51ed514307303e25fe87a72bd47598b4206a9622d5631751a497dfb1f662
+
+Count = 166
+Adata = 3efc7cc2d16bf82d2bcfbc559a09b2c9
+Payload = c11b9c9d7607f387359c0038d3e8ec4d527562ce63c3384c
+CT = c670785a42af6397d1c75c49c874c5353b9504be01a43d1f7dd300167d267ad700dea37fb475ecdd
+
+Count = 167
+Adata = 0ff89eff92a530b66684cd75a39481e7
+Payload = cc17904b166f28df82f57889f391159a4a308e752d714ee5
+CT = cb7c748c22c7b8cf66ae24f8e80d3ce223d0e8054f164bb6303e9c9bd0d8e4aac42894ca03d6ab06
+
+Count = 168
+Adata = fbd11bc75759f0461e796f6917aeb42b
+Payload = 6f97e595ea2f40612ea84a2097b974d235055fe1dae59403
+CT = 68fc0152de87d071caf316518c255daa5ce53991b88291500953f46e0e9cf1369e9eb018a4df3c09
+
+Count = 169
+Adata = b79940952f42537484aa2907c72dffa9
+Payload = a48cbf933b88c0ec5ddcdd8fcad186391c2cbef308607de5
+CT = a3e75b540f2050fcb98781fed14daf4175ccd8836a0778b68a1702dfa0cd9c290c5ff9c35cc83705
+
+[Alen = 17]
+
+Key = 9267ebc99ccf648b146cba3c251187e24a9947d806ceb0ced6894211641a1e0d
+Nonce = 9b7298950280e8762ecdc9bbe4
+
+Count = 170
+Adata = 5824689453bc406bf891b85e4576e38fe8
+Payload = 967daf12f16f166b7b5038f83a1cf0b980f5abf4c7746f2a
+CT = 7cfe2a7a54306eb8d8a63d3d1ae86794f9a2c22198b2cb4f10ca926f1a430c08c12e23db3d913e93
+
+Count = 171
+Adata = cd15973753b94b77bb4b778de8b3b0cabb
+Payload = c4a756f6024a9dceabf6e264fffff9c719217fb418141ac5
+CT = 2e24d39ea715e51d0800e7a1df0b6eea6076166147d2bea05d5b674fd15410cc235dba6d8c8d82a8
+
+Count = 172
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3f
+Payload = e0d5de7d1eace211c0e70859ff315ff485d1200c6dd13f93
+CT = 0a565b15bbf39ac263110d9cdfc5c8d9fc8649d932179bf688750b5f36c86e7eda9015e960a7471a
+
+Count = 173
+Adata = cbbecf92551a15f5cf00a5be4a50b0eb17
+Payload = 05a4a4ba28fe8876f9bcfa5ec60651fd3fd4732f22049bd5
+CT = ef2721d28da1f0a55a4aff9be6f2c6d046831afa7dc23fb0d5fa842209dbbc04c87965f78500fec1
+
+Count = 174
+Adata = 873ba7f8b71517ec50297b21cf94cdb7a5
+Payload = 9cdebaeee8690b68751070691f49593668a6de12d3a948b3
+CT = 765d3f864d3673bbd6e675ac3fbdce1b11f1b7c78c6fecd67d147edbe114bfdb3f3b9b37d5719ef5
+
+Count = 175
+Adata = ac087420feb1e1e8c2546c2a8b8a5af0d0
+Payload = 5672e61cf664d73918dc1ca84df1fce82db0e305a61d57b9
+CT = bcf16374533bafeabb2a196d6d056bc554e78ad0f9dbf3dc57b4c2bbc377937d15b3b89543e29d0e
+
+Count = 176
+Adata = a12c690568114fd7a677f49d74e84fc1a6
+Payload = 0f5452e6b51540cf219998590995cd7f8785fa40b4f217fc
+CT = e5d7d78e104a381c826f9d9c29615a52fed29395eb34b3992e6ca774074b47b59adabeaf8835582d
+
+Count = 177
+Adata = 7a78ddfe5afb2dc90ee4a600c2fc014b0f
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae72f7
+CT = 7050bda358442a350db77d357ef4910f0dafd9670168d692bd320f48a7221537e3cbed5ac4154a56
+
+Count = 178
+Adata = 6053e466ed1f647a3cd88c4d2052ec00cb
+Payload = d17b8d556e83190c84d4a812957c64ffa7f336298f4e2c72
+CT = 3bf8083dcbdc61df2722add7b588f3d2dea45ffcd088881740574e201f9a26932a87c8d822505814
+
+Count = 179
+Adata = f7673e3beb526834d6507058fe62e34987
+Payload = 2eaef86b0f602364f86510eabc58bc9ad1e6f0a6f6df0b83
+CT = c42d7d03aa3f5bb75b93152f9cac2bb7a8b19973a919afe6837dfa3fdef2f012b6609de2ac5dd9d6
+
+[Alen = 18]
+
+Key = 7a855e1690ee638de01db43b37401dcd569c1ae03dc73dd0a917d0cadb5abc29
+Nonce = 8f160a873a1166c8b32bccbba7
+
+Count = 180
+Adata = 72674aca7eba2fc0eeafbd143c2c4d8aa6c8
+Payload = 33ae68ebb8010c6b3da6b9cb29fe9f8bd09b59ec39f4ce4b
+CT = b22afdf4f12c43ec23e01ac1215a3f5286059211207e957057e9a9203da74387a9468f8af5e27547
+
+Count = 181
+Adata = f7da3f100b80e2ade812f1700aab6b72f746
+Payload = dbb29817b86cb80e0d008742cedfbf52b236f15ee8cad50e
+CT = 5a360d08f141f78913462448c67b1f8be4a83aa3f1408e35a3985f12a49eac424a35c94645917e91
+
+Count = 182
+Adata = 4b05eaadf98505d0806c233b2cdcaf4254e8
+Payload = 145aa8cfd544a2f46bae1aa83cbdb3d21c3d1350078a3af4
+CT = 95de3dd09c69ed7375e8b9a23419130b4aa3d8ad1e0061cf4ab089a8724b87a1167180963d44ec65
+
+Count = 183
+Adata = 05a3aaa08b9a6aaeb84704431425d0e45a14
+Payload = 6b32e8906dc89194a69410b79cd041b62eb01afb28a3e10a
+CT = eab67d8f24e5de13b8d2b3bd9474e16f782ed1063129ba310a7d1520141892e140448292185c41c7
+
+Count = 184
+Adata = 74db01edc26a2d2044cb8eaad8b907b78863
+Payload = 545ed03588fd85a8bbfeee66d2082ae6f8e2f3c9dbd8725f
+CT = d5da452ac1d0ca2fa5b84d6cdaac8a3fae7c3834c252296472d3eee219d94bd788f62df4add5ec40
+
+Count = 185
+Adata = 5f2c6ddf5a2403e04dac8b2813c060b67e76
+Payload = 66dd5fd8611c551973a3d0c078ec2b4d39ad163d9168de3c
+CT = e759cac728311a9e6de573ca70488b946f33ddc088e28507c600496f4f8b1b7da118ee36d8cd57f8
+
+Count = 186
+Adata = a650a2a5e3c6f7c95614570aaefd0cdd9a42
+Payload = 6f364b3f778376cbf3f4b0b0c5350a8fa278f9d8c25faad6
+CT = eeb2de203eae394cedb213bacd91aa56f4e63225dbd5f1ed4710004d06ce7a7efbd19da4e3ce3cf7
+
+Count = 187
+Adata = 477c2484cf5c56b813313927be8387b1024f
+Payload = 3de4798d8ad84c460b92abc10b7f5e7c9fae46a1dd353687
+CT = bc60ec92c3f503c115d408cb03dbfea5c9308d5cc4bf6dbc304099641c4ec3dc2c54fdf4f48dbef2
+
+Count = 188
+Adata = 564e1df74aa2d7ee33b66cfeda810774e16c
+Payload = 7769b45fea11f530fb9a67f1b5b1964a34cfa32bbb03f4b1
+CT = f6ed2140a33cbab7e5dcc4fbbd153693625168d6a289af8a905c1b05e8945685f8688faea777eb43
+
+Count = 189
+Adata = d5e66502529b0045883d935e05acd242baa8
+Payload = 0c0a502b42f81b51806c7080a8155280f493f2922cdc7df8
+CT = 8d8ec5340bd554d69e2ad38aa0b1f259a20d396f355626c3ea5a3b6a8bafde4006b993cfb3b13557
+
+[Alen = 19]
+
+Key = 0ebdc6ddb4c502725dd6ee8da95d56a0d1044b4694d6ba8475a4434f23a8474f
+Nonce = fb717a8c82114477253acc14f6
+
+Count = 190
+Adata = 41e9d65632f74f449a6842d5e6c4a86ef83791
+Payload = c7360282c85484a5a33ab1c68dd70873ab4e74ffd4a62cd5
+CT = 2e961b3a2fa1609a4e6fd04bff6ac5e306ae2638706f997b42be2e2ba05c54b619850db5c9d684fe
+
+Count = 191
+Adata = 555304659bde926cb2553b8a4605251fcddd92
+Payload = 1332314d1cf783b9f64e0fa2d42d43d225da9fd5165b5f0a
+CT = fa9228f5fb0267861b1b6e2fa6908e42883acd12b292eaa4bbdee2605bc69601b1e83d1e7a0b400d
+
+Count = 192
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9
+Payload = f264da8606ea429e0e25da3f2efafe28beaff05b42097369
+CT = 1bc4c33ee11fa6a1e370bbb25c4733b8134fa29ce6c0c6c7304611baf530932da7954f714514d228
+
+Count = 193
+Adata = d7186a67061319b44eedc0677ebf5d932d5bce
+Payload = c9ee6482144dc61c43041324a2c18ede370011cb4882b0c5
+CT = 204e7d3af3b82223ae5172a9d07c434e9ae0430cec4b056b6d1d44e26404b7324767f0b3f7486f8b
+
+Count = 194
+Adata = 38f37d5e2da017f1953ff3701be0b38809ba80
+Payload = 40524a4d32a711e7d5a59809878c318f42b6e2375b77b8a7
+CT = a9f253f5d552f5d838f0f984f531fc1fef56b0f0ffbe0d095453724d2db19f606c85d00e49b0bb38
+
+Count = 195
+Adata = b3b2d249cd3517555fa692bbe9116f069e7405
+Payload = 961c15bd7dc34cd5409c9e8869988676ec6845ecb0ee85fd
+CT = 7fbc0c059a36a8eaadc9ff051b254be64188172b142730536db1e4112fcd650e8c0f0f6fbf2d07e1
+
+Count = 196
+Adata = f5b5bcc38efaff01f69bd3a106dcfca3cc6414
+Payload = 879568ab9ebdea768a5459ced1d3181d822536c3d1ba38c3
+CT = 6e35711379480e4967013843a36ed58d2fc5640475738d6d1cedb29e68322e47ff9997f859257d98
+
+Count = 197
+Adata = a2098e3e23826e01f31107a208202f710eff00
+Payload = 47cb57599686716c75d7ecef5541d20fb908e6d98c39925a
+CT = ae6b4ee17173955398828d6227fc1f9f14e8b41e28f027f41c12bf2a3571ed672592b27e986e9058
+
+Count = 198
+Adata = 20a3d53e77201599540344c4e746c3ae3a5f84
+Payload = 4a8667b5ee09d3d4a6dca9a95f4ad406f1da94b846dcc6b8
+CT = a3267e0d09fc37eb4b89c8242df719965c3ac67fe2157316f12b2be8f5966d96602111c28f87b104
+
+Count = 199
+Adata = 92c592ead4b3f193cc36687593d4f0f412a5d5
+Payload = 1dc9e32ac4176f64bd78a6edd651ebeea3ba85dfcd8298a8
+CT = f469fa9223e28b5b502dc760a4ec267e0e5ad718694b2d06776df0a0cf048892e65bd8ad77cb2255
+
+[Alen = 20]
+
+Key = 2ff64bbec197a63315c2f328dcb4837d0cdc21a5d6f89ff1d97cb51195330cd8
+Nonce = a235f8ee3de9896b71910ac02c
+
+Count = 200
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112
+Payload = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a
+CT = 1bf122798bd8ee8e73391d589bd046a294d1615794e69cb9e6f3ba30143acbc3a1c1c6ec74333107
+
+Count = 201
+Adata = 0248359f8071143c3cc1d61882a3547a0b3d2175
+Payload = 4a6a7151465c2abd7e7fa1fd13019ad098b6ebcd190e96f7
+CT = 1b8c01056a837081553cb646ef73115a3ddcd3a095074e6436cb510c13a039f4df8cc26a942f9911
+
+Count = 202
+Adata = cca77bc4cf6c0abd3393dac3fbe90fbc8a1154f7
+Payload = a94f5ede43929d48d2c5a58c3262d9127d2ac3cb2fbd5768
+CT = f8a92e8a6f4dc774f986b237ce105298d840fba6a3b48ffb7fe0dedc2899dff81a251cff16bf5897
+
+Count = 203
+Adata = 9c082a84646c070bb11b7d6b92b62f06ee5b5b71
+Payload = 7303bd41cf47289a3111366d08e8e21548baf293052029eb
+CT = 22e5cd15e39872a61a5221d6f49a699fedd0cafe8929f17886c43ac23800de60a1fd2caef0f03261
+
+Count = 204
+Adata = 1c3ede1982a807a410ae1e21947bf430f8db7027
+Payload = fa9743a67978c20316cb91801d7789e350079aae3aadbd43
+CT = ab7133f255a7983f3d88863be1050269f56da2c3b6a465d026f7907e235c09d3322c4092d2e88f88
+
+Count = 205
+Adata = deb05a30a026ff66ce71e98afa62f0255aef84f5
+Payload = 99599b4042dcdb685350cdecfdf24992fd5b165670025d0c
+CT = c8bfeb146e0381547813da570180c21858312e3bfc0b859f6bb44a28c145d49f49f2821d4044e4b6
+
+Count = 206
+Adata = 93dd9b00a3353e5331338dcfcb7ca7e0bb873a4e
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 14f771712219a85a79678ae220e5c0f9c4bf49c59c1507400f7d20aa3d792d6a3ebc5ee0df2fd89c
+
+Count = 207
+Adata = 0855263860043207543c8c34648d53ec51c4f47e
+Payload = b2db87b7787531968d603098cb20ca7c438b4af72623fea9
+CT = e33df7e354aa6baaa6232723375241f6e6e1729aaa2a263a7ca4733f0208668b0a7879305e861d71
+
+Count = 208
+Adata = ee2d3a66deb3ebca867a902bb9202226ed516ded
+Payload = ca18ce38086223e63b4f0b616d110010f9e45eac42f2ba46
+CT = 9bfebe6c24bd79da100c1cda91638b9a5c8e66c1cefb62d5d76b482ff20429da8f60f0f863e1af50
+
+Count = 209
+Adata = 8e531aaea849addab6a83497cbc504f489505952
+Payload = 5717ed5da5b8aa806a18bfe979502bab6632c9428d3a7725
+CT = 06f19d098967f0bc415ba8528522a021c358f12f0133afb6aab66e1ac2346ef97850a4985c64b737
+
+[Alen = 21]
+
+Key = 24e9f08a9a007f9976919e10dc432002e2e078a339677f00105c72ed35633a3f
+Nonce = 15977424eeec0ec7f647e6c798
+
+Count = 210
+Adata = 2d838eb51a4bc69a001a18adf2084a680f02a3c5fc
+Payload = d3416a81b4246eb0bf8119a72a886bbc0ac9449c69f71d2f
+CT = e001a8fae390dc5d672cdd18f86a1f728158ec83a002050def9af5679edbcbb7db20ab6af30698db
+
+Count = 211
+Adata = d83ee7ce22fd1a2882d8d552346e4d7b3efdd67da4
+Payload = 22b6f10b482448626f6c7bebb14f1497896d071738133b4d
+CT = 11f633701f90fa8fb7c1bf5463ad605902fcaf08f1e6236fd435a5a38f84387f63b13407f65ec86c
+
+Count = 212
+Adata = 2d5537b24d0b0f7a45703c1e131656ec9edc12cdf7
+Payload = d60edc830be8207ffd9e9f646d3b4343b10b3d56acb89d44
+CT = e54e1ef85c5c929225335bdbbfd9378d3a9a9549654d85662ede8a705f8c988f55459542bd631b1c
+
+Count = 213
+Adata = 1a750eb326923412d94ccb35f5acd0f87415268178
+Payload = 716d3132f449a9def383978102ae50ed3ccae0cb346ba1df
+CT = 422df349a3fd1b332b2e533ed04c2423b75b48d4fd9eb9fd986de774a612230ce6c71449d26732ce
+
+Count = 214
+Adata = b10fc523bc4562d44edfe5956f93c15c4ab38bba3c
+Payload = 063c2ae2a15f26f979bf90657d20643e3184f1a9f75a3aad
+CT = 357ce899f6eb9414a11254daafc210f0ba1559b63eaf228fe710431005264fa7d3fc04bac50fc1ec
+
+Count = 215
+Adata = fe4f60ce9634e7dbc5e56204c4bf8aa9be577027ec
+Payload = bdc513e56a5bb70c02abc041af04d6e45e735d10cc88357f
+CT = 8e85d19e3def05e1da0604fe7de6a22ad5e2f50f057d2d5d5c13bea6ad0cad724e6cd02c89517ffc
+
+Count = 216
+Adata = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e
+Payload = 7dc5d8cd90ce2faf76bbd0d52e5ae11b310fc2b0051c4377
+CT = 4e851ab6c77a9d42ae16146afcb895d5ba9e6aafcce95b55d2a5531655aae01e249f213e0e04af0d
+
+Count = 217
+Adata = 199ec321d1d24d5408076912d6bb2b6f192d6b347f
+Payload = 66c2696edec26ba3d07bd3f485a0d6ce8a1b0a85b20083e7
+CT = 5582ab158976d94e08d6174b5742a200018aa29a7bf59bc52a127ef341345f9641b26e91265e1482
+
+Count = 218
+Adata = 8b013f5782d5d1af8dbd451a4202866095dac975fc
+Payload = f4da8ac3e8fe5ec6a5b6a2f27b68396e850b46a024d441f0
+CT = c79a48b8bf4aec2b7d1b664da98a4da00e9aeebfed2159d2a005ca13c4bf715c3b7b2782f799b23a
+
+Count = 219
+Adata = e320df32b71cc530e8493b12b9afbeabc255c5eb44
+Payload = 244891cb4af66cc8e99a3784a2e82475e51bd5c7fde67cf5
+CT = 170853b01d42de253137f33b700a50bb6e8a7dd8341364d704642aff9cb9288d49f0e567dd837e05
+
+[Alen = 22]
+
+Key = 0ec1b22b8df05dc92135d2dfbefed8ea81458f5ea1b801e8a218faf6cbdf1a79
+Nonce = 97ebcb8575bb58260208d5c227
+
+Count = 220
+Adata = a2f6337f86dd00d1a58448851e95d8c9bace4a5c8710
+Payload = 2f59d94d4ab8eeb84c2a6fefb7fb0a3ac059c1e1a65ae34a
+CT = 7ca0b1dbe34b0391e524b868b0af08b3e096917664d6aa2cabc1f9d0132394149c9062b74b82f04b
+
+Count = 221
+Adata = abf26b05558252c8e38c52b1ace087bbd1eb3d561239
+Payload = c25381853f73a3dc4195fdcbc45dfa1a40eb8324749adb2e
+CT = 91aae91396804ef5e89b2a4cc309f8936024d3b3b61692486d7df57c6a792f6f6b24cb5f87e92123
+
+Count = 222
+Adata = a13ade56b47803897666e42ef2ef88be0e779ac86c28
+Payload = 8dc5226a2a13088c87f4bf94262e0c0413f06b35d2fda79b
+CT = de3c4afc83e0e5a52efa6813217a0e8d333f3ba21071eefd4ac19b0b74cd9d5e100598b96c9f1f2e
+
+Count = 223
+Adata = 3c5b68b65edf62755b7e064bd26c843816bf6c1cd481
+Payload = ee4b23039cd512cfab8c7a2d0f2c78d66764520bc88759e1
+CT = bdb24b953526ffe60282adaa08787a5f47ab029c0a0b1087a77a27eabfc79f192c0ac491280af8d0
+
+Count = 224
+Adata = 0213fe13c49083d7c00335e1864dc139c9e7123162d1
+Payload = 30b48d4021838090fbd5251069ff8c631452daee5ef899db
+CT = 634de5d688706db952dbf2976eab8eea349d8a799c74d0bd39935f91c1e29fc1e4c5c5427ca9da79
+
+Count = 225
+Adata = a32291746b151be8134e183798aa82bef210343feaf6
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = 717fc97b74739e53db427ec6262a9d8b12485bfbedac9bfaaeaec90ada2a1ffef64c3873af645a40
+
+Count = 226
+Adata = a30f2fd445820cdf800145540602c877da0e4c311272
+Payload = fe703ca0901e4a706ce1393c7d8ce18a03eb2caadbfa7b8e
+CT = ad89543639eda759c5efeebb7ad8e30323247c3d197632e87932952831d0ba25c77c18fe154d8ed8
+
+Count = 227
+Adata = ed438e393e0e37629cb25044ae89de9fd0d42d60c1a3
+Payload = 7043c67726870bb5816da925925bc2722478311c8a606cca
+CT = 23baaee18f74e69c28637ea2950fc0fb04b7618b48ec25ac234fd0241d00f3890a23ccd0bf16dcbf
+
+Count = 228
+Adata = 1013946815001a2c08acca4196e0d6668ffbb3883cf1
+Payload = 695e9712dbbf883e9bf8af9188bd01fc631968928258168d
+CT = 3aa7ff84724c651732f678168fe9037543d6380540d45febaf43498b0c3f70c119f82d5812db940f
+
+Count = 229
+Adata = 44cc9b2510680c4d73f1938c77de21242c8ee790ed7f
+Payload = 67ba90d22c6bb5f649bc0c505c5ed23a299882559a3bf520
+CT = 3443f844859858dfe0b2dbd75b0ad0b30957d2c258b7bc46db66dbb03a4c943ac089ed11eb214bbb
+
+[Alen = 23]
+
+Key = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Nonce = 451101250ec6f26652249d59dc
+
+Count = 230
+Adata = 7cc9c51b69f98a06391ab32742fb6365e15106c811fe8a
+Payload = 065ef9eeafbe077c1c7049f43eb0d8999708e8609f214d5c
+CT = 990065322a438e136860f7b019807e9feff52a642bf3d44a9163fa7a867f04cab6f52dc250070f31
+
+Count = 231
+Adata = 7bb1bc069a783d45d51d8ecd0a53ab7a386fa1f5ef12a1
+Payload = 69b2b056f2265e707d3e31e68bff6a060544c8a737b2a9b9
+CT = f6ec2c8a77dbd71f092e8fa2accfcc007db90aa3836030affd33dd9155619fb040dcd6038c7b7367
+
+Count = 232
+Adata = 0dd220919d0eeee3b7cec36c47e376b778583b38bf61c8
+Payload = b98d79aaa4c04171398c7f1189497acaa7546ef068bc7a3f
+CT = 26d3e576213dc81e4d9cc155ae79dcccdfa9acf4dc6ee3294fcba5a886b1f33cf1cf44618d28f01f
+
+Count = 233
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c112479
+Payload = eeaeb773ade5fb2d27b50bb892916333e0b123c6e3ae5bdb
+CT = 71f02baf2818724253a5b5fcb5a1c535984ce1c2577cc2cdeafe2c670eac203d5e90b9d520e7a618
+
+Count = 234
+Adata = 614b0ac4611b6c6d3b4ed089510dcd2215567bc3789f85
+Payload = f2198e1f91fde2672a1ef60403c0d175f366b6780ee9f1c2
+CT = 6d4712c314006b085e0e484024f077738b9b747cba3b68d4f0388746438e83b731b5588fef53f1f3
+
+Count = 235
+Adata = 866fea4483d4e903566844e31c24283571832dfae32c74
+Payload = ba37617342b4eefd4bdce8fad30c4751b206d47814973b3a
+CT = 2569fdafc74967923fcc56bef43ce157cafb167ca045a22cfca81f8b36d16698a600fd701f2c6424
+
+Count = 236
+Adata = 9d7546f7e8b949c539d21a357f81d0151e278d0bf2c5a5
+Payload = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f6
+CT = f6f3563424142a9d8a8edc1d384bea5d612e770ac247b8e04c15a6d292c7ed2f31cf9512435ec7d2
+
+Count = 237
+Adata = 42b692048c8b3cce1b5e83f4f33232a7d7d0bc20695e7e
+Payload = e0753d4248643642c7a96404de8d76c9d80527b659ec6d31
+CT = 7f2ba19ecd99bf2db3b9da40f9bdd0cfa0f8e5b2ed3ef427a2ad73179d0314b5fe52dd7217518cb8
+
+Count = 238
+Adata = f1dfb6fdb31cb423226f181c0988a52ee4015aef4536f4
+Payload = 79ba959c7221b293e2115f538d9394c64284c756563c04b0
+CT = e6e40940f7dc3bfc9601e117aaa332c03a790552e2ee9da69ccc5ba1caf933b80bfc6f281109688f
+
+Count = 239
+Adata = 8eafce9ba466fd53eb87f499d7c76bd486db0e90a3d281
+Payload = e1590206717a708cad9cca7d23a3b8ee5f7fb7786aa3be47
+CT = 7e079edaf487f9e3d98c743904931ee82782757cde71275173271ec36d92fff34609169f579c8f1d
+
+[Alen = 24]
+
+Key = ef4c1d2314e671f666cc6667660f1438a293208c7cc29b412d81277f0a635c91
+Nonce = 50b23b052922366c25dd40e348
+
+Count = 240
+Adata = cd0522ebe1fed82465277d1c10ae9316a98b4469be63b180
+Payload = c99c3e79125b6fd95e737326a842424eb6c6ecea4c0475c4
+CT = 76df4be4ec8373864399acda11294b220b9f7c3a7d2b3660b25764e40ac6a171e7e6bab4fdee4288
+
+Count = 241
+Adata = ce5bf070678cb07e963263b1562ff79311144addb6e4de4f
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 519d742d71422c63c2fe1661c32e7a45cf9f7f2290f4454ffca49758d17f2073066b82667eae6ce3
+
+Count = 242
+Adata = 07175be2475cc735c9a3c1140895277378debf8fb1c87c24
+Payload = 6d5579aaaf8737b01620424f3ddeaf538f10dfad094e5ec4
+CT = d2160c37515f2bef0bca9db384b5a63f32494f7d38611d607c1d64d7e9de47a6ad7878283da9d870
+
+Count = 243
+Adata = c821a8d4bab9d993c20dd206955304a55968e6db5ab6480d
+Payload = d0628b2027f06c246497977d05f211b2c2e302d5b82700b5
+CT = 6f21febdd928707b797d4881bc9918de7fba920589084311adc2bb471862d25cfe25e66fedb8e28c
+
+Count = 244
+Adata = 68439bc9d176feeeb4119d00ed5449dfefb72b5a582bfd97
+Payload = 6cc9749f48c61050e421afa3a10ad3dd3aa02cc3f8586915
+CT = d38a0102b61e0c0ff9cb705f1861dab187f9bc13c9772ab1319a493abc947945f1312395ea98d937
+
+Count = 245
+Adata = adb262c924942e4e1964e9d97c6a8c159fbf9bfedc5ff296
+Payload = 92d50736466e64e6225962e76bd90da824f716a3301a1a90
+CT = 2d9672abb8b678b93fb3bd1bd2b204c499ae86730135593421d0602d29447ba6b24a67509eaee1e8
+
+Count = 246
+Adata = fc7b08707d3c3dac7689ec18088ee6502ef08d3ffbff38ed
+Payload = 87c7ac031fd63e4c83280dce6b68a92dfafb6ea19388fa9f
+CT = 3884d99ee10e22139ec2d232d203a04147a2fe71a2a7b93be52a2eeacb1f023e849161b6306b6cfa
+
+Count = 247
+Adata = fd43dfb66041b117f2ac54c94f7b6e2677860864d9494175
+Payload = 6b53c46266b2f4284d8fe7f0549c98977344d67e178e9a8e
+CT = d410b1ff986ae8775065380cedf791fbce1d46ae26a1d92a0d8c5b1e96b21460e0b5414639abeb0b
+
+Count = 248
+Adata = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Payload = 8e7d8a44244daa7df2b340993e32dac50e05d7b2e103be98
+CT = 313effd9da95b622ef599f658759d3a9b35c4762d02cfd3c1c97260d20797d374c595cbc2ff080bc
+
+Count = 249
+Adata = 9895b24d12b004b215583eac70a95f4fba7442164f35c57b
+Payload = cec07df916ffb7a453d0eb588b7462096f22874bd5abf814
+CT = 71830864e827abfb4e3a34a4321f6b65d27b179be484bbb06cd287afcbdbc5531f11246080b22677
+
+[Alen = 25]
+
+Key = 8544808e8fbf8c3a5e1d4ca751d4b603af9fe119eabc6923205815e0e748b7e7
+Nonce = b44a58724596b4d8dea827c1a0
+
+Count = 250
+Adata = f5b2c88f5232c37273b1e66aa31cfa7201e33c21d60054d025
+Payload = 617d54fc6a23601c79e3984f93bfc2d151fde420863206b3
+CT = 57b3414db48982c6567265e1e0173bf38fdfaffe4461fbebc1411af83237c0f9eb0bfe8ed914da66
+
+Count = 251
+Adata = 8fabe14dcb3aa2fd28281147c326e98ad699ca7997f03a105d
+Payload = 337290d0b4ce1e87afc3cf01d6c98f8c17a4603120dcfcd1
+CT = 05bc85616a64fc5d805232afa56176aec9862befe28f01897ed6e23720b60ffe54bbb9f7ff371008
+
+Count = 252
+Adata = cf193eb3d755cb8e06c5be2334b5c8b7a22b6524d46d547ba3
+Payload = 01ef7ac6470aa02ccd8c1712827e52699d05751b78e4c5a6
+CT = 37216f7799a042f6e21deabcf1d6ab4b43273ec5bab738feb6aa6b284e7720acbd027a50317f816a
+
+Count = 253
+Adata = b4cadb5f9cb66415c3a3b71421b926f147566a174160a0bcc0
+Payload = 64fb9322210fb7d8da8e762498b233b0eb172c91231c50cb
+CT = 52358693ffa55502f51f8b8aeb1aca923535674fe14fad937058e9c0164ca079668097fde19e5302
+
+Count = 254
+Adata = 48400d76ff882d6d5129c8674acc71f445356c9db9c91f8256
+Payload = 291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4
+CT = 1fd4b1d21a105eac9b37075c91d66d2386495116fc18fbfcf988611d5ce0f65b217bb4787bf59bbc
+
+Count = 255
+Adata = 749d369d837002ad33feb8aa22c3f68705eb4872e1b8f85a7f
+Payload = 141cdd7f964a78815be144a785c6a2a298c54230e73039e2
+CT = 22d2c8ce48e09a5b7470b909f66e5b8046e709ee2563c4bad6251a5fd375a48583a6d0f8eb75cbb4
+
+Count = 256
+Adata = 80214108b16d030feff6e056c9a07a00a1d5e3ebb07abd3f4a
+Payload = fa2441cb7f9d072b8a3f1a496b2be6728a38b94a4f44c9be
+CT = ccea547aa137e5f1a5aee7e718831f50541af2948d1734e6af1dab0f105414293cb130bea285fd6a
+
+Count = 257
+Adata = 8b9fabe29718a8f297c9bf6f199c80bbc71f94eb3034a11ecb
+Payload = c8ce88ab40b62229223d46cc44f21bb39cfef27aa9fdccad
+CT = fe009d1a9e1cc0f30dacbb62375ae29142dcb9a46bae31f51cc3f7640a42460be877fb7059a3ed61
+
+Count = 258
+Adata = 8812f28a0cd5fdaa226fdd44ed857241007377057be3bea577
+Payload = cf59f75ca4d6d216cf8862b44b5192c382c140f862def117
+CT = f997e2ed7a7c30cce0199f1a38f96be15ce30b26a08d0c4fbbe0ddd2e7f4aa2024b3fec9281b6cac
+
+Count = 259
+Adata = c8f05e96d703a4850bae1421ae9ff3aec7531baf9b899dfd75
+Payload = 4eed58f381e500902ba5c56864f6249d191e14d1b1fad3dd
+CT = 78234d425f4fe24a043438c6175eddbfc73c5f0f73a92e85e5df1e5e96bb84f730fcb253d468278f
+
+[Alen = 26]
+
+Key = e19eaddd9f1574447e7e6525f7fd67e3b42807e44fbb60e75d8c3e98abc18361
+Nonce = a8c459ce0223358826fb1ec0f0
+
+Count = 260
+Adata = ef88f4393d6c1e7b7be55a12144209ee051bb779e440432721ef
+Payload = b3b0de10b7c0996662f1b064e04e528b7d85ca1166985d33
+CT = d63e6082c95c6c5ff2bc0771321a4f883ef61cff7b99e0ea8a20a1abe7c842ebc08c8c81a2743c81
+
+Count = 261
+Adata = a4c891c9dd1fcc982c35bc74cfe71651bae424602519672b466d
+Payload = 4f0b40913f07269550b7b06ab9027a4d9331f8ef98a45dca
+CT = 2a85fe03419bd3acc0fa077f6b56674ed0422e0185a5e013845e2d6de83ab729dd200a21088a1ec3
+
+Count = 262
+Adata = 4db5730cb9794f3b1facc9d6738115d02ba9f27ba02330fbb856
+Payload = 841e032773d58bc72a3237bc9b24c61b9efdd850fc2ea605
+CT = e190bdb50d497efeba7f80a94970db18dd8e0ebee12f1bdc10ed272c732247a696a608ef67510f9c
+
+Count = 263
+Adata = 471a900ee49f2cfa1d3eb37c951d810c349364d4cc3b5b64fc47
+Payload = b4db42e523e65557157b93dc0281601f7997e6731543a914
+CT = d155fc775d7aa06e853624c9d0d57d1c3ae4309d084214cd15f0df52e392c37ec15f7458469dae84
+
+Count = 264
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5
+Payload = 73e0ed35c0e847188e607cde46586eb9e237fbdc5d59163c
+CT = 166e53a7be74b2211e2dcbcb940c73baa1442d324058abe5421433dafea2b5484ba87b5050e1fb49
+
+Count = 265
+Adata = d563f5c048a1b45265182b99ca7b9004fdc73a9cb07806dd44fc
+Payload = 4f7669caaedee961dbba6bde9d09fee1a20eee55baaf98f5
+CT = 2af8d758d0421c584bf7dccb4f5de3e2e17d38bba7ae252cdf91749fe3cd52a9431d9a847a8c2a9a
+
+Count = 266
+Adata = d301a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a
+Payload = 154454fb74e9565c56775a8e4654f75a38b954dd28c4e939
+CT = 70caea690a75a365c63aed9b9400ea597bca823335c554e07563d37846f5185bb44d71be1ea6a73c
+
+Count = 267
+Adata = f74b48d168f77fbd3429728c0b168ecbd854264eaef70b74fffb
+Payload = 716b371857e68a17b20ea06651cdcfd4560a741830ca8a13
+CT = 14e5898a297a7f2e224317738399d2d71579a2f62dcb37ca55e93bc2d3f05d7016747690fb920e12
+
+Count = 268
+Adata = 3a257ce3592a8f88162f0bb4ecd5db3bb79b54ab17b0bbc61506
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb39303b4135269
+CT = aa55cdf1e6c6552366b55f36afebaa845dc045eda912efb01c46822f839f09c41b7aa6dc06035c93
+
+Count = 269
+Adata = 21916ebeca9e66b77cf55d1cac80a4c85d8b6b014f268ffa73ca
+Payload = b4b67ac551d1966caa20d951351387f384c2e5d81a76a92c
+CT = d138c4572f4d63553a6d6e44e7479af0c7b13336077714f54f8e77600c5bbc6d028fa25ba61a1719
+
+[Alen = 27]
+
+Key = 9498f02e50487cfbda1ce6459e241233bd4c4cb10281dcb51915dbc7fb6545c0
+Nonce = e3bd4bc3a60cddd26c20aa8636
+
+Count = 270
+Adata = 70cfcb828d483216b46c3cd22e2f9ee879e9e3059b566179b6e16c
+Payload = 0d16cc69caa9f19b88b05e151b3d26accd018ca4a5786a80
+CT = f1c4bedb8d6f91676881daa37656a7e6402f472735b04a0f1f8332f4236437737438e7aa1b5100c7
+
+Count = 271
+Adata = e7e5779282db80f424dc050b2c1e7754b2a5d3a8beae77beb74e34
+Payload = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c
+CT = e85f94f2b407756d46c94172eb5944b1f4fd7c625e3135138be2f6f356c2eb401468be15104e7763
+
+Count = 272
+Adata = d17e8189a94a559b07be9549f73d653172740e8e978f5b0a38ad43
+Payload = 00a23b25bca7c206edd051814d81083db1cd00048ce8ead5
+CT = fc704997fb61a2fa0de1d53720ea89773ce3cb871c20ca5a9646f2b6c2455603f1a6f20ea5a4611a
+
+Count = 273
+Adata = fda37ff136895de7ebeaf81e701e5751245201baed2e13d7e1b591
+Payload = a89409b0977f60a029dc4c1560ba6dbe7c65b068633acf74
+CT = 54467b02d0b9005cc9edc8a30dd1ecf4f14b7bebf3f2effb303fa5d8321241b1c9e18a5909d6e428
+
+Count = 274
+Adata = 9c179fd0d6277a5e073e77dd6abb4cba00ad9c9932e6c002b951c7
+Payload = e16c69861efc206e85aab1255e69d6d33c52cf058dec9d0b
+CT = 1dbe1b34593a4092659b359333025799b17c04861d24bd849e8cb01db1da077502814db1610662ce
+
+Count = 275
+Adata = cf5703228e615428d3d3805e428e754961d205c5aa0297ecdea71d
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 9ed11e0c94a00d79827cb97fac9fb60fc6b47e43ac28fe1d40a02a49857d7b280330b8105efac854
+
+Count = 276
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb796
+Payload = 790ac86c5e9d8ce8cbec1dfb7e4fc4dca3d0b1039adfe585
+CT = 85d8bade195bec142bdd994d132445962efe7a800a17c50a5ecfa9dd03e2db70aa212ee7dcb573fd
+
+Count = 277
+Adata = 96f0b7cd7439721d4c9cc4f69585f8c90a95bed8fea22150efffba
+Payload = 3cfacd61ea3398de20ca6bdb00e81af482320614bdfb8642
+CT = c028bfd3adf5f822c0fbef6d6d839bbe0f1ccd972d33a6cde17a7a0cd162945a3616892e101e3e93
+
+Count = 278
+Adata = ee71e53d0b4eef82575c2bd38d7bd21b41fabe58c6f571954fe159
+Payload = d75c153e34ae1c6d1fcf5b1052190d8882041e1f9c5490e2
+CT = 2b8e678c73687c91fffedfa63f728cc20f2ad59c0c9cb06d15fadc2d79841d230cd55c04379f22b4
+
+Count = 279
+Adata = 18a4aa894861c7720ddb43809c3d2ed2af2f1bfe8f9fd4f872c14c
+Payload = 0e728056c7c64214be8f1f1727408d8cca8c42e2ac7bf67e
+CT = f2a0f2e4800022e85ebe9ba14a2b0cc647a289613cb3d6f1b229b9bae4634eea6b723f432e19ae55
+
+[Alen = 28]
+
+Key = 3ac7d5bc4698c021e49a685cd71057e09821633957d1d59c3c30cbc3f2d1dbf8
+Nonce = 54c8ff5459702aac058bb3be04
+
+Count = 280
+Adata = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c049dd1ec
+Payload = 89198d3acc39b950f0d411119c478c60b2422ffe7e26e00b
+CT = 7717b8e4447afcea1eeebf3e39ffdab2f52828e7931ef27e475acd27900478f09fec1f479ab3a7c8
+
+Count = 281
+Adata = 9a04820205234795ecd540b6a0b2fbd0b19f18106c42f374a2b98425
+Payload = c0f61950f98110db4226e269cf197c7e2794c5b87ad68cf9
+CT = 3ef82c8e71c25561ac1c4c466aa12aac60fec2a197ee9e8cf7b7ed6e8ede6ef5a73b484bf13b3424
+
+Count = 282
+Adata = 0e4dbd167da0240298f4795102ef18ff9a8772c6fd73b3374cdfa30a
+Payload = 7960dbc9136880e2eea7956c3271adfe2aba7dca53da917d
+CT = 876eee179b2bc558009d3b4397c9fb2c6dd07ad3bee28308e47d08ea0788f7ca0ecd846689c8027a
+
+Count = 283
+Adata = 2de4291068a5d290b599a73c6a8ecff4f9fd6c9cc48f14c233e18581
+Payload = 0c5d7055bbfbd2bc213cfbbafa763b71b1fde6f4de96fa59
+CT = f253458b33b89706cf0655955fce6da3f697e1ed33aee82cd081f66b1c7b70718dc50367c3da6792
+
+Count = 284
+Adata = dedeb714f555575fcedbd9de8171484090e6466dd4fba3c6b7c42eae
+Payload = b5654edcc8f09e4f80d0258c9376d7c53fb68f78d333b18b
+CT = 4b6b7b0240b3dbf56eea8ba336ce811778dc88613e0ba3fece672883438da186741e6c542b3f805d
+
+Count = 285
+Adata = 03d340904ace1cd52d4b72a96d96afd77aee68ac3936415005ed0d56
+Payload = d796f3409a7eeb896c3d4ebef46e9c6e553aab28b1cc4a90
+CT = 2998c69e123dae338207e09151d6cabc1250ac315cf458e5cf58d4a5552bc8ed1b1dda46703a256e
+
+Count = 286
+Adata = c67f9aa8cf1be3b4377c30c175d33ab2af390982c6a015d99209acdd
+Payload = e4dd279a79a381c68de777df941a4779e50a1381c8aa9122
+CT = 1ad31244f1e0c47c63ddd9f031a211aba260149825928357f95cf2b57e06de4d01bbb6c0e39f37e1
+
+Count = 287
+Adata = fef1b2ccd661b9fac85ba005addebdf8317ab104920549d3a490a21a
+Payload = bbf0c267d952aeb6f810601b9cf1962a92dcaba7273e6902
+CT = 45fef7b95111eb0c162ace343949c0f8d5b6acbeca067b777589cd12984286af98908db88920323c
+
+Count = 288
+Adata = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b6349c2fc20f
+Payload = e8b13a263e0c4fb5645e500e88ab8074ab7d92e5a8dac6aa
+CT = 16bf0ff8b64f0a0f8a64fe212d13d6a6ec1795fc45e2d4dfee8fc441da990dd92c0caeac9d956699
+
+Count = 289
+Adata = 85e5df4ddec99f0bea14b3338b2eb190ab6584f5253c6c2ee3064637
+Payload = 067de2869333ed22c7b63ed7eeba1301bbac69b0d430adb5
+CT = f873d7581b70a898298c90f84b0245d3fcc66ea93908bfc0d502f5434bea8c3c13ad5422ff90e218
+
+[Alen = 29]
+
+Key = 948882c3667caa81c9b900996e3d591e6fcb3d08333eeb29911e9c6338710c17
+Nonce = 43b0aca2f0a9030f90559fa6d3
+
+Count = 290
+Adata = a516ca8405e5c8854e667921b5c5e1968bdd052915b55ac9984b7eefb3
+Payload = 8b9130b0c3c15366831bbb19f377e3209a8dbf7619cd09bd
+CT = 4646b2acdeb11174171da23999cd54e297daa32bbc13d30512e57c576b315f48c11877178389aaa0
+
+Count = 291
+Adata = db3121ea71294983b185207a9d8de3e484a66c0431bf07c962eb82977c
+Payload = 7f369bbc99b6f08049eeb43566269a174829d4dddb05cb9b
+CT = b2e119a084c6b292dde8ad150c9c2dd5457ec8807edb112366775e693f93af6575dccc7903538065
+
+Count = 292
+Adata = 1651cf38fd9b2da65ebb4922b97dcb861128eeefa060d6c1c94b25eb4e
+Payload = fd0900b5fa72e2fba43d611bad25de40a3507a5cc5d186c7
+CT = 30de82a9e702a0e9303b783bc79f6982ae076601600f5c7fb70d8de40c2068de96a274d3b5086b5a
+
+Count = 293
+Adata = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12cb3047625e
+Payload = 36318d80c02a1da41ef1652d9a752e155526b5f597fba226
+CT = fbe60f9cdd5a5fb68af77c0df0cf99d75871a9a83225789ee7da096d2fb28f20f64a000fe93e96e2
+
+Count = 294
+Adata = 0680d5bacefa2ab14aa12b0e517a1432862d4215dc72dc4d5ac6b96c1c
+Payload = 7a29aa2994d11215ab3ef3382b3db6ed581164a235c4b1d1
+CT = b7fe283589a150073f38ea184187012f554678ff901a6b69b88748a2de31261534cdb2237565bf8a
+
+Count = 295
+Adata = 9af701f0a9de52309267289bd170fb97c03c131c0a169d736137ff3d74
+Payload = 3542fbe0f59a6d5f3abf619b7d58b199f7caff0205093f8b
+CT = f89579fce8ea2f4daeb978bb17e2065bfa9de35fa0d7e5330c003eb65ceedc98ae4e38ef341ee47d
+
+Count = 296
+Adata = dab7845fb7ead205569475753c7e26540c09d3a74312f2de25181511f8
+Payload = 83c15520d9541c86b3dd809ede42de22bbb2b75ff18a023b
+CT = 4e16d73cc4245e9427db99beb4f869e0b6e5ab025454d8835c2fb596d8ff6a863604cd224fa3be42
+
+Count = 297
+Adata = a844d6dbd05545ecc736994dc9fc2260c5ab63ed6ffdc40b915f8744a1
+Payload = 793a188fa3efa32f41d6e4c5b42353b95024117d546c79ca
+CT = b4ed9a93be9fe13dd5d0fde5de99e47b5d730d20f1b2a3722ac782e2cd8ecb06172eef2cb9b0e331
+
+Count = 298
+Adata = f9112503884615c0e8a1d8414724b0d19298988f393a27c436b2b6734c
+Payload = 6b237444fb0e1f4150701546c4cb24021c5edad30d9b31dd
+CT = a6f4f658e67e5d53c4760c66ae7193c01109c68ea845eb65f814492b42571033f4dffc0282ea2f51
+
+Count = 299
+Adata = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c2c94d3a5b4
+Payload = 6342312e8a72f71f2e5afe04cfcde4d60a41556111752103
+CT = ae95b3329702b50dba5ce724a57753140716493cb4abfbbb75999099df2de6e436bd99f0341423f4
+
+[Alen = 30]
+
+Key = 3bf52cc5ee86b9a0190f390a5c0366a560b557000dbe5115fd9ee11630a62769
+Nonce = f9fbd02f28ecc929d369182752
+
+Count = 300
+Adata = ebf0b3e3199a5c3773c761c725c7600add5f9d8321c9f8e5e5fd1c7a5d2f
+Payload = 094b538110495e938b08cf748a6bcf3e0c80ff9c66570237
+CT = 4d8b53016fc8bc9677184c0fa15bbd3d671b9366d82ecb67f8562eadcdcbcdbad1299bea1523f5d2
+
+Count = 301
+Adata = a865b88d512e485ab3f2844c29e6dde0cf1151efa9ad3b3021d06fffb74b
+Payload = 23edddd8732cdbf03af08162f0e4a24c9222bdbb4549c663
+CT = 672ddd580cad39f5c6e00219dbd4d04ff9b9d141fb300f3359ff77cf0962455b3539dbf91f3077cc
+
+Count = 302
+Adata = 16918dbc785d94a8f1720c5ad234dde860219874c9fb076a5c290903f85b
+Payload = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0
+CT = 535828ec4840b24a3cc7c35daac685047a743c977247e0806dbed76d94c90595b49d50c84c3efc76
+
+Count = 303
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918
+Payload = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32
+CT = 49c2770fef2086a105bd2aa754e23ce8ff8b0598aa61266248fbe60c146056e5cb01268403e4b9f5
+
+Count = 304
+Adata = 2de5222a0609f058f60e9e581b6e4f0ddebed84fc8302c8e985d17b89241
+Payload = b0c3858231e284af6d231f043b95772f5e7b16a34ffcd2ec
+CT = f40385024e6366aa91339c7f10a5052c35e07a59f1851bbcacff35df1ec942b43eef5aef980cb038
+
+Count = 305
+Adata = 3fc7453df038a92829dc103d44b63ad097d7cd7f9ae7996547012090c7c4
+Payload = 319f396cc02834f8e69d65f77496d0eb31ce1a7b7e324820
+CT = 755f39ecbfa9d6fd1a8de68c5fa6a2e85a557681c04b817091a93f5fc28e5f4f351cfb888da763dc
+
+Count = 306
+Adata = 18f1e92bd3c4a597ed970911d03a78ff9a6790147c9bb0ca5f23b70cce7a
+Payload = 25550c03f8fa02b3781330f96e0fdc58681b0c0bc5e83fe9
+CT = 61950c83877be0b68403b382453fae5b038060f17b91f6b92c6a90ef2e9a969ec0576fae1d126a85
+
+Count = 307
+Adata = 09ecb2406054716418ff3600c3c5cacb0845a377a2d80542abc36ec81bb1
+Payload = 210ff7975e08388b9a46eb732230e3a3856a497549b5eb49
+CT = 65cff7172189da8e66566808090091a0eef1258ff7cc221959fd6aeb047200907911621e8756b45f
+
+Count = 308
+Adata = 62d515bb0525b565a6a3613ae20343c8da7424c8368e8cad6a862b7d37a5
+Payload = 5d867265965bb2aafebb0691de9e157a24066d06fe3cbd7c
+CT = 194672e5e9da50af02ab85eaf5ae67794f9d01fc4045742cc4db6d5fd910c83fd77aefba3f7665d8
+
+Count = 309
+Adata = 00617ca141e55b045a188e4934caf6db63d4577f634db92c22010e1cbf1e
+Payload = 396b27afd16a1081f37bbc1f742b549f5f68df799b93083f
+CT = 7dab272faeebf2840f6b3f645f1b269c34f3b38325eac16fdf5f21f32cbe5d272004f1c104cbcae9
+
+[Alen = 31]
+
+Key = e45bb1730d0d539aab3805350ac986540de9f0f6c239ee70395c291397b70309
+Nonce = d5c7824af715bb7822b6b340fe
+
+Count = 310
+Adata = 860f4a09ad8b3d345c2aa18ffb803f0bc3b734a4d047a1437701a5e3d95288
+Payload = bc8b3bc48c7a88c9fafde258b6ccaa9d4f0d018703d63871
+CT = 95f083ad6bbaee6ab540fe023858f8baf25e333fd3e89c00e678a392d228b210dc5c991905dacf3f
+
+Count = 311
+Adata = 8a84b57915bdbe7bf5a1c1a426512b3c178d883251cc46c95a8bbc8ed9e56b
+Payload = 9499ea48edab9bc21b91dd614f04934ca20db8630622f481
+CT = bde252210a6bfd61542cc13bc190c16b1f5e8adbd61c50f010fbdd3b305522dae6b652322d89d9ac
+
+Count = 312
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3fbd1219a21aaa84044c4f23c08f5d
+Payload = 73843a4e9e7937fed24bb1fae15822213b1aa86c07f1b5d1
+CT = 5aff822779b9515d9df6ada06fcc700686499ad4d7cf11a08b6b08548e794eaf85ad9f5de80b1c00
+
+Count = 313
+Adata = 61bb196b212feab645f05a8aa1986f6210a384c15bc749245d840b3565fb36
+Payload = a8e24266e5981b2ed14213a29f961cbbf7f02f63a33c987e
+CT = 8199fa0f02587d8d9eff0ff811024e9c4aa31ddb73023c0fcc73643a7ee9291e15137d7046a92f3f
+
+Count = 314
+Adata = a49c2df94ba65107f375ce1c53b72406143f6bcd270945de5b7811682fe361
+Payload = 3e3c402caeca41687d12897102e04312edf7b8c7d8567a22
+CT = 1747f845490a27cb32af952b8c74113550a48a7f0868de53204438662ea82f423a69c6e4e3c0623a
+
+Count = 315
+Adata = 7c48480e9bc87ba299e03899698b2259eef150ee0f2efff40a5583b80ab484
+Payload = cfa9292b9052ac6bb863205d3c0dc2d9e20d2ba6a680d2ed
+CT = e6d291427792cac8f7de3c07b29990fe5f5e191e76be769c6ea00b9cd881e3f4b1e838dfa31f6560
+
+Count = 316
+Adata = 5cf9744090366d828b477dc890eab8ebebd44f6aeaa5b101291bf67d12867e
+Payload = e0fe4e139ab0deb4fdf2145b719f35c50b869e6cb20608b5
+CT = c985f67a7d70b817b24f0801ff0b67e2b6d5acd46238acc4c59b3b87d722a58cd1de58f3963d12b3
+
+Count = 317
+Adata = 761d74be5fae170a1bdfa16081b44c1e49972e15ce0818df1390bf7204f619
+Payload = 665fdcdf55a1231e9912562eaa5a5011d69f6948e29e3f8f
+CT = 4f2464b6b26145bdd6af4a7424ce02366bcc5bf032a09bfe158759886124f1f0ce8147c94f4e7114
+
+Count = 318
+Adata = 9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cb
+Payload = 7b2d52a5186d912cf6b83ace7740ceda3f5f443530c5a49f
+CT = 5256eaccffadf78fb9052694f9d49cfd820c768de0fb00ee6310a79c9932456dbc00515b264f3168
+
+Count = 319
+Adata = 69dd1a050c8d79dafbbe3403af4dc1f070b9b2b980888aa796e6cff68d9060
+Payload = 3cea5ff50167c5641066852fd00061df35b1f66bedb894b7
+CT = 1591e79ce6a7a3c75fdb99755e9433f888e2c4d33d8630c6da7e97f9984a7db3b93aefb4316d9acb
+
+[Alen = 32]
+
+Key = 2e6e34070caf1b8820ed39edfa83459abe1c15a1827f1c39f7ac316c4c27910f
+Nonce = c49ccef869bb86d21932cb443b
+
+Count = 320
+Adata = d37e35d7cdccd9824a1ae4c787819735e4af798a3beb49d4705336d6496853ad
+Payload = 771a7baa9cf83aa253349f6475d5e74dba4525307b022ba7
+CT = eebac2475004970071dfa2cfb855c4e78b1add8dcbccfc0bd6b14027324b657a56263df148665393
+
+Count = 321
+Adata = ab22bc22bf2628b0e0ab245c3db2fc5128d13a011c2cc9b9fea05a79a3410704
+Payload = dad95a4b4d3754613f0542caa62cfe4e375dfbdd369ec32e
+CT = 4379e3a681cbf9c31dee7f616bacdde40602036086501482a8c810b6944815fd2e434193520b1d5b
+
+Count = 322
+Adata = c48c5aacf701137fc40fd0d3649641aaa5be427ceee702cf7ddf6408f458a581
+Payload = 3f28df9263e473be648fabad163aa4142b633388b16d8392
+CT = a688667faf18de1c46649606dbba87be1a3ccb3501a3543e8aa447b79284c588bef50b423de97908
+
+Count = 323
+Adata = 477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2
+Payload = f83107b50a1f192ed45cc43fa80e6b519bfd859173ea9ee9
+CT = 6191be58c6e3b48cf6b7f994658e48fbaaa27d2cc3244945d4f4a413eb3ac2c474134995d4db9a16
+
+Count = 324
+Adata = 143bc037f1d0bd4ec16825c58cb3796bf8989200d27bda9beabbbc49247f59f7
+Payload = dfeb324ba459ec4a5c54d2534e98002412e67db19cfc66bb
+CT = 464b8ba668a541e87ebfeff88318238e23b9850c2c32b11756a3fb2e06734b28fbd57942a609d914
+
+Count = 325
+Adata = ffc416f1dae4e43c1a01339a604c44d6a0f25ab9ca3978c6aacb6d270d510ee6
+Payload = 0765949e6f22c422ebd47dc1ed73f1b849d7a058a1656fc2
+CT = 9ec52d73a3de6980c93f406a20f3d212788858e511abb86edb94280d3c4a1cd8cb00705f60ae36f2
+
+Count = 326
+Adata = 6090b596b4082ec6926576137f6561cf13916860ad1cfc43650d1b5142a12041
+Payload = 6db320cbe76bc5b8cee9ef89aca11765571c6c501993195a
+CT = f41399262b97681aec02d222612134cf664394eda95dcef612caca26cc3bbb289da3be0616b3445f
+
+Count = 327
+Adata = 178ba75adb7c5bea6769270bb3b4f6ce208d4a786913d3ced7bb4090b5f65544
+Payload = 0875020959ed969cfb38636d1d5aabce9658b00171a7614e
+CT = 91d5bbe495113b3ed9d35ec6d0da8864a70748bcc169b6e26cc8c665289d907628eb0e299c2d411e
+
+Count = 328
+Adata = 90f0474dca998916075b1b1428df14d90be05491bb8d5d88e32e65ec890ba9d3
+Payload = 4f89ca6ad371f86a6e073ec12fb1b928bb10d6639233b918
+CT = d62973871f8d55c84cec036ae2319a828a4f2ede22fd6eb4f7e481607a2a0529f9cda1d5903325b7
+
+Count = 329
+Adata = 5ad8dd40ecdce52d5b30424ca0bccb666f34f66b0c9a4c1260051ac04ca06aab
+Payload = fe2009d0a4a1711b83057b948cd0b174a3a042fd97579ab8
+CT = 6780b03d685ddcb9a1ee463f415092de92ffba4027994d140a1b9ba2bfe5bf778b859f0ff0c29a67
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp
new file mode 100644
index 0000000000..b796541cf5
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = c0425ed20cd28fda67a2bcc0ab342a49
+
+Count = 0
+Nonce = 37667f334dce90
+Adata = 0b3e8d9785c74c8f41ea257d4d87495ffbbb335542b12e0d62bb177ec7a164d9
+Payload = 4f065a23eeca6b18d118e1de4d7e5ca1a7c0e556d786d407
+CT = 768fccdf4898bca099e33c3d40565497dec22dd6e33dcf4384d71be8565c21a455db45816da8158c
+
+Count = 1
+Nonce = f7a5098b2a4d92
+Adata = bc498326755503ff25d02805eb3517221b54eb4fd79af0fcdf9312b2a9ad95f7
+Payload = 3e2144e2a381b718962a77e167778bf579957a8fae29612c
+CT = 98ce91033fabaa8fe853d347be6cbe5de102fdccf042e7be697b41c9a69acaf8386140ee6e36f406
+
+Count = 2
+Nonce = 732d2dd64b4a25
+Adata = 495b03df82e317e4f351c5323d17c673f4c77856983179d7c7cb75c2b0573c72
+Payload = 4bb0d170bdcc70fd18f19605cf9c6181082c4367f1e6fbce
+CT = 9bd9304259962448fa8487bc15d950303621213afd88f1e32d442ff663242fa269c4a742a220edc5
+
+Count = 3
+Nonce = fefd3ac595428f
+Adata = 91ffb6be8e129cef9189f7e0fec8e937afcfc6083b6a79a778a724bb3e8d0794
+Payload = 9e8c4f1292e8d7e5179b34ae5d2ba2491d7754acc54bb91d
+CT = a5d012b3062cc93b831860d76539169c88854b85550c67fc564a2f1cb7d77e0223287740d5ff9003
+
+Count = 4
+Nonce = e14d81ee3b873a
+Adata = ecdc5249ceb48e8d5a4483043921c00c1acb1843fae00155a28f3a127150b1c4
+Payload = f99e23288e6b5ae85c14610994d90d5fcbcab62b4ed1333e
+CT = cc4ee711d0202deb58664e00cf0cf70b737f48ddadcefd6cd217fb611daeb66fa2d8e1bd43cb2131
+
+Count = 5
+Nonce = 2cbeaba94dbbd1
+Adata = d129674c6c91c1c89f4408139afe187026b8114893d0f172f16469b183fee97e
+Payload = 1b42cb685bd462fbd40e0273a81c767aa81cb43f17d3c0c9
+CT = 1a1b1c7130aa63098dea17ffbb2216d1d276cb10145b0762a45116736e95d823e579d73dc31dc487
+
+Count = 6
+Nonce = 8a961df9c23f6d
+Adata = 07185502bf6d275c84e3ac4f5f77c3d4b30d8e106603be84410c11849a3c18ea
+Payload = 434e182d04ecda519a6119fbaa4c45e8c9803a9a3eb51dae
+CT = 3f603939c6226d8208b2b0e675b82557609ceaeeee4032c7837ed517dbd7e6fe34ea42b01c69d370
+
+Count = 7
+Nonce = d3604d390faab3
+Adata = c95e7329d36145664da69d25f24b301d334e1bca2baa74b2d5c325ed7d04fae4
+Payload = ee104be898a225eb1da99163bbf768d8ae6d5850af6f8767
+CT = 3e6a7683d9d804f791f77d2b69996102ba82477ec4557747ef2e0b322f51abb366a1e8e37f4fe4ee
+
+Count = 8
+Nonce = db5004a1cdae8e
+Adata = 1370fc9d5bf1ad2d071be5a28b235402a85270f536b5601c221519a3b329c71a
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 6db54d6f5c3f3efa6da67aea1234d46e8b679a5c257c66d82e4ef944778281ed186b4a8099b47fff
+
+Count = 9
+Nonce = 783477f981ef05
+Adata = 04bbf2a826bdf3d55069b1936c4f8e8e08189f54066a035c950c7347604b1b65
+Payload = 6150f132b25727ebbaed9f16bd91ebce00c68e5b39bc0ef9
+CT = 36f78cef22cacaf9f3d4464821737f7fbacd79be517b4727bc5c098625c51ac7fdd15da2cc9ef4b6
+
+[Nlen = 8]
+
+Key = 0b6256bd328a4cda2510d527c0f73ed4
+
+Count = 10
+Nonce = 21fd9011d6d9484a
+Adata = 66ff35c4f86ad7755b149e14e299034763023e7384f4af8c35277d2c7e1a7de2
+Payload = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2
+CT = 5a0be834c57b59d47a4590d8d19a1206d3c06e937a9b57f74034d9fdb43c3f48932aa72177b23bf6
+
+Count = 11
+Nonce = 97f940d7c1230bd8
+Adata = 78337ddfe38be7897372b0f805603a9a9e55598452285764641c3bb7aeb54a3c
+Payload = 772aeff60eb3adf5a9589ad54dda0401cc9765589609dbd3
+CT = ef5c408dc6d0b501925a47def54d8deb9880a07a3e6380bca20a3995cf25c5a7b9477d8916adff73
+
+Count = 12
+Nonce = acfdf302ed116ac4
+Adata = fe9d9989bffae3c9e6161eb0aa9d54ee8f5051f0dcabb5a750c5478c11798ce1
+Payload = 99ffe16de323a9b65fe60305a2d062cae490ccca6d9fe9da
+CT = 1bbc2c7877d845591660636cb6ccf4edcd4c156996a26a707d0e2fe322f203c08f44d7f9bd7258c3
+
+Count = 13
+Nonce = c8d36e13b7459c47
+Adata = 3f3c3a4c26dba18f385274ac5ac3df73282686488d91bc8190b7f61071b07f62
+Payload = 316ee95430329f706348886b8ac7779e3056809e25da0a03
+CT = fd2db9611a26a3e90f4861467df60edcc595f442332b089905fdd72307c3355b19ea66d4a16ef17d
+
+Count = 14
+Nonce = 5822755a3e47c27d
+Adata = 1d72d6b371e85ca359483761704f80b3360f4d6610e6d5e490b0d509f73c3233
+Payload = af4ae8f19cf6cbd199677fe033859f56906f1979b1b5926d
+CT = d5ed6f8d5c42f4f3ea527094173b278724a2ba787e416ad759124db19ab1373a5376f46ec7095ef4
+
+Count = 15
+Nonce = 6c1c94c2e71b865b
+Adata = 298cac1e4684182786f386ef3de79c11e30b2dab7579b8ca18d0312200860403
+Payload = 6e4d992d7541e02a4aa167e56c7e47206abc25fea6c5125d
+CT = 560cd43a502a6e8b1af478a3b640a68937d1a83057110d38eaa52d69ab9790edc384b9a5d8c91dbf
+
+Count = 16
+Nonce = ce7ec65cfeda31da
+Adata = 13c1298cbf7fe6a9ab378f86d3c2207944cc2a232f9383513ceb3b202086d365
+Payload = 196c80d02b663bdd89fdaa31e329b5a8f7c596236ee8dd80
+CT = 00174dd83a7f8edc71afbe5da095160336be9184f693db3db1f45de395e021c6fb1b2991c91bd643
+
+Count = 17
+Nonce = ddb739acda6c56ec
+Adata = 7f89bbe513b9a7ebe9be3f6eb88782080593c83e8cbe47fbe15bdc3e5782090f
+Payload = e95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d
+CT = 819d73dadaf095652cf39729b2e2cad7fc7783887a5acc15713d941b845d96a5bf65e9f80ae7f923
+
+Count = 18
+Nonce = d9bb71ad90152d5c
+Adata = 20bfcba120cdbeb07c5f4d70338ffce493822d78a03c9e80b5b934e16e39f70e
+Payload = f1fe98b50ea2f9f088f6f93910757cf744d5aabf3081966d
+CT = 36decda8ade6ab104a201c6d370412b907a559738eef59665e99761cb1ac77d772b9cce9345d9a75
+
+Count = 19
+Nonce = 2c9ec9f1f1358c50
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = d74badb8ad7f2c2bcdf67e497151d35a4fc2a3c4c871868a
+CT = 0e9066270da6e03cb4307c43adc71b4b596213a63fc8032085ce60506ac3bd97327904ad2e072a6a
+
+[Nlen = 9]
+
+Key = afdccc84f257cb768b7ad735edbd1990
+
+Count = 20
+Nonce = b7776aa998f4d1189b
+Adata = 9f9ac464de508b98e789243fdb32db458538f8a291ed93ddf8aeaacfbfc371aa
+Payload = 56d0942490e546798f30d3c60ad4e3e110fc04f5b1c1fa83
+CT = 96f124c74fd737819008ddef440320f4a3733d0062c83c893e259aecf12ba08f2a2e966a3341d6d4
+
+Count = 21
+Nonce = 278cf1f09b13f467fe
+Adata = af9627922758a9f7792345716782e8837ca78e8f9db16e3fe12a7124a3d4e99d
+Payload = aa9b9e80cef47b6db3816b1d665f233e696337e21bb8333a
+CT = 5eba7e3b3ecab78121b0d56acb9dbfc6756c1255b42f145d11751638ed36c1fd3c7268b71633c1cf
+
+Count = 22
+Nonce = 4ae701103c63deca5b
+Adata = 5872a1507c833c581ac2750b2b54add4b92be14e45d72db7679f8fa2b4d1eeeb
+Payload = e832b053854fbd40c0d8b6d6b8fd5de2da0c173f5fe594ef
+CT = 3b2b964c3a90d51c0ace186db79818b4d0f7b81236d36017d3635aa1d8167087600b01643b0a5ce5
+
+Count = 23
+Nonce = cfb5b12928e1c36849
+Adata = febe755bb8e4475d8d12f5e96269abd0d4e40d73cb966e2c523343e9a6d2d71a
+Payload = f46d6970dcc37d32d93ff062e68034c1906ee487fd28eefa
+CT = 0d5332a42fc583f4f81744b899cdf2a64cad1e78d577112fee6f8c4b252e10b42fbaf8c7af1e9f3e
+
+Count = 24
+Nonce = 68d5863cafc69e6ceb
+Adata = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab7da44d2887485954
+Payload = dd4438d7ba3edc73872e42dbbf78cf300fe4bf0eac9e16b6
+CT = 874d3ef7f916db2c2799b6892ef4bfbeb4729ecbf26ac4983a8639f21f8548fae45dc76de57bcee0
+
+Count = 25
+Nonce = ea09fbe5da0fa4fe91
+Adata = 63ee18eb720b21ee4c157dafcb8c7bcc6817f54d5c1b8dd7058c37228a03f8ad
+Payload = c1811d613bf0789beeef693611ef733cd173da703b66ab3c
+CT = cbe5c799952b28fadf414607a6cf8194e9f41194abace4541d3853a52971b0ab46cc0a3eded435c1
+
+Count = 26
+Nonce = 0021be18ed76b3a34c
+Adata = bb5eded483f0ae1106fd08c5e2b91cf06d3a7a73518ad4c479fb05e631ba5399
+Payload = 2d5531d1c51c6ea100b028596bf9f24dd90be14eab58f07b
+CT = 7af0449f7359b7f3e5f6c1e7bc264c7724037f4f16077fd0a2a8e3cfb827c7e6edabb34f7bbafd01
+
+Count = 27
+Nonce = 449b51ee0760179e35
+Adata = e99bdf783070a3a48431704e90277ca65a9704c12eeae2e2d70b62f816115267
+Payload = c4896d58442877c986e4f862a9f3a3179f0e9b96316a90d8
+CT = af7531c073df01077fd5c8ea9a5530c2fe1688d529e5c2f24aa8feae6a500919a336dbba1d9fb7e9
+
+Count = 28
+Nonce = 232114642e0c6b55b5
+Adata = da288d2014616f16a2abf5923dea49aded1748592adbcd97415c33ebfa57150d
+Payload = 11fd3f94b5a5ce94f2740a27a0771aeeac77f3155d2bc12c
+CT = f0c174a7927da0bb88e92917af8ae1df4ffc3527004e9e2d0b25cea7ed6e4fe9069a2ce49875230d
+
+Count = 29
+Nonce = 660cb6d654afcbdab4
+Adata = bd96c3c225099fc58cc1f97779304606b11efe9712fba13abf74fc1d7d44a900
+Payload = 793c0bc3deb6e0bec4c1d1fc17e455eb1aa5e9e25cada861
+CT = fa4b14a381ee41fec7b7279e58f0d06a3beec26d645f81336218635754d5563f2cd48bdbb267e5ca
+
+[Nlen = 10]
+
+Key = 6ccb68d3838d4ddf660b9cd904cad40f
+
+Count = 30
+Nonce = c4fb7519a19f13d9d1fc
+Adata = 092e64fef08b5655a86cdb8de63ffaa7772e8730844e9016141af8bad2216246
+Payload = 5ea35c082e2b190e9d98e6b2daad8672f587b4f2968072fc
+CT = cda5fe3d15d00150b99120c7f206b88a4c2c4a39ca9143425603ab284a73a38cc916f8b653c92ab4
+
+Count = 31
+Nonce = 45927852550961f1ae9e
+Adata = 53ae030474795ffda4d9ac0fc3c45afb592ddd761f7b5335c13a6747e21075a7
+Payload = 6c5f468077536b4c9a94ea4a6fe3cf621083a210daee45b6
+CT = 694847b6429cbc3902d9cb7049625aef1e97b569e1e3169035bb811491d142cf1b26350f8451bd14
+
+Count = 32
+Nonce = d8c54463dfcf02d0e327
+Adata = ff95c0ed0da32d1b5f57570b815a50592ecdc9c1c4e727e0f6dfd93fc10ce88d
+Payload = 7321a6de8d694ea05623206f5df438c5c2cdd6b1eccab4d8
+CT = 9cf8ef119aa5cf3d6305d50b2b520a0b10bcd240e27276749c68e8e641b0120f7dd66e8f0cfa4205
+
+Count = 33
+Nonce = f690f3a996928275050b
+Adata = 41c05fda535770699ed22cef253753b658437f833afe65c9c393581d835f0fea
+Payload = 56520a4bfd7b73a471e0446f9524a407e81c2681b7329e35
+CT = 14aa15f9f64c4c64f6e88094e012ecb24193249f044c033dda44a62f97c0fead3f65b28928bfbcc3
+
+Count = 34
+Nonce = 26eb9ef25be62148fa61
+Adata = 8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748
+Payload = c68094c26c7f017b79f126dc26b3bbcb95f97535ca412da5
+CT = 7ba8a0c2fe2b230768d1c1874085ddff8926931961bc4558f0d5444466bcc631bef8e58fe5818af7
+
+Count = 35
+Nonce = fad21bc27dabafe7a4ae
+Adata = dc5d7fd97bb3243ba585fa0d71a07191667af418e30a6b76bedd05b32c673403
+Payload = c247fa8d8091cd3f299cdacba7fb7af93549e9e3160f9cf8
+CT = 3097d2ec0f8bf00b22504ab03a75e740d3e59c269c3ee3f00b5419293a67eb008aef0f9f675201df
+
+Count = 36
+Nonce = c911348848fe67406dea
+Adata = 50d50a0b5ed4d6904ec3045263af0255a6494b7a7e2e95ea806c4bb788423dc1
+Payload = d846c170ae0111348362901503b26d58f5efc17b6d296aba
+CT = 5d72562f7dfb47bf34b90ee4ea11ff9f726c915b07f4d843dec5a554f4bbecbf6943ffdab8d8a26a
+
+Count = 37
+Nonce = bb921b46a16d20ae4046
+Adata = 7d17f8f60ad1e61a168b5b0e7fbbc90cee79b612b6d6c0d7ff6ede042341e8a1
+Payload = 71bb6ae84262646c9be95e0f4289ffeab7555ec6746c6ae9
+CT = bac123320888b553666249756e6d63b3498760791cbe9e34e5b1162b7489a59a50c0f0f3618e6c2e
+
+Count = 38
+Nonce = 61a8b8cbfc9bdbadb2a3
+Adata = 51cf2a8949e13eaa087a34c9ec4d7fd92b862efd6a0b1fef8b016fa2c6933426
+Payload = 362f9a46aab59fb6213c83d791b2129b34367ac2de2048fb
+CT = b8a57e8714d8789f4ef2af29e0efec21b1ef67fdabc7cdf0ed5505f1f0ff77723771338585c456b7
+
+Count = 39
+Nonce = 6bc4cd23c32a913998a7
+Adata = 92fbc970b5e64198ce2a138de92767edff8d82f12f8832444b346d159657356b
+Payload = fa442383da234cf8f0c5fb667218bc3bea0c091b3a8e6b77
+CT = cdfe3e83aba43a9804c5a1832e0e47a9a153359cc32db907714025f485c7f40256049f16f859b859
+
+[Nlen = 11]
+
+Key = e6ab9e70a4fb51b01c2e262233e64c0d
+
+Count = 40
+Nonce = 74e689eb5af9441dd690a6
+Adata = 42f6518ee0fbe42f28e13b4bb2eb60517b37c9744394d9143393a879c3e107c7
+Payload = ba15916733550d7aa82b2f6b117cd3f54c83ddc16cd0288a
+CT = dcc151443288f35d39ed8fae6f0ce1d1eb656f4f7fd65c0b16f322ce85d7c54e71ac560fd4da9651
+
+Count = 41
+Nonce = eb118fb41284bfcb1bc338
+Adata = b5a6067fbac46578cfc8d3fe04108588c9de077eb009249374f205553bba9d02
+Payload = 863da00c7accf45418d47c1eda72338734dcc49cd599f328
+CT = d64de7a56146b971e21bf5784d67bab32dd837cfb81591da4a0177883346dc896eb39e8a32bc1393
+
+Count = 42
+Nonce = caba2716d07e95de83855e
+Adata = 0e0ff2c73ea5fa8f8726a3514cf906ce1610a1a6dc19b22682f9e4619f762d82
+Payload = 2af6d5636ab65db2058b2ba16df257369fc4e8aef8b9481c
+CT = 3c9e006c7d8eff5f448b0cc9c27c964713241aa7fed3665d775ea25fb272981de8b8aa0a637498fb
+
+Count = 43
+Nonce = 314c136999e41d137bd7ba
+Adata = 366c659bc45d0a88acd54ef7eeaa3e140e1cafb1b01474a065a9d460c5e83bfd
+Payload = 217b19ea6a431a1f66bd9d02b718e8507a08ab8e6f603e3f
+CT = 33d7b672b23e8b03a39ff3fd1e7b0f2be67163e3e3bae072f2aaa211dec623947a50b1252bc5aad3
+
+Count = 44
+Nonce = 6fe51f5013f53d4e4fd907
+Adata = ff182f2e179d790e827cbfd0bd8b9297ecae57ffcef9e25ef114474a22e4ec5b
+Payload = c6bf582b49dd4ab6cb33f3f88e8a4d14fe32b308ee3b4682
+CT = 26cd5dc5eac2acda283ca03354260ad57af79e20c5e92f5775ed171bb0fbaa6f431c5411cf9b536d
+
+Count = 45
+Nonce = 24bc8dc1e2354667b79ba4
+Adata = d0d48d01fc79685c6bee04d45e40d06cdf1f4607542b1ece556fc2d1bb2b03f1
+Payload = 90f52ebb1bd5439386faeaa194623285f750672a7baae64b
+CT = a7f43f56c50705a1a101044b954414fdfbe32b518e934d38f391749ea3acd624c01e4583ab1506b7
+
+Count = 46
+Nonce = 89ce46b3de3afaf2518d41
+Adata = 5767202c913584d653f37d926a0c5ac1c67db3efd1dc58fbff998778a6856254
+Payload = b2ab379a0dd15baf91415eee3a4e56e7eca54d4c1c3094f8
+CT = 9f530e455a54b86835eacd8801b34c884a3b2ac819ba38f894e43a6b1cf73cb2d6a1dd8331549520
+
+Count = 47
+Nonce = d3208eb695e84c7a925037
+Adata = 91d8fa65a6885f162a795afe2898f391990a8b3a87c11f94734dcbddf5f58da8
+Payload = f15e39f0e4eaa5bf81359d8e30186522f1a1a415436668cf
+CT = 7f1d9fcd9e5cce3a81e3495bfecec817fd7180d8bbfe0abab27fb6425fcc3537ce471425a5b17dcf
+
+Count = 48
+Nonce = 067de2869333ed22c7b63e
+Adata = c31e441fd551b3fdfbe23ceec5ec1f838f31a5300f6055ad2a936a9d0c1c856e
+Payload = 1536d9c9a09302d142c85638202f5bbf0c287f68115d51d8
+CT = b1a5c7a7fd23228dc7ea26885802daa0719f6a23681e1d65dfb879c21b46f3307ef22f1da579303f
+
+Count = 49
+Nonce = 15f61b4526d19bceae1093
+Adata = b97b122af73e928e617e98684f845be4cb80566345739b7a884c6a3eec5102bf
+Payload = 37c81988c07a5b01e2b40ff9f9ada5f50ca764efb717ff9e
+CT = 0d93a5c77482d573b7f1b8c5e283f2571efc9f54216a4c01900504a73c8817ff2b55618b2602bf38
+
+[Nlen = 12]
+
+Key = 005e8f4d8e0cbf4e1ceeb5d87a275848
+
+Count = 50
+Nonce = 0ec3ac452b547b9062aac8fa
+Adata = 2f1821aa57e5278ffd33c17d46615b77363149dbc98470413f6543a6b749f2ca
+Payload = b6f345204526439daf84998f380dcfb4b4167c959c04ff65
+CT = 9575e16f35da3c88a19c26a7b762044f4d7bbbafeff05d754829e2a7752fa3a14890972884b511d8
+
+Count = 51
+Nonce = 472711261a9262bef077c0b7
+Adata = 17c87889a2652636bcf712d111c86b9d68d64d18d531928030a5ec97c59931a4
+Payload = 9d63df773b3799e361c5328d44bbb12f4154747ecf7cc667
+CT = 53323b82d7a754d82cebf0d4bc930ef06d11e162c5c027c4715a641834bbb75bb6572ca5a45c3183
+
+Count = 52
+Nonce = 6a7b80b6738ff0a23ad58fb2
+Adata = 26c12e5cdfe225a5be56d7a8aaf9fd4eb327d2f29c2ebc7396022f884f33ce54
+Payload = ba1978d58492c7f827cafef87d00f1a137f3f05a2dedb14d
+CT = aa1d9eacabdcdd0f54681653ac44042a3dd47e338d15604e86a0e926daf21d17b359253d0d5d5d00
+
+Count = 53
+Nonce = d8e133e7ff8e0a0ec6c4096e
+Adata = ef9e432c15d8c93a4b5c0666608e61c824cd466d7940d642acd3dc33057c0395
+Payload = 2836de99c0f641cd55e89f5af76638947b8227377ef88bfb
+CT = 5edb056d85dafeaaf74bdf4caa47339d6a75bf1ee998565e9f9cdf6ab825f6e026f5be2ad895033e
+
+Count = 54
+Nonce = 2fa8120398d1a946f391367c
+Adata = 377cd407ad28dc02bd3835a31d92f8295c9dbe597f56662ceda112c588dc73a5
+Payload = 7a37255b682766a0bfecf78e5162528885a339174c2a4932
+CT = 701f5f506fc7e9ea4a27a4db5cb890f7be3b4f6bcb20f97ed3021f6ad620648b8196ab1693710398
+
+Count = 55
+Nonce = 8d638ef43f56dece910139e9
+Adata = 87ea7b095388de70ac0ed23e86f502400910028a8ab5e3bbb91d05821c0d2d61
+Payload = 7370d9b453936955b9c9d336f4b283237986232de007bf41
+CT = be2f03f6ce1731418a5f53b6f6e467b73992a0c8102d8ffc2d236162688096d80b8733d2afbcd244
+
+Count = 56
+Nonce = f479ea8812b6b2f6ac78fe9d
+Adata = 20c2b8f5d3a65a66ba8a25e2ee339a779a32d45f5db91077efae6cf308feef50
+Payload = 59ff9f7581a781808d36fed378080963f35c00ea5a6e3932
+CT = d127c956349c16e2186f55b72254c677f03c61f1c4ada9e661bb9415b32d6a58f5f7647ed41de685
+
+Count = 57
+Nonce = 423515f7bd592d6a7a240866
+Adata = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032972c939db300d8c1
+Payload = 3c379f90b11c622a765756a15efc8fc3ca7b08b3281945f5
+CT = 15792e01fc17f5294c3405484291082c00a8f46dd9af8ca230ba95c4058501234a1b97543c998e9d
+
+Count = 58
+Nonce = c3f3da69e13c5733039744b1
+Adata = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc5731303fe0bd56b11e
+Payload = 9db6fe9adb8c0fee87cac9a7f01a7ed8a84f0512d09b1834
+CT = 9b6b829ca1dc4e90d4402188632ea3377cbec2ba60f0f072afca1b08b6dd589a17a32d49b6f7135b
+
+Count = 59
+Nonce = 0a57d59f21ead5b6d80cd2ce
+Adata = de5f2d413c98c6ea2a5640a7b1c424aebe75cbc78b06710b5bff8bec6afb5a76
+Payload = 0b5f6389f7c20f4ba326e8f05d373ca27b7ebe59e6d729f0
+CT = 0b704e14bc7d2977d89e0b2e7ed7fe3c9e0f2ea80d2d6165f344f2f1b2218d9b4283fe640a6d315b
+
+[Nlen = 13]
+
+Key = ac87fef3b76e725d66d905625a387e82
+
+Count = 60
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f3898390e90d0a0899f69f9552
+CT = cabf8aa613d5357aa3e70173d43f1f202b628a61d18e8b572eb66bb8213a515aa61e5f0945cd57f4
+
+Count = 61
+Nonce = 2a27257bfaadf23a87df082c57
+Adata = 0001dc666c9daf3560daeaf514270db0b5075d295068e6caf231c1de0e1a9300
+Payload = 6cbbfa6d736fbcc4cf73ab4d7be537420e0e574ee1f2d1b5
+CT = 72d525e6bb312bf2c20b91f41108779789c25720797ebffa4cd9d735f51430275387c565cf1a69bc
+
+Count = 62
+Nonce = b94ac8ed14895c80a91fda8367
+Adata = e1eaf35fb266f243a3fa407cd41815ae6432ad79877bfa59d8f196cbf19bfbb2
+Payload = e6ec561496ce18d96b26d594a47ffad02d68ef25d2d2edb9
+CT = c63500445239bbdf71a8dfe3f8c01061d659cfeb038b825dc89fb5f507f5aeefaa9365f0b18dcb3c
+
+Count = 63
+Nonce = bbae10aa491ac9c668a3ba8d7a
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 9c629c375f014e162895cfc25a972c29839f97407e7c7cca83d0a61d453d596fbc5c2e315d9780bf
+
+Count = 64
+Nonce = e0b10e78e9fb41ee970143e9e3
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf3c99c9d1a35bd8e4ed36596789
+CT = 867799b30558697d6efb4afcfe458cfad8da21139a0b43128e8f8e13b7896b244d0c9aa52ed31a95
+
+Count = 65
+Nonce = 17b61109f5e37754e4e92a28d7
+Adata = 0bc2fdd890c19882640f8d4188b88b9db99cc1934cc3e98a5df08589287968a6
+Payload = 347c1eb4aff917bc0012f005e74caadc93f4f18f2b614ece
+CT = ee19f3120991b67b2389e6f36543d99590f2e6d785c9c8ecc40eb85585cc3b7520a940a4e993327d
+
+Count = 66
+Nonce = db3ca9e80ab761804349379961
+Adata = ce01369d08d37dcda2c899c9fc0d11ccf94a0051b2816a1d6c3ad07fc8dd02d7
+Payload = f0e1af1276d2918be91a191814660bfe735463d3983de1ed
+CT = 0f1b1228729b181772d7cf55ad257fbcb19cd46f7b31a885401358c7b44aea27617b429583103a1a
+
+Count = 67
+Nonce = 1f57959cecbd377374477e33b3
+Adata = de1c7c83ac61e1f99ae99b198f4af5d24f8de60ea98fe637f3a801fab38b2a4b
+Payload = 42a42b84df098ceb43519c4cb86c14c2fafca39346159e13
+CT = 12425453de653d0fe8103013fde1ebf4a8fe18f76f0c9d60e93525fe8048c3b2147a149f12eaecd3
+
+Count = 68
+Nonce = c9db03e2efbab713b0b6404210
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918696a
+Payload = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c
+CT = 5cdc183c32b4c1878eb83e8473a17c55c88e2ad6b944ab1f64ddee42614aa737231207636c114575
+
+Count = 69
+Nonce = 89ed296a3ac03fbfb71422b921
+Adata = 1ffbe1aff0a1e7fa3e68be31a74612a1519b59397e7007ef61fc015f316d55b5
+Payload = bff42516e30c92ed46710013c656600406a48a84c1fa32ce
+CT = e08c1ab4ae7edb5184c30ffb3e74689ea855f50b0e890392f26b130720f75c422fdf66fb174383b5
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp
new file mode 100644
index 0000000000..06e9ff5655
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = ceb009aea4454451feadf0e6b36f45555dd04723baa448e8
+
+Count = 0
+Nonce = 764043c49460b7
+Adata = 6e80dd7f1badf3a1c9ab25c75f10bde78c23fa0eb8f9aaa53adefbf4cbf78fe4
+Payload = c8d275f919e17d7fe69c2a1f58939dfe4d403791b5df1310
+CT = 8a0f3d8229e48e7487fd95a28ad392c80b3681d4fbc7bbfd2dd6ef1c45d4ccb723dc074414db506d
+
+Count = 1
+Nonce = 026a0b8b17be95
+Adata = 44caa8ecfaf38e5e773cb0366e1b04aa0b9fac5c34a362310f471960c4a1e1c9
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 3417044bad5fddd9455579123dda4fd342c273a57ff6333dfedf191496d88cbe17c6271b65096e66
+
+Count = 2
+Nonce = ea09fbe5da0fa4
+Adata = 1d9799f2bb0f7ab57fe3de27949ff64066131c81bfee172b308f9bb0b3171067
+Payload = 469ff9698cfc96b581d7115c822e4363d7355ec5daed2eae
+CT = 1dae7cc16f1b469290902cfad47b959784b4d6f48a79e690d47e30b635d10d1663477d61d7ffb55d
+
+Count = 3
+Nonce = 8d27bcbf9ebfd3
+Adata = a7070b85b7add9193c9dcd2e6c03f6e7ecc52ffe9e099866baf7472f20c03aab
+Payload = 225651d072dc9d93762dd79691ac2b6ddba00ec1252d69eb
+CT = 5da819adefbf794612eb458519debcd524c283763eb3d7252eca8766bdf0db6bb2dcc793e1749c21
+
+Count = 4
+Nonce = 13f560187b6077
+Adata = c4ab4244db75f8256e55c5b613a07b11c963c3cc24f66128aad4ba8b7ca99331
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = 3aedcf8347aa23fd3325ce08b6b00462536baed69968a753feab6761c55431bb5668e1f5b7505e89
+
+Count = 5
+Nonce = 61e0e28bf344a9
+Adata = 5f998952de70449ad46428f2ff8a01c5af43c0107a1bcc6930f19d4112598666
+Payload = db21b37e875d7709a02239ce6ea529cf37255d5b617c153d
+CT = b8f5fed39c723d7643d6dcf2efd3bbd1ba0da1ec901305fd64b2302ace4f66216ca8b4d776197692
+
+Count = 6
+Nonce = f6be4aad63d33a
+Adata = 18339be863fb8a887d04ae9ff3b4a7db095075cd5d113a9ec87b41fe85ea405e
+Payload = e53101e6eabcda32c13d7b1dd1d88e7c2ca3ddc2064f64c6
+CT = b758858ab60e1630a0883d4d330119a593729a3015c42525effb985b9c2dd9ec954bd25d9c464c67
+
+Count = 7
+Nonce = 2c1c59aa0d8eff
+Adata = d44af86b89fda8448a9b2fcae20ea156dd8738c8251699c02b785811c830bf72
+Payload = 1fd7188a43dee7b059420e8634d71d2c0658f6d0d308dc73
+CT = d046f845a67800a5a58f461e5a8641e8fc9b4c53b32e61d172adafffbacb297d67f6b5c02b982e04
+
+Count = 8
+Nonce = 48e4598edd191e
+Adata = 61588bdc980ea2310e87dec4c651e9a55c27e3858b6505cbf3bf85e51931badc
+Payload = c25868f390af5e59c035cb5830e018c62c5b96bd35b764f1
+CT = 0ece161bd77b7f969b3b20c818769a98c178d84524544664500ff4cfe66ade1832babc019778acc3
+
+Count = 9
+Nonce = 6d576ce3c5fcb5
+Adata = 92c598cb5ca2926c11f67c3b3cf25493d77606fa60d7290430e0e975091644a6
+Payload = bcd97479db934357a163a9e5f5a85999ca987f8243d8017b
+CT = bee185e11b3d42bac846b9d92c70a078aebfa630ab763840391031b3a22b2adeb9791ee35765c8cc
+
+[Nlen = 8]
+
+Key = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193d
+
+Count = 10
+Nonce = ad749d596d88a4b4
+Adata = c67219909828adef64422286008e1e306867a1c0b3da95444507a68b45c953e4
+Payload = bd92d6744cde446fc8621625658fc4bc00dcb97f06195ad7
+CT = 076cffd0ca978fe2bad411ced45a090abafb22a99896f6a75a1969276aa2b0cdb37ccaf2845dbf6e
+
+Count = 11
+Nonce = b1dc81d116d94f5e
+Adata = aa4b71906b6642f10f66c2391ec157c7cde97eb322db10045af4c5248807f691
+Payload = 9aa6dbe1cd3eb98d330c937d31ef93bee8938b6c5cfd38de
+CT = 720f6876ac91665f20147483f0655fdbe21963a01e36f1daa67e36d7cc8d54cfec0762514475127b
+
+Count = 12
+Nonce = e758738df5c89af3
+Adata = 5715fa238f432c926e62dd93708d0e3145428e0ed45e1efa8148d2c4ab6cba50
+Payload = ce80b99039a16e69018d1e3c239dd1bf06e94a78b0b1df37
+CT = acdf7ba3edca1563727ed85cabf085c2f0c8f27556c3c064ef50d85bc3ade6a773d956b2660ac367
+
+Count = 13
+Nonce = d586c4c67d535476
+Adata = 1e8dc63c6c54a540b6b02067ba7c719221cf289fa3897299722c9a2bd6eed05b
+Payload = 2f88305117f9a5d807d54b7e95ecfeb7327e52d9acac352f
+CT = e42b86e619be1a38973c934babeb4688243a9012c85d643d81e024aaf0a62b353f9bed36681288d2
+
+Count = 14
+Nonce = 77e83758f68d272b
+Adata = 25c80edef3d5bd8b049fa731215b80ca2ee9ee6fb051326e8c6d0b9e11e3d7ef
+Payload = 92e47b82b728d639777d5d5843de2a5c364956cb4b21cabd
+CT = 1b9177f5b76403cb8c690b39c3dd22b55da35cebccb9b64e05fe32f796f0b4a75a459fce6c7d740c
+
+Count = 15
+Nonce = 311dc245549206cd
+Adata = 87767f13bb4904d0df0d64eb22c9ddb65e81b5739baad86ad5e2c239ffde9f6c
+Payload = 8691c0301a216a5f3ed9123886d100309bd85630d6b845f5
+CT = f39fe3620a03b37a4bf457909e0770447b498ad2a2f0f9d7b75f9e4239e43bbf93066897e60f6fbe
+
+Count = 16
+Nonce = 2a17b70f10e120c0
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 92187955ee1ae702ef01a385537119b2bd4545402e8b2384a0c069a2439a2d8843302c6a9999e658
+
+Count = 17
+Nonce = e0b10e78e9fb41ee
+Adata = 9d072b8a3f1a496b2be6728a38b94a4f44c9be40c8793b69afd81d01696a6b4a
+Payload = cea28e7cd0eff0c5eafeec908d4aa8ba303e72ada33db087
+CT = c605e48f2e66e8e0a92471e466981ae5e31db3e4ad80b09f5005b06d15f63f2f015cfe447828da09
+
+Count = 18
+Nonce = 02d72dde23f9772c
+Adata = 2dc44c39940e2d9c94d2dbe40bbf5cca5efb4d4b250a31aa24f208b87e9c2453
+Payload = 809343e986f6ff47f54d4cac22ed39babd12271d4c7edb58
+CT = 0bb59581f22f6b15de76c0066645495a5c19e44381c349263ed92ebb789c314a89c83542b15ed694
+
+Count = 19
+Nonce = 28c4d6de3e2ce51b
+Adata = 913a8eda924589d3206ce0a951fef93668c6c0c454824b217997bff6b3026d54
+Payload = a19f65ffdafd6ad5ee43570f7e168f94a8b4a7b7402ac80b
+CT = f0c91a29f1222b906550ef5c7c0944c5c4236cb6c31122cfada8e796f2ce7f9449f42de504873868
+
+[Nlen = 9]
+
+Key = 8cc622645065c72d0d2aca75802cf1bbbd81096721627c08
+
+Count = 20
+Nonce = cd84acbe9abb6a990a
+Adata = 447b6f36acdad2d1cfd6e9a92f4055ad90142e61f4a19927caea9dbe634d3208
+Payload = 597b3614ff9cd567afd1aad4e5f52cc3fa4ca32b9b213c55
+CT = 2d7fb83e6621eed9073e0386d032c6941bef37b2cf36a4c6c5e36222d17c6fb0631c3f560a3ce4a4
+
+Count = 21
+Nonce = 1fc7a43ed124745d04
+Adata = c892b095173076a40e24522297be27fd3a765c8d417f24c71a9f03b3fe3d8e20
+Payload = 415cd8312dd20a1c26f4b90d98104cdfbe06739466fc0aa5
+CT = 7bebd6f55f15ae57ab73f92f7be6ff37ddd99740e988f01a7a2a13c22df4a156e6d6063235452c85
+
+Count = 22
+Nonce = 19ff5e7c1f2c594abc
+Adata = effcea4e4dbc57410426b39fcf51c9daecd9d310888590d77827973a29c4ebff
+Payload = 97fd2c259a4e672e9555a9a5b98f4c0ec8c4c49c7ade26a4
+CT = a460674c2f358762e97dfc958d90973e1e419dbc6a832e987579b2c4a6bcf0356f48cf8959cfa54a
+
+Count = 23
+Nonce = 64d9bd368ac2357cf2
+Adata = 62c5a16f946b4312517f67c80afe2614c822e3a01b87dc81538c00bbf3fc0108
+Payload = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f9
+CT = 8fb5e0954388b9b58519482962487e9b0768f0cee08afe9a92be2b06a0ecd2d00877abded7d9634c
+
+Count = 24
+Nonce = b4aaf2cd93efc0ce93
+Adata = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d1ae70413e4e43d14
+Payload = dd42449da4c95e858b796085b6b5b3b5eef484dbf3c2bc8b
+CT = 893f86e29972928c1f3c3e25c73947c8d677814bca7fff2cf8d301ceace678f9bf91fc361dff5812
+
+Count = 25
+Nonce = 132f3e19e12f462a74
+Adata = 176cc5a280f6171d00e247edacc81f05c1b9faa87fc831163ac9d76aae59a6c3
+Payload = 8ea05a5033ab8b009664fa2800c24e217488ce6888cad147
+CT = 4771d210ea678dbfab96e320e9c44b68f47cb05b01826ccf42ca4f4ccf986eb6a6b85b99db2fcd93
+
+Count = 26
+Nonce = de709ba64cb75704c0
+Adata = 0cf8e9ab95766b6fa85e88d86e4f349a17c0d90509939e343eede988e7462255
+Payload = 51dd9fda9549f25dd868245a6a54b8d59346d2f336adf9af
+CT = fccc3e44afa6bd2fbcfc5c834db63dc9d152c04c0dc0b43d393162252ae91ca46fb8e8338cbeb75d
+
+Count = 27
+Nonce = b11b4c1b7a26387265
+Adata = 14ed867cc909c0619f366918a7d5ae25279fb137e1dee7fd98ddbe3bd19d841d
+Payload = e35ea4a16e274fcab457fd4dc7886c3d81fc668c19e0f374
+CT = dcca8aa2eab8ac3f5db9cd9560ae0758d7df40d7d868d1f71f498ea6ec8251a6d149c7ca38b25fe4
+
+Count = 28
+Nonce = 20d03227a7fcaef1ce
+Adata = c5c15245e641687d0ca9e913406acd2de3f21fbaf2dc5e4e8963222da61d02a6
+Payload = 6775e5faffd0b13e78da70a789042245d5ef31eab5245380
+CT = 4bb8ed2207f36f40f62d3a2c90f8e3bd8f589059b69037118ce3ab864545ea81943ef0ea9489d223
+
+Count = 29
+Nonce = 267f76b9ec0f5e7c6f
+Adata = 2b421be47d07dcb12a0706f7490d05024fce8f433079e18ec78f4c8678f5f155
+Payload = 9330bb23428ab45f573923e977db74882282cbe1371da68e
+CT = c6ae24f82ac5cf9c18a2d98e610027eb2566a1ccfcf99945655e14c7bc8be97ea47388cb7b18bcf0
+
+[Nlen = 10]
+
+Key = ab72eef2aba30205c986e2052d6e2c67881d24ae5fceaa8f
+
+Count = 30
+Nonce = d7a46e726ed43f1580eb
+Adata = baa86f14271b2be7dbb37ddc7c95ce4857e57aa94624d594d7bd6ceeaada8d5f
+Payload = 2a794b84fc9e4a7e6d70a82b5141fd132177a86b4e8fc13a
+CT = 2d7f76464417613bb61d3657481346b74fc9d6abc6a3babd39365dce86859cd82395d11bfc8cf188
+
+Count = 31
+Nonce = d0afcbc1b2524a4a4553
+Adata = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da8
+Payload = bfc5ce1316ccdbcd8ac62484e7656c87947ff98cbba8e1e9
+CT = 4772c121367d0e8d3edade883342395f3ea065fe7dd7be8c8355b915ca2633fd557ca7ed41e00926
+
+Count = 32
+Nonce = 6eecffd227e8d5349523
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c122e0b1587302894c391
+CT = e2864c6e12ac089daaa1e94af4b2ed04060d7ef65d2f72f0e7d017514d498f1f3c07d650afde8293
+
+Count = 33
+Nonce = a67c0675753f725a8fd4
+Adata = 7dd546397a9a0129861fb6815d419a307f90d259d55f3503961754126cd1b776
+Payload = 80f1f1ea46c92d28f2d60eab39ce056a4aefe63fa688538e
+CT = 882c687c03eaaad9d7f591649e736f0c1c78f95e40d40cd77499a8544bc2a8fe95f55fefc7316f8d
+
+Count = 34
+Nonce = eb83928f0d5f7aa3a74f
+Adata = 060cd3e4aecdb03837dfa9f544318c0a16cdc37fa2a3135be7888ac67e7eb26b
+Payload = 81e9174e9472777b6b184707108c01d6ea6b5d108ec3c6c8
+CT = 243cfa0a0a36a4c20333968910e6f52acc04c6f74e704180623f3a13fc13db958cbac49f7421d6af
+
+Count = 35
+Nonce = 5757abe01f7a1183fdcf
+Adata = 744629263041f0eccfce4a1ebcc18c4c984010f9241d35966263a8b2f72ee26b
+Payload = 991049f26b529af8b0bee0cc83989cf817d248254182f332
+CT = b20469b5f33f0996e8de869ad10ce09924a0bdd7b67a89a09c447a3132fbe5213133650000d50b06
+
+Count = 36
+Nonce = d9adfc5b44ad7aa94b05
+Adata = aa6a5448c6ec87be75eca35725ad2e902dbccf840d25b2bdf7e62e4a8fa4a511
+Payload = 14682301a99bf680805d1ffe62e1506d48cee8c51ef1d255
+CT = 9b44efa185b0c10325bb4c3c0815e6a6e46eea366b9a416b5ae554cb440eadd875657fd5cecc214a
+
+Count = 37
+Nonce = dc3ca30782c9c0a7fe89
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = f9cb86f24536931a1b095b426a07e4621c000cf09b472bf8
+CT = 463f9124d1cc387a0f8b971d1e2da448f0efffc3956ebb2af8312986315522081f0989838ef0429b
+
+Count = 38
+Nonce = 9523f53f92b6e4ba86e5
+Adata = c3b123ccc916d26a2e6a8b5e30041ad69a944217e9b402b7acc0170c31e8c2e4
+Payload = b9bdcac80f64175836ab51bb1a1bee5ffe3a6b9b71afe3ef
+CT = c356b5a78cebd123808fb740754dc47a8ec7c9448bfacf39768e94f062e86129cc9210dfcd3e6128
+
+Count = 39
+Nonce = 16bdf18c09d60f3a2a32
+Adata = eedd0796f23612749e9fd282c864f3118d0683409d3bef1fda352e1422273c7e
+Payload = cc96133e473d197be1bafdfc1a21d58e57d0d89b2ba1c3ff
+CT = f9d78e9e3a41b3bcbfe756385a3715776eb84bb7d8d15432978757883f07802b25e9a5b15c43b451
+
+[Nlen = 11]
+
+Key = af84c6f302c59aeee6d5728ed5da2e3c64a5a781c52c4d1b
+
+Count = 40
+Nonce = df990c42a268950677c433
+Adata = a6ab5d78427f297a4b7e21f1091ff3a5b20caa3fe1cbcb09459d9df596a6c8e1
+Payload = 6db41aeb5f7c24df8929dbc30483b3c7934b3bd1cdce5bb9
+CT = 8c9328258bf71970d33e23a3ff81cc1c9cbe196a1294264bfd6a7255e4801963bb30a63de3fc5b82
+
+Count = 41
+Nonce = b7ea72641bbe2dca6d85e7
+Adata = 4e0f2ddf183281ec131693bdcea3fc9743733c07a486a42d5737735b3f6e3fdf
+Payload = 726844e41b1e4d883024b32fee0dcea38c889cb328885b7c
+CT = 9a133e4582c2ebc445862a9c6f2f4e39223c84081e322c8f262de30da6ef505fe640c53d765f672c
+
+Count = 42
+Nonce = 446fee1e75e79c0dfc9ddc
+Adata = 42b598eaee271e06d9e98dd94152b28ef10f506d65bd660b2fb8b1be9a2d7254
+Payload = 0cdcf348ecc9c3588001802c2106fb64be9c301adcc66e73
+CT = 0c2657b0482b6ca92e1b1c8fdf75eae3b0cd3af205e9bca396ecb1e46beb16000d585e1d9559ee22
+
+Count = 43
+Nonce = 2e6e34070caf1b8820ed39
+Adata = 8bd1ef3a1831fcc8919d736fb23111ca3ef4cccaf20264fab8eb3b071e56667f
+Payload = ca0860cc1e96506c2beb25b53d2947fbab634f0372afc8ba
+CT = 19e4774030e43e6853ab5bf176ba9c4b59f29f285977e3c15198cbe3e34c884c3f56a732974aa1d6
+
+Count = 44
+Nonce = 428542ecfb94a745980aa6
+Adata = 8efe01716b9018084e2ea7616f85b7333d945c0c970f8cdd400130b98db67cda
+Payload = bc6b59120ba2845b0e41f65a55e2ef1c45a81485c926c14c
+CT = cb48b0af6fad251d409d14ce0fbfae9cd9c40bf4a0c1e2b7e7cec415030997e1ac5db974b617b5a7
+
+Count = 45
+Nonce = eff703e6d72ddd23ff52d9
+Adata = d7fc74035e66709d2590b7bb3276245dd43824c9896fbd801ec1d07018b39b6b
+Payload = 1a5432e8085511ddac1be91be3e2945f85f0cdcc3a1c9f8d
+CT = c0a00cbaec65b7ca525fb26e80ee0cd18c7ef47c39c704833e59bfecf263bfdb24686627fd95e120
+
+Count = 46
+Nonce = 6a652ce21334a40a259dcf
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d34e141066f543526db6
+Payload = eb8f1988cb405041bf48d138ad41da7ef364d4ac59a9e324
+CT = d4f23166c09a15466c7e0e2b30627ee5a84f22d7e6135b4a0652b67d559a84b4a915ca6a420fd300
+
+Count = 47
+Nonce = 9382e12d447c0ca23cc9c3
+Adata = 239129eb760f8a770410c160e4e13a6b9497077c3e463b65397393fcd3cb5c70
+Payload = b40e80564263c7f450c53ef84df67247d72e8a04dbb284bc
+CT = 6de2ba26caa80874814816154784912c55e3d6da83488e7250f5a52f82211542b4e2661cf870c80c
+
+Count = 48
+Nonce = 2c3a4148cbb02504a2483f
+Adata = 33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44def0441dc528
+Payload = 60a31736d99c3dcf25b349f6110e1c152b93506e85a01e67
+CT = 4d5e705d08f3ed1ca6f1caa74b46e4b1eee18a0783686f207de16aaa41d06bc071657dacf14da754
+
+Count = 49
+Nonce = 691cdf6fe9ecc2154d0101
+Adata = dc096596644c4e09c44078b86e5e0887c45094042eb0d74a6a13aa2524463076
+Payload = 77e6441ee017a93dd876ff2c7980540c77ee15edb0f23933
+CT = 24cecc81c8ac7ca9906372dc5263f2220b4dd162f1e08283f07f23e65475a20fd96e45c6c695cd83
+
+[Nlen = 12]
+
+Key = d49b255aed8be1c02eb6d8ae2bac6dcd7901f1f61df3bbf5
+
+Count = 50
+Nonce = 1af29e721c98e81fb6286370
+Adata = 64f8a0eee5487a4958a489ed35f1327e2096542c1bdb2134fb942ca91804c274
+Payload = 062eafb0cd09d26e65108c0f56fcc7a305f31c34e0f3a24c
+CT = 721344e2fd05d2ee50713531052d75e4071103ab0436f65f0af2a663da51bac626c9f4128ba5ec0b
+
+Count = 51
+Nonce = ca650ed993c4010c1b0bd1f2
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d50d344340c
+Payload = fc375d984fa13af4a5a7516f3434365cd9473cd316e8964c
+CT = 5b300c718d5a64f537f6cbb4d212d0f903b547ab4b21af56ef7662525021c5777c2d74ea239a4c44
+
+Count = 52
+Nonce = 318adeb8d8df47878ca59117
+Adata = feccf08d8c3a9be9a2c0f93f888e486b0076e2e9e2fd068c04b2db735cbeb23a
+Payload = 610a52216f47a544ec562117e0741e5f8b2e02bc9bc9122e
+CT = 83f14f6ba09a6e6b50f0d94d7d79376561f891f9a6162d0f8925c37cc35c1c8530b0be4817814a8e
+
+Count = 53
+Nonce = b4cadb5f9cb66415c3a3b714
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 22bade59214fa4b933cb5e3dc5f096e239af4c2f44f582b0
+CT = 2296e3f8a2245224d274f1b90ed1287cbeeb464c70a89ee475ecb546efb8872a3f8b0281b3901752
+
+Count = 54
+Nonce = 72e6cebdaf88205c4e744286
+Adata = feaf010f462ad40a38eefb788b648e1cc292cd4bb08ebeff3c39182862296042
+Payload = 30655a6b5a5965db992e7248d24141055e988d726abb8e72
+CT = 69b27f2bbaa61c4f24e1c25e0779147fef79ec1582486b4651cffa571570618e2ada3376bd9f3e5f
+
+Count = 55
+Nonce = d8030fb31eca2c43f3f5eb88
+Adata = 66704365ddd0145febeb33f68b228a3f09e1e5a4b68149e6e06d886301841295
+Payload = 9d014a02507a6f266bd1ace21b55ab8b73983ff503bb9adb
+CT = 233a883650538ab8c0da30b90527f880fcad5b16bd435e762beeeea7a638c717e63764b3a5118a0c
+
+Count = 56
+Nonce = 58038cc35ad3dcd75195e125
+Adata = 3da7a757e942409a3b39ccdc0669ce6401f7e133c07c4c42e366d70a8e9bdd49
+Payload = eccfd817fa5e3a0146967fae13fc2471ee3944cee37969f4
+CT = 415a36872a04f5b4b5372f63394ab9fb353e0eb9b430450133a87fa29e5fbfa9bc0430b0cac00b7e
+
+Count = 57
+Nonce = acd82ae31bfcabd90af5af45
+Adata = ce22126f01bde16249c47102b4da68ad3edebcd4a16c24a16ea7ccdd5d364d10
+Payload = 9d2126d34963d3ba12cd841bd321036cb82cfb78f2a6535f
+CT = 88a5b889e6fd74fc15336e23374b430988416c7e6b6e7248b336cbbeb64fbebf2e7076a98ecf5bbe
+
+Count = 58
+Nonce = d24457d567fd0a65fdabf219
+Adata = 0091d39f3478d2c59bf874b96db9ce0f7e8b85a9b805e07dc96b219819d51663
+Payload = 6da3ac85505e93c4f391ea367a9e15fa9b388ef7ae2693c1
+CT = 7039a8a49cfa6402b4ba3b840e69200c13ac4a3eb1c709a30ea909047af4998c660afbaf346ed65b
+
+Count = 59
+Nonce = 50c59ca54eb64575b82b13c6
+Adata = 5e4e42cbf172853c351d597c7d6d38b1a9cbb7ac92c00863a80ac4a2d9f0e7fd
+Payload = 25b2ba0a937b71f3ee68e7172cf2c4524b662efcd08ce2b3
+CT = e95fc44287ce39c5ad6b91c88582563fa68a9e304094deb8b193dd767f17783f0b51ac0fb7323301
+
+[Nlen = 13]
+
+Key = 36ad1e3fb630d1b1fbccfd685f44edd8984427b78deae7a9
+
+Count = 60
+Nonce = 3af625df8be9d7685a842f260e
+Adata = 308443033ecd4a814475672b814b7c6d813d0ec2a0caeecbcaba18a2840cdb6c
+Payload = 8b9db1c8f9b4892a5654c85467bcffa2e15e28392c938952
+CT = 6bc6890fee299c712fb8d9df9c141f24ee1572b8f15112c2f8c99ccf2d82788cf613a61d60dae458
+
+Count = 61
+Nonce = 24eaeaa437649e61b706942b8d
+Adata = fff75462f96157d9554bddb6aac156fefd88fd4a90a8536dfc28cc577f19c83a
+Payload = 49ff4ff85f7407ca383cfa4fd7177adb4dab26e642c8186d
+CT = 3647fae50c588d792442f43a20125e77ab5db3c469391d24d0a421bbbc002eb9ac9ad01f625f824b
+
+Count = 62
+Nonce = 7325932d6694aaf61a8204c172
+Adata = be20ceb8ca14e9bef7158b280a26bcac763da79cd0eba9b1833ea808c5e7a66a
+Payload = 2861494eb40b9d964d339797c1b6aac63c6674187768957c
+CT = 286dc74001e2a6000a23db164f4b2912de4afcf1df8c3aa5ee32a7ffd4e7bc303d3482fbac431828
+
+Count = 63
+Nonce = 61c9949df5853e42599e5ee0c7
+Adata = 243d09ceb16755cb58d62065df84890b840ad9b7eec1132c6427cd7c3d843fcc
+Payload = 943a49073db6ae94a88844ed895f8fd99ed25c3f42a2f78c
+CT = d3c56bd265a2cb0811dd218f248800ceade4f02b5403b9635eb30cbec49cbb51c41cd5032b7fd759
+
+Count = 64
+Nonce = 07b6c18dd3b0fd9e8ff026a436
+Adata = e85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b8ca9f321a178a2056806
+Payload = a18b0a4618063c0519818d113b8e5435aaf153f664058f1b
+CT = 69f933a2a5e774e8d013cbf78c6ab0b73e6ca323d0c52691acb5cf2631987d3d963349b035324aac
+
+Count = 65
+Nonce = 0c075df70630dec2fe81834945
+Adata = f3f5c5ffbfe8247bc0c33c793652f749fe91b6dd141cf0db56e71cef8a2fd266
+Payload = ddc4bac4115e8cb06d29d22e400674dbc615a667f933603d
+CT = 26bdd25c9f204fc7520d26c161464c28fb35e395b295b3db4e239d33283d18415b54c2aad4bde354
+
+Count = 66
+Nonce = 0c2d20375057fcd4241d290f6a
+Adata = 70ff1b9ff8ec08fdb18b0e7dbe01127ed0cfe0b0a449ca2ace4992b7b6248b71
+Payload = dacbdf1979e000d52b573e74800761b30acc26681f372acd
+CT = 6a642c389433a3464fc64783ae6a14a9a45f0998b56a5b9162d7e0320dc930df3640a786d7ea9ae4
+
+Count = 67
+Nonce = ea0801cb3dab853750a922dd25
+Adata = d83360d0896e022bf014bd33710ab212ddedda6d95a54996f33db304e5f12f01
+Payload = 46cc5653bbd8300dfb0df6d0af3fb7c7639a830bdc9f68c7
+CT = f1b0728920351d9edfdbe7df360b21f6cc5b628dcf43a3f10d06b4a545609a2128a95d4d73471559
+
+Count = 68
+Nonce = 97e6de379c90fccf3fa8f27013
+Adata = 539f8eb802bfecaa4fb5b19debbf3d4847db9c4e0473a308ab3f3c859e68fecf
+Payload = 8b013f52a828905013f250fb9c006a173f6c66a64b5ba317
+CT = 556a439bc979dac1cfea8c5b64aa78547f52a62896c19893f3512baf72cd79ba9301194be204bcc0
+
+Count = 69
+Nonce = e832b6330d3e5e190598cb9c61
+Adata = 093be516277e8b197ba5e9c85a831529befff0f3971510ab611dfe0dfb50a2ad
+Payload = 635d2d7894bb816f154210946a369df37ea492993ba23af9
+CT = d8e19c67e5aa7f14a16ecaaac414a2b15a15bb5f966932e6b0bfe9a5857fd36df94aeadda7f83a79
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp
new file mode 100644
index 0000000000..2817684910
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = 553521a765ab0c3fd203654e9916330e189bdf951feee9b44b10da208fee7acf
+
+Count = 0
+Nonce = aaa23f101647d8
+Adata = a355d4c611812e5f9258d7188b3df8851477094ffc2af2cf0c8670db903fbbe0
+Payload = 644eb34b9a126e437b5e015eea141ca1a88020f2d5d6cc2c
+CT = 27ed90668174ebf8241a3c74b35e1246b6617e4123578f153bdb67062a13ef4e986f5bb3d0bb4307
+
+Count = 1
+Nonce = 195c0b84baacc8
+Adata = c7d9557b2ed415652ce6faa8cff5217ac803530ec902890b31eaaf3eeb0aa98b
+Payload = fe012718481b2c4e1d7f9a7685e3daac43ccf22cad0df900
+CT = 893af0f130f1317de9f217234274b0c04fcc202cea9a0df882c00b5b463654adbf82888099a7d258
+
+Count = 2
+Nonce = 363e0e921c6f11
+Adata = 805678936d4e94746ab4818dc5f50c41e32cf32e7a8aafb300fb91af6406108c
+Payload = 7e7e33e1a07d4e8fde2f33304f21cb564d146860ccfeb49f
+CT = 645cdd11a1c232815ce1e07ca3ea83f372eba46cedafddd980adf2762a1617adfd4d8356bb48aa8a
+
+Count = 3
+Nonce = e323cc866af462
+Adata = 163c747f3ba4ffd68af87f2475f48f2714659a2ec43b9ed115e02fe0e3c8be99
+Payload = 2bfc76f3b108ba3118b07433c4d3d5f41564d22547c12822
+CT = 0db04c6b068e73e3c4d71059bdeee3d27622f99dfd07d868fb9c02753c57fec7e1a5fa8f3860501b
+
+Count = 4
+Nonce = 03ae777078b95d
+Adata = f1dacf9062dff9a6a3d0498f9d058782f891475684196bf2d8e7e905393acff7
+Payload = 38c4275a5f605fd1d99517e13deebf0c9794ef586070fa9a
+CT = df8f524872b5f06f3f219ba76524990b466409894930d7e0d104990e598eabd88cc8342ac16424b5
+
+Count = 5
+Nonce = 1c6c351d4fe9be
+Adata = 14285e97cc3cae452e1a52e2fa0bbe24df96abf2faf6b9779acc59764612eadd
+Payload = 9e2220f3c17532e1ce0d6f562b049fcef35bcaf9a7e196be
+CT = c274b28228a6b13b670c325080f88d188d40d78d385481eae004894b1861db5d2d8ae98ed8926c1e
+
+Count = 6
+Nonce = a121dc27479397
+Adata = 359421e9f78cc4a31f4f019977d7fd29780524e20288798c50002a682a6368b9
+Payload = d42b16b32e77637724144eaddb21ca8d7db4e7f73acbf707
+CT = 56e3e3e59e978161355e7d8573dc0657db400ca0b083dae8ed2ac2cb63e1b9d7dc598634198fe4fc
+
+Count = 7
+Nonce = b1f0e26b60bf1d
+Adata = 2ab4239fffd13762fb5391f5a4760d12d96ea12666a793b4d651e9f4891c22c1
+Payload = 9a2851083ad4e7b915bb0526bb4054e4c0b4adf8626edc90
+CT = 5b2e0215523ff37f0df46e84f996fc9fc779986c766fa51595b8a23ee377d5c2850f4ed95a385253
+
+Count = 8
+Nonce = 50412c6444bcf9
+Adata = 09cdcaa87ddf8bbe6db8411d14bb9064e4a121286cc8a6e97fce1844935f436b
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 05cbc32a6ca797684636dedd16ce65a1eed69bcab1b1bdbd514ef5cbf9991a919fb4974d55506ce1
+
+Count = 9
+Nonce = 225557b0faca3d
+Adata = 21611da060fa90cf7fd68b721caf303307a56e56453326495b628c7dc93cd175
+Payload = e831b739e8eb9f787f63c0bb071ddcc9f44cab8d5b447d23
+CT = a97e0879407eb3b7f93118ca73f17eb34e9f4baf43b07be2e8a3f7b848054cb235e1b58d6a12c5cb
+
+[Nlen = 8]
+
+Key = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+
+Count = 10
+Nonce = 790134a8db83f2da
+Adata = a7a86a4407b7ecebc89434baa65ef173e88bd2dad9899b717ca578867c2d916f
+Payload = 59eb45bbbeb054b0b97334d53580ce03f699ac2a7e490143
+CT = db4961070f528ccd1a5a0681ee4d0ce3515fb890bccedc2dbc00b1d8b2bc393a8d09e87af7811f55
+
+Count = 11
+Nonce = fb2441d1594a488a
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 1bca7b0d35a68c0ffc568ffc8221cca738b67b95e3ab26efee21c5738d1f7fddf3030d004a702704
+
+Count = 12
+Nonce = 0855263860043207
+Adata = c7fc24863c33f7e8cf97b337918495d52d864ac570c99cbb09d151758d6b504e
+Payload = 61fcd7ef9bf151b9d8a81dc1ba4f82c45e9c2e4784627acd
+CT = 9b939b6b188e1d0fe016f366fb01eb79a99ef7b1b57c6f7ab223454c57c714d96681cd4d55615afd
+
+Count = 13
+Nonce = 415cd251a5e36943
+Adata = 1a393c7e85fb286709f4eb50f09640e1d65ec1135cb4443820136b3cec69772a
+Payload = 66ae08d494dc9df9b7f8f53199fa37d0c88885458b168c57
+CT = 1731e260ae31b8068ad1099313b167d9e6cbe49f471da61a9af96d3ce4ea94213b60cb69d92050e6
+
+Count = 14
+Nonce = d95bd65242bb2265
+Adata = d0e20e1358be5cc1c45c1cf02c82d0a6d0824cfcb65774cf95f047b9f2cc1d3f
+Payload = 312c3791c64d79205a11eebfc14b2d7a6b00391793c9559b
+CT = c3fbe558ff9ea83ed86b7d66503ee38eee94e4a41fd53f0f627a352d056712e0d44404c61712e2ab
+
+Count = 15
+Nonce = 3f0bf0141dd3ace0
+Adata = 9dd4ed18209dd6cdf19cc76fee443827e7331aaf020960c15d7bbed0f6a3b1f7
+Payload = 08354480047eee3beeb5ab165da17d23f2f1a4ad98720611
+CT = 2db9d2c54134d37ebefcecb9e2076034b975677fde58ef6032645a322fa9bc8aace600f942a84db4
+
+Count = 16
+Nonce = 3fd8b3a3ff563a42
+Adata = e58327efebad3276a7cd1b1ccb56db0caddd02a303cd9fc7ea5c607a2ebefaae
+Payload = d1abd89351384e1a3c3366f77c3175f6390801554d7cd783
+CT = be284dcb357ae99ada7cc891730320ebb32ca627eb8c80623957a2a5b6164218fc83e12c42d5c532
+
+Count = 17
+Nonce = 14db1ffc1c87117f
+Adata = 6c2b091433833a0ed915354dcb70d982095b614dc51a95a22cec417184d8e786
+Payload = 0594307491f157821e63f50c94034f9284f095d5b897153c
+CT = a114c84a10071e359bba2b2ba4ea67f893e27e6ea880aa4b2cf16ce68a93f8839245baebb2278300
+
+Count = 18
+Nonce = 40b0f74ff27a3fc8
+Adata = 3b9e1f4e9b57a6dfb5e0ca7ef601fc6af30a1f8650228e51e0dc61180d0bec6b
+Payload = fc8b7dbceef6b0ffcbade789e09303044042cd671607e819
+CT = d00ef56074a8213740af8b8f974f778db560ac365d6ce916b8d191130e864bcfcd1dec94a1aaeaef
+
+Count = 19
+Nonce = 96cbe9cd19351359
+Adata = cf498fd042f9a07503e490cec4873d4df91162cfde60bd2cbb2b710c6681a9fd
+Payload = 315e81c9ce556dcf97a5b68503fd2228a7a6a174a15cd618
+CT = 7383c2de08bce3f0b7e504dc03d062f44396bcedd2180fd954e6ec9f6ae1e0976ecf04dbee6463c2
+
+[Nlen = 9]
+
+Key = 58ae7965a508e8dd2eda69b5d888a28a1cb3783bad55d59d5b0da87137b72e93
+
+Count = 20
+Nonce = caa3d928d2bf2b7f2c
+Adata = 304678b3ffd3200e33a8912bcb556b3cfec53ca17f70ecba00d359f9f51d3e3b
+Payload = e61bad17640ecff926d0b0238271ee4c9f8e801dd7243e9e
+CT = 7bb1137c14cb4d324a4a8f1115c619ebf74927f0bed60a8d5a9140ff50dc4da375c7d2de80de097f
+
+Count = 21
+Nonce = cf09ca67659a583bb1
+Adata = 5507c4c3107cb446d19975f91207dbf3e2a51d1dcfd7da2f082159dbc3f41547
+Payload = 1887bb0c02500093a30a44b99e137483704b06615d308c6b
+CT = 834d3b2e5f0915c2348c706b4d2ff2717983ab4490edcc63971f02b7122d1e4f78de9c3376520f5a
+
+Count = 22
+Nonce = 97f940d7c1230bd8d2
+Adata = 56be2c9e09b555373d58f6fe2a0ca9b4ddba899addddf12b0fda860ad791773a
+Payload = 5ac67c9bec9b95c54e187a4a6812f5d701c4ac8f847c005b
+CT = 9f372ba1c87a115847cd708aaf5b8a143b6981ffc2c61cefd30ece13481609809b218de04c4e5ed0
+
+Count = 23
+Nonce = 147c7ebb6c92245054
+Adata = f95d64a513a9f3e6c95c9ed27b22fafd7dd10da52636029523142149116aff53
+Payload = 08f199a8d7e3ea821dd3106e8947cd2e9d485342b25a6471
+CT = c438aa6d187643d030dfe4d6b5b578f84838f4dc5c396d700c0986ecd7dab44e5e97db37392a485a
+
+Count = 24
+Nonce = b9bad794d49cdac9b3
+Adata = de9ff2a43f49cdc502cd17a373989bafd13fa6ccff6660557ce05b6295186d47
+Payload = 40d1cd4063750184356a1d7cae1cf1824f552c5d59a62dc1
+CT = 9952b25f4f4f375440cd958456184fe61610381ba92ca48f38dd977042c4d97da84e4effa650799a
+
+Count = 25
+Nonce = bbe054fbef86db3ce7
+Adata = dcec76181e3b872a5a6e79f070354e38866c7f67fc428fbca29ae6d929b1dd7f
+Payload = 5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c
+CT = 4d176f48b09b772dde8adbdaef720aba128a8d38a902847ebf22c81a5d824b4916660be6f9b513e6
+
+Count = 26
+Nonce = 6a35e1a4307f6efc6d
+Adata = af28120505a84a75b0f6b18cc9d8c75c661bf143be29c11d8ede78b9bb98c98a
+Payload = 5e2f601395ec406fcf96785f768162e849f867dca77667ab
+CT = 4e305e26d34711c6aa775f490939cc6560d3cb6905f5b0f5588ace6fc303600abc8e5825cbaedc7c
+
+Count = 27
+Nonce = f6c237fb3cfe95ec84
+Adata = 038f8ed89444784417a9c23bf11e9b436174e6c10959e00faa1704ce2f7f2c7e
+Payload = dfd9cacbf7d73d688447ebab13d2e13f3613652379b386f6
+CT = fb16c17a6b22a8658f446203ad46a48b34808083b271cabb015a1f78abc287bd2a63381ead07c558
+
+Count = 28
+Nonce = 50d024a3e7455d7249
+Adata = 8513365786b7988b208984e11022c15573f978bbdc29e8a7a4745c8a81885a1d
+Payload = 400317786b7df63373ffe541efcee6318cfc95bb673aad3e
+CT = d33b3141fea3a9ebdeb80d1da32dae42680be78471fb3023721f714120162514555b60560afa4256
+
+Count = 29
+Nonce = 02769283d5a06c363c
+Adata = 292c0be3713c6c588cb4e29a1c43b3e6353e33556194e568e800e4e44e8281e0
+Payload = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb
+CT = b15b1789c323a68568f86f35483bd7e204beff8f318ae14351f5e62b3b923a937e6c307af202fab3
+
+[Nlen = 10]
+
+Key = aecc5e18088bf9fd7b17f089bdd5607b69903b04b726361f8a81e221b1c91891
+
+Count = 30
+Nonce = c527d309ab29ee91c5fc
+Adata = 8f9a73e7bc1c11e2919020ba3a404cbddf861e9e78477218e3be2cd4337b278d
+Payload = d4291c99901345afe29f58912a414a7498f37b44362bdf3c
+CT = 392784a9e0b14bcd37639ec5409d6ead3e75f855e5a92c33ffc040ef3977e0035ce6ea6d157c18d3
+
+Count = 31
+Nonce = eebc31a5813b4fb93b63
+Adata = 9c87ad77953bf8a811e001ddb946eefafbfaa598150e85f0701853fa307d77d6
+Payload = ebcfd71120b0f9a2cccb898e6dfa082998cbe10032de3e61
+CT = e38eaad1e2df77e85e7129a8ce0f82cfc32b0aef79ab651bade65aa17e4dfb0aafe18cf71a72b180
+
+Count = 32
+Nonce = 231b33dc406c9210f59a
+Adata = 38be46d271bf868c198052391f8a2147c663700d9bb25a0caaa36974f18dacea
+Payload = 9032f910347daf661092b5c1f15b5ffed1369b194d9e12f0
+CT = 868b85288828501cf1d06610fec25e8b8a4b437e2e4f5563b7f3b898a2356909784598f8a8916f5a
+
+Count = 33
+Nonce = f2a88c3ebc74e62f24c7
+Adata = 5f495c5da035cabeb77e8aef10e91a05bd5aa414d1a37fa1099af959b26e5403
+Payload = cfe8ee9b475e36058471e2984ae66f6ba1b3cb477b15155e
+CT = 22c16333ac651cd9c183e78aba3e9312fb3b77dd6f9199502788860aae5534cf84979e30c3327d37
+
+Count = 34
+Nonce = 9cbaf1c83ba60b1e90ea
+Adata = 7ef136bd9a5809676abbaa68016d6fc713e34ac4b768a8246b1198c959f43085
+Payload = c3bcb0aaea93893f05eeb6439c8619dec17670a6439e2921
+CT = ebd9fb86563aa8f10062624441336f982c161ce5717d990a599ca6ec1c61a14c37b5902389e47aee
+
+Count = 35
+Nonce = e25322845d87d8a76753
+Adata = 2a89b9f0e56a1cf87dd38ed78028b6286ef8b7141dd2b3c65c5a8e1ed79bf4aa
+Payload = ae622ff9381854f831892c318bae5c003e74b15199bc12c0
+CT = 144c920f0fe278f353d0b053563d907c7589e4f1479d7a93a0604deb3fd9cea2d89987833ff5c2f1
+
+Count = 36
+Nonce = f4d7978fad36223623cc
+Adata = 8671de7e994967f2521d263925e745af9273682d9c08ced07d4a98fc985f68a0
+Payload = ef9b4ff8da108cabc972192ffecd5f96594c6d0871ffa6aa
+CT = ae4948b3bc1e50beb9f5d005871fc0d3dbde295de1c9ec3cbc866ab47bea7a4d0070e52b492fb8f6
+
+Count = 37
+Nonce = 6597ffb9eaad0fd9d830
+Adata = d2967ddf69ef62a9e23c9118dfaa55df92b4116322f1c9275131e3875dc92faa
+Payload = 5015c894b2437ff15c46bca9236830ff4bb057cd5764f027
+CT = 0b1dcb3cb0b4c32f398f3c43eccfe8f4242f33c99a2a2283efcb3dacac25bed0304f227fd5b77b8f
+
+Count = 38
+Nonce = 80e376b87272d99cde28
+Adata = c9cc8f967dff45c05b9345d03813b6e30dace99556f7df75b7120bb6e5f55827
+Payload = 615f657e24129a3e0f119988959608821219ce8354c4be26
+CT = d3e8b8f7ff8faa666ffe2509187fa7befc7412fd4e3bdb06cd2f7494b1fb0a0c6a2184e5c4787fea
+
+Count = 39
+Nonce = 344cce96455541d403f3
+Adata = 748cce18fb40126ce125dbe341fbbc59d2aacc170ed5ef0293b15713c9184a07
+Payload = 828b6a4cd49f499a6e8e8508f9ab35255d8e9fed33ba4d91
+CT = b67e582a74d7f022a16ada2de7ec18caafdefa6b104baf4ed93b6f8c8a1bf72be75976e4ebe6dd1f
+
+[Nlen = 11]
+
+Key = 97bc7482a87ba005475dfa3448f59d4b3f9c4c969d08b39b1b21ef965c0f5125
+
+Count = 40
+Nonce = 0bcf78103ec52d6df28887
+Adata = 049c10f0cb37ae08eae2d0766563b7c5a8454f841c2061a4f71a0a2158ae6ce5
+Payload = b99bf4dc781795fc4d3a8467b06e1665d4e543657f23129f
+CT = 0d3891fa0caac1f7ebe41b480920ffd34d4155064c24f3b17a483163dd8f228d1f20cd4f86cf38fd
+
+Count = 41
+Nonce = ab6374c6b2faefd92fa3d3
+Adata = f19c044023e5cf339203738ee70e76527519763664c06ae00e002a5ba94c32c6
+Payload = a2e5c51f516db01688b64c173bb25645182a005018022ee1
+CT = f70c598df3c64d3527ebb7fc8408b7de2cfaa1da7984ec361f1ad61758d828b70d4881b7d6ae8cd0
+
+Count = 42
+Nonce = cfb89e7ddcba601e875110
+Adata = 052714010da516c896ac5842a839ae845324643cddb080e6206148432d0d0407
+Payload = 037f206cab78a6ca0745dc8fc137e22e14f3d7183917ef83
+CT = ccd675862502a2e2520a33250150b8b7b220e84db854888c316dd62075fc761e2bc80edc5c564bdf
+
+Count = 43
+Nonce = 967cb6f8530bf8a43adb42
+Adata = cf391a84d03e2e22aec1965cec821f99e7bf21a7c3580dffa531464b22d83225
+Payload = caa3d928d2bf2b7f2cd8a7f357055b6d6895a5e34f47972a
+CT = 4f4f509debe6e52eae4af8b1740dde0a5338f78711a3b4ebfc8b5aca6d606222d6af7cfea0d1f4e1
+
+Count = 44
+Nonce = f5b7b5dd2b5e1ec93710c9
+Adata = e7a6b228a67d37b9d29a38efc547e50b4a6d95d599b45ee189ece21101ac6b5b
+Payload = 4a74ff35418723f2cecec1012484b52114067b2b2393e7f4
+CT = 25b140922a9d4f2ce153a4ff86596a49d7de6a6184e931e8b2ff27a98029b23484e00c2a5d291887
+
+Count = 45
+Nonce = 713de00faff892977d99d0
+Adata = 14ea93488d4284d21d4c7ce14414adf45c1ed9d2d99db866d0e59accb6234dac
+Payload = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698
+CT = e4d92ab8d1ffb0976670d891cc8338da12f86d5d79b334103d2ae816edf857c810b6fdc7f2c71f1d
+
+Count = 46
+Nonce = ba87934808de09b2ae829b
+Adata = 30e2ea2a505f19e8760a0a84961000c7a0b7fe3460a9d3f5a38f54149be2e9ee
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 6df893eed2be958e5f542f8cb4adb392b34786cb4ce821ec93fc57997b977948d55bdb026db5bc48
+
+Count = 47
+Nonce = ea09fbe5da0fa4fe911e18
+Adata = 237dc8512b29bccdeb8ee39cf83b9b6dd203823d175c44d5f605b194e7ec136e
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = 2f204ebcf549ee2a800d870e6341b9a89a41ab4ae91b6902ff704a2bcfb8becd0226f76d68fbb08b
+
+Count = 48
+Nonce = 5b80d7affc4ab4a4b68bdd
+Adata = 3a38dd7da30f5c312fb1e978d87b7a39792fd9ea3e9ab1565874e99df587327c
+Payload = 5ff92f6d3ca791421363e10cc84b4e8e21e0ebe5d8c55d6c
+CT = 05472db7875d59f8bed45606f355a516de93740aa2baeba18df9400df42baee6b9a0d75b45840104
+
+Count = 49
+Nonce = 514bba483fe7f2b7e555cc
+Adata = ac8beb419099cdb42a39e9b46fd900cc52eec4b43a96ed18b37b899b63fb931c
+Payload = b0b11dfca9b3936d1b4a423c5acd3d012b399a487c19c994
+CT = fa20629d514c4ce7bf727629bca5aa1c0c7e7851fc1bfc5c847729a70d7b4cff5281aece37006015
+
+[Nlen = 12]
+
+Key = d6ff67379a2ead2ca87aa4f29536258f9fb9fc2e91b0ed18e7b9f5df332dd1dc
+
+Count = 50
+Nonce = 2f1d0717a822e20c7cd28f0a
+Adata = d50741d34c8564d92f396b97be782923ff3c855ea9757bde419f632c83997630
+Payload = 98626ffc6c44f13c964e7fcb7d16e988990d6d063d012d33
+CT = 50e22db70ac2bab6d6af7059c90d00fbf0fb52eee5eb650e08aca7dec636170f481dcb9fefb85c05
+
+Count = 51
+Nonce = 819ecbe71f851743871163cc
+Adata = 48e06c3b2940819e58eb24122a2988c997697347a6e34c21267d76049febdcf8
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 70fd9d3c7d9e8af610edb3d329f371cf3052d820e79775a932d42f9954f9d35d989a09e4292949fc
+
+Count = 52
+Nonce = 22168c66967d545823ea0b7a
+Adata = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4ac9f3b61e7e8047fd
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 30254fe7c249c0125c56c90bad3983c7f852df91fa4e828b7522efcd96cd4de4cf41e9b67c708f9f
+
+Count = 53
+Nonce = 225557b0faca3d6cbaedec5c
+Adata = c7aafe7d3b419fa4ea06143897054846ac4b25e4744b62ba8a809cc19253a94b
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb3
+CT = 2369b56f21336aba9ac3e9ba428e0d648842a7971182d5ffac57f6ae1080efab4ed93f8b4ce1d355
+
+Count = 54
+Nonce = 78912be1a35e156a70fb72f7
+Adata = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb80d77fab2c4900e0
+Payload = 113efd182f683596862ccd5eba2e2d4ffa709d9b85c6f1d5
+CT = 835a22eb8d718c0ee1531a2d1bb95f58215c997c612908eeed3ccaeb7a814f69d3ec1fbf2ee9792d
+
+Count = 55
+Nonce = 91ad90b58d2044abacf957e1
+Adata = 4fc795b9126c23dd7fd514c2e5a8ca583e88a783b28cbb2a5df09f8b520ba0d1
+Payload = ed55f6b9eb8fe74474c037ede94ffd84ada846ede4ecff74
+CT = ecb595276fd5d412a7cc3f5cfe960f47a0d0e2df0b08a11ac257d67143722a976c9d7f44b09a767d
+
+Count = 56
+Nonce = 4bbe4ca29122c4892ca09b5b
+Adata = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364449b2391230be846
+Payload = 8dd497bb777bbc3e56e3af25a43545007bb00f2b9e9f815c
+CT = 563d61fc0a5b82804a580a7d752a8e61d3342fb39372b39b6843a685bde3175695796f6e64f35901
+
+Count = 57
+Nonce = 218e7b8a8fd62927f90b70e5
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf001429122e46bde21735f63adba
+CT = aaceb16589b9de253c99d0d32409a631db71e8df8a7644bfd027e3466e8220144cb0552f9b2800e6
+
+Count = 58
+Nonce = eecc9f106a0721334cc7f5ba
+Adata = bf38d0ee11a796a517539bbc9ab00ff85a4ddbf0a612d46e2bc635180ad34c50
+Payload = 36cefa10af1a3446a2c8d4a1171144b9ddd8e33a7cd5a02d
+CT = 9bf3b2df93cf5b587ecc96f45fc75e6eb066cb286cb06f284c9027fc41bb8c848025fcf9d092a873
+
+Count = 59
+Nonce = e41af8ca408c4c12e37561a4
+Adata = e0b20892875f60b5d8763a04958487fa5b7cf8d67a456e430475b337245d671c
+Payload = 32a4da08bdd51336ed5798c7177b853a534bc98f2e6f7d4e
+CT = 95ffdc68f721cf2294d0d88002e3814167306fd906dbebdb7e6e0e5dc0a03826e51bd94269d7a41d
+
+[Nlen = 13]
+
+Key = 4a75ff2f66dae2935403cce27e829ad8be98185c73f8bc61d3ce950a83007e11
+
+Count = 60
+Nonce = 46eb390b175e75da6193d7edb6
+Adata = 282f05f734f249c0535ee396282218b7c4913c39b59ad2a03ffaf5b0e9b0f780
+Payload = 205f2a664a8512e18321a91c13ec13b9e6b633228c57cc1e
+CT = 58f1584f761983bef4d0060746b5d5ee610ecfda31101a7f5460e9b7856d60a5ad9803c0762f8176
+
+Count = 61
+Nonce = 8a56588fe5e125237b6cdc30f9
+Adata = b3aee5fbf409bcfe9b46ae68d570edbbed32c12d13926ffb5ddc60ff0bdb7f85
+Payload = eca81bbd12d3fd28df85e2cc3dcc2ecbd87408002fd00fe1
+CT = 9aad62a5443550d11f9efdab2de0eba74d47ae4f7d16adf4276664f6567f2f978bd4be4d80cd07be
+
+Count = 62
+Nonce = d908b04840caca2280e5293ade
+Adata = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+Payload = ad1109ea5c79bb55d22e9713eb2df42767cb29a2eba3ad2c
+CT = 61fdcebb158cd03151697ae7871c0a998802997e0672e5886e5a9df1b1d6284ef657cde6f74734bb
+
+Count = 63
+Nonce = 6df8c5c28d1728975a0b766cd7
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = 704f60f9cc3ef7bc00b4f7a271ca70a89f4d5605387b3e2f8cc80aa08572b90e9598d0a73712b720
+
+Count = 64
+Nonce = 6c6ebacce80dde9fefb7e5bb47
+Adata = 93f0fca0c8c84d5cc48160b25e246226d489225c0f8275e52856da592c715aa6
+Payload = 46820aec46ebd0d61706129584058a1498514928a87fe620
+CT = 00f6cccf45f046da1e6266afe61eed61c60c28515b2e1ab386b2c952055899184f0d95ffe3959f89
+
+Count = 65
+Nonce = b94bc20d8c9abca7645fc6bebf
+Adata = e1c083c93663f5a066ef337a61aa3fddde7c301a42463137c375cc2dcdd76954
+Payload = f1fca581d3dbbc61060c0c02adb47bc57954d25a283f66d6
+CT = 90c65d23e0e1786cebb95f9b1306d001b2e503842cdedb75e37a53d77b9e38605febdd7b2b666f98
+
+Count = 66
+Nonce = a4974791d417d7e9eea0f4ae8d
+Adata = 33602f308f3a0f7e1c75fc1e4321d545ffa278234958dbadd37f59a0f85349c3
+Payload = 41712c058d2d56b43b2c79278e790858a289320746c15a60
+CT = aab5656a1ef060c9b1ef7e2f3cc0bda40ff067900401182563ceb824708a20724c99c83f1caacd70
+
+Count = 67
+Nonce = 6003b771afe4e99e1ef1ed4a31
+Adata = f60d8362b2ebf523681bb051fd3ee13919ad86acd963c703c4178a5f01a84236
+Payload = b766022311c5e1d74a607fec7cb8ee805b8397a6c5f374c1
+CT = f73b2a6dbf8f798d4bfb489a6578c9c79152e42aa3b81b64a84e7af3116a18f7ce44ae93f420270b
+
+Count = 68
+Nonce = 27861168ac731a223dc35c03e8
+Adata = b7ba1c66282cb6092ba601407ff9578afdadf7ba7a4d08edef06dbbfd87171bf
+Payload = 0822e3e6ba982091d532cd5271fbde25305d1f6e71880f81
+CT = 5ab3e5296cd1f08704c82f6b42939702515b7733853d723d4009312bdae46958d844eca502bcb005
+
+Count = 69
+Nonce = ef284d1ddf35d1d23de6a2f84b
+Adata = 0b90b3a087b9a4d3267bc57c470695ef7cf658353f2f680ee00ccc32c2ba0bdc
+Payload = bf35ddbad5e059169468ae8537f00ec790cc038b9ed0a5d7
+CT = b702ad593b4169fd7011f0288e4e62620543095186b32c122389523b5ccc33c6b41b139108a99442
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp
new file mode 100644
index 0000000000..f79db90b4d
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 2ebf60f0969013a54a3dedb19d20f6c8
+Nonce = 1de8c5e21f9db33123ff870add
+
+Count = 0
+Adata = e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603
+Payload = 00
+CT = 0ead29ef205fbb86d11abe5ed704b880
+
+Count = 1
+Adata = 98d477b7ef0e4ded679b0bc8d880f09823ad80e9732fde59c3a87da6a1fcf70b
+Payload = 00
+CT = 5b85d144bb51d4927074d3536a2db83a
+
+Count = 2
+Adata = 28f32de10b6c9d3c3f46efec7aee24006208a54c4d1c2bba4b8cdce166cab7d9
+Payload = 00
+CT = 01045de4a09486eea5efa33ecc6cd299
+
+Count = 3
+Adata = af397a8b8dd73ab702ce8e53aa9f0189995c6c9e920dcb75795149550b499deb
+Payload = 00
+CT = dfd75400b59c3ad387bc86dfbbfb52ac
+
+Count = 4
+Adata = 3fa956bfaa27e249bf0a1276468d808259f3b8e2687851d780885d44cc2f04bd
+Payload = 00
+CT = 2b11d2549b4e2f0a81c07ee90af4d081
+
+Count = 5
+Adata = babbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79
+Payload = 00
+CT = 10f76ab445f4ec158ccc1f7c6fee3ede
+
+Count = 6
+Adata = 7fba0bfda3b03c736c121cf9a257db55060b621be5168619ec4182f13ef6a408
+Payload = 00
+CT = 59e02d6a6aa3fb2692b04e65a0e735da
+
+Count = 7
+Adata = 057354a29808f4ed77671ed3dc36f8b03f5cd952caac5cb80dc3b319f3333e29
+Payload = 00
+CT = 367a2ade4087964dcb0ca2984d44657e
+
+Count = 8
+Adata = ec08b618602d091e9304715cb552b357c16fd1d7f7f023a28d84a98ba21ca0ab
+Payload = 00
+CT = 47cb92cd40bc89328d4dd44fbd727032
+
+Count = 9
+Adata = 45622834ea658b09b17f32777d18b34b387ef957bd344468f68e7178417a7c24
+Payload = 00
+CT = f5185afb8359b5ef995483c0bc4192c3
+
+[Plen = 1]
+
+Key = 6ae7a8e907b8720f4b0d5507c1d0dc41
+Nonce = 7f18ad442e536a0159e7aa8c0f
+
+Count = 10
+Adata = 9c9b0f11e020c6512a63dfa1a5ec8df8bd8e2ad83cf87b80b38635621c5dc0d7
+Payload = 0e
+CT = 4c201784bdab19e255787fecd02000c49d
+
+Count = 11
+Adata = 73616a428f1a567b2e9af86b1fc8aec6d597b1b55f2aa2219b3b662fa6bd3407
+Payload = 30
+CT = 72f14519f06b63fac3d5b2d9bbfa0cb758
+
+Count = 12
+Adata = 6d62f4e15e8bcc9ba4993bc50a046737121016f0d15020b90068250551167b1c
+Payload = 34
+CT = 7676b581a28ca0a0ba5178eba7fe028da6
+
+Count = 13
+Adata = 8f0b8289a1834ecc2167b59ce3c9d3b58465c4cfaad50c728d04360cb7e5bc41
+Payload = ec
+CT = aed99b805c0a4785ff2913cab3e50f6205
+
+Count = 14
+Adata = 477b2a6932f838f0d1bc420c0ca306981d8e2dab945b6f259e15fe888667220a
+Payload = ec
+CT = aeb50e41cd7af84a8fdb6aee144e904616
+
+Count = 15
+Adata = d6518d409b1f05708d0b44f18fb5721f20f3220f8d2f2718650aa9932e4579e0
+Payload = d1
+CT = 9312639c863974f077fe8236c943b464c4
+
+Count = 16
+Adata = 865e7cde73b558e9bfd05356923f8a697970811fc484acad2d5b3528baf1f986
+Payload = 24
+CT = 66d7265cde50bc7a3989458437baf06db5
+
+Count = 17
+Adata = f0c3c67a935eace53ed32435655dd0974fafe283622e8294a15d70977398eae2
+Payload = c5
+CT = 87063144b25d2268063815d1b42ebbac34
+
+Count = 18
+Adata = 341e71b2ef26e9db03882e06d06cde2c0617326cd157d5984d22f6f3407a9c39
+Payload = 34
+CT = 767da45c10d0d6498716bcf3f13ca7e26c
+
+Count = 19
+Adata = 31fce6735ba9a3385df11c153179b8e4141a3c6b8ad6eceaa211f3f17bfd0474
+Payload = 7d
+CT = 3fcb0a6f562974cfb3fb7c8d5cafd50f2b
+
+[Plen = 2]
+
+Key = 3d746ae6cac5cefd01f021c0bbf4bc3c
+Nonce = 597b3614ff9cd567afd1aad4e5
+
+Count = 20
+Adata = 90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad60
+Payload = 4360
+CT = e38fdb77c1f8bbac2903a2ec7bc0f9c5654d
+
+Count = 21
+Adata = 6bc3d30925c67371573271f1a4273ad76e91e07dfab65f7bce0b241b5e4cd00e
+Payload = 17c6
+CT = b72955210d62e1393e4fda647c2b2e59a47d
+
+Count = 22
+Adata = d1bb4cdfc3f2c16d92576068543692aa4b5a427d688387af0f1583e91a0e8b3c
+Payload = 6575
+CT = c59ad54fd88a47b9f6e39cb4606af86d13e8
+
+Count = 23
+Adata = ae6136df9ab43631ef143515dacedbe759b3459e951bfaf4712a21c86352f1c0
+Payload = b1dd
+CT = 11326de841af64b55bb7ebe3fd30ba493c7d
+
+Count = 24
+Adata = ffead34ac26e21158212d07c367c3a7cb6b795887ee2d3d8ae25c60556ea88d3
+Payload = cd16
+CT = 6df93a206339de534271f6469edfa5ed07d3
+
+Count = 25
+Adata = e768e7d867820d46c1cc62ee0e51d4dac6f5c4b5785b5ccfbf05236871bdce2a
+Payload = 12f5
+CT = b21aa8f65144f2ec5809e2ccb38c8760f7bc
+
+Count = 26
+Adata = 402e802885e4119df17fe85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b
+Payload = 39c0
+CT = 992f9af825957abe7d89e175b6e8c0b84b5f
+
+Count = 27
+Adata = 8a3a622b3d347c0c5210d484adf77fa33205ba02224ddceea71d89c9ad8429ae
+Payload = 912f
+CT = 31c025d6a12e91e84e355934547f6b5dceb8
+
+Count = 28
+Adata = 636114e5e5f83cec94e1df21d6babb9f6a14a532fcbfc3bcf649fbd79ac1abbb
+Payload = cb6d
+CT = 6b826db959a21e9e4ebf25ca4f98501b560d
+
+Count = 29
+Adata = 04e84f9156998c2eca9e96079a6001f2947dc49a081b3d75e47d75f71ed4a606
+Payload = 5bd2
+CT = fb3d2006ff22ff231a6646ae561923818a21
+
+[Plen = 3]
+
+Key = 3e4fa1c6f8b00f1296956735ee86e310
+Nonce = c6a170936568651020edfe15df
+
+Count = 30
+Adata = 00d57896da2435a4271afb9c98f61a650e63a4955357c47d073c5165dd4ea318
+Payload = 3a6734
+CT = 384be657bfc5f385b179be7333eb3f57df546b
+
+Count = 31
+Adata = 50f6e6dd57bd3a24f6bfdc8b1c7b5a36ebdd07fd6d194e6e82da47151d9c88fb
+Payload = 4ffad3
+CT = 4dd601b8ca97bda492546d82dccdebef441f8b
+
+Count = 32
+Adata = 70e132023acae1f88c7a237b68f5bdce56bcfc92be9f403d95d3bcc93b4477a9
+Payload = 8a594b
+CT = 887599fa0f3e397d9a580aa39c7028e1a508c9
+
+Count = 33
+Adata = 08d2b011f36e05dc728c1a8bda3d92c779a3d2f27c4b041810bd6222c852b14d
+Payload = 1f89df
+CT = 1da50d593460d335e2f7a6d40b8fe305b0f690
+
+Count = 34
+Adata = b207eb870aeeab27c6201ef04650bdc7ea30028a243420f7d198f1c9c9a43023
+Payload = 72e9c1
+CT = 70c513a2d49e1a113767ea4219107819d88b65
+
+Count = 35
+Adata = 74294088721fc9e7aabd5f1c66b5369b1e2d2cdb3e73abaa28ecd1c37d4ecea2
+Payload = 016083
+CT = 034c51dab1c819778be8453db163c882063af8
+
+Count = 36
+Adata = abbd347999a1c26368cdb17ab08bf57a8e942d1248296e952f5f42f2cabbf0e6
+Payload = 25f665
+CT = 27dab7537eb435df8d0e48c3f7e0bd1877c866
+
+Count = 37
+Adata = 231b33dc406c9210f59a5df1cfd595c803474db34b9b1848f0bcbe7b28df33c2
+Payload = 158606
+CT = 17aad4da549fc63d55b5910bbbf64435b95220
+
+Count = 38
+Adata = 69b851e63a78baef90637978e3dfe8c47be4b21e85bb89bf67051cf251004376
+Payload = b07452
+CT = b25880d5ee29fb2af47f8040fad585921057f5
+
+Count = 39
+Adata = 9b1f786c887d310b8efd3e8192fe504f603024c94aaa4ec9123736a40bf1605d
+Payload = 65187c
+CT = 6734aebc3ee43e10205f83143e0d3794a6734c
+
+[Plen = 4]
+
+Key = 7ccbb8557f6e08f436d0957d4bbe7fdf
+Nonce = bb8e2ef2ed9484f9021cda7073
+
+Count = 40
+Adata = fba1d18a74a3bb38671ab2842ffaa434cd572a0b45320e4145930b3008d8d350
+Payload = 4cabeb02
+CT = 32501f4235c4dd96e83d5ab4c3c31c523453c317
+
+Count = 41
+Adata = 78b3faecb2bdf6ed14ac2b86ded07aa791b60f5d54f9e24a965a8453f5131898
+Payload = 5ff73653
+CT = 210cc2137907d6a03e66403a7d9330d30d934a8d
+
+Count = 42
+Adata = db1239528eb464dd063e2a97ee83a87d6002ebb4fbafa77036f72c14f3fe959b
+Payload = 062fa9ca
+CT = 78d45d8a44f4bc78fbb969935076134437df82b4
+
+Count = 43
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cad710b4
+CT = b42ce4f459692911fea2e0034d06c3b2e89af3d1
+
+Count = 44
+Adata = 7381471a62b1fa6f5061c4c37e9721f07099d007ffaf8639aa2ae3f82da5a559
+Payload = 7ac716b4
+CT = 043ce2f468484e22381923bfcaed16e0cb85b0f8
+
+Count = 45
+Adata = 19bea6d92d5892216e8e4a30dda802387800bb046a6717817fc46c7edafe17b0
+Payload = 362da02c
+CT = 48d6546cd081de39c247df309c4b56c31c03690d
+
+Count = 46
+Adata = 8503c8eb9cebc6110f259e35e03a0740267768130ce6f61b1c7d1d25be942274
+Payload = de52b209
+CT = a0a94649c6c6bd7b3a9d7c4dfa2738847ea3cb33
+
+Count = 47
+Adata = d2445db6efecaa3f426b06de8d496ceed54a1d0171384cc762e21b31e265c6d5
+Payload = 8fe8b383
+CT = f11347c32ca874d18d0b790856837555f4d4699a
+
+Count = 48
+Adata = 8cda7d1e135cf5fde1ec9473c4b42c1bbb445c27fd87b5f73df61ceb2d0b6f75
+Payload = d8d6b2c9
+CT = a62d4689932c2f8d78e322aaffc90846025190f1
+
+Count = 49
+Adata = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5a4c25393ecbf2025
+Payload = 6a029e53
+CT = 14f96a13c346a4084918081b4bbe53b50d896788
+
+[Plen = 5]
+
+Key = 3725c7905bfaca415908c617b78f8dee
+Nonce = c98ec4473e051a4d4ac56fd082
+
+Count = 50
+Adata = 11bc87f1c2d2076ba47c5cb530dd6c2a224f7a0f7f554e23d7d29077c7787680
+Payload = f5499a7082
+CT = e378b776242066751af249d521c6eaebdff40b2642
+
+Count = 51
+Adata = d54219ef4fb851bebd1c546011ae3922b8337e19c28d4d58428efd66f80edcf0
+Payload = 513c46fcce
+CT = 470d6bfa68e7258df363e0e9af67a543c86db3c994
+
+Count = 52
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = 9d62e557c3
+CT = 8b53c8516572b7573e5b27a1d0e15cdb7b06c8857f
+
+Count = 53
+Adata = 77d9c306aa257379053cf1f2043c388a301dac2a9e2bb89eb8bab6eb3f150fe3
+Payload = 7a05db235f
+CT = 6c34f625f9de691a412ad54bbdb6ceac45ed45902b
+
+Count = 54
+Adata = 081568ae0b948aa647b9d4dda5d42641ad5de72aa9874d8d0717d872007720a8
+Payload = 30a22ca0fc
+CT = 269301a65a8a1bb8ba3d6763dcb1bdd3400e3459f7
+
+Count = 55
+Adata = 695ba4dea0f84baf190ec25a25fc00cb9898902d7a17e6f5ff2df323b974f7c4
+Payload = 35e25aa51f
+CT = 23d377a3b9403897d496cabcd5bd9de3282199a8ed
+
+Count = 56
+Adata = 1f3ba0336a634efdd11f8168c0fe25039f9403bfa70b3898f4dbe577dbd52957
+Payload = 8bde704c74
+CT = 9def5d4ad270a81f7cb0ab7ab2b495f51d66abeee5
+
+Count = 57
+Adata = 097b9ebff3ff93a143678d59721fdf359e95cbc82585ae47727a773317925d38
+Payload = 428542ecfb
+CT = 54b46fea5dce68e9b01a4462a2221bd2f3cadf64c0
+
+Count = 58
+Adata = 76d0341dd44c39e43a23dbcf4cb602f15d5fb9fee20c3d0d262d539c3fd1dfd5
+Payload = bd6866ded0
+CT = ab594bd876f2545964ef3978cad3387d61104bab84
+
+Count = 59
+Adata = 7e7c40ad64b511005b4546f9ec61ca24829390fbc4bd8507225bc348ae0807d7
+Payload = 5822755a3e
+CT = 4e13585c98002c41938a935d51905b2a708a2c5194
+
+[Plen = 6]
+
+Key = 80bead98a05d1bb173cd4fca463b8fa3
+Nonce = 8a14a6d255aa4032ebff37a3d7
+
+Count = 60
+Adata = bb4e706e73d21df66f64173859d47e247527cd9832e20dccff8548ed5f554108
+Payload = e479990bf082
+CT = 89c9246238878427f36b1f6c633e4542f32b50ca8edb
+
+Count = 61
+Adata = 9db2182c8a4f5471082bfa1a8496602cbcdef2790f7e8f71f791303bd48dcb05
+Payload = 017a7fd1aecb
+CT = 6ccac2b866ced76fe54da69af5edf8309c7f013bb07e
+
+Count = 62
+Adata = bf483f59fb73681f27b68168c998c90ea8ceea997654c6fab2bd737dcdc884f9
+Payload = 512fc5e4973a
+CT = 3c9f788d5f3f662f53d17f7cb6673415bb2324ca0666
+
+Count = 63
+Adata = b91e641d8210e1ef705fec2beb9f58a391c7d1a38935cd1d13f2c00363388ff5
+Payload = 06212e989616
+CT = 6b9193f15e1340c86156b1065b64af1e4d6c89b32603
+
+Count = 64
+Adata = 5cebf908e232d797fcce8453c4c3000868d4172622a4ee0d6a1bdd876a0b7c96
+Payload = c45629069ebc
+CT = a9e6946f56b9c07ef5349903b928e39e99e2e32625de
+
+Count = 65
+Adata = ab92cbc97f3aa6f9ea4dae5d8c3d9e91231f43ffff548da7b668e61c183ac2cf
+Payload = b949ced37725
+CT = d4f973babf205e40654ea16e83cc6faeaad668c416f3
+
+Count = 66
+Adata = 2c3d2f9c7e89c2b9e07317c4db6e9f00f5faadfad531c5bea79d164ac24d4543
+Payload = 517ff7b383b7
+CT = 3ccf4ada4bb23102a502dbba0c280e1d5fc627fe3a9e
+
+Count = 67
+Adata = d798e77ab0f3697768f23014fd31b9e8762ae65b6aa8a4bbc17ecb8cbe78461f
+Payload = b40d863ca4ff
+CT = d9bd3b556cfa6745fd4c954396e696697731e1f9a262
+
+Count = 68
+Adata = 45b44e3dec57e24d960fd1767797ffdbbab81e38bab37e6974df262c3d932327
+Payload = 56e00289a003
+CT = 3b50bfe06806bdf2b2dd47077c98234eae5d47c3b594
+
+Count = 69
+Adata = 645d27970ccce096d082fccfc1183955bad2611af0dd7c58c9d54430f28bd992
+Payload = aa22bb1de579
+CT = c79206742d7cea66649ad7e204a344d3234125aa324b
+
+[Plen = 7]
+
+Key = dc8ec91184ba18eae31ac2d3b252673f
+Nonce = 0da4c988f521f5648259f2bec2
+
+Count = 70
+Adata = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024b3651eb227e73bb5
+Payload = 2a5775986551c8
+CT = 4f259f2a718faea852a7c4358dfa9f5467357638acac90
+
+Count = 71
+Adata = ff0ab5021ef466e2e898b0993d691145168be558682c74914c172f2b5e863754
+Payload = 8db3c1ca0580f9
+CT = e8c12b78115e9f8767c76e707d48a2144e090812e0192d
+
+Count = 72
+Adata = 2ee03cc28f79773af139c4ea55ec4daa48bb2885b8adcd5f066eceda5c4ec27b
+Payload = 3c69e2e83236b6
+CT = 591b085a26e8d05486df740083c959fb62ef7e2e221602
+
+Count = 73
+Adata = f041504d4c1b3d5be358bd6d350af42921205d29ab22b44ffe221358adef5bb4
+Payload = 777828ab5ccb68
+CT = 120ac21948150ebdc4d2b86b2528f75db4a7f5423f4395
+
+Count = 74
+Adata = 81ea116832d69542ac8d3d22c16c82eecf2ccac39264dd933c4f9c13c8d0f1d4
+Payload = af556fef3584e3
+CT = ca27855d215a85a7b06d1b710baa15daef19069ecf46f0
+
+Count = 75
+Adata = 8a0a120ed290a62456f002da1c250a0ddb1ebd57185a733d8fb562aad482679d
+Payload = 98f26635351f14
+CT = fd808c8721c1723811129add52e1406d50cbff4aa82802
+
+Count = 76
+Adata = 12b5a76faedf6f855e328c2cb87be8aea78c5e926b32d828e167b46205c86de5
+Payload = bd22c1ec05dc26
+CT = d8502b5e1102401563d3da8a6cabb7515f642e42fb4b2e
+
+Count = 77
+Adata = 8dc32f35ef4bcbfd040ad25dc36d0bd2486f93d0cabb7704cd1582dc99f65449
+Payload = 2a87c0d64806fe
+CT = 4ff52a645cd89817609a21f703253e5e56beef4ac71759
+
+Count = 78
+Adata = 83ced632359a11eb0c4c99baad84df5cac15bc5453b6593d9ffb4c5e8c84037f
+Payload = f05f39eb0a3d64
+CT = 952dd3591ee302236c72f98da859b54be7c598d85c37eb
+
+Count = 79
+Adata = 771a818a24e7da7b98f4b4291ef34bec7e1656b0c6c6e9474a989a04ea7de385
+Payload = 59dad755af92c2
+CT = 3ca83de7bb4ca464c8cd38cbcc46e7f09bf3e1c6590c71
+
+[Plen = 8]
+
+Key = 19f97ef5318b8005fc7133fa31dd1236
+Nonce = 01ce9814c6329dbee1d02b1321
+
+Count = 80
+Adata = 85853f120981f33cf1d50fde6b8bc865fe988a9f12579acdb336f9f992b08b89
+Payload = 6d972a673fbe1ca1
+CT = 2f12a7e7acecae5d2563309efc19368cdee8266538ca89d3
+
+Count = 81
+Adata = a4ec5aee89e2cce2115b6c1f42570bc5062887cad08192a682d0b4508fcd936a
+Payload = 68b1b6367a15fe49
+CT = 2a343bb6e9474cb528096a5fec5e5359c369833eac3b7efb
+
+Count = 82
+Adata = f5499a7082bf1e6e2923211271f5f7f6d7c7b26db7963071705a58ddc4dca0dd
+Payload = 707023615563a40e
+CT = 32f5aee1c63116f2754a65863efb60c98dbb536e2b5a69d8
+
+Count = 83
+Adata = 765f267befe6fcfaaa4b46eda32e7bfab87f12ceb07fa3b37be74965bb664a21
+Payload = b56454bc50df3e28
+CT = f7e1d93cc38d8cd40b6e9b7f3b3541ffee66a1f668f67d28
+
+Count = 84
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154c55e40
+Payload = 962f765da3565bde
+CT = d4aafbdd3004e9227018c9db8baf6be349d93d4eef7d7c9d
+
+Count = 85
+Adata = d0125e30c36232a8c07cee9abc53453b276849a7c04ade80ad586ed8cbcede51
+Payload = 4f18bcc8ee0bbb80
+CT = 0d9d31487d59097c501b28887f05fd66f050525943d101f8
+
+Count = 86
+Adata = 90dfd9e7bb7bf8fb70c22a879ffa760d14cda7b79ce4968f69b8a7f2b7a59642
+Payload = ca293c9e1780b401
+CT = 88acb11e84d206fdda53dde2e1aef96b3658a7635ee54188
+
+Count = 87
+Adata = 58f518710e6b282482a7f1950fa353b13bdda10c9aaea6d5f0d7ea0a965d31e8
+Payload = b9df9fb4a6b299b4
+CT = fb5a123435e02b48b62a5ec234f1efd1b52c8fad1cf09890
+
+Count = 88
+Adata = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb07545e6802de7e807
+Payload = fb2441d1594a488a
+CT = b9a1cc51ca18fa76bc051ede6f37cf67543a7252d7d9b203
+
+Count = 89
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f266
+CT = 07948ca59d94409a5be4be6bc6b18104fac167b6e3fc15f7
+
+[Plen = 9]
+
+Key = c17944bfaeeb808eed66ae7242ab545f
+Nonce = 910b3db64df3728ca98219e01b
+
+Count = 90
+Adata = edf64f98b3ab593cbcf68ab37a8c9472e49cb849d4a744deae925a5a43faf262
+Payload = 7caae2640e734539d3
+CT = 0dae8b3ccf0b439f6ff8ee4a233dfb7753f6bfe321b3e26959
+
+Count = 91
+Adata = 29ac8fd6a20a5df4ec79660c44d373da42de7d7c5fc35982b6c29b480723b484
+Payload = e574b3a37af3bf2251
+CT = 9470dafbbb8bb984ed63b1477d9506a51ae23abbac179d8b02
+
+Count = 92
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b227
+CT = 5f3899f74deec1149bdb0986198bce2e486581c041029a81d9
+
+Count = 93
+Adata = cc8e789462879e348d20be4e1161d7b7fc6f8371d8f8cb2d25d13f0e07de47b0
+Payload = 16f22817c5b79f9fa6
+CT = 67f6414f04cf99391a0cbb2df2079a6eb964c3469f4f326122
+
+Count = 94
+Adata = c63061f2800228269015693336f78bb535ae8b88869e4ccf4ead2f3b0ea4e48a
+Payload = 64fe8076d4e8538e18
+CT = 15fae92e15905528a4a40ca7622acf7266b7c24cf0c3202e4c
+
+Count = 95
+Adata = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b787660e7b1a581af11
+Payload = 4814aaac48bdf43c92
+CT = 3910c3f489c5f29a2e7de20e98586cd5d684bf015a7abbe82c
+
+Count = 96
+Adata = 8f4947f8588ed866ed7477d7f1a28046430c6470806a50e3c9e80958c61f1b42
+Payload = 392a692b57a8a97f60
+CT = 482e007396d0afd9dc8d503f5d87818f7c0e173b857cef4288
+
+Count = 97
+Adata = 9d44f6df58c2b43db67e3daa95b176c81daff32e996d670e86405e15eae72e93
+Payload = cba1e00e345b0cb7eb
+CT = baa58956f5230a1157c85e2283d9e80700268a6459d1451d00
+
+Count = 98
+Adata = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f93006c1ca2ff66f87
+Payload = 22f5b6752582919dc1
+CT = 53f1df2de4fa973b7d1056aea3d3e4f7a5219170aaa52465e1
+
+Count = 99
+Adata = d6411fd5b25433f67ca75e4560ceb809d3721266beec358dde126b2f6a514137
+Payload = 6e1b55d6f5288c5451
+CT = 1f1f3c8e34508af2edfbfcf8200a8a3f8d995f50284a7280c8
+
+[Plen = 10]
+
+Key = 0fb9df6f638847f5de371f003dd938f4
+Nonce = c9ddf61c052f3502ad6b229819
+
+Count = 100
+Adata = 4f9938d5bc3dcbe47f6b256d5e99723d0891e50c6175aba41b011e4686113c49
+Payload = e10cc36bc1c5d3c646ab
+CT = 7f797367de50be6dc04e4cf0d8c24189affd35060cb7ca3dd136
+
+Count = 101
+Adata = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304a643141855adac10
+Payload = 15841284c959febe63f9
+CT = 8bf1a288d6cc9315e51c4148ef85caab151488c1a6b3df540d21
+
+Count = 102
+Adata = 147d77d509f642189594df17574a0ce62b52a838feb62310e11533995ba4c851
+Payload = a8b4e5829069c335d1d8
+CT = 36c1558e8ffcae9e573ddaaa1e7c22b3efa8362abb3d31ee8884
+
+Count = 103
+Adata = 0bb09658e23fe8a08c01a6994ef36cb8dcc9a806297a09c67efe3558ca56bb5d
+Payload = 1bb2da0f1ae7e044deb0
+CT = 85c76a0305728def5855317b141383ad38dd78569d5f846f2520
+
+Count = 104
+Adata = 34eb2e6149bad764837f6f25ddd96865e5b05d5cbf233c4f6cc2aa654dfea3b7
+Payload = 63af538196add9b3fad2
+CT = fddae38d8938b4187c374e6432971aecf6bf7cf5244d21f7f173
+
+Count = 105
+Adata = b69f26fda6d1cd92897e03758cae020c4e1beb019ce5ad987f872940780a9468
+Payload = 6ef2df5a1688ae795537
+CT = f0876f56091dc3d2d3d2e4d0ffc0f0add38a80c7ffe6b4701e54
+
+Count = 106
+Adata = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117d25f6d4ef9c2fcbc
+Payload = 3f46c83021069ac488a1
+CT = a133783c3e93f76f0e4447fdd0b2f29f39094ba5a7375e278349
+
+Count = 107
+Adata = f9b91f7298b4e43843fc739a2f41c57c3f2cf36378fe4c34b574a43f9cedee7b
+Payload = 86c10a6dfdd6a06ef638
+CT = 18b4ba61e243cdc570dd57500f913ee3f46801e1bba9d4db7ecf
+
+Count = 108
+Adata = 9d35876d9449a1642b5062dfbfc7a26a7ac080b7198f4aeff2c79e463565cfd2
+Payload = 196c80d02b663bdd89fd
+CT = 871930dc34f356760f1856a6b87519b4807a2114ced587f72189
+
+Count = 109
+Adata = f2d5e927eb507f889efc6f21d783851f638f978c74960cc347f89f2703476114
+Payload = bd27ae3ade0781a33d5f
+CT = 23521e36c192ec08bbba2101012808adefe9b8166e04685bd537
+
+[Plen = 11]
+
+Key = 006ff7d3153caf906ec7929f5aef9276
+Nonce = 57db1541a185bd9cdc34d62025
+
+Count = 110
+Adata = 7d9681cac38e778fba11f4464f69ed9ebfea31b7ffcaf2925b3381c65d975974
+Payload = 31be1b241cae79c54c2446
+CT = 9dd8a4244fbdb30b624578a625c43233476bbb959acd9edebe2883
+
+Count = 111
+Adata = 1b0012c468009bd2851653013782c7b71ef43c393afd4dc0aec4d6d0c3fa11c5
+Payload = 8802831e22092b30110cf7
+CT = 24643c1e711ae1fe3f6dc9d477ca066ec2befa854a1faef018ea8b
+
+Count = 112
+Adata = 48b216375c00ca7e9c4048834b37944d2543e24fa091fb3c7290e11c53a6b6a0
+Payload = 3b3f782d637319d7fd161d
+CT = 9759c72d3060d319d37723eb6be9a78dfbd9e16181679b782969ad
+
+Count = 113
+Adata = f3e06a45fcf1f6abeb00727bf2c9bcea00ce621d38f7b7eba17c27e51f04c793
+Payload = e98f5e5a20d02c80372d6d
+CT = 45e9e15a73c3e64e194c533d9574d95b821a5170e9b61d8e6b2ff3
+
+Count = 114
+Adata = b36e27729f9a139d8ec4f61215b7bf1149cbb4d93a5c14bebd7cfb7c6fe585cb
+Payload = ceeed4fde3406ec40f7ac6
+CT = 62886bfdb053a40a211bf8aa193d257907be1330abaa56bc4f431a
+
+Count = 115
+Adata = 8886ed7fa414d74aef704a9751b197cbab02c41c6aedcaf65cda019dc2d2d815
+Payload = b38f03449883773135c0cd
+CT = 1fe9bc44cb90bdff1ba1f31d92029a6428748664b5c815f15ca1b7
+
+Count = 116
+Adata = 816d81af167d2294497d9b06a39fdf75e37cbacf4d10c3a444068c891b361bba
+Payload = 8efb141db7b77c521003cf
+CT = 229dab1de4a4b69c3e62f1386e4ad7c72ce0081a85d4cfd34254c7
+
+Count = 117
+Adata = f427c47e10c45bb3c7e75e9e604503b3560427691470358efdef48ddaf3794d2
+Payload = 6dc38e37d1379732df4dd5
+CT = c1a5313782245dfcf12ceb98eeb05bc376a1042735569d5b63f8fa
+
+Count = 118
+Adata = f3df712b5e8dd8e4aa8b7c5f41e93bd11b0df66a3456a01f3d0094ad91482cdb
+Payload = e0e358aff203369dd5960c
+CT = 4c85e7afa110fc53fbf732065b03ebeb68a9153cb4ed152ce0d64c
+
+Count = 119
+Adata = 264f2c7b095a296eb8ff6b5151ab3d9497ea8dc0002a9e5b09c2fd0ccd32b6ff
+Payload = 57b940550a383b40f3c308
+CT = fbdfff55592bf18edda236fcd16c8360a408e2787f930ed275bf3f
+
+[Plen = 12]
+
+Key = 026331e98aba9e8c23a9e8a91d0b0c97
+Nonce = bccfe69bba168b81cbdf7d018a
+
+Count = 120
+Adata = 26e011143a686a7224ddb8c5b1e5d31713fa22c386785e2c34f498ae56d07ed5
+Payload = a82200ef3a08c390dec5cbf9
+CT = adf4fc6f9be113066c09248fcb56a9c1a1c3bb16fbb9fbaedacdb12b
+
+Count = 121
+Adata = 97a720ae4720546e31263a1a538ce1d35c198c23bd4362e0023a67536328ab9a
+Payload = 7fc58d1bb450b396b9161f53
+CT = 7a13719b15b963000bdaf025002120b619a391fbd23402e5edd4949e
+
+Count = 122
+Adata = aff6c8cefda055c67262e9c68825d1ad2a7488e5b09640a111fabf6254d96cc0
+Payload = e9ea182d7f895f312b9738db
+CT = ec3ce4adde608fa7995bd7ad48b6e9a8de0099a28cebbf5c2bad42ff
+
+Count = 123
+Adata = 35a3963b43f47855ef3df12af5de3626e0c5c8d9cd2a534c737cd695609b05a9
+Payload = cfbc8bcbb5e5bb744bb1f340
+CT = ca6a774b140c6be2f97d1c36df80fd62e751757bb0a32a987980afe6
+
+Count = 124
+Adata = 46a2e6bd3fd5336abf02eace3cd1e1f6dde505ab976a9fa596edd6fbde7175de
+Payload = a334f8f41897cbcaeb5cffdf
+CT = a6e20474b97e1b5c599010a93b211350c70adf9bab5c01081bdc6a99
+
+Count = 125
+Adata = d110651c00ac5540f9d1ed9eb175e06b97163fc36d43f048565e5d0c30a069b1
+Payload = 3f781267290e8e73c6355e75
+CT = 3aaeeee788e75ee574f9b103d7f65690d9a2fb6759d658c9bdfdfc37
+
+Count = 126
+Adata = 978644dc4e36f1d98a2a63e19bbf8af11785d09fce58a95c00cc6bf6cecf6161
+Payload = 3dc39dbb91efe8b16396d488
+CT = 3815613b30063827d15a3bfe0d5df472f49e7f713cd1373293810906
+
+Count = 127
+Adata = 5ae7528c5e965880b1533cbd78c1e81a8187379327a2fc3f76ff45829049e183
+Payload = 6caa8c0764512baa39dabac0
+CT = 697c7087c5b8fb3c8b1655b64bfca9ef00b0f2bbb03c1a3f7a0862e7
+
+Count = 128
+Adata = afe754828be6e3731d3eee54b021b4fa182247bd958e9074fb0094a11030f5e8
+Payload = b19bc92e2305883580dd7742
+CT = b44d35ae82ec58a332119834a03be1d1d262b03c0ab425d533fe4ec1
+
+Count = 129
+Adata = 0650859c635654ca4d815963c0a99f9d2f47456ad37f739c425e924d4360bd7e
+Payload = dab87e79544df1cc98096b91
+CT = df6e82f9f5a4215a2ac584e7da61ca8461925996880e2874393232d6
+
+[Plen = 13]
+
+Key = d32088d50df9aba14d9022c870a0cb85
+Nonce = e16c69861efc206e85aab1255e
+
+Count = 130
+Adata = 0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa
+Payload = 4b10788c1a03bca656f04f1f98
+CT = 89f15b1cb665a8851da03b874ca6f73242f2f227350c0277e4e72cdaa6
+
+Count = 131
+Adata = a533b3279db530eaed425842b0d3528f5c5e4c16acfa0f49de43d6491f0060a9
+Payload = de6ea86d3641d916c4394fdd31
+CT = 1c8f8bfd9a27cd358f693b45e594271cc06f81d510075728cfeb89222c
+
+Count = 132
+Adata = 8e6c1cde142e18635c1b4f0cb54d3cf817f22ad7c25bf6a022501682f6a7da1c
+Payload = 6f3b32adc8c0314872947f3d31
+CT = adda113d64a6256b39c40ba5e5ab1aefed75400a41447b2bd8f0605542
+
+Count = 133
+Adata = 248a4389da2d51b87907dc11c46253515503ba80de5d06c9b505cb89906614a6
+Payload = 0cc992a8c736b44fedb4ad498f
+CT = ce28b1386b50a06ca6e4d9d15b46b3a6463876f1a43a287748f339e913
+
+Count = 134
+Adata = 2e2c8244a2cbf53816b59e413207fb75f9c5ce1af06e67d182d3250ea3283bcb
+Payload = 98104fd3f3413ad1f57ef4912c
+CT = 5af16c435f272ef2be2e8009f8f625786bdc58af24b17c1ba34fa87baa
+
+Count = 135
+Adata = 4ada86d88d5f49dfcde13fc30ba9a1af58d5254b47fb1885a20fad915c87952e
+Payload = 3b4fec79d52d8b2a533917b75f
+CT = f9aecfe9794b9f091869632f8bd4a918290cf97208232c76908514b07a
+
+Count = 136
+Adata = 9e3b23232e5a9e69747f8bcb148cd6d282fd9b7ecd6d97e8bb5cdc261b2fc86f
+Payload = f10c19c76ae7ed55e1651155df
+CT = 33ed3a57c681f976aa3565cd0b01d6306bb91c315bb4a23fe23d496d09
+
+Count = 137
+Adata = ccea2c815ea4efadc3007f511d633e98f9fa38b0e0fb572b282ed6a610adf7a9
+Payload = fa34af376868d9a49aa200f59a
+CT = 38d58ca7c40ecd87d1f2746d4e620d9d3004587c5d510e2a857fc857ea
+
+Count = 138
+Adata = f7277fb296e2c0d2c9ceb7013ea8b59fe37e26b3b42a0b8cd01aaaa8d35283d4
+Payload = abe2fd996bb6804ed3286c057d
+CT = 6903de09c7d0946d9878189da982d2438a5138977bde5f514e2335c28c
+
+Count = 139
+Adata = 14dd1810df3eeee78ed3836c77edf510d91ea28f119bf57111e580d70da94b74
+Payload = 395ea6979b77dabd2042aee4ff
+CT = fbbf85073711ce9e6b12da7c2b78100a05448fa6e74bd3ed16c3bd364e
+
+[Plen = 14]
+
+Key = 7301c907b9d2aaac355c5416ff25c59b
+Nonce = 7304b65b6dab466273862c88b9
+
+Count = 140
+Adata = 2c5d114eff62c527cc2e03c33c595a80fe609bfc0fe13ce3380efe05d85cceac
+Payload = 484300aa3a506afcd313b49ead8d
+CT = 928ca58b0d373dc50c52afac787ce8eeb5d5b493661259a9d91ea31a5f7e
+
+Count = 141
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d778da52c4
+Payload = 8b318f75ed79a7978adc17c4d2d4
+CT = 51fe2a54da1ef0ae559d0cf60725552193439abfedda67d765d030cef30b
+
+Count = 142
+Adata = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7ea337e548cb706780
+Payload = 0256b0d154c768c85070da6ea8c7
+CT = d89915f063a03ff18f31c15c7d3615013c2bc9338868fad0d2fac11df019
+
+Count = 143
+Adata = 08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a3
+Payload = 89ed296a3ac03fbfb71422b92117
+CT = 53228c4b0da768866855398bf4e66c3c4cb8c50891d6523245e4c619aa99
+
+Count = 144
+Adata = 7d653792bb8683e07c7d2c800db6f7f08343c85af2377115df4fc86ff7d8fcaa
+Payload = 414b6acb1db479028f5cc8800f2b
+CT = 9b84cfea2ad32e3b501dd3b2dada792d2cb93e45811a4c897ae9d907c9cf
+
+Count = 145
+Adata = 4d73c1484f9429eb15742f29ab05cbab6552abf40e127b93427d649d195ed25a
+Payload = 163f67b3766c3c650ce26c5bd8b5
+CT = ccf0c292410b6b5cd3a377690d441983a87812eaa7b66c5a0e54a01cb882
+
+Count = 146
+Adata = 2fba7a881f019a8745691343d79ef3656e25bb37b93fb5ab7311889f92010a5f
+Payload = 9c5b4aa703c27d16d82013853e16
+CT = 4694ef8634a52a2f076108b7ebe7b0afabd23b33765a63753cad66b0e6db
+
+Count = 147
+Adata = a640343fd4a866aec07b667d25176e11a32fb4d8bfc08fde2c46dc9b492fa010
+Payload = 99eb86b3202c7ce68a2339065f47
+CT = 43242392174b2bdf556222348ab639b8d0f97540373a7b9061aa3b2f7044
+
+Count = 148
+Adata = 9efd58d3ef5f74f663b2b5ca5e96c5a2fe85ca5eac1495d7f1751c7d8b412b3e
+Payload = 3f5c1d038161e65c9ed955c961af
+CT = e593b822b606b16541984efbb45e312c803e29f7be7c5eb236401037a320
+
+Count = 149
+Adata = a7d7ba684c0903323f7efc83dc32815195df325394162fb5a18f201047be7999
+Payload = be8dea2b4e602a787ecd28f2f7f0
+CT = 64424f0a79077d41a18c33c02201fd929c717d75388387dc25bfcf90b707
+
+[Plen = 15]
+
+Key = 38be46d271bf868c198052391f8a2147
+Nonce = 6758f67db9bfea5f0e0972e08b
+
+Count = 150
+Adata = c6de3be97f11d0e2ab85c9353b783f25b37366a78a2012cecf5b7a87138b3c86
+Payload = 61bd1385be92097e866550a55278f0
+CT = 7c9fa8d99b38f825315ece6a2613f55e902f296dcce870263ae50cda4fadae
+
+Count = 151
+Adata = 7c8cf9c650511f33af82e807e60336ec086bd2d9400a5f35652b8c3fcf968ead
+Payload = 7e5e51301fa44a21f2734731ee3710
+CT = 637cea6c3a0ebb7a4548d9fe9a5c15cae8a9e4b606f5fbeac2b829b42a150a
+
+Count = 152
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75
+CT = 81c8805a3bf6b176ff72e06be0e670f5419c6085e5434f056162cf80f6729d
+
+Count = 153
+Adata = 238d3c9d9de32f2040b1dd0dd040b921e456c3653263f4020cffdc552b948a46
+Payload = 20660408d6890aed84aa65dfe23032
+CT = 3d44bf54f323fbb63391fb10965b377fedcc743389a9d48e6b871dc0dd63b2
+
+Count = 154
+Adata = 3b5d61ca21953fdd22280747dd4ae908a511750127875da84dfe7d0063a318c9
+Payload = 9ab83c81f2d2c896c6596660c3974d
+CT = 879a87ddd77839cd7162f8afb7fc488137e0a856d3d911af9f420b68d8110d
+
+Count = 155
+Adata = 78c1751e86144a78285a30dc04f51742bd47e3d36b607bab48d91cddabfff4b7
+Payload = c1ec469aa9c73b677af225a9f5f6f8
+CT = dccefdc68c6dca3ccdc9bb66819dfd5644448fa8445b6cd185bdf9b3718033
+
+Count = 156
+Adata = add33e9a1d7e91e2c160c1123537e3f7e3535881cb4aac1a80ecbe367379212c
+Payload = 9df1d6b6debffdd316aeb27143508e
+CT = 80d36deafb150c88a1952cbe373b8bbd38e4dc44f768cef0c51344e3a7f7b8
+
+Count = 157
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c12
+CT = 04cc4b4b35a7397491d696dab137172e7f2ec918099898b843a34c385f2a57
+
+Count = 158
+Adata = b40c8d22069b8a65cddb51c1ea3571160cacb19fd371552436b19c7122b28d08
+Payload = 2af5db43f2a5fe8b494b40661510bb
+CT = 37d7601fd70f0fd0fe70dea9617bbe94c2709685b0827cc42f3a25b579db28
+
+Count = 159
+Adata = 9de5559ea8ccc70f4375a436ce0b72551a75960ad5ed6a1949ee8f6c47548558
+Payload = 5de41a8ca8ed8011304fa9e9f36498
+CT = 40c6a1d08d47714a87743726870f9d63bf4b40ce7e672587816fdcda16efbe
+
+[Plen = 16]
+
+Key = 70010ed90e6186ecad41f0d3c7c42ff8
+Nonce = a5f4f4986e98472965f5abcc4b
+
+Count = 160
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f2
+CT = 8e4425ae573974f0f0693a188b525812eef08e3fb15f4227e0d989a4d587a8cf
+
+Count = 161
+Adata = b6fecd1edeb55a9a4148b1aefb716a1e162779a5ab2a682e4adce4479c527bd2
+Payload = 0e6118d0409751d36cb642504678535e
+CT = 3e171226f809dde516bc264351e47cbedf7f186e8d3d7c21c549c41ebcc7f505
+
+Count = 162
+Adata = 5c3933c30bf9d4841eff4000aaa1cb4d39cdf8ef1240e2aabbf9da95bdee5270
+Payload = 5c8a5fb36f860d00c21ae9e3f24097c4
+CT = 6cfc5545d7188136b8108df0e5dcb824810a68be1814f53c09aca4066527fef8
+
+Count = 163
+Adata = 7ca7ef30d3ac08aa51a9e5d3d84e8b6bb7fdde921e72b98ad6a93ebf2efc6b04
+Payload = ebd1cb4b35257790c9806be476bd25a3
+CT = dba7c1bd8dbbfba6b38a0ff761210a43cc30245a6e64625c4f6531d7497fb144
+
+Count = 164
+Adata = 90f1416768fca7dd48d01230dabf95f2f1a0c044bf2d755448aaf72316c8448c
+Payload = 842b7e5f22d921b2b8ab3131684b7eff
+CT = b45d74a99a47ad84c2a155227fd7511f10d85725dacc274034669acf7f34fed7
+
+Count = 165
+Adata = adc5c36849283d57acb2bcbc0e12465cb7c1830cb4e314b9ce6e25acbd8d460c
+Payload = f0c2cc5a1b4c4cbe839338fa0d7a3435
+CT = c0b4c6aca3d2c088f9995ce91ae61bd5f731b465eb59c4989e42020d86102a59
+
+Count = 166
+Adata = 80a7a483d1dbcdf00ed02a700e93d8b87fa6ac5c7368d1e81bd1b32cd1621cd7
+Payload = 2c1a5f906f2ae0373cc25e3519df2ba4
+CT = 1c6c5566d7b46c0146c83a260e43044484bcd2775448447ed801b3b0ff071c19
+
+Count = 167
+Adata = 13c02992992d2708250184a579c43bc29a3a8cf1e02dade4496cbd8b1214f97d
+Payload = 1da5190517546f1ad852f64263e1f679
+CT = 2dd313f3afcae32ca2589251747dd99901d1919f1451ad16f115cde863f15303
+
+Count = 168
+Adata = f6f18dfe093e4c0c3fbfa8a5b1f4a703c08addc2ab959741611a594b93d08bf7
+Payload = 13ccb08a580efea53dfba6a59626bbe2
+CT = 23baba7ce090729347f1c2b681ba9402ccae4f6ec07bf73d6f086cf09e2e14ed
+
+Count = 169
+Adata = 63708e12dfa14f192ec5ee5856dc3cf2403817d9628c31899b4613f65e1e61c2
+Payload = e0b5fbc6c2269d445a60273bf844892b
+CT = d0c3f1307ab81172206a4328efd8a6cb2bad8bf67d32a855c3940ac908397a5f
+
+[Plen = 17]
+
+Key = 79eae5baddc5887bdf3031fd1d65085b
+Nonce = 9da59614535d1fad35f2ece00f
+
+Count = 170
+Adata = 46603500af9e4e7a2f9545411a58b21a6efd21f2b5f315d02d964c09270145b3
+Payload = 001343e6191f5f1738e7d19d4eec2b9592
+CT = 2162e27bfbf1d00f2404754a254665fd9270f0edb415993588b2535e2e0e4fd086
+
+Count = 171
+Adata = 278afebc604bb7d87bed3574a2c5053de17eb8ca7e18ddc7892f2c54b38104a8
+Payload = ba47d5bfb36f6150a100e36caa116405c4
+CT = 9b3674225181ee48bde347bbc1bb2a6dc4778e3c4a11f3f9dc42554d45796379ef
+
+Count = 172
+Adata = 3239b2ce4efe4f6a6255dc53347400a6446ed3280c65422386fab471ef09eed6
+Payload = 96eccb7f9b0e16c6883de0a381e4767f5a
+CT = b79d6ae279e099de94de4474ea4e38175aab5540cc01d867f641c9b196fa159291
+
+Count = 173
+Adata = e2a5488d5f7930ea4ce399f2a6c0810265f7c0dc52fe824d19a0fa0d9ffd55e6
+Payload = d68f5990da1a2fe39ed81af145ab834fa4
+CT = f7fef80d38f4a0fb823bbe262e01cd27a46366fbe302e142dcf6aa16337d98550f
+
+Count = 174
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cdd4d8b3d8f6e4742793b456cefc9e686d
+CT = eca5792e3a186b6c3b701081a556d0006df88c07797267bf5a49b3d0f601a225ce
+
+Count = 175
+Adata = f5d6989587e463969d97aadabea9538511f8d109cc2d3cecf09ba7cc346aaea0
+Payload = e7d7fc60ae852b68102e01b506f9dab986
+CT = c6a65dfd4c6ba4700ccda5626d5394d1865c9fbf69d81cef238ac513562d4a0dd5
+
+Count = 176
+Adata = e0b5fbc6c2269d445a60273bf844892b26fed03b82869edacd6dd7a63fd69e8d
+Payload = be9f51abfbe2da5a56db0f9a31b67c9f83
+CT = 9feef036190c55424a38ab4d5a1c32f783e2c748c8c9e3190de095de8eb0650203
+
+Count = 177
+Adata = e6bd0010c98e60b9af7cf905c58e0653bc425e2ccc809bd4f9cd7b1f95c18786
+Payload = 81b9c73029cea1936ef8755c80ba8d4093
+CT = a0c866adcb202e8b721bd18beb10c3289305cf563c5b4ba4ebd5bf107f2ad3555b
+
+Count = 178
+Adata = b1688cbc058816974694cd26c0f28ba9418e9912867fc8c5f4e7bd9c891a8d2e
+Payload = 618dc26853ee339689467ffbc2a77be69e
+CT = 40fc63f5b100bc8e95a5db2ca90d358e9e60dbbd8f46343c8442b03a472da4e23f
+
+Count = 179
+Adata = 469e004fee9878ed40621b41d04ec34af175f213d64d16e2f77d0bb2b6efe2e3
+Payload = 4f18bcc8ee0bbb80de30a9e08629323116
+CT = 6e691d550ce53498c2d30d37ed837c591643352e46995e8c1aee43dbdb26b46c30
+
+[Plen = 18]
+
+Key = c14eda0f958465246fe6ab541e5dfd75
+Nonce = 32b63ca7e269223f80a56baaaa
+
+Count = 180
+Adata = 733f8e7670de3446016916510dfe722ce671570121d91331a64feb3d03f210e6
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb
+CT = b2dc1e548b3d3f225a34082f4391980a0788b4cc36852fd64a423fb8e872252b248e
+
+Count = 181
+Adata = b6ec659856866959ef6fd4e71ba930f0e3e5fd49d7465fd65f6813ab4ca1a770
+Payload = b8b342c49c28bffc2a1c457db0b537ad46bb
+CT = 6b17343e86e28518c5abf8af8d3aef21e08895a66eb5b902bb23a1a8584249409fda
+
+Count = 182
+Adata = 89eb3636fff80230352a3582be5698e3401c9e0579d48f2680c6e5e24d99f74b
+Payload = 37d694ba94d0af8df662134f20d142903839
+CT = e472e2408e1a956919d5ae9d1d5e9a1c9e0a7fa792fb7246218f7d56d5fa4a5476bd
+
+Count = 183
+Adata = 03434f3709e19a1e37edfcaabc215116763b71ab1c5e053dbdb599f86959f25d
+Payload = 90e4c0550cb7b279ef61f9140b7d94b8003d
+CT = 4340b6af167d889d00d644c636f24c34a60ea83dc3f0012ae6da32a15fd1684835ef
+
+Count = 184
+Adata = 0e2ddb65fcc72094ac388d53a1055c7e902285c4c3c33c13bb6fbb4f1956414a
+Payload = 69b851e63a78baef90637978e3dfe8c47be4
+CT = ba1c271c20b2800b7fd4c4aade503048ddd7f09d38d3dba01995e36bd685c8ea3371
+
+Count = 185
+Adata = a42b2538ee2fb5f6a85d4d00524b01ad3331f61c404069243f35f28e2c2d0a82
+Payload = b7dbf8382115199dd2a2d87938c6ae6c4241
+CT = 647f8ec23bdf23793d1565ab054976e0e472c89becf8d2bb935cb17f44b950df3ef5
+
+Count = 186
+Adata = 09bc5c426dc1faa4d71f50908bd6f297ec8e754d4d20def005585b4bc1fa31da
+Payload = d53698d719c51bf9eae346269c6a1da07162
+CT = 0692ee2d030f211d0554fbf4a1e5c52cd75196e28badf0202097e80561451796194d
+
+Count = 187
+Adata = 2ac87e59c2c86532cf165af3e8ff4871d730f5e742cccca38bbcdffff4472c93
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb3
+CT = 1c7f059982909afe194f55f140306f0bb880710d4d7f66660891ac655d6eca4a3f3e
+
+Count = 188
+Adata = 05d2fbc3d0ec81f52f31cb0c4bf960c2076867f6d9f0174ed9176e20177b2693
+Payload = 56fdf10dc0c1dfd10965b83938e557459c61
+CT = 855987f7da0be535e6d205eb056a8fc93a52f90ab18925fea6964490f364a975a473
+
+Count = 189
+Adata = c2c3902cfe8622254b3787cc13e79c5a3c388c2357c29f1c1ab5539a10bfae5c
+Payload = e7c9812eda2ed7dcfc80fc5fe0d43e1e5982
+CT = 346df7d4c0e4ed381337418ddd5be692ffb168a00e5e7a39b371024927d3ac98fe43
+
+[Plen = 19]
+
+Key = c5e7147f56ba4530b8799ababeb82772
+Nonce = bdd38e173fb20b981659c597d6
+
+Count = 190
+Adata = 3a069a2bfda44abbb0a82a97e5e9047258c803da2c66190d77149e0f010b3af9
+Payload = 2f3bf0b566440912a1e47a0c07f1cfd39cb440
+CT = bd6265dcba9e14c59e515e395dc60bd053345fa6d7568c738e3a7fdf142d8f2d1562c0
+
+Count = 191
+Adata = 7709132415c94960025cc39c950ead208703a9d5a71e224fd022dc0a1817d0f4
+Payload = 7c880d787726c4ddeb2304b5d161b4a257298e
+CT = eed19811abfcd90ad49620808b5670a198a991f22337efa5cb7db7240e7518b67ffbb1
+
+Count = 192
+Adata = aad77595f87a27f2c7995fc7149317f4cbebcece8336db2068380070784a4283
+Payload = 08c43bbfa706512aa39e2bfa5c365aca11e22e
+CT = 9a9daed67bdc4cfd9c2b0fcf06019ec9de623140bac6094528f02eeda093312fcf716f
+
+Count = 193
+Adata = bdb1b82ba864893c2ee8f7426c7b9a8460b00a50f164fc8f2ff2ae9cddab8657
+Payload = a531c0ed8840b2fcf08d76eca71036153b6e11
+CT = 37685584549aaf2bcf3852d9fd27f216f4ee0e0c041d86dd483c1d6da366e91bd826dd
+
+Count = 194
+Adata = 38b3b9f45041ceb743fc2655b409213fa081427e41c833a2321a09fbd566c80c
+Payload = 177946b4dc3b0b825a505f097a0a203eb21c00
+CT = 8520d3dd00e1165565e57b3c203de43d7d9c1ffde45ca2a83dec2f930bb652a6fcdc5f
+
+Count = 195
+Adata = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878742de83154a578da
+Payload = a2634ef20a2a418b2c3be64f0b5f79d7ea9b7b
+CT = 303adb9bd6f05c5c138ec27a5168bdd4251b648b89aa22cd7d0170a975565cd3a33dc1
+
+Count = 196
+Adata = 8f6c1de4efdc5ac2d6e5452b5b4f58416d618da672f521332fd297ede8350134
+Payload = 40e52edaad5acf2d4eedfb3f9ac2908112e9b1
+CT = d2bcbbb37180d2fa7158df0ac0f55482dd69aed960b33c3df5cd38a82980dc0950ada4
+
+Count = 197
+Adata = b0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0af
+Payload = bf97780f498c23adcf1c49f60873780a235969
+CT = 2dceed6695563e7af0a96dc35244bc09ecd97638fa273c4102b5ca050b23044ac2064f
+
+Count = 198
+Adata = 7d02a323aa769a8201549bf48a520d940bf6f69ed6106f1ce68856c22a594216
+Payload = 58bfe1eb2d38d91f80b3467db94fdcb84ff5f3
+CT = cae67482f1e2c4c8bf066248e37818bb8075ecc15438af1bafac3eac61e1c24ed00ab7
+
+Count = 199
+Adata = d4b90ef8abad08c552c8c3b080b8c37df314d514049d45e27ec4527cb06cdf85
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59
+CT = 305f3482ac73cf9c8a520b04144a55ddc8cf464422d9e2f4f84fde49e9701296294d5a
+
+[Plen = 20]
+
+Key = 78c46e3249ca28e1ef0531d80fd37c12
+Nonce = 5de41a86ce3f3fb1b685b3ca4d
+
+Count = 200
+Adata = e98a77f2a941b36232589486b05f4278275588665a06d98aec98915cc5607e06
+Payload = 4802422c9b3b4459ba26e7863ad87b0c172cfe4b
+CT = daea2234ea433533bf0716abe1aa3844b6d3c51e9d5ca3d8ec5065630d2de0717cdeb7d5
+
+Count = 201
+Adata = 5970a836de1f1e91d94d7eef79742cbbd46a759c413715eb0224fd6a27145333
+Payload = 796a69ad0e9379173ef6b66f44f5c84fa70a0e28
+CT = eb8209b57feb087d3bd747429f878b0706f5357d0ff0648ddb07f42f815b38bfc95688b1
+
+Count = 202
+Adata = e3f08834c4894f6fa66a55a280c0e677a79e97c1ef9488b21384e74e57b1b51f
+Payload = 98e1f8cf250183b13ad418024dc40c1a6a7ee8ac
+CT = 0a0998d75479f2db3ff5e92f96b64f52cb81d3f93ddd9a6977ea8e7adf5c5234346e560f
+
+Count = 203
+Adata = 18349be2894d49290339b97f4db28c92b3e112ffac77100abbf9c093935b1a46
+Payload = 4a856d9b50a5b40d6566b38eae6a53ed0c192805
+CT = d86d0d8321ddc567604742a3751810a5ade61350bdee05328a7ea8cc6c2e42bf3faeeda0
+
+Count = 204
+Adata = 7355e34ad13880de17a1d66b02672ea5c9f51774019f64ecbe36747ffcd9b671
+Payload = ad048eb2ad75266b43b59d9d1f073c44e4cbf25e
+CT = 3feceeaadc0d570146946cb0c4757f0c4534c90bafb1435cf929db35ec5986aabaf4a7d1
+
+Count = 205
+Adata = 4be21ba2eb26234ddcbb6aac6b4c3be7ef644af64edf51b7c29ffc3ddd80036b
+Payload = 5b527ac6cc6d1b4c3c56f8315bc96dae91632df9
+CT = c9ba1adebd156a263977091c80bb2ee6309c16ac736be6563cf9f5bce97486b7cc6f1c18
+
+Count = 206
+Adata = 266e0e3365e06d3b1e864c6e5897145df7bdde90eb744013a7b36632d4cf6580
+Payload = cee059cb0fe91a39faccc2914340baeab4b644ce
+CT = 5c0839d37e916b53ffed33bc9832f9a215497f9b2e90335fcea56b969b4fce65442768dd
+
+Count = 207
+Adata = 55a723883a340877d85ad1a5f264f2c834d824c7bbf207cdd8500c9d11ef9225
+Payload = 85321fef6a2b7d31cbd079c4bf2bfbbc979df90b
+CT = 17da7ff71b530c5bcef188e96459b8f43662c25eacd6afdb3578ebc75e8a408d32758931
+
+Count = 208
+Adata = 773864475a1a60a778468a66cbe13dfe3458094e62abb593f50c8495e3a8b81e
+Payload = e227b8d44320bd3ce9d3f7d688f3de887947b1e9
+CT = 70cfd8cc3258cc56ecf206fb53819dc0d8b88abca19fb73fc0488d9f29a09c1b47e3e066
+
+Count = 209
+Adata = f64f3b00c9117aed3c486aa4c8d574b44d679be4069e1078bb7100af38cdb190
+Payload = 206e9eb2bc3f8534d844a38debf1306df808744a
+CT = b286feaacd47f45edd6552a03083732559f74f1fce2c5ef8cdce76b358739e2a1b173fb3
+
+[Plen = 21]
+
+Key = 8883002bf13b3a94b2467225970df938
+Nonce = 818a702d5c8ee973b34e9acda1
+
+Count = 210
+Adata = 545aeac737c0ca2a3d5e1fd966840c3a0d71e0301abbe99c7af18d24cc7e9633
+Payload = d516bbff452e7706c91c7ace3e9baa76d65ff7050f
+CT = b85242fdc06344f2bd9a97b408902ebcd22aece3d42f2da4dd4d817c9fa2d44bc02163a0a9
+
+Count = 211
+Adata = f032db01da60ca078d35c3fb5d05d6750fce1c01911a0422e827e8976946e4dc
+Payload = 590d1aa655fed50ca2e402299f2da6fe20eed56071
+CT = 3449e3a4d0b3e6f8d662ef53a9262234249bce86aa180f41bccbcd47c8b7890754c032269b
+
+Count = 212
+Adata = 71ecb4252518997b53491cf42a3e0fe1496a2af2329a16f9fcd9c4f249900341
+Payload = ecd86cdb7d78d310dca5b477cd9da2612f5a05ab39
+CT = 819c95d9f835e0e4a823590dfb9626ab2b2f1e4de21d6ba58cc2eb474401851bf9502c3413
+
+Count = 213
+Adata = ec7abed9bda4a52fdf1bf278b6bdd6b0a27d4688deb9ff5ca9c8c865a4d2f730
+Payload = 0024b14c283df032cf80c22ad8d2c96289ee229092
+CT = 6d60484ead70c3c6bb062f50eed94da88d9b3976499b94d4b7a2044696c72322e850537b6d
+
+Count = 214
+Adata = c2c77d7ad7b27d7c0f976a1e28881ea4ec7ad03b63a4e67f47280a40b8f58086
+Payload = bc6965d8f62d066d118c14044c1fd2a224b9d95110
+CT = d12d9cda73603599650af97e7a14566820ccc2b7cb9d8da8e718570caf8bed7909fbff3ec6
+
+Count = 215
+Adata = 28929286bd1391468ac75f5c03689f74780ddd7585fc16f9a9bf7b00357a72e5
+Payload = da4a630cabaff0728a1cc3e6a79721a7176b708f1d
+CT = b70e9a0e2ee2c386fe9a2e9c919ca56d131e6b69c6e671012690c61fe3c9abd50a78eb4736
+
+Count = 216
+Adata = ed360d22081b019dc979420a3a45c21c8903c59daedd9f1b4ef2bfdedff0ec1d
+Payload = a95058f8e1f6bc0f143a9ca7e4425a2a63eb2f7e33
+CT = c414a1fa64bb8ffb60bc71ddd249dee0679e3498e8e657e2250427130acef7032454cde7b6
+
+Count = 217
+Adata = 2b4022d0b951fe48635d04fb3e2fa032c07c855fdd73f45670953bb9ddc77cb4
+Payload = fcbbc7f9d1ace60e830ca56ec84814fbd2579993d4
+CT = 91ff3efb54e1d5faf78a4814fe439031d62282750faac6ff0a264b8199550d93c1f06063da
+
+Count = 218
+Adata = 48e553a87a7d3c1bd68af39f96aca67583da86e06701d5e4c4ed404dc66d70f3
+Payload = b95d298d391c6b893c6cad66f9780534516e71455e
+CT = d419d08fbc51587d48ea401ccf7381fe551b6aa3857e68bf636e81c332f72063dc0d6fc2b6
+
+Count = 219
+Adata = e8e2835e47144365a2f218d4c95d7522e824fb43b66d4727ee570f8303dd6dd3
+Payload = bc79d444dff9d9e722effab07b068cb7723ae8fae0
+CT = d13d2d465ab4ea13566917ca4d0d087d764ff31c3bdf3af9e9c4e04bad261dc17cf00a00dd
+
+[Plen = 22]
+
+Key = 5cea00ee44cfb9cfbb598d3812e380ef
+Nonce = 948788a9c8188cb988430a7ebd
+
+Count = 220
+Adata = 50422c5e6a0fb8231b3bb6e2f89607019be6ad92a4dae8e0fe3f9e486476004b
+Payload = 33bfd0713f30fcac8f7f95920ac6d9b803ddd5480dd8
+CT = b168747dea3ae0fbede4402af9a3dc3185d6d162f859d828101682de32923788c70262b84814
+
+Count = 221
+Adata = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192eada64ae00c726b2e
+Payload = 5576d94b577ed26820fb13c00ab0e2d1a1c3589bfdc4
+CT = d7a17d478274ce3f4260c678f9d5e75827c85cb10845bafc4ae4d31907def6f648b081174e2a
+
+Count = 222
+Adata = 5140324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+Payload = 13303e14068205cbfa992d4ccb6a265804ea64a15d7f
+CT = 91e79a18d388199c9802f8f4380f23d182e1608ba8fe314e378e9ed6e725a14c07632b02bdbd
+
+Count = 223
+Adata = 74da07d324060e590356988f27d9879fa3a3ade0fe71e2a0e49054211cfa1fe1
+Payload = 567e6d14b446add630d53ea86a537c0938537c4604a8
+CT = d4a9c918614cb181524eeb1099367980be58786cf1295bc2f2f9331536f7f70be09c41bda0ad
+
+Count = 224
+Adata = 0e403cff47adee3ec5bb6b178dabfc7d53b60a04eaad33a2fedd9db705358a4c
+Payload = 9f3d165d44cf1c5770346d211d4ff34ca2ecd6b28549
+CT = 1deab25191c5000012afb899ee2af6c524e7d29870c86b59cc9c3c008bc5876ef86327859cbe
+
+Count = 225
+Adata = 211e6ce3d0c3abdef069e6e4fa35015797bd8a9d64bc9b75f20b028b12cca04a
+Payload = d726e599db6a6d40629bc4bda5e3fa2e5aeda229cea4
+CT = 55f141950e607117000011055686ffa7dce6a6033b25135e6d59a5385a78658d60d254f99962
+
+Count = 226
+Adata = 3c5c67b083322115e1b3112c2b6968efc050094e23e646dce982eac9d6e67d10
+Payload = 42646cfb8a99e48a35cee3f5f9b3e6175695973f6de0
+CT = c0b3c8f75f93f8dd5755364d0ad6e39ed09e93159861e234e83d9a0570dbf2b2fa59ce3cdbd9
+
+Count = 227
+Adata = 37a931f1dd05755b376d1a164aa36b8de802e39f8108a0453c1114754665fe46
+Payload = e814c7b5c72d973a9bc7ccd463f107325ffa3321783b
+CT = 6ac363b912278b6df95c196c909402bbd9f1370b8dba2084e352b1b157267228576dd056c1a3
+
+Count = 228
+Adata = f1ddc2c49da7363526ba36c600c589b4c3121fbb8c5b9a8aa0de0e7453b30568
+Payload = 4f7a5618870945b89f194e31b1aa802c5350326dc691
+CT = cdadf214520359effd829b8942cf85a5d55b36473310bf88ad35ee338e489e55bb49732447cf
+
+Count = 229
+Adata = d14b3d3803df432488b5d66704abef6a500d397e855bc2c2574df746a515cf70
+Payload = f555216840a1f40b411d44128e567617e2694caf1621
+CT = 7782856495abe85c238691aa7d33739e64624885e3a07ab67f9397a81371ef6ebc775cb7007b
+
+[Plen = 23]
+
+Key = cb83f77751e72711401cbbf4f61aa0ed
+Nonce = c0b461b2e15b8b116ef9281704
+
+Count = 230
+Adata = 2bd112231f903fa0dff085db48a2e2a96ec0199249b005d5ab4c2eab753f9ad0
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06
+CT = feb114b7bd3b43497b62454a675a632c3546d2802462c6af57647efda119c59862cd5dd3904efc
+
+Count = 231
+Adata = 864e0e728aea856fae6c6daa6357d1542cef7177f441ba21a563f6c4f6fdc1dd
+Payload = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0c
+CT = 9a394d88d7405656df1a50e7e45fa8ddcca85e9ed5a3cc2af4027ca5824b41c7bb238d3e8eeebf
+
+Count = 232
+Adata = dac7f3cba0b5a47f67f85b226b66df695a8ae2501355e36aad105375bb95f732
+Payload = 66e34540d7accf377877aa2d3e6d2db0cfafc608a1eb3d
+CT = 768c5047e50dbc42dc0126fa23723db5882ffb7a2452fdf7fbd7044ce1d7b266bdf545247a3c2b
+
+Count = 233
+Adata = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c930905aadd156b1dd56e
+Payload = a9ebd04fba7155c39b5c29c5571b5354c9ae228f5e5b13
+CT = b984c54888d026b63f2aa5124a0443518e2e1ffddbe2d3afabc559b552cf7c7730c7dca25bc3ed
+
+Count = 234
+Adata = 2d24e79abd157af2c21b60932947fd9f9d6478f09ec56fffd341ea04a17b8e5f
+Payload = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381
+CT = e116203ddd955c7acd6a23c8d69e0e3a2284dc3fe82a41488ca99e0f85ac388f981ce25560b8f9
+
+Count = 235
+Adata = fea280f710379e4665b5ed3d1620729a7bc164899dc83e6aee3612d538fa20db
+Payload = 6c19a18eab544acc883c5886eaa89f54d61ae5f1f1368c
+CT = 7c76b48999f539b92c4ad451f7b78f51919ad883748f4c9156faae3d8860bed216e8d497a75962
+
+Count = 236
+Adata = 18f2e3457127c35f2e0cff2d821af8178028fcc7803bc795c49f4a435b37abeb
+Payload = d0df1bdf1df6203241722fb9c9c1cf7405017497ae1545
+CT = c0b00ed82f575347e504a36ed4dedf71428149e52bac8588cd7791c544d1098b2de49d04b1e0c1
+
+Count = 237
+Adata = 35221f0efcb109cb93c38a62c58b5ab8b236437e171e8507cf417a569af1767c
+Payload = 479526b33c42c240b9a4549ca70cbfb691f16ae3be8888
+CT = 57fa33b40ee3b1351dd2d84bba13afb3d67157913b3148c523fd8a2524717f63dac75c22268fa6
+
+Count = 238
+Adata = 95f2ab02af01aeacce86b02cf846f9fbd516963d06e350e8b7f6df2778765a01
+Payload = aa6761148b254a2ff202b620c2ec2c5e623bf61f05e483
+CT = ba087413b984395a56743af7dff33c5b25bbcb6d805d4392904f05dc2397596543df73de5aa708
+
+Count = 239
+Adata = 3746a36154e42dd600049d506f5ce4d034864263b1a65cecd24c8e25fb9c82e1
+Payload = 2f298f106703b8a994cbb20acf47f9442e44f6b5e82c38
+CT = 3f469a1755a2cbdc30bd3eddd258e94169c4cbc76d95f8c3cbfecfa3f75fb111ef0011222b7948
+
+[Plen = 24]
+
+Key = 43c1142877d9f450e12d7b6db47a85ba
+Nonce = 76becd9d27ca8a026215f32712
+
+Count = 240
+Adata = 6a59aacadd416e465264c15e1a1e9bfa084687492710f9bda832e2571e468224
+Payload = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5
+CT = 14b14fe5b317411392861638ec383ae40ba95fefe34255dc2ec067887114bc370281de6f00836ce4
+
+Count = 241
+Adata = e82fc3ffd276218a82aede65fe5abf4fd35c7059a26923f8dbb97a59c903a7f4
+Payload = eab8cef576816a82ed036f158e5036f5987b195e60582a6f
+CT = 4b0f27aa559a3ad6b7830e7e46db62a2e578476540f489460d2d30268e9f1ce0e7c762993297d828
+
+Count = 242
+Adata = 776aae7f62225556b6da522c0c9432ac70fe72ac6f3f361071ef3deb4a6715e8
+Payload = 566ef9ce1d397be2547c385639507a9e7d6f9eed9a3b1055
+CT = f7d910913e222bb60efc593df1db2ec9006cc0d6ba97b37c0939e56f0b7200d1b1409f3f8e8179cc
+
+Count = 243
+Adata = d9aef0955922f89747ba4a8ddcdb8c1c7579aefd3c2eb8ad0589c66576a8504c
+Payload = 8c28b6d93b23f1ea031d5020aa92f6608c3d3df0ee24a895
+CT = 2d9f5f861838a1be599d314b6219a237f13e63cbce880bbc138e3b817023993608be06fe92efca8b
+
+Count = 244
+Adata = 13c222a65ce30570ecac85a185a2a0922a8c96d633339a1ca067ce57ae426e1d
+Payload = f0c1cd60f5fa8d1efd5e2e1ab37c4f7e6aef76d15e8d6ac8
+CT = 5176243fd6e1dd4aa7de4f717bf71b2917ec28ea7e21c9e1f3ca13b4ab7fd0d4badf158972570c06
+
+Count = 245
+Adata = ce40fb0cbfdf07676ed55b040ae6be5db8f0a0f28816ae8ea71da3cbd71661d8
+Payload = 570d5f79aa8db14b1ac99ee567cc105ae9e238e482b52628
+CT = f6bab6268996e11f4049ff8eaf47440d94e166dfa21985010a79fa4e8b27a31ff360a1b6c05ff844
+
+Count = 246
+Adata = 446b01d09cbc41b6393ef81ca65ab7e099018187d5f9d22f5074dfc491e72077
+Payload = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4
+CT = dd919b7c2761a912eaef0b2e37551e09b99f76833c0e8e8d5d34ef0ca0b47d6a2ec7442cbb739504
+
+Count = 247
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2398e86ac3fe48bc7
+CT = 6a46fbbbd89e7738148905f4f56971e5448dd8971f4828ee8f607d154393e35fd1efc1ae8cb244e4
+
+Count = 248
+Adata = 5032b818d202872f3fe2b08fc7940696df02cf393a6d6247f5c6f5f2125cb08b
+Payload = 4324a89788e8ddae5d560cf937df701743cbbc3bf980558c
+CT = e29341c8abf38dfa07d66d92ff5424403ec8e200d92cf6a5617d9cebea38591a00c9fba4ef9c8e71
+
+Count = 249
+Adata = 27b661861717f00a3ae22ead78f4dc3f32b40e8fcb8ed58167a31a61f2becd77
+Payload = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad1
+CT = 7ac530d240e740f8a5fdaf87c6adc5ff73cdbb312e39d9f897062a1ec759a515b938780f902fa7c2
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp
new file mode 100644
index 0000000000..abf1775dd1
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 086e2967cde99e90faaea8a94e168bf0e066c503a849a9f3
+Nonce = 929542cd690f1babcf1696cb03
+
+Count = 0
+Adata = 58f70bab24e0a6137e5cd3eb18656f2b5ccddc3f538a0000c65190e4a3668e71
+Payload = 00
+CT = 3bf9d93af6ffac9ac84cd3202d4e0cc8
+
+Count = 1
+Adata = 760d065275e345900a7bbab451cc9309fb161e6cfec526538b98800e4102e14d
+Payload = 00
+CT = b0078a769ab68db44e723993da382abc
+
+Count = 2
+Adata = ffedc67efd355ea404fcbcb3993d3bae81386ded86230270771deb747163bf44
+Payload = 00
+CT = 31fbff2d715a2eb9af54e8320a8e42e1
+
+Count = 3
+Adata = 55153ff5e4d208d2e647794f382c788e0e36f293e63e7290ba9ff2657ae0f167
+Payload = 00
+CT = 945839d62c9d1b899f6dcd0ca9517e68
+
+Count = 4
+Adata = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe6ffbad084f639915
+Payload = 00
+CT = 903f90d23321a6882d6c4c1955b14847
+
+Count = 5
+Adata = 7b95cd827ab93507f1819ae76627d6e2a31d29890c092e5c300f0e2f9e4ef4d2
+Payload = 00
+CT = 652ec5ab43088eb568186d0d9887b30f
+
+Count = 6
+Adata = bd144c9bb974729aaa1188ceefdf85e1d9fddc0b0c8afe8828ba204aa9293feb
+Payload = 00
+CT = e6c1455d1117eec49338c96f51007309
+
+Count = 7
+Adata = 92b911cdc3137a6f7f32651b788eb82975660aea52b2c03b4759755a6da4a0f8
+Payload = 00
+CT = 1cf3c32fb229dac209523eaa517bb59a
+
+Count = 8
+Adata = a8200dbbfe4086015cdbdec2fc8e4934d0d663527430c424627ed44065ade091
+Payload = 00
+CT = ee10bfeb1cf9b3cd5a0faebd4d8f3fe1
+
+Count = 9
+Adata = 3b7f37b6b8e3c1390a99d59c47f7c102cf659d361a132ef8b4e70b9585bafebb
+Payload = 00
+CT = c51ed994253adb9bb5b9a8c34a27f225
+
+[Plen = 1]
+
+Key = 992d38768b11a236945bd4b327c3728fac24c091238b6553
+Nonce = b248a90b84b0122a5ad8e12760
+
+Count = 10
+Adata = 27cabc40da0e1eda0ea5f8abbb7c179e30776250a7b30d711b0e106c5ee9d84a
+Payload = 1c
+CT = 1a96f58c3f38c44d1a345f3e2da6679f20
+
+Count = 11
+Adata = dc2e28d5ae726c1beadb1e7e92ae7d14f5546320deb81a910bf170cbe0210eaa
+Payload = e9
+CT = ef0579aee7c17482691f3f832d867ffea7
+
+Count = 12
+Adata = c579f912ac1b45d5aa8cf20f78f0a1ace32abd3dc7fd0b3f3a7182a008795c7f
+Payload = 97
+CT = 913452d8ece38ffa1d4107d6a053acd8c8
+
+Count = 13
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9fd48894c9b55e6e8eb360a6211
+Payload = f4
+CT = f20d760b9fe29530738157db0ba2d253f0
+
+Count = 14
+Adata = 622835dea57b2c70cca8f7548d6210714070b55b36adde7a4c547269c07aba9c
+Payload = 9f
+CT = 996fc21f24dee7b52f51d69eea30819f4a
+
+Count = 15
+Adata = 67ebda0a3573a9a58751d4169e10c7e8663febb3a8cf769d81bc872113f0720f
+Payload = 43
+CT = 4594c5b8db0064426a77dc536814c56147
+
+Count = 16
+Adata = 255412e380e9a28cbcd345be172c40f72dec3e8a10adfd8a9ab147e9022524e1
+Payload = c1
+CT = c76d36c0b0d699a22da3116dfb8f453181
+
+Count = 17
+Adata = c7c8e7151eb6844a954d091b460f83add0f0a634aa5ac213b774f2451aa497fb
+Payload = 31
+CT = 370c3a1690acc3f0eb09c9cfd3396c7fa9
+
+Count = 18
+Adata = 63f00b2488809fdc49ca5f05d54e98468906308115f7e702da05ddfd970b5537
+Payload = a7
+CT = a1ad45070fe4c61270c13cc52247fee411
+
+Count = 19
+Adata = 8e2c5e55c0bf70014e9897b6f6940e4e738b1e84e8269b6382f0b1fe59b0e162
+Payload = 40
+CT = 46b2a2a8b283ff7eeff5c2670f77b8809d
+
+[Plen = 2]
+
+Key = 5012db40ff6ae23c1e1ce43768c5936c4400b0e79ae77f30
+Nonce = b67e500b35d60ad7264240027c
+
+Count = 20
+Adata = 40affd355416200191ba64edec8d7d27ead235a7b2e01a12662273deb36379b8
+Payload = 0c6c
+CT = c996ef3d6ef9f981557506ecc8797bbaaaa7
+
+Count = 21
+Adata = c5e12e17e02bcc12b3a4c14cf837250e2886db3ee1c717d28bd11e8a3b764ddf
+Payload = 23df
+CT = e6254405257a837c5343b59d5689d6de5269
+
+Count = 22
+Adata = 213b5b6015d472bd593be5acf85ebba6d6a09f3a962be302ba83c6d70c61f241
+Payload = 0dc2
+CT = c838e93e67d37d2367bb1f27f71b54b29317
+
+Count = 23
+Adata = fc1b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+Payload = dc88
+CT = 1972ca3744a4ab375af9060621a9dc4f4c32
+
+Count = 24
+Adata = 5b2eb1a6fa585d61d1fb3da68f5b93829c8e2d5e4fe03782617553d7a130ecf1
+Payload = 8179
+CT = 4483172626e930d24052bc056d8609c4175f
+
+Count = 25
+Adata = e2b3c3bf33cf847660929e48cce51d9d9289945169651aaecb1e939756e93105
+Payload = 01fd
+CT = c407852310207be8d3417de800b372700da2
+
+Count = 26
+Adata = 6051f12cd8aae68b4023aaf7178fd086aa582b8d8821e36637abc97025f5e858
+Payload = ca18
+CT = 0fe228553bc037954dbf4ce5db99792c2c7a
+
+Count = 27
+Adata = 2d3555faf285caaddfe95c010c2a7f233e09c2fc0cd30d644035269280527ad7
+Payload = a855
+CT = 6daf904725668634d6345bd8f90a3831b452
+
+Count = 28
+Adata = 4fca820dc545bf93bdffed33a04b67eb45384e696f092c2197e5d79cecd09913
+Payload = 5555
+CT = 90afdf6098cb3135c3045a54ffce88efaceb
+
+Count = 29
+Adata = 1789ae403e183d2225f431f001d475b53bccdec66572bb027340ae592839ba8b
+Payload = 11dd
+CT = d4278568e8c08ff5ee5ea0a608589c2fc029
+
+[Plen = 3]
+
+Key = fa15cc7f0de294d7341b1fd79326c8be78e67822343c1992
+Nonce = e5257aed2bda0495aa44591db4
+
+Count = 30
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+Payload = bcb898
+CT = 68f08298d9a2147776dca9c1a42382bce323b2
+
+Count = 31
+Adata = 4863dd810ee70ef0f5da81f60c5ce550abb96454619032322e34657af25207de
+Payload = d1da2e
+CT = 059234a9a77755b324f3a557217752ade14ed7
+
+Count = 32
+Adata = 173594fc26b167f044aeaf9bfe920cab99a27eb2b01827d61f7553cb2018b5fe
+Payload = 394f31
+CT = ed072ba4441a79a90e228a28069fe109d5d876
+
+Count = 33
+Adata = 71cdd16eca9255aeedc23bd623513918ea97da21485074415fe75bcc42f454c0
+Payload = 868bda
+CT = 52c3c065f272f44c5210b5bcc571e819580910
+
+Count = 34
+Adata = e84418d332d16d2298e69e7ff3c37bc7b6e030cc822e73b3f4a0029bc2ea4d80
+Payload = 52d6bf
+CT = 869ea559c5f7f73a1b5f419c9f63ca401894a8
+
+Count = 35
+Adata = 42d962109bea1d50be0f3d83b4c2a6033d53b3d7112591866b1ae52dc84cb5d0
+Payload = 6f8d58
+CT = bbc542220b828cf5365137fb3f1df67cc8d2a1
+
+Count = 36
+Adata = 943b4327b5c70dba63c82f27e0412b3ada012bc0f7dd39ebb13db2f864daf80e
+Payload = fda286
+CT = 29ea9c422b0f41075ac79a0afa2d1047cbbfb5
+
+Count = 37
+Adata = 6076b94caabfa476ab7e6482e4fda9b29f2e2b2883efe44d668c7c74628505bb
+Payload = 8651fb
+CT = 5219e1ae68cd6d6815ecbfd01293d160d4d38a
+
+Count = 38
+Adata = 3e4bb5781f84b4bbd23583e3dae561c6ff4af8eff35e2a4f35b50d2f360d3469
+Payload = c3e179
+CT = 17a963fbaa81cfdbcaee476860cd5102f556e4
+
+Count = 39
+Adata = 364008acbad330d0b8d574641a97b0682c49279cfdc80ff309b7514514d18a44
+Payload = 4a97d5
+CT = 9edfcf7ad1520564b68824a3a939371c21a336
+
+[Plen = 4]
+
+Key = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf
+Nonce = 2ef29d62b40d8643848797cde8
+
+Count = 40
+Adata = 1225b036e6044df52314016760e92750de0936120395de750a2c54a7fa0cea82
+Payload = b46b343e
+CT = c2c39d6f9344e2de064f269d065a2a6108605916
+
+Count = 41
+Adata = aaa6257d6783936a4445833c2ac3bea8cb7334f22ade9c035d515bbc91d6a78a
+Payload = cb216301
+CT = bd89ca50693d90b8297b90bc41c231d08b0204fb
+
+Count = 42
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c1124797e564b63e008e7b8ab
+Payload = 697a8696
+CT = 1fd22fc79d0146fe373437c529fb2eeb169e4bd7
+
+Count = 43
+Adata = 864d0f786497c7ce283762ca0959ec9c825ed445a5dbe5b4b2e5772fe88ce7f5
+Payload = 6bee3db9
+CT = 1d4694e8e389c549bfc4ede936d7896e544b23ad
+
+Count = 44
+Adata = d5388b0b548c58886dcd335dff2b1ed23ce3eebbb708fb5bbd831c83e959d3fa
+Payload = 85d95855
+CT = f371f10495177a9fe6d9329a585c8737c92a4d29
+
+Count = 45
+Adata = 83cddd189736f224cad6a29efba45e43c75450a14f1541713b7fb926ffc768c6
+Payload = e8b23340
+CT = 9e1a9a113914431a10b1f94a2b99b9e442f3dca4
+
+Count = 46
+Adata = 8fccbd1fc5240691cf24e8807bf3416c1b2d87fc86dbf3955fa2e52b9a3a8457
+Payload = 595c4d7c
+CT = 2ff4e42d383d8dc98b22010dd93cd0cbb396d9e3
+
+Count = 47
+Adata = 513d45f6f37f3f051667dc743215059e06e4fdc8945789b16d50556a2e839368
+Payload = 314e0c7d
+CT = 47e6a52c40c513bfc92d1a7db5ed7cab2d8212b0
+
+Count = 48
+Adata = 70828be102e554f0d4b07641fa3254bc8db06eefaf5b85a7c97e01c217fc8f3f
+Payload = 35753e32
+CT = 43dd9763ea98f4ac6b3eabd483f1e6ab92f3b83c
+
+Count = 49
+Adata = 343d5a4ad39acf81adcf24e9807618932abcb3bc076734f179174c77c8cb89e9
+Payload = a531c0ed
+CT = d39969bcf99fb67b1e2aba2d232db2445e6aec2a
+
+[Plen = 5]
+
+Key = 30419145ae966591b408c29e5fd14d9112542909be5363f7
+Nonce = 27e6b2a482bbc6f13702005708
+
+Count = 50
+Adata = e04e81e860daf9696098c723085d8023c240ebe7a643131e35359ab04bd650fe
+Payload = 8ceaeb89fd
+CT = ec9d5ed36243ddf77b33d8cf2963ba76fd4e19f3c5
+
+Count = 51
+Adata = 6217cd581d4b3b2f7bcf1b8dad9ad6430e2e3a0063cad52260e0a1cd6fc9e73a
+Payload = 7e51d6f870
+CT = 1e2663a2ef6b73fe9e638e205b27f78ed1bb9b0ed0
+
+Count = 52
+Adata = 8aa7847e496f5e9f1f87851442de844f27a21c1b48f82fe525f0dd5a88b8ec38
+Payload = e0023b674d
+CT = 80758e3dd25936115e23158aff1916edec241fad56
+
+Count = 53
+Adata = 3612abc865a4d8d7b86a84109388584df6526525adb1006ec6c8d00048d725bc
+Payload = e2b5b6f36e
+CT = 82c203a9f1f15aae4b70dbee244be1daa74475d7e2
+
+Count = 54
+Adata = 849a99c6f1cae0ad4bcde4bd0811e87ca5ed7b913de1a8285a206e980b4b7043
+Payload = 9a17e4a22a
+CT = fa6051f8b5bbff424487848385f8501ab5a77f327c
+
+Count = 55
+Adata = 9066367c784de0a4d1116bbe95ce55ded85edddb6273c2049ee24e0fb3429352
+Payload = d4e765fc78
+CT = b490d0a6e772d8d5da6f593a8d9956731b42645aa9
+
+Count = 56
+Adata = e7aa9f767fa8920f96f91c41d9e86755faaedaeda596a444b65f99b7a9e23e85
+Payload = 1074349e10
+CT = 700381c48fe3eca12b835dcfd08166ac8831585626
+
+Count = 57
+Adata = bc0db1ebf910b6f4dcad5401401d6bc2272e23130947dc236ca664d5b5ed6d66
+Payload = a46dd7fb58
+CT = c41a62a1c72bcce66018e9e552d2c8a229301361df
+
+Count = 58
+Adata = fcbeba2d0d73239d05f691a52b08152c9dd871f8dc76c2c18b8a638a74460d31
+Payload = 2e0ca09221
+CT = 4e7b15c8be3e41a50a28ea3be14baadf12964a37c4
+
+Count = 59
+Adata = dcdefce64ae4339f46c0759a4a10b29d59daaaf1e5dbf75cf11b4e4f73c5025f
+Payload = 2e108ce0fa
+CT = 4e6739ba65bee2ab25bfafa76dc3e54832b2f76864
+
+[Plen = 6]
+
+Key = 748ad503388a34041a7bdae6361d57894357c333bacf02ca
+Nonce = 518b79d194579b19f2d8845b70
+
+Count = 60
+Adata = 691dd98f61fd213b0840ec5a6f06ef9a1420be0d59bde5e43546347a2a865a94
+Payload = 24d6880aed7e
+CT = 270120f9634ec15536e21d961c675070ec4cff9037bc
+
+Count = 61
+Adata = d1fd047cdb18463766841abb1fcd25257f1458b595bfcf24066ff9385232fa97
+Payload = 2298028d0213
+CT = 214faa7e8c239b303af0b098f902dc24e66fe56adc6e
+
+Count = 62
+Adata = 65a480d120a0459dab69e8f23094801e10092666cc56f9fb2549662982bda6d0
+Payload = f248e5225e3d
+CT = f19f4dd1d00d1b657925a9740d6828bd85cd12205764
+
+Count = 63
+Adata = b738a53fbc9689dd49f68f97f5a99665258cd52e74dc653b594cffec045508aa
+Payload = 611dade00cec
+CT = 62ca051382dc395a1c49129ef6cce0ad5f6ef378aa1c
+
+Count = 64
+Adata = 7006f54184f0ff0ab215ca408d46325b86c1cbae6da7838435b1826ff81f55dd
+Payload = 5871a8300471
+CT = 5ba600c38a415e68468d1b2b516be3d688567d84ab80
+
+Count = 65
+Adata = 9e6e6675d4c6b1e0f3894aac071f4c99a364708edea12f319cbc27b40fabc0f1
+Payload = 3ca8a7520e94
+CT = 3f7f0fa180a40ba1af163049d16817021665d183bc9e
+
+Count = 66
+Adata = 10ceef716f54b74d7c8a435d6aa38a10ff23939ca29e2de7b6c3e0a8269a23c9
+Payload = 9c2a0070fbba
+CT = 9ffda883758a670f35869da9821b6ff1fab3e6062ad4
+
+Count = 67
+Adata = 3ee0865f29be50160273b4a94ec078932b9cd10a858e31838d5b607867e1ce69
+Payload = 436179c74fd2
+CT = 40b6d134c1e208f395250fd79087c858b83755411114
+
+Count = 68
+Adata = ec2b8bfe1ccd491b02aa4a9178fd6f099556963e39e2ca5fe6ecb6b5d2a46085
+Payload = ecfa41c614c5
+CT = ef2de9359af5afcbd9af2d584a0f638d066f2496d9be
+
+Count = 69
+Adata = 5b6f6369643d83b1db33d75257d7dea761e574e6e1f1ecead64e5e354a2f4235
+Payload = b48c10105dbc
+CT = b75bb8e3d38c17861882b8930296fd51d969a1e9489e
+
+[Plen = 7]
+
+Key = b930cca30a3fd230c237c8f3cc6792d0c4084dff5c18d775
+Nonce = 7574802fd82fe96c05431acd40
+
+Count = 70
+Adata = 1cf83928b6a9e525fe578c5c0f40c322be71b3092239bff954dd6883738d6d71
+Payload = 2a755e362373ef
+CT = f06238b0450fd1f4b6cab1383adb420c4724aa7bdfefb7
+
+Count = 71
+Adata = bb5450f66273f63b2f79dce177381ce846584ce4f7a0ad5a0171a56e149370bb
+Payload = fab43224bf8989
+CT = 20a354a2d9f5b7a1f99175d3dff5a73f0053a95c36fd8d
+
+Count = 72
+Adata = 3e5e1037bd2922eb20c34200c470b76e537baf7e7f1d8dd2f7a184a593c66554
+Payload = e3aed6715aa429
+CT = 39b9b0f73cd81734b4ad0e41117940abf530093dac648e
+
+Count = 73
+Adata = 3cc88a096a1a440827f5b7da675389e50b5cce35fa2cc36674d6bfc5a3a966b2
+Payload = e78db0f83997cb
+CT = 3d9ad67e5febf5663a8324014550430c7eaeffbd8568f7
+
+Count = 74
+Adata = 2cca33a10b9da7ba99a6b552d1405f2df3fdfd15358d8fdab5e15296b38f9135
+Payload = 726557906845b1
+CT = a87231160e398f34ab635c4eb5b38b86e71da8af3840ae
+
+Count = 75
+Adata = 2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947
+Payload = 043a759b578be4
+CT = de2d131d31f7dabd9961766e03eaa7e8888227c98d1f42
+
+Count = 76
+Adata = 8b8e3d7c88fa16d70130cee290b7e2eecf0ce711118cd9265093b11467e63554
+Payload = f31f2fb4b3fd80
+CT = 29084932d581be637842d96d13c4aab97e296458745a9d
+
+Count = 77
+Adata = 6341370e126097f9721a13c977eb4875cf1286e15c3adfa4e7597e0e13d93b6a
+Payload = 7e3c8224104669
+CT = a42be4a2763a57a51ac46611366c666cab6bfd3d1baaa5
+
+Count = 78
+Adata = 227926b62f7cdd90e4d3b0cb5457e71fb087d329671f0fa891ec06eb8edeb58a
+Payload = 26a0528ae6f9c1
+CT = fcb7340c8085ff8c7d7e5aec14845f844ad38544a2f11d
+
+Count = 79
+Adata = 05b50c40b02e79b74b94d726a7ce8b2b7216ef8af6e7a42d041d2a692a58ad83
+Payload = 61dcf53d1a184e
+CT = bbcb93bb7c6470f1605ab8a2332012b759ccd2eedbed24
+
+[Plen = 8]
+
+Key = 314c136999e41d137bd7ba17201a9fa406025868334e39b3
+Nonce = 65f7a0f4c0f5bba9d26f7e0ddb
+
+Count = 80
+Adata = 5c7ce4819b30b975ae6ce58dcc1bfa29a8b6dda8f4b76c7e23516487745e829c
+Payload = 4d54d8b06b204445
+CT = 2baf90c490b11f9607482362ab3f157c42d0e9c6c5cffcf0
+
+Count = 81
+Adata = 90257ed88679197b8219bc4c2434a71a4e3664d5859c4ffb9a075654898ffedf
+Payload = b2a35df881cd63a2
+CT = d458158c7a5c38715389509b5b6f2df1faf7e8c39203970f
+
+Count = 82
+Adata = dff8ad83525d8235eacdccc91abeb80795e6b5f463fd28af35c46199f646ceb8
+Payload = e98f5e5a20d02c80
+CT = 8f74162edb41775395328747ca544e987df28883d0377b35
+
+Count = 83
+Adata = cde159c5343cd9d98001cd719d3e9ea25e47e1ff13fc87055d4a53b741f59285
+Payload = 90c3e48313cd4fe4
+CT = f638acf7e85c1437a4ba841883a0d7aeda398c043161966f
+
+Count = 84
+Adata = fa88cf5a08be4fb0c1a7960f45726c303eb559861fa60d17aa8dfe8bb5795382
+Payload = 8ad6d5a28ec075e6
+CT = ec2d9dd675512e3509195efe66c5faf413e0f68df8cb647d
+
+Count = 85
+Adata = fe9e93a9370b43efa1560aeb017ff04fca7f207191e6f707c1c35b2e90c44eb2
+Payload = eb83928f0d5f7aa3
+CT = 8d78dafbf6ce2170b51af067ad69ad96009e50ead3d03f02
+
+Count = 86
+Adata = 35792c854fdf1c8cf7f3f8ed2b8ec4f31fe17bf8d4ba49caec03f954bd8bb17a
+Payload = 4cd74ed2fd083011
+CT = 2a2c06a606996bc26b1cb03ee76587f84364825f7c1fcbe9
+
+Count = 87
+Adata = c084108f9c0a74cbf70f614dceae592546865006930db0401828a0eecff98671
+Payload = 52365f94579e0646
+CT = 34cd17e0ac0f5d958fa70c5e195f1f955d64892f532b7683
+
+Count = 88
+Adata = e8045949de61c5c18a63e628330a4d1d12782379a8f9187755409d1825f453c5
+Payload = 8fb85c857a3e38e7
+CT = e94314f181af63342ddf297bdad58083645a052815d29a83
+
+Count = 89
+Adata = 53cfdfd66d63c2924bd583487b90b1dd9ec199f90d660cb9c3a763a4776abfe1
+Payload = 43d2828e86f7856b
+CT = 2529cafa7d66deb81ad3b2be41dbc39df4c0145dcbae3e76
+
+[Plen = 9]
+
+Key = a19f6be062ec0aaf33046bd52734f3336c85d8368bef86ab
+Nonce = 7f2d07f8169c5672b4df7f6cac
+
+Count = 90
+Adata = d68d5f763db6111c5d6324d694cb0236beab877daae8115ecb75d60530777b58
+Payload = 13511ae5ff6c6860a1
+CT = b3859b757802ebd048467fd8e139eb9ee8fcdca45ed87dc1c8
+
+Count = 91
+Adata = f6e219b29884dab9ea9bad34d9ef8a50ae389c9a908de7154a1f2e894f27141f
+Payload = 7e7e33e1a07d4e8fde
+CT = deaab2712713cd3f3789d0ee8323ea2ee7a68aaaa9c49b98df
+
+Count = 92
+Adata = bcca002d69d9d1044c40ae741ea33ce6b8463f5a28d0514e044fdae2fe7d3c3b
+Payload = cc88980c73e6c5f0cd
+CT = 6c5c199cf48846402437c9fe3d9feb0485e6d7c04423b77a53
+
+Count = 93
+Adata = 39cac8f0825ffdb0668455933ad1581263a23b9e5f1305340528f0320d4b1269
+Payload = 34cb528f50d073cfdc
+CT = 941fd31fd7bef07f35b87e90a71ffe6c30bee1771078a701ab
+
+Count = 94
+Adata = 510a02a44d142c8e975d1d933f828fd7e47d28b88223f1698cf009dc3b079be6
+Payload = cbce3df86438a61065
+CT = 6b1abc68e35625a08c9e9c5be0657649448c38692e8d703d30
+
+Count = 95
+Adata = 40e0418cd52f74d78a8e18ed86210e3661a86d8574aedcee540340d8996d9852
+Payload = 80a2b835f8b0729a4b
+CT = 207639a57fdef12aa213e5f2bfd33101597cfae7cf334a8528
+
+Count = 96
+Adata = 1f2938b3bde19e1af91299c08638061dc3c1ea3284c259d415e996477cb37b0e
+Payload = dd04794e65ce34127a
+CT = 7dd0f8dee2a0b7a293516a7310fbd4ceb90d8db9a86cb6311b
+
+Count = 97
+Adata = cbae5b46e35fa2a279dcaa4c724b923805d4707412a84252b64228c91cedd019
+Payload = 00c4101052f54462d5
+CT = a0109180d59bc7d23cef6165af65f3522dfbfed0293db39ecd
+
+Count = 98
+Adata = d0f27c7f42892f3ad4c0029c5b698abb1d035ba5869a665b1de8861db6c055e8
+Payload = d0865445d3b26b6f49
+CT = 7052d5d554dce8dfa00726434c1349e3e874a2d6bf598d05fc
+
+Count = 99
+Adata = ab0f5a829a9319a74d5d5179aa0a410a0fcf52f344a7a896aeb1f7a6c5d398ea
+Payload = 7c7c8580b944ed3fd3
+CT = dca804103e2a6e8f3aab491e60fc97b3cb5248291e4866dcab
+
+[Plen = 10]
+
+Key = de1c8263345081d2dfa9afdf37675971135e178df554a4d8
+Nonce = a301bb82f91a582db01355c388
+
+Count = 100
+Adata = 9ad52c041390d0d4aaf65a4667c3239c95e7eae6178acc23fb4e70a852d483c6
+Payload = f777aba1fa70f94e6de9
+CT = 9d8bff6d2dcde77104ac6aba025abc01416a7ca9f096ab2529cb
+
+Count = 101
+Adata = b49c7e7b47870c1cc339c7c09aaacfd6115fa8a0f04990367eea10cfacb9d23c
+Payload = 349feebfbe58f93ea3c3
+CT = 5e63ba7369e5e701ca864acb200e85a0d4753a8ba226aca72f98
+
+Count = 102
+Adata = e61ca7310172eec16745a73e34516f65844eecd0dbc5566ac5213626b9096ef1
+Payload = 678a40b4c2c7df0e4c9d
+CT = 0d761478157ac13125d87869784e3321183d8c044657a020e9b9
+
+Count = 103
+Adata = 690f5e5d8da6cdb0f492e80449e152ffe88fea9742564d8383c79cef739a7f74
+Payload = 2b81e0533313664bf615
+CT = 417db49fe4ae78749f5070634d00b1facf0e9e9979ca257a71e2
+
+Count = 104
+Adata = 78e34b0a1d61ccd411cbfd306ea2ef3ce89c0b085deb4cfbaec2ab72ce16daa9
+Payload = 1ac63aa38a206d8e7d68
+CT = 703a6e6f5d9d73b1142d994630ed92e2973b22773f229b45bdad
+
+Count = 105
+Adata = 51bacfcf87ea11da34b76acba8c444792ec3db3c8ee6e600d69679975a682a54
+Payload = 027a7fd7897808ec7a56
+CT = 68862b1b5ec516d3131304571b015bb6b4651f1eb9f6fb3a7b74
+
+Count = 106
+Adata = 5159357a133e4743f903d05bd641da369a3675337760fcd2424a99221ba70b78
+Payload = 1086953d352e94a51a6d
+CT = 7a7ac1f1e2938a9a7328bb0e11ac4608081fd0702a137da0aea3
+
+Count = 107
+Adata = f567820865340314d46a17f520ff315efb6b33bdeda590ca9c4fad604c2d8e8d
+Payload = b8b148aafec4a035e9a7
+CT = d24d1c662979be0a80e252c9ec1317ce30dffeb4c9bf3fd0bbdd
+
+Count = 108
+Adata = 0cfec933831644b468724e808bb3d25fe8f15850ce513fc341da46089c845208
+Payload = 884242a87779d3921f8e
+CT = e2be1664a0c4cdad76cb691e32be3cdd9721a13aabad26dba58c
+
+Count = 109
+Adata = 8edc2b85d44297ac66bdd90d05d8df38124033d6a583bb8dda18a2246ba096e8
+Payload = 25c32770a299020d8500
+CT = 4f3f73bc75241c32ec45333a381be77800654aac335bf9220ac9
+
+[Plen = 11]
+
+Key = 248d36bd15f58e47fcf1c948272355821f8492e6e69f3661
+Nonce = 9e8d492c304cf6ad59102bca0e
+
+Count = 110
+Adata = 9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f5
+Payload = 33709d9c7906e2f82dd9e2
+CT = 9114d36b79b1918b2720f40cddce66df9b4802f737bea4bd8f5378
+
+Count = 111
+Adata = ba13974d95f2eeb367b63850609c53dc66c2710f682f10bef0142d48f851b430
+Payload = 84172985e7d194ba28a87c
+CT = 26736772e766e7c922516a12c94615be2bd81bd598f3022f5775a4
+
+Count = 112
+Adata = 5f16180bfac9b7483774cb0e1d57a43e9bf3cf03bf6fe758293aadcbbef25b80
+Payload = 9a34d32070c71d7de8f512
+CT = 38509dd770706e0ee20c042758e936750e335702542bc598e211c4
+
+Count = 113
+Adata = 4352057bdd1735a85dc0fc4dbeedc73279c27eb24a97641236f03f11cdafb8c0
+Payload = 2054a268b1f6fae4f15d91
+CT = 8230ec9fb1418997fba4870762bb2a7d04ba2ad251d595d0619dc4
+
+Count = 114
+Adata = ddf118ae403b2509e75eb7a26d17e73e527acbacfbe49a56fa3210169030144b
+Payload = f71afe9a60f08a0ef694aa
+CT = 557eb06d6047f97dfc6dbc27d85594da3fd35bd8498d7e389ee7cd
+
+Count = 115
+Adata = 973904409e8154132439926f0dc45c0d81bbbd5793f7f81e20eb818bfa374d58
+Payload = cdf5b47ff73306aa55c496
+CT = 6f91fa88f78475d95f3d80055936db383a8ad10b152046d721d3f7
+
+Count = 116
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f3
+CT = 3cdbdd9338e3992f9d5de5d57e228369e24fe955fd8924526af6e5
+
+Count = 117
+Adata = 8321f65baf9dc856ac1c24f3fee5c74d697eb0b50470d59d8f4a14b506e86c53
+Payload = 685116faa5cc527ac8bfa1
+CT = ca35580da57b2109c246b76c23abfb3b4eb39deb8da2064390dfa8
+
+Count = 118
+Adata = a4e7738038a5116592bb9d92d6d4ed191ab774310f6409e4e45fe907674c006f
+Payload = 9e8c4f1292e8d7e5179b34
+CT = 3ce801e5925fa4961d6222b4272c0639e8e6a1d356fb4fea86762c
+
+Count = 119
+Adata = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005adfe9faab253b572
+Payload = 3ecc2ba566c723462eb0ea
+CT = 9ca86552667050352449fc0633a0f9cdc9490231ec2dd69f6e35db
+
+[Plen = 12]
+
+Key = 77a67fb504b961028633321111aac2c30eb6d71a8cf72056
+Nonce = acadc0330194906f8c75ac287f
+
+Count = 120
+Adata = 8c18486d52571f70f2ba6a747aaa3d4b3ebc2e481ee1b70907dddb94bdfa0ca6
+Payload = 10554c062d269ff6dcd98493
+CT = 7f8b0cad79b545e5addf0b04ff4b0f2b2a5067283210aba8630d0306
+
+Count = 121
+Adata = 4e0b4771c7f6c66f9577c430611fdeec5702296ee3691b6bb8c6a81217edabe4
+Payload = 1c9e7875cf02129ac52daeb0
+CT = 734038de9b91c889b42b21275b16dbdf0b9be3c8c82ac652992d630d
+
+Count = 122
+Adata = 4a687e1d0a95ed2efb95b4c6b040999fcd35136811cd665f934d10224b6064c2
+Payload = 34575694dde459d195b7357a
+CT = 5b89163f897783c2e4b1baede629274d654ef5a4480e24f6bef3bc8c
+
+Count = 123
+Adata = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf823641a12bfce9f5
+Payload = ab20c8e8aab1aac1e4f64206
+CT = c4fe8843fe2270d295f0cd9142ab5407a08b648ce24e9955e28fe47e
+
+Count = 124
+Adata = 4f19bbc3135d7a216465b4c1df2616e8bfc3cc64af0bf52bdc42543f4d2448d4
+Payload = e556ca05bcd1991d2c9836a9
+CT = 8a888aaee842430e5d9eb93e151e94d311c7cd2c1b9048575076ceac
+
+Count = 125
+Adata = b6ffc7387b19786282bda7caad52eb37fbe7e557afcb80faaf57767e2a0f178a
+Payload = e5b665600a2aa413e117c538
+CT = 8a6825cb5eb97e0090114aaf61b71330d72506050368186a5619f180
+
+Count = 126
+Adata = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731203ba3f25b52497b
+Payload = 870864a611aa0475d120bc40
+CT = e8d6240d4539de66a02633d7ea21e36f99e5aab6ffa85994d13d5bb0
+
+Count = 127
+Adata = 8215753d9efc51325f182199e39f9082cc3fe524400f2a7434c68df7eb2b06d4
+Payload = 71afe8d00c6f2ea8c8b050d4
+CT = 1e71a87b58fcf4bbb9b6df437cc93a50dea11c5e0b19f14b9c8f16bd
+
+Count = 128
+Adata = eb8f198da6ee92a03913c6575343f6c749d2377a09430eb751b13c041e6edbea
+Payload = 7021f18b8f398a5999fcdcd1
+CT = 1fffb120dbaa504ae8fa534699cbfd1beafa2d2942f6812b8dfc88e6
+
+Count = 129
+Adata = de2ee30359e390db72f682c2ca0f14b72b60ff9bccd8c6fbd19a512b12add794
+Payload = affca856eb412f0b3276ae6e
+CT = c022e8fdbfd2f518437021f9337405235dce6161441caa25cc6007c6
+
+[Plen = 13]
+
+Key = 0d423519e4110c06063061323f8c7c95387776b6ee4e4b6e
+Nonce = 39abe53826d9b8e300fe747533
+
+Count = 130
+Adata = cdd9bf1b4f865e922c678ec4947ea0cb02e78bd5c1538f33aeb818ad3f47e519
+Payload = 4021ff104ff1dbd91e46db249f
+CT = 7953d3cd66d093785d123f65ba37f16761dd6aedbfc789ad96edf1490d
+
+Count = 131
+Adata = 342de5fe61e05c2e58ac2978a871fbdf186a7294ec5f85c4631c21b584231211
+Payload = 95050ca1d494bdb561d4840f8a
+CT = ac77207cfdb5f5142280604eaf8f8e855ae975a1fc64bcce3e7492e9d6
+
+Count = 132
+Adata = 7871482948d8d09d0a7491d915543082cb5fc7d6c1e82ee2218279f54c15c154
+Payload = c45823203b20821a48502f9c67
+CT = fd2a0ffd1201cabb0b04cbdd42017a6515156691b3161b747576078da4
+
+Count = 133
+Adata = 65781d018f27ca0c72a9fa9ab4648ed369646dd3ce45d7ad3a54f6b051f1b6e9
+Payload = e901661b7d47c9918244ee1077
+CT = d0734ac654668130c1100a515225cec7d2566a07cd78181ae94577befe
+
+Count = 134
+Adata = 05556b04dae5cde8525633d1862aa200c54af534e302d2cbd34ddc2b78532a60
+Payload = 5556f799d6a6cffb343f28c1a9
+CT = 6c24db44ff87875a776bcc808c133f51dac00f973fd42e0948fab70ea9
+
+Count = 135
+Adata = 151304e3e4f3c2d4d3227e035d849e0d3841ba00cf6cab1cf2e3e4d6cc760623
+Payload = 56bf26be81c7b55ef898e23981
+CT = 6fcd0a63a8e6fdffbbcc0678a4fe78bdeaa8d408ffe8fe64811aa87742
+
+Count = 136
+Adata = f870cc1fe67d6169279f905b0fe5fd9a0436c36498e4b7c6f584f00f7efe8784
+Payload = 36b304a72dbf4acfffa1d7d624
+CT = 0fc1287a049e026ebcf533970197228d155dda2bc814ff33ebeb9a7ffd
+
+Count = 137
+Adata = 5692c9d452ea1c067e62fdc554ddd2b18c8433d59067f971316797fd9853ae6a
+Payload = fb529eb5ae79a0830474ffbc98
+CT = c220b2688758e82247201bfdbde7ba03e144e34a4ab34791a372a2b8ab
+
+Count = 138
+Adata = dcf7fe16b7ca9e27ec3291103398eaa2e77c7b770b67f8858c215af4c523822d
+Payload = 6218c778955d9a56360f06c704
+CT = 5b6aeba5bc7cd2f7755be2862103c2eb5ef0657306d12b753a0694efcc
+
+Count = 139
+Adata = b0f1e2668611dca86e8d0f58c2a4cf4a9472d81ba013e271800b75841fe5ffde
+Payload = bf6b143fb713a81c965c5a9d8d
+CT = 861938e29e32e0bdd508bedca87cc6119151393461ecf65bfe06e0163b
+
+[Plen = 14]
+
+Key = a60cf7ceb62bf3118532bc61daa25ce946991047f951b536
+Nonce = 7499494faa44a7576f9ed5580d
+
+Count = 140
+Adata = baa482c64eefd09118549a8968f44cfea7a436913a428e30aa4ab44802a4ba35
+Payload = d64f9426febce6a84c954dd5ded5
+CT = f7580f17266d68237747bf57c7ed8242ac1a1979c5a9e7bc67d7698c7efa
+
+Count = 141
+Adata = 2ad8ecc5ac9437ace079419f17e6018625b10490120fbe2f12b41e64b73b653c
+Payload = fcd9b67717bcadeceddea336c671
+CT = ddce2d46cf6d2367d60c51b4df4918abced491c063d8bfd0e7341febddc3
+
+Count = 142
+Adata = 7585ee95e74d7a869bdc0b59ca9939dd57e7b09afab179079d467bfe0668416c
+Payload = 18232d7c792fb80e6ca1c8f2c3cc
+CT = 3934b64da1fe368557733a70daf4659ecbb3dbfbcdb0f913abedf8afab05
+
+Count = 143
+Adata = 41be6ca6188f34da1ce83fb8c27652848dc2a71e32bd3631fb9b33ae69e5d879
+Payload = 764dbefb42644d18d23e5e456868
+CT = 575a25ca9ab5c393e9ecacc77150a220d5ec0b5397d6b4e323b5dc7d1b63
+
+Count = 144
+Adata = 197cee3b15320d57996191dd13106fbd4546a5cc3d2bcf0c886af52ea3d9a855
+Payload = 8003586af34bdd0acae4f5547394
+CT = a114c35b2b9a5381f13607d66aac3a5f713f5d0793b732c6e114805cc9b3
+
+Count = 145
+Adata = ee0b647a47656a6e9e09c2d64f734a2cc3fd45b7ee52fea51c24af59ee22a006
+Payload = da143266516a4145cde92c93f961
+CT = fb03a95789bbcfcef63bde11e059ed90e8650bc16f590789dcc625b9e63d
+
+Count = 146
+Adata = 9f5bfffa01f1425d95465723735b49fc1dffbad06cf37a00ca4b59efa21739c1
+Payload = 3842b033f3ca31a6f8e5a638b39e
+CT = 19552b022b1bbf2dc33754baaaa6bda183dda1aef021d92210e27cdd7c5e
+
+Count = 147
+Adata = 64e92ba2748d07f602808f7c5ded15cb0e43140400d37107e59a01e7d45b4c9c
+Payload = cedf60b17185fc71b957cb759260
+CT = efc8fb80a95472fa828539f78b585e4087fb314f893937e95383e66745c0
+
+Count = 148
+Adata = 6ebcaeb4bd44ff4c990305ac64264dfe2ada5f7cd4b294eb9f492865cd28905c
+Payload = 035f449bb28f43365f4a0556096a
+CT = 2248dfaa6a5ecdbd6498f7d410520a71ce5813c578532b742d704fa92276
+
+Count = 149
+Adata = db617207dccd1f6baea5f2242d5e577adb8d69af3bb1707a7a53a8b75452455c
+Payload = 9a2a45424f4965a71270e77cc403
+CT = bb3dde739798eb2c29a215fedd3bb7fc45d15d6939668065d2282fc589c7
+
+[Plen = 15]
+
+Key = 82d4bc9aac298b09112073277205e1bf42176d1e6339b76c
+Nonce = 70325ef19e581b743095cd5eb1
+
+Count = 150
+Adata = 6d14bb2635c5d0ae83687f1824279cf141173527e1b32d1baf8a27f7fe34a542
+Payload = 25a53fd3e476dc0860eeeea25fcb0c
+CT = 4a1cfd0023557a184b929965b0a445cb3993ca35acf354cb2b4254ff672e7f
+
+Count = 151
+Adata = 9f8a56fecf32fa7d50f033b2524c3d798e254bc87245cce57e38edd6ee5d5f1a
+Payload = 797dca47597947c057789433309b67
+CT = 16c408949e5ae1d07c04e3f4dff42ea25b5eb103bac224cad66ec0f100875c
+
+Count = 152
+Adata = 86f15b8b677b7655f358a2c7fd5785bc84d31e079ed859b6af88e198debd36fc
+Payload = e61f9a663d3a2b50ea2f9475971270
+CT = 89a658b5fa198d40c153e3b2787d39b598cc6ec2295c586e7ae270a01846d1
+
+Count = 153
+Adata = 4de6bd43c28143ea5d40919cb5330a7e674f5bd8aeb7b178343a2851281c8668
+Payload = df990c42a268950677c433555319b3
+CT = b020ce91654b33165cb84492bc76fa97ff732093f7d0a96b30d8cdfd1bd583
+
+Count = 154
+Adata = a5c3a480dea1b2a1e3a0ce416148b04f60104217c9d24a5b267b4aa6aa07a4dd
+Payload = a7e72fb4bec3768594a2f6f5b4379e
+CT = c85eed6779e0d095bfde81325b58d7ad98e32a9156e125ff021ef6951b0c40
+
+Count = 155
+Adata = 51b041f1666c59045d333fe63d43457107e1adad34fcbf965e0d191f3e414776
+Payload = d3d1550047cf90eceaea7000d8e280
+CT = bc6897d380ec36fcc19607c7378dc9390f10df08a84c21031626861b201fbd
+
+Count = 156
+Adata = 22f8a3c9d85b2d53ffd92078d3c94373f855ecd01a8ac521d1abd0f2c7cba9ff
+Payload = 756412c4ee6416f2f4e0342011cde2
+CT = 1addd0172947b0e2df9c43e7fea2abdd5d840bb8c4348a9a548482e6b93043
+
+Count = 157
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 666e4a4b3f6cf598aa763cdada4109
+CT = 09d78898f84f5388810a4b1d352e403f0d49927cd6103e3705ba201e8f73c6
+
+Count = 158
+Adata = 2db3ded385ef9c82fd39ea5782d9befe66e8a070066269b2aa7c4bbfac3711c3
+Payload = eb9013a74352b0677a88bd73052477
+CT = 8429d1748471167751f4cab4ea4b3e2d97f7c2b3b42bf570cce79bf30ccc50
+
+Count = 159
+Adata = 194c9e1eaa8e376f9c41bf33823efa28ee60a9213438665b7002cf0fcad7e644
+Payload = e3126400e3c571a4d39b37bc938a22
+CT = 8caba6d324e6d7b4f8e7407b7ce56bd3c2a4fc45d014a0c54edab2930a5bdc
+
+[Plen = 16]
+
+Key = 6873f1c6c30975aff6f08470264321130a6e5984ade324e9
+Nonce = 7c4d2f7cec04361f187f0726d5
+
+Count = 160
+Adata = 77743b5d83a00d2c8d5f7e10781531b496e09f3bc9295d7ae9799e64668ef8c5
+Payload = 5051a0b0b6766cd6ea29a672769d40fe
+CT = 0ce5ac8d6b256fb7580bf6acc76426af40bce58fd4cd6548df90a0337c842004
+
+Count = 161
+Adata = e883dd42e9ddf7bc64f460ba019c28597587d06e57c3b7242f84d5e7d124ab81
+Payload = b31dfa833b0cda20eaa84d2ecd18f49a
+CT = efa9f6bee65fd941588a1df07ce192cb8707b1a4d9ce3def33703e19eaab6dda
+
+Count = 162
+Adata = 409401eb49cd96b1aad2525c5124c509766ff86f88b2011c67a1d501d3485e31
+Payload = 24bc8dc1e2354667b79ba4d7061448ff
+CT = 780881fc3f66450605b9f409b7ed2eaefd9041ddce37d88e79fba28e385b2327
+
+Count = 163
+Adata = 83bf5c063bf1febf71688a832d615e09d6f14badedeaeb6ffbfe343fc7274e78
+Payload = d41d95a1d2326e12cba636910ddfca53
+CT = 88a9999c0f616d737984664fbc26ac0291d971893543868bd8c69078fc2bdb24
+
+Count = 164
+Adata = 8cdd70524e24318c64d681aa27752d4c86c5348c05c9e48f06ed41594785a6e6
+Payload = e8a4b80e081919f1912542d3136764f2
+CT = b410b433d54a1a902307120da29e02a3866b23e4c991f4007e56a1ee9265c6cf
+
+Count = 165
+Adata = 615985f63571c0f94ffcd4df77326abd41e84f388f061d97573a181da7ee5695
+Payload = 7fca7388058d6d1438b6eee0292131cb
+CT = 237e7fb5d8de6e758a94be3e98d8579a2abbea637996b954027efa9464ced6b9
+
+Count = 166
+Adata = 17aa90f2bff0419011b01dee62be31354431cbc89f22332704b096143d4743f4
+Payload = aa540554ee80dbffa475f702d862d6b6
+CT = f6e0096933d3d89e1657a7dc699bb0e757bc8d48d82ebefc76f17323c518ecc2
+
+Count = 167
+Adata = 85288b2be612e42335c144fb058a7dcd567c382fbcee3962bd5be4cc7a7000a8
+Payload = 6d745581831edba437e70ea89cad217d
+CT = 31c059bc5e4dd8c585c55e762d54472c65470c81e487a26cdc26830f2b51bd1c
+
+Count = 168
+Adata = 288f9f52824b54b608dd7226a0a89d43ae8c05107dbae761e1c756911a003b74
+Payload = 811a61869c7a6b2aa9ac0fcc523ef784
+CT = ddae6dbb4129684b1b8e5f12e3c791d5a3043722be9448c3ef144f2288066f75
+
+Count = 169
+Adata = 51dbaba180d4746edbb3420461919b5b735797bf7dd19f84d80475f5efc2748d
+Payload = 378a4e39817f308ed1e639f943b694c4
+CT = 6b3e42045c2c33ef63c46927f24ff29549aba95e04e11cf18ddf73773d395c1a
+
+[Plen = 17]
+
+Key = 3cf8da27d5be1af024158985f725fd7a6242cbe0041f2c17
+Nonce = 07f77f114d7264a122a7e9db4f
+
+Count = 170
+Adata = 30457e99616f0247f1339b101974ea231904d0ef7bd0d5ee9b57c6c16761a282
+Payload = f6dd2c64bf597e63263ccae1c54e0805fe
+CT = ce3031c3a70600e9340b2ddfe56aa72cffdc5e53e68c51ee55b276eb3f85d2cf63
+
+Count = 171
+Adata = 42370f115bbd4b31bb99fe82cca273b3c93072f96b2e09bdc6718d926d48db69
+Payload = f45fee3e086c28a7c590ec0cc05b972664
+CT = ccb2f3991033562dd7a70b32e07f380f65c6328a7476db2c10ec7bca3f6bd3df42
+
+Count = 172
+Adata = e2d692c5678124998a7862b8e87276b0a19e293a609103c99583b36305bcb2b0
+Payload = 4ad69a8ab433ed8909825c71f6081f64a7
+CT = 723b872dac6c93031bb5bb4fd62cb04da68080f0d51d3b8841683eff361984f7e4
+
+Count = 173
+Adata = b5b38791160959dd2836ec1ad25286c1ba410d7212347a95b5738a3d725bb651
+Payload = 3d47071c13f994cb42fb2887e5c6e53a54
+CT = 05aa1abb0ba6ea4150cccfb9c5e24a1355c1428ef5d40bc9e363817f219af2ed56
+
+Count = 174
+Adata = 02691171795a77d1e3bdad513b6fab5b50d1def81bcc1df15012de3433a6aa78
+Payload = e8a4b80e081919f1912542d3136764f264
+CT = d049a5a91046677b8312a5ed3343cbdb65fdfb37dfd1236198035c8461b304152b
+
+Count = 175
+Adata = 7371d8ae79e628f53ffede174eb068db2318c05e2f6d94ad2233a59369b16db0
+Payload = 549aa84bb182312dd016e3107f3b1f9c5b
+CT = 6c77b5eca9dd4fa7c221042e5f1fb0b55acefde0e84a3ce0cb702ceb73ca1dd9a5
+
+Count = 176
+Adata = bb1e1f51082e470f7245458ec902098e1e41d0ed28efa31be71d21ce86527ff7
+Payload = 31a12ca6d69db2e6e252474d7d59ed6552
+CT = 094c3101cec2cc6cf065a0735d7d424c53f8441d46dc5456a587b765e1a820c11c
+
+Count = 177
+Adata = 7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b4
+Payload = 5bb121e70452a954f420a56aca8cd5c059
+CT = 635c3c401c0dd7dee6174254eaa87ae958d0daddcfcc92349ef059149c54a25cd0
+
+Count = 178
+Adata = 505687182c06e6f4effe7fe03c1f436199a9015380ff21d0b2aa9453cfa10b1d
+Payload = 5b80d1cf745b14cb71cbc8dfe0bc7c7358
+CT = 636dcc686c046a4163fc2fe1c098d35a5948c1242b89490c6ee69dedc1e91286ee
+
+Count = 179
+Adata = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee451bd1429cbb33fc1
+Payload = 79ac204a26b9fee1132370c20f8c5bcada
+CT = 41413ded3ee6806b011497fc2fa8f4e3dba2ddd54e509bca0a45dcf2fd514e1496
+
+[Plen = 18]
+
+Key = b46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a
+Nonce = b79c33c96a0a90030694163e2a
+
+Count = 180
+Adata = ea9405d6a46cac9783a7b48ac2e25cc9a3a519c4658b2a8770a37240d41587fb
+Payload = 56d18d3e2e496440d0a5c9e1bcb464faf5bc
+CT = 01baba2e0d5b49d600d03a7ed84ee878926c0ca478f40a6fbde01f584d938a1c91bf
+
+Count = 181
+Adata = 72340d595f3dbd23b46513f8f2b73b6249328c705e7968084bcb647fe734a967
+Payload = 7a76eac44486afdb112fc4aab939e4d1eedb
+CT = 2d1dddd46794824dc15a3735ddc36853890be4646492b6f4cb169383c075756073b6
+
+Count = 182
+Adata = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e06bb90e07460172e
+Payload = 48348c5ec996f7a97ef0ba2cd6885572fe64
+CT = 1f5fbb4eea84da3fae8549b3b272d9f099b4f584289f560cbf76606942fe1a92dd63
+
+Count = 183
+Adata = ffa6277395d31d5db13034d362228a87610e441c98ca3038e252a9db12bdbcef
+Payload = d5c58f10e1a03d8a2501d1eaf5fcdfff3ae5
+CT = 82aeb800c2b2101cf57422759106537d5d355964f5f5532d7cddd7207f0e9a6aace9
+
+Count = 184
+Adata = daf83d02a9bd992ea58c23e7ad18d41796314bae20e864e729f40ccc215454fc
+Payload = da2a863ab1c58ddde320ecadeecac9c5d2d8
+CT = 8d41b12a92d7a04b33551f328a304547b50890ae047e35aecfc38ffdc07e7d8f5705
+
+Count = 185
+Adata = 21ddad5f550044dc5cb123ade17eeef549c4e0173b216bcc602c1e736764cca8
+Payload = 4573969afa831c244817230406fe51183091
+CT = 1218a18ad99131b29862d09b6204dd9a5741b2bdf539ceaa35015712dd15265ca476
+
+Count = 186
+Adata = 9228265ae5c3daf1485ff8011738da508bf2a73731396c5d9aa56fc554e0c00b
+Payload = edf5557e15473b747a819398c9ac1459ffdb
+CT = ba9e626e365516e2aaf46007ad5698db980b241412124ae20b84c13b0c3671d305c9
+
+Count = 187
+Adata = c0a2ff0de21b3ba961e06015ccd71374856a65a4c57cf8cde0a1643aca8ed868
+Payload = e139263478900df806a0f3446bd6600c1aeb
+CT = b65211245b82206ed6d500db0f2cec8e7d3bee9803747bf9fa63412bfc4e10aea89e
+
+Count = 188
+Adata = b54378f031a31cf3985f573829c9ffca14616742e0a7e03b0a2d7f05eff0219e
+Payload = 660eaff0f113eaa2f5f7ad4b62bb849a3a25
+CT = 316598e0d201c73425825ed4064108185df55afdf430b57845dcf622d4f25cdeb2a3
+
+Count = 189
+Adata = e67f35c18a9336469eae23040f98f52338ca8d0cab269ac32fe6bc7605d3ea56
+Payload = 0f89897271f5d0349d57399005ea60c0cadc
+CT = 58e2be6252e7fda24d22ca0f6110ec42ad0c7ed4c04c4b4dd585891ecfddeab8cc87
+
+[Plen = 19]
+
+Key = 7b71045ccef735bd0c5bea3cf3b7e16e58d9c62061a204e0
+Nonce = 2b9ecfd179242c295fe6c6fa55
+
+Count = 190
+Adata = b89166f97deb9cc7fdeb63639eeafb145895b307749ec1a293b27115f3aa8232
+Payload = 890d05420d57e3b3d8dbef117fe60c3fa6a095
+CT = f842ff6662684de8785af275fa2d82d587de0687ebe35e883cbd53b82f2a4624c03894
+
+Count = 191
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a49569a5b27b
+Payload = 6b425cdcdf8304e7fbb70b2973d55e6940025b
+CT = 1a0da6f8b0bcaabc5b36164df61ed083617cc807d4824f0a98db2d87365a42ca3b80e1
+
+Count = 192
+Adata = 9b4fc98fcdcf485205e7054bc9d1e02d0d8584420537e20d3821de2fd6824787
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2
+CT = b9f0ee7ba0c4018d6d9b513fe92670eaabd221404e631735c544edeeb4c0105c55bf0b
+
+Count = 193
+Adata = 45622e1472542be2f63f463d253617eafd4f2ad609f9020884905dd5c22fba53
+Payload = 12b5a76faedf6f855e328c2cb87be8aea78c5e
+CT = 63fa5d4bc1e0c1defeb391483db0664486f2cdc16a4cf37e8e96eed1217d21133e83d1
+
+Count = 194
+Adata = 958689aea3c6cd19020eff9d635ef44ee0793424df38fdf13a238b969d429777
+Payload = f0927c3cb0a876d7877466507da8bfa0bd9a16
+CT = 81dd8618df97d88c27f57b34f863314a9ce4859facf81a636351f6e67d6ec12636ae0b
+
+Count = 195
+Adata = c22911efc36fa739048af0c951ef2449bb3605c52f65120c4d71fe5976026032
+Payload = d2c5d4e2362f19c99de66da7bd9c495c03d9a1
+CT = a38a2ec65910b7923d6770c33857c7b622a7327ce73a7e2db69d30441f89a03fd0e84e
+
+Count = 196
+Adata = 799da61e2c10ebb4783f618b8f69da7704a1b2b925cebc228af57d7ceebb9825
+Payload = 1c9d7f5b329ef4d384b8b7955a20f8a3fc15cd
+CT = 6dd2857f5da15a882439aaf1dfeb7649dd6b5e8d787a9d06b8533ca96fb1db8aecc8e5
+
+Count = 197
+Adata = 14a8e18afe0b9fe18ddfd754219a7e18ed36f419f8262d91678e10daffb31c81
+Payload = 3a64414c3588d7c26871d7d054ac6c8420d491
+CT = 4b2bbb685ab77999c8f0cab4d167e26e01aa028ff5f819d552c08054b5ac02063e102a
+
+Count = 198
+Adata = 7294a8b4ad97c81969e4a2876a3dc0ee322d554726997dc9ed98c5601985ee5b
+Payload = 545dd71bea9967e07a89f84a2027aacd132187
+CT = 25122d3f85a6c9bbda08e52ea5ec2427325f141cde5af8fada67c47cbb5787a6b2d9c9
+
+Count = 199
+Adata = 99294b22d73805805630fb416d20d4fca67419ab660ff45cd19a3729e81b9f69
+Payload = ec1b17b885c018272652453f47fa6e9ed972b9
+CT = 9d54ed9ceaffb67c86d3585bc231e074f80c2a7412640b179bd3e8a417dc38462c16e8
+
+[Plen = 20]
+
+Key = dc7c67715f2709e150cceff020aaacf88a1e7568191acbcf
+Nonce = da56ea046990c70fa216e5e6c4
+
+Count = 200
+Adata = f799818d91be7bab555a2e39f1f45810a94d07179f94fe1151d95ab963c47611
+Payload = f383bd3e6270876b74abbb5d35e7d4f11d83412c
+CT = 377b5df263c5c74f63603692cbb61ea37b6d686c743f71e15490ca41d245768988719ede
+
+Count = 201
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d27ad5132d507504898f61e
+CT = a5a59286e8ff1d8b9aec209ecc84cd022e76df5ea9bc8cfaf2a1734a792076618c4b9690
+
+Count = 202
+Adata = 4586f73a1f162b2cdb65f6e798a60b5f48938d40b4612d84c1f39244f14efdce
+Payload = 6e923e1f404002aa5cf8f8aaf1b9772da425e21c
+CT = aa6aded341f5428e4b3375650fe8bd7fc2cbcb5cc5122df904b052e4d5580fdeddf5297c
+
+Count = 203
+Adata = 9f7ae892e5662803408d4d062265846441a43c1fa202da59f640ae722a692671
+Payload = 68115771505daa18bb3ce90054bfb7d077e1f37c
+CT = ace9b7bd51e8ea3cacf764cfaaee7d82110fda3ce0ba1bb1af18e15ade3316c21d6b41fb
+
+Count = 204
+Adata = 1f0769a7ae82bd985661e031c4a892c15d3ef37bdcfb45243d02f40fdb51d34b
+Payload = 681fd2a324b3fea4cfebed567ae4546ba373c8f1
+CT = ace7326f2506be80d820609984b59e39c59de1b1dc71e342fbc44289ef7e53e28edf3839
+
+Count = 205
+Adata = bf957ef5ab2805e58ea752da5793f7f23d98fce1b2b67738929e5de8a15f9801
+Payload = a7b9d2d069941e8b943706a02d2847ea713bb103
+CT = 6341321c68215eaf83fc8b6fd3798db817d59843ced1fb4a2a3e349aa590aabbfc3d13bc
+
+Count = 206
+Adata = 833264c1bebb597043b4158087cb651960915d9023189c9509c0d2aed84e7fe4
+Payload = 9b946e8198ce69d2173e970f4e0c103a47ee4160
+CT = 5f6c8e4d997b29f600f51ac0b05dda68210068205079f6c2739e2b789b6e3d3c60389374
+
+Count = 207
+Adata = 94c8414cbbec52e2d73bb8f02ef687c91432495c0c744666317d02e6d46706d2
+Payload = 81ac4618f3db6bcf9bbf67220b7671be4bb4f8a2
+CT = 4554a6d4f26e2beb8c74eaedf527bbec2d5ad1e22a02f287db7217148317d897f65f6a0c
+
+Count = 208
+Adata = fced1131dab3dabdc1a16d3409fa09a90ffe02f0e2c814a63f77f771c08c3389
+Payload = 90851933d4d3257137984cdb9cba2ca737322dac
+CT = 547df9ffd56665552053c11462ebe6f551dc04ec362df9f8b41b1dd4821f8f14e9e633d7
+
+Count = 209
+Adata = 495dfcf91f4735ab35c6bc4deef8468bd988e4099cd291a32b4707f93e13d82b
+Payload = c14ce6d57f0fe7367331c9fe159ae1fb8f1ccb2c
+CT = 05b406197ebaa71264fa4431ebcb2ba9e9f2e26cf61ffb51e56497ca9f39c6665fcbdfa8
+
+[Plen = 21]
+
+Key = f41e369a1599627e76983e9a4fc2e963dab4960b09ebe390
+Nonce = 68ef8285b90f28bcd3cb1bacea
+
+Count = 210
+Adata = dbe3e82e49624d968f5463ceb8af189fb3ad8b3b4122142b110d848a286dae71
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326
+CT = 9f6028153e06d14d30b862a99a35413413c04a49dc6f68a03a11cf00d58f062a7b36465d13
+
+Count = 211
+Adata = d9acfd611e5bbb08c5d05d56791b8aebabf8d69734ec89153c91a1f65b2e1adb
+Payload = 35f6bb3f6a388f3a5a039b0a495b676d0b928aeb19
+CT = 2b3bac123fd395813c44aaffb0362b469fb10781e3ca1fb470b666523a19f83481f16481ed
+
+Count = 212
+Adata = 6003b771afe4e99e1ef1ed4a31b10540d95f4ac49885f0c8e5cdcb63d213127e
+Payload = 6aa7e3802b5a29d4f9ca88eb59f94af783d1054466
+CT = 746af4ad7eb1336f9f8db91ea09406dc17f2882e9c53cb05bfcd64da2b45c2e9a89a380b49
+
+Count = 213
+Adata = c371644275a6290821e7d308714bec2bf62d36c30f7fa77a0d60b28894f1c82a
+Payload = 13332b67ba5ba18137c306bd860dc3eb0a9a0b871a
+CT = 0dfe3c4aefb0bb3a518437487f608fc09eb986ede048f70fbc680cf7092b3dd90b943fc6e5
+
+Count = 214
+Adata = 8eceb15300ec4220510ed5b7deb3429de6ae5f618e1c222c28990a9ab4b4bac8
+Payload = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4
+CT = 1b550aef3ff6a8638484e9ab50c99df7a01154873ee386f33c0b8da8d0c5934e617dd618e5
+
+Count = 215
+Adata = 96d1cf3690c48c77a155ce13e67bbd62e6f03d88c893c1f7c30a6435d5ab36e0
+Payload = 60249343a8cd4d33c6edc583ea7e5c221ef3064787
+CT = 7ee9846efd265788a0aaf476131310098ad08b2d7d3d2db1360fb1121893f4d197731bce4f
+
+Count = 216
+Adata = 379bbc9f919dc2a8687f2a86cc9c3291804240a9b566c58519956848102e6155
+Payload = 79003a8d3d20d412f468f11712cec4d37cee847440
+CT = 67cd2da068cbcea9922fc0e2eba388f8e8cd091eba335ce1bfafc0948f2523e75f2aad86f9
+
+Count = 217
+Adata = 9bff9c9a8f94cd77e7016748da31f86d1b9c68465cbf954511c93a4776981524
+Payload = 7d078a8b200514a00628756250d410f7a0f8a769e6
+CT = 63ca9da675ee0e1b606f4497a9b95cdc34db2a031c7dc265e281307f0f4c38cddc556ac725
+
+Count = 218
+Adata = 25125a4668c31dc2e8a68b6c4c95ad7cf9322852e371b415a357d09acb01b587
+Payload = d9b0eaaff786165f882f41a98dbc0c355b3a1aaf40
+CT = c77dfd82a26d0ce4ee68705c74d1401ecf1997c5ba61c78a2f85a447c3e62b6197d65b9065
+
+Count = 219
+Adata = ad34d8f0902a5b79fb145b8206bb4d3b77e0bd8ae2d0964815389eacb33b4007
+Payload = 17b517ef577f588da374340d2522cc9ea642c8d8ae
+CT = 097800c202944236c53305f8dc4f80b5326145b2540312d067c08a9b4400e1df8bb7ed671a
+
+[Plen = 22]
+
+Key = 3289e59e3a7b29bf4a309afc253030bba4b9bdd64f0722f9
+Nonce = 30259ce106e9bd7a8bacbaf212
+
+Count = 220
+Adata = 2870bd9a26c510e9a256920899bbc77a4eb9b53f927045a943d5ed6b13638cf3
+Payload = 53911a67b65738f87fc7c20d6db8044bde1af95838d1
+CT = 70cf37d4b6f7e707376b1574ce17c040b5143da47abb2fe9afafc2fccd98ccf63b0fdec30eac
+
+Count = 221
+Adata = 611032a95ee87f89ad6be7c0fed8bd245c5f81076087b3bda4cde5587b8d14b6
+Payload = 46917e38b8a542296d290d065b0aa7c8aaa38950c386
+CT = 65cf538bb8059dd62585da7ff8a563c3c1ad4dac81ec102dfd8c231d6a355f079c213ce6858e
+
+Count = 222
+Adata = 2e7ea26d1cceaca3b7862a7a8469e366b52ec27ca127e3317222ee651d8da4a0
+Payload = b527828c89f674dc6f024f8cdd80c694bb3ebd57b2d9
+CT = 9679af3f8956ab2327ae98f57e2f029fd03079abf0b36df11febe34dd568da12c374674b9ac4
+
+Count = 223
+Adata = 0bf4413010daec585de34142224d1cad3072f9720f91ac664ad152820e838741
+Payload = 78230f73f9c0150f630eca4cd679818551d449db82e6
+CT = 5b7d22c0f960caf02ba21d3575d6458e3ada8d27c08cb2916540d9439b832aa44236a7e187ac
+
+Count = 224
+Adata = 2e7cae3306582eb5bad148247aa6c6ec943f8748e84b8a069ca9488b11844716
+Payload = 847bb12e0e56fa07a086eeda5907ae148148fa4107d2
+CT = a7259c9d0ef625f8e82a39a3faa86a1fea463ebd45b80d0768a18dead55700901408aa3f901a
+
+Count = 225
+Adata = 63036dc4ad13aee5dc1832e867f7538da108188fec7b08262af440d07579c451
+Payload = ec59e208c4bb429a371f1b3ffdf07fce5dea8a05f0ce
+CT = cf07cfbbc41b9d657fb3cc465e5fbbc536e44ef9b2a45f2073605d2a441805b6ff89d8beb68c
+
+Count = 226
+Adata = f9ec5ce4b63156d57e451eb67ab6d7a59cc397f43f6d26dc07d1036f0fb4a8cf
+Payload = fb12d94bd21b5748b23132a03065c78dae65a0bd2cfb
+CT = d84cf4f8d2bb88b7fa9de5d993ca0386c56b64416e91dcabef6907811c6b7df4e74c7a63d83b
+
+Count = 227
+Adata = e13a204e16f42bbf4716e95f1cb7e125ffac66a87f591c8ef2c7b8485ff707fd
+Payload = 239fa31d4a65de0318bfc5b60a06d706c129dcf255ac
+CT = 00c18eae4ac501fc501312cfa9a9130daa27180e17c626aa8aa37e858cd990f5593d9ef35f2a
+
+Count = 228
+Adata = c4591c3ad984a1e189c526b719212f8248289eeb277827272b8205d78191eb2d
+Payload = 57caadbb1a56cc5b8a5cf9584552e17e7af9542ba13e
+CT = 749480081af613a4c2f02e21e6fd257511f790d7e354d81e424d6b4528901ae46fb35f8b3106
+
+Count = 229
+Adata = cf4795bc7f43c30d3c3a8fd1b8a9d77d69bf59eb8b59d0f464315f40cb52335d
+Payload = a68c74e05f0a44d4a0372c0e5915b83d8e6729efacbb
+CT = 85d259535faa9b2be89bfb77faba7c36e569ed13eed1f25a4bfda35e1390f3f16f638dcd4047
+
+[Plen = 23]
+
+Key = 40f1aff2e44d05f12126097a0f07ac0359ba1a609356a4e6
+Nonce = 0df3fc6396f851785fca9aa5ff
+
+Count = 230
+Adata = e9699b20b0574fce8b5cbc4ef792eb96e2c1cce36b1b1f06ea2a95fe300633cc
+Payload = 8d98c580fb366f330dbfda20f91d99a0878b47efd14c6d
+CT = 579cdf9da62a2df471e03450516adb4ce99ae0f70b1776a39c3b429a1f922fac0b59e29a122e43
+
+Count = 231
+Adata = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402677aeb51e216335f
+Payload = 7391ba60fabe2c632bbaca16af9a235b2c7dae61691c0b
+CT = a995a07da7a26ea457e5246607ed61b7426c0979b3471067bf538e40f9366adf8758968f06ce8a
+
+Count = 232
+Adata = 4f263cda4a50b0e5379ec2fb546b326a07943527c1d175c029455a917753883b
+Payload = 7e1e93a6ca35a2c0e4f08fdb2e7ee22b9f486f0ab919e2
+CT = a41a89bb9729e00798af61ab8609a0c7f159c8126342f964a1199251b54f419720a30de83161de
+
+Count = 233
+Adata = 4d43702be4f0530319555d7f1a3356160f6cae48051f12e22a153d7e405c1149
+Payload = f94ff053c7413f34f96eae41fd1ac101151069af5a9428
+CT = 234bea4e9a5d7df385314031556d83ed7b01ceb780cf33b417e4cceb8dcf45ef33cc0007755bbc
+
+Count = 234
+Adata = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259e319266042db8887
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c566990
+CT = 60030c2802e3fa28e822c465432f75b671e0af548c328bd35aed57f49dcfecf248cf9d246ac024
+
+Count = 235
+Adata = 12e4fe727b1f27a619dd67bb976ddc2b18b2ef8b7184290d9553494a500d933e
+Payload = 872940780a94680a791c937994ceafd2c8b7a22b5f4927
+CT = 5d2d5a6557882acd05437d093cb9ed3ea6a6053385123c97cda0e04d2ff65c2e06a8276bdf6f97
+
+Count = 236
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830
+CT = 0d1c7e9a22393a1c757245d27ed6bb18079b3b2db6232b3494dd2ee0a0fe5bfc9f69234c8142ed
+
+Count = 237
+Adata = cefc4f2fb796c2502329ca3d8f8af3200dd9edb8f164e15acec90536a15b6fdc
+Payload = cda681aa3109ebf5f21ee3a849098ea3a551e844fae4b4
+CT = 17a29bb76c15a9328e410dd8e17ecc4fcb404f5c20bfaf9008ead8e923997508eebf5e776198dc
+
+Count = 238
+Adata = 94fc7eb8febb832097ba6eecd2697da91b5a8a1f2248f67a7659e0ac55a09a0d
+Payload = d4f8d262870b5000a40b8fcce88f55c65c4d12e729975e
+CT = 0efcc87fda1712c7d85461bc40f8172a325cb5fff3cc45f136cc6ea1b0fdb554e0803053875b89
+
+Count = 239
+Adata = 459085184094e302b2e921cc04270b676e75bbcf0e4b53ed387df2bd0e75e0ac
+Payload = 732f211061c0a32c6ad124c58418d560ef5eab2602314c
+CT = a92b3b0d3cdce1eb168ecab52c6f978c814f0c3ed86a575da8ceccae093888daaf92c95817fc3d
+
+[Plen = 24]
+
+Key = 91f9d636a071c3aad1743137e0644a73de9e47bd76acd919
+Nonce = 1bf491ac320d660eb2dd45c6c3
+
+Count = 240
+Adata = 3bdfd7f18d2b6d0804d779f0679aaa2d7d32978c2df8015ae4b758d337be81dd
+Payload = 4eaf9384cad976f65f98042d561d760b5a787330dc658f6c
+CT = 635530cab14e3d0a135bb6eebb5829412676e6dd4995f99cb7e17f235bd660e7e17b2c65320e9fd4
+
+Count = 241
+Adata = 9de45b7e30bb67e88735b8fb7729d6f3de46c78921b228bad8f17cc9c709c387
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 7444449ff443f1ab73fdfda2ea2a04d5163a1209e868b1d99f40890c7d650afccda40fb2a4cd603b
+
+Count = 242
+Adata = 783477f981ef0551b5e7a714b640bbb38316c53756c96e30c898cdee3b72e6f4
+Payload = 4e7f3c86d846ff351db81dbe1d2e9ed73ec0450587ae681b
+CT = 63859fc8a3d1b4c9517baf7df06bc19d42ced0e8125e1eeb50236cf1a12a9e3542a4051788f9775a
+
+Count = 243
+Adata = 2851d40243512a43f70f9c25e9b18c122a1433f05c61e65017e197e88b129e43
+Payload = 2db7cb2739c839383b64c2c93c7d5c906d984756c3dedaa9
+CT = 004d6869425f72c477a7700ad13803da1196d2bb562eac59b1bbad9861192df356c6678b2f561ea3
+
+Count = 244
+Adata = 1cfa2d62cc1f6313fb0c6eb21803e09cdf61ee3ddb15192529560e5d8096cafb
+Payload = 2f2b82497c78369890809460d80a16be4f3330e8a0089165
+CT = 02d1210707ef7d64dc4326a3354f49f4333da50535f8e7951da4211d4c28d2d91568117fc99fd911
+
+Count = 245
+Adata = 5a14b556156191b2704936f64df0bf1dd2bd8d587418f4f85472338fcf86aa52
+Payload = 7cfefca725da1b6bb5d9545e3e50f5a624a8160bdb0e7d4e
+CT = 51045fe95e4d5097f91ae69dd315aaec58a683e64efe0bbeda99be0e054bb881a25a74b547d3ed5e
+
+Count = 246
+Adata = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c680d71fd1f9801fa
+Payload = 5205165c4e9612974dc92f60d1e328d68aa9466e27dbd499
+CT = 7fffb5123501596b010a9da33ca6779cf6a7d383b22ba2694c1fedb47fa30ff2ead6bf382431b2de
+
+Count = 247
+Adata = f852e38703097cc37c589b7860dbc333e091411462d5576dc9909a8cf6ac99d4
+Payload = f968f2833427abbc9fe1cab7e7a3f905a3b23a35802029ff
+CT = d49251cd4fb0e040d32278740ae6a64fdfbcafd815d05f0f338762a4e4299615c67130a28b56a383
+
+Count = 248
+Adata = 43df03a0e23c7ad0d13485150ca224c0b3f39d4e5f2d718db6308e003d3dc683
+Payload = 67da6ca42655188af0b8e389152b2a1b6e2c3ed88926afa5
+CT = 4a20cfea5dc25376bc7b514af86e75511222ab351cd6d9559dbdf61387294812f483aad76d48d899
+
+Count = 249
+Adata = b297dce04ada2ddebc7e94eff7c51b87eee2f98c410c5c0919d0652653ab7458
+Payload = 9777cf90dd7c7e863506686fc3ba6d3d05328f78b350f92f
+CT = ba8d6cdea6eb357a79c5daac2eff3277793c1a9526a08fdf078177541e19b11dfec995f40c99af70
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp
new file mode 100644
index 0000000000..e9cd7eefe9
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = c6c14c655e52c8a4c7e8d54e974d698e1f21ee3ba717a0adfa6136d02668c476
+Nonce = 291e91b19de518cd7806de44f6
+
+Count = 0
+Adata = b4f8326944a45d95f91887c2a6ac36b60eea5edef84c1c358146a666b6878335
+Payload = 00
+CT = ca482c674b599046cc7d7ee0d00eec1e
+
+Count = 1
+Adata = 36c17fd901169e5b144fdb2c4bea8cd65ad8acf7b4d3dd39acf2ad83da7b1971
+Payload = 00
+CT = 67747defe5da5fecc00b9bf3b249f434
+
+Count = 2
+Adata = 9a37c654ab8e5a0c6bdfff9793457197d206ed207d768cbc8318cfb39f077b89
+Payload = 00
+CT = c57ef5d0faf49149c311707493a4cfd4
+
+Count = 3
+Adata = 5ab80169184541393a6975f442ee583cd432d71a6d1568fa51159df7c5b8f959
+Payload = 00
+CT = bc2fb5571a7563bb90689a229d2f63a7
+
+Count = 4
+Adata = c78a22a667aafab0c94047e03837d51b11490693d5c57ea27b901ff80b6a38f9
+Payload = 00
+CT = 428888c6420c56806f465b415a66e65a
+
+Count = 5
+Adata = e11e30cbf63623816379f578788b0c8e6b59ee3c9c50aa6e1dcd749172d48fed
+Payload = 00
+CT = 9f1b7520025e1075731adc946b80121d
+
+Count = 6
+Adata = 05716168829276ff7ab23b7dd373db361e6d9e1f11d0028d374a0d3fe62be19f
+Payload = 00
+CT = bd36b053b6a90f19e3b6622cba93105d
+
+Count = 7
+Adata = 3e915389639435629fcc01e1b7022d3574e2848e9151261ad801d03387425dd7
+Payload = 00
+CT = 458595a3413b965b189de46703760aa0
+
+Count = 8
+Adata = 2f496be73a9a5d9db5927e622e166c6ec946150687b21c51c8ca7e680f9775ac
+Payload = 00
+CT = 8b259b84a6ee5669e175affca8ba3b1a
+
+Count = 9
+Adata = 0a8725bd8c8eab9ed52ca47835837b9f00a6c8d834ab17105b01eb4eb30402e7
+Payload = 00
+CT = c5f35fdf2b63e77a18d154f0ddcfedbf
+
+[Plen = 1]
+
+Key = cc49d4a397887cb57bc92c8a8c26a7aac205c653ef4011c1f48390ad35f5df14
+Nonce = 6df8c5c28d1728975a0b766cd7
+
+Count = 10
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a
+CT = a5f24e87a11a95374d4c190945bf08ef2f
+
+Count = 11
+Adata = f6cfb81373f1cbb0574dda514747d0099635b48cb809c6f1fa30cbb671baa505
+Payload = 40
+CT = ffd43c5f39be92778fdce3c832d2d3a019
+
+Count = 12
+Adata = 5a88b14bada16b513d4aa349b11ce4a77d4cda6f6322ff4939ad77d8ecb63748
+Payload = 41
+CT = fe753b7b661f1aad57c24c889b1c4fe513
+
+Count = 13
+Adata = a92b95b997cf9efded9ff5e1bff2e49d32e65f6283552ded4b05485b011f853f
+Payload = 06
+CT = b91c5ac66e89bf2769ef5f38a3f1738b24
+
+Count = 14
+Adata = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd24aab5f2bbe112436
+Payload = c8
+CT = 773fe64379cea1a8ae3627418dd3e489a2
+
+Count = 15
+Adata = d3029f384fd7859c287e38c61a9475d5ddbfd64af93746b1dc86b8842a8c194c
+Payload = e2
+CT = 5dabc529442ff93005551b7689bcb748f7
+
+Count = 16
+Adata = 51ca3d3b70b5e354451a5177d7acfd8e7b44eae55e29d88b5e8eb8fc1e5c62fc
+Payload = 1a
+CT = a5ee68e416617ac974b3d1af7320cd51f6
+
+Count = 17
+Adata = 8c6c6791f1ac957b18bf008e260a0af4a5b7bfdb1e0008d6eaaa227f45cf4f62
+Payload = dd
+CT = 6243883d93d7066991e0fac453400b4fbf
+
+Count = 18
+Adata = b0a1af969a95025385b251afd1e89f353426ed6e5d71019cd73366aa31d5b464
+Payload = 4c
+CT = f3b940d416f3435812f9d1b18f441b7721
+
+Count = 19
+Adata = 7e72b2ca698a18cb0bf625f5daddb0d40643009db938340a9e4fe164a052fee1
+Payload = 88
+CT = 371d27e9a32feea28a6a7e7da2d27e1cc4
+
+[Plen = 2]
+
+Key = 36b0175379e7ae19c277fe656a2252a82796309be0f0d4e1c07fdde88aca4510
+Nonce = 021bd8b551947be4c18cf1a455
+
+Count = 20
+Adata = b5c6e8313b9c68e6bb84bffd65fa4108d243f580eab99bb80563ed1050c8266b
+Payload = be80
+CT = ecacc3152e43d9efea26e16c1d1793e2a8c4
+
+Count = 21
+Adata = 38e5032c5949c2668191ef1af5bb17eddc28abdb4e5bb41eaffec2523b2525d6
+Payload = 82c9
+CT = d0e5d06bf4b50ccce0b2acfd16ce90a8854d
+
+Count = 22
+Adata = 0b50f5173249fb7118f80d25874d6745d88e4ce265fa0dd141ad67ae26c31122
+Payload = 8239
+CT = d0158d784f486c1dc4a2bafd5b02ca1e1c05
+
+Count = 23
+Adata = 0296743a3125b103a2b2a78a109e825ea10834bd684215ab2e85cc4172e37348
+Payload = 16c1
+CT = 44eda3377002a48f9fe306d157358e6df37d
+
+Count = 24
+Adata = a94e64becb803e211785ba51db7f3db042fbf44a7a821509156a6828b0f207e9
+Payload = 2801
+CT = 7a2df6c09bf1dcb1c82bd98c6e2c13a8d7a5
+
+Count = 25
+Adata = 105358cc17b12107e023a23d57b44c66a2c58d8db05100311575e1ea152fc350
+Payload = 65e7
+CT = 37cb2ea363c0d8864363056467570959ba03
+
+Count = 26
+Adata = 669f9a63cf638a202dca1965c4116273249813ce0b39703887d89bdf5b3b12d6
+Payload = 819d
+CT = d3b16519377e6d0252b5f80cdf3d0253eccf
+
+Count = 27
+Adata = e288590a3eba28ac6847a50b0294ab6bd0a548716ff5102c44a5b656b2d9ddd6
+Payload = 761e
+CT = 24329a4dee6ca2cde473f08f76f779856c3c
+
+Count = 28
+Adata = 5b222aae3c7786c3b9021ba672f9136190ec931cf055f84c85706127f74c6d5b
+Payload = 56de
+CT = 04f29e65c0f01e644e74092253b470cd5511
+
+Count = 29
+Adata = 2082f96c7e36b204ad076d8b2f796cccf5cbc80b8384b53a504e07706b07f596
+Payload = b275
+CT = e059809fa107f379957b52ac29fe0bc8a1e2
+
+[Plen = 3]
+
+Key = ddb739acda6c56ec9aefc4f4cbc258587f443da4e76ddfa85dbe0813a8784944
+Nonce = 0bddf342121b82f906368b0d7b
+
+Count = 30
+Adata = 887486fff7922768186363ef17eb78e5cf2fab8f47a4eb327de8b16d63b02acb
+Payload = db457c
+CT = 54473c3f65d6be431e79700378049ac06f2599
+
+Count = 31
+Adata = 0683c20e82d3c66787cb047f0b1eb1c58cdde9fb99ee4e4494bbf27eb62777d1
+Payload = 62a6c5
+CT = eda4853b186edc15c22ba24e470eb5a072da9f
+
+Count = 32
+Adata = 413074619b598f8bed34cab51ddf59941861ba0169ebe7570a5ed01d790c08e5
+Payload = cc67bc
+CT = 4365fc52a1fb5a58bd51931230c1a7dfb1a8c1
+
+Count = 33
+Adata = 2d65a5175c29a095dc082dab9cfcf4b895efbfa715c57614589d4db159543ce9
+Payload = 33800b
+CT = bc824b7d3810f59176cb108c7e969da51d4d79
+
+Count = 34
+Adata = 6a831b6059456be98e6fce608d8c71cb8efb04a96b45c2dfbdaeabf5420a1482
+Payload = b2c826
+CT = 3dca6646ffea832595c9c86e6517215541ddbd
+
+Count = 35
+Adata = 3a04a01160402bf36f33337c340883597207972728c5014213980cd7744e9e41
+Payload = d7e620
+CT = 58e460e89a6725f0fc35622d89d2f3e34be90a
+
+Count = 36
+Adata = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f6a2443ee03f6390b
+Payload = 795af4
+CT = f658b4b1bd7ad5d81686aeb44caa6025d488bd
+
+Count = 37
+Adata = 7bef8d35616108922aab78936967204980b8a4945b31602f5ef2feec9b144841
+Payload = 66efcd
+CT = e9ed8d0553c801f37c2b6f82861a3cd68a75e3
+
+Count = 38
+Adata = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe01ec1b66eee216341
+Payload = 78b00d
+CT = f7b24de3eeb8ea6c08b466baf246b3667feb3f
+
+Count = 39
+Adata = 71bf573cf63b0022d8143780fc2d9c7dbd0505ac31e9dce0ad68c2428b0878a0
+Payload = 9dd5e1
+CT = 12d7a11db811640c533794bfec6eeb977233ec
+
+[Plen = 4]
+
+Key = 62b82637e567ad27c3066d533ed76e314522ac5c53851a8c958ce6c64b82ffd0
+Nonce = 5bc2896d8b81999546f88232ab
+
+Count = 40
+Adata = fffb40b0d18cb23018aac109bf62d849adca42629d8a9ad1299b83fe274f9a63
+Payload = 87294078
+CT = 2bc22735ab21dfdcfe95bd83592fb6b4168d9a23
+
+Count = 41
+Adata = 75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e
+Payload = 0f28ee1c
+CT = a3c38951b5de3331078aa13bd3742b59df4f661a
+
+Count = 42
+Adata = 8fb9569f18a256aff71601d8412d22863e5a6e6f639214d180b095fa3b18d60e
+Payload = d41c9c87
+CT = 78f7fbcae52afe7326a12a9aaf22255a38d4bd0d
+
+Count = 43
+Adata = 8b62d9adf6819c46c870df8a1486f0a329672f7d137bb7d8659f419c361a466c
+Payload = 046bc0d8
+CT = a880a7957543692a72f0d599de48b5e5f5a9413f
+
+Count = 44
+Adata = fd98f8f39dfa46ea5926e0ffacbabbe8c34205aade08aa0df82e1d4eaaf95515
+Payload = 39bd4db8
+CT = 95562af530fc357f5482b9004d466bf858586acb
+
+Count = 45
+Adata = 09bf4f77a9883733590a3cc7ee97f3c9b70f4db255620e88cd5080badc73684c
+Payload = b43cdd3a
+CT = 18d7ba77a9e8db046fdd548b52d40375c1e9a448
+
+Count = 46
+Adata = 40326d765e0f6cf4b4deccb128bebf65a7b3c3e5bcf1d58f6158e1e9153b7e85
+Payload = e0052e9b
+CT = 4cee49d64efbdd4ad8d3e863172d9372fca07c20
+
+Count = 47
+Adata = aa5ae6dcdc21b5446489bdabf5c6747bdf3bbfdb3de2c03170efefe5ccb06d69
+Payload = 696825f6
+CT = c58342bb95bd661b32bc18025808f8b4035acad6
+
+Count = 48
+Adata = d3d34f140a856e55b29471fde4c0e5f7306b76d03faab26db79c10f95ffb3122
+Payload = 7eb07739
+CT = d25b1074ac05b072264e31a4b2801a6d790512d7
+
+Count = 49
+Adata = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671194646e0b0136432
+Payload = 9cad70b1
+CT = 304617fcc00514d260e1d211de361c254369e93a
+
+[Plen = 5]
+
+Key = bc29a16e19cfbe32bf4948e8e4484159bc819b7eec504e4441a1a98ca210e576
+Nonce = 4f18bcc8ee0bbb80de30a9e086
+
+Count = 50
+Adata = 574931ae4b24bdf7e9217eca6ce2a07287999e529f6e106e3721c42dacf00f5d
+Payload = 3e8c6d1b12
+CT = 45f3795fcf9c66e1a43103d9a18f5fba5fab83f994
+
+Count = 51
+Adata = 99cd9d15630a55e166114f04093bd1bb6dbb94ecaad126fe5c408dee5f012d9f
+Payload = 76fc98ec66
+CT = 0d838ca8bb6f3cd579294f706213ed0f0bf32f00c5
+
+Count = 52
+Adata = 1516fdf7a7a99f3c9acc7fff686203dec794c3e52272985449ddf5a268a47bc3
+Payload = 6564c247cc
+CT = 1e1bd603117d38e026f706c9273dbcb6dc982751d0
+
+Count = 53
+Adata = 0c9c35be98591bf6737fc8d5624dcdba1a3523c6029013363b9153f0de77725b
+Payload = c11b9c9d76
+CT = ba6488d9abc3e46166767c6ad2aeffb347168b1b55
+
+Count = 54
+Adata = e74afe3ba960e6409dba78ecb9457e2a4ce2e09792b1d2e3858f4c79f7ddba62
+Payload = 45a4e0d7dd
+CT = 3edbf4930033a7dca78bcbf4d75d651ee5fadff31b
+
+Count = 55
+Adata = 96cbe9cd193513599c81f5a520fabaff51ee8cbdb81063c8311b1a57a0b8c8fd
+Payload = e5861b2327
+CT = 9ef90f67fa11585167c83105ee16828a574c84ac86
+
+Count = 56
+Adata = 2e7ea84da4bc4d7cfb463e3f2c8647057afff3fbececa1d20024dac29e41e2cf
+Payload = f5b5bcc38e
+CT = 8ecaa88753ffaba456f78e431f4baa5665f14e1845
+
+Count = 57
+Adata = be125386f5be9532e36786d2e4011f1149abd227b9841150d1c00f7d0efbca4a
+Payload = b6cc89c75d
+CT = cdb39d838034714731f9503993df357954ecb19cd3
+
+Count = 58
+Adata = 3fa8628594b2645bc35530203dca640838037daeaf9cf8acaa0fb76abf27a733
+Payload = 3802f2aa9e
+CT = 437de6ee436c1b008b7572752f04362b2bfdc296bb
+
+Count = 59
+Adata = 642ae3466661ce1f51783deece86c38e986b8c0adea9e410e976f8a2fe0fe10f
+Payload = e082b8741c
+CT = 9bfdac30c1a3f7c3c29dc312c1f51a675400500e32
+
+[Plen = 6]
+
+Key = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9ccdf139f33be76b18c
+Nonce = 7a76eac44486afdb112fc4aab9
+
+Count = 60
+Adata = a66c980f6621e03ff93b55d5a148615c4ad36d6cbdd0b22b173b4b1479fb8ff7
+Payload = 1b62ad19dcac
+CT = 4ad1fcf57c12b14e0e659a6305b4aeffae82f8a66c94
+
+Count = 61
+Adata = c13f65bd491cb172a0f7bbc4a056c579484b62695e90383358d605307d5be0a5
+Payload = 3ef0faaa9b79
+CT = 6f43ab463bc779fa7932d365e2da9b05c00a7318384a
+
+Count = 62
+Adata = 59dcca8fc50740831f8f259eb55d4db11f763a83187d93758d78d166f4d73cd5
+Payload = 1a98ddbf35f1
+CT = 4b2b8c53954f813229912137b7a4945dc07cea24a974
+
+Count = 63
+Adata = 578509ca4f57aadb78056794bf18b0714090970db786e2e838105e672165761c
+Payload = f46a7b1c28ea
+CT = a5d92af088546e045f19f737a24c8addf832ed3f7a42
+
+Count = 64
+Adata = 696c0c6427273cf06be79f2206c43af9cbda0b884efaf04deba0c4bf0a25cb26
+Payload = e98f5e5a20d0
+CT = b83c0fb6806edaae8a7dcd3b0fbb59438f88743ec6e8
+
+Count = 65
+Adata = 95a66b60249ed086eecaeb9bc449afcee9de212619e87516ca947351b25120df
+Payload = 06319c0480e2
+CT = 5782cde8205cd9cb636ca6543c4e35964f47341f2814
+
+Count = 66
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112e1130c21d411cdf16a84176d
+Payload = f4c723433b7c
+CT = a57472af9bc2ec82eadf4eb1f055da1a92a82052ab8b
+
+Count = 67
+Adata = ff3bff3a26fc5a91252d795f7e1b06f352314eb676bff50dc9fbe881c446941e
+Payload = 02f809b01ce3
+CT = 534b585cbc5d01b10a7ae24a4ca2bfb07ea2a3b31a97
+
+Count = 68
+Adata = f6be4aad63d33a96c0b5e9c4be62323c9e2308b29961fff980ba0dbda0549274
+Payload = 2b6004823a29
+CT = 7ad3556e9a97231323a4b88af5d7d0b07c0e73ddce1d
+
+Count = 69
+Adata = c3706a28d7420b41e072dcecc06b6b13116cca110bde8faea8e51f5107352d71
+Payload = 236c60cba4fa
+CT = 72df31270444db30eb33d2ede33abbe22f37704fe68b
+
+[Plen = 7]
+
+Key = f7aaeff3a1dc0cc5ecf220c67ad9f6dda060b4f1be3cc609cb4f18b2342a88a2
+Nonce = d0d6871b9adc8623ac63faf00f
+
+Count = 70
+Adata = e97175c23c5b47da8ce67811c6d60a7499b3b7e1347ad860519285b67201fe38
+Payload = d48daa2919348d
+CT = eb32ab153a8e092fa325bafc176a07c31e6cc0a852d288
+
+Count = 71
+Adata = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b6df8e69e5e1111fa
+Payload = f95b716bfe3475
+CT = c6e47057dd8ef1a24840f4f40a7963becde3a85968b29c
+
+Count = 72
+Adata = efcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd64
+Payload = 4862e3677083f0
+CT = 77dde25b5339748f2a4a5c276727e0a210fc2efb5aeabe
+
+Count = 73
+Adata = 360bcb407603fe92f856bf677625b9882521e6dae8f35fdfc3dc737f9398f609
+Payload = 7f1ca0728f6d65
+CT = 40a3a14eacd7e1051734fc31232ab2ab63474020ab4dc9
+
+Count = 74
+Adata = f12ee9d37946cfd88516cbe4a046f08c9bbba76a3973ff1e2cb14493405bd384
+Payload = 67478ef73290fa
+CT = 58f88fcb112a7ec715244f307609ffa253e4e3659b0ece
+
+Count = 75
+Adata = 5833dde0c577b2be4eb4b3d01d7b0042fa8441ad7043ea462bbbbd56a59790ea
+Payload = 36bb9e511276c5
+CT = 09049f6d31cc41f11047da612d2987fa2e50ada5ae7f9d
+
+Count = 76
+Adata = 1e103c63d8ead36b985f921044cd32b8f9f04a2ba9fa154a09e676ffaa093970
+Payload = d68d6556c5a5b1
+CT = e932646ae61f35382f7648718127ebae7eb7443ebd2c2c
+
+Count = 77
+Adata = a1cfb61d45a140bdea6329ba0fe80429ff9aa4624a1d31bc752f7c97f1d390a0
+Payload = 0568cca4ff79dc
+CT = 3ad7cd98dcc358cc40a5e7fffb1fb9a5dd9d6ba91bede1
+
+Count = 78
+Adata = 116b5b015e44ceef0061b2d2e73fa0b386d5c1e187782beebdfc6efb5a1c6935
+Payload = bd93d08eea4263
+CT = 822cd1b2c9f8e7468d2b70c311732f11ed72b57d83e500
+
+Count = 79
+Adata = 3d55882e6f3f89309b6940a3b408e573458eedd10fc3d0e1f3170eb313367475
+Payload = 4fb62753024e92
+CT = 7009266f21f416b41a70f548e359add30c0e5746fbeb2b
+
+[Plen = 8]
+
+Key = 493e14623cd250058a7fc66a3fee0c24b6e363b966c2314aff53b276b6c2ea7b
+Nonce = fe2d8ae8da94a6df563f89ce00
+
+Count = 80
+Adata = 579a637e37a0974cd2fc3b735d9ed088e8e488ffe210f043e0f9d2079a015ad6
+Payload = e5653e512d8b0b70
+CT = 75d31f8d47bee5c4e2ba537355ae8ab25cc9ed3511ff5053
+
+Count = 81
+Adata = 1583138aa307401dddc40804ac0f414d338fc3ffb2946f09aaaa7079426fc1ee
+Payload = 2c4ba9ce52e01645
+CT = bcfd881238d5f8f1781a9e359804831f31a1efb1ae1cb71d
+
+Count = 82
+Adata = 78d3dda40e433bba7a330ca3e5bd5170f0895f2e3e438402344ced79fcb0c719
+Payload = 5eb2d054a0e58c62
+CT = ce04f188cad062d62dcc77c4e1fe2bafd477598977835f0c
+
+Count = 83
+Adata = dfc762466fa84c27326e0ee4320aa71103d1e9c8a5cf7d9fab5f27d79df94bd6
+Payload = bbbf7830d04ab907
+CT = 2b0959ecba7f57b308946723baf0dbf613359b6e040f9bd5
+
+Count = 84
+Adata = 7e8ea82d1137c1e233522da12626e90a5f66a988e70664cb014c12790d2ab520
+Payload = 10c654c78a9e3c06
+CT = 8070751be0abd2b2003bd62ca51f74088bbbd33e54ac9dd4
+
+Count = 85
+Adata = 873da112557935b3929f713d80744ed08b4b276b86331dbc386fba361726d565
+Payload = 668d32e322e1da3e
+CT = f63b133f48d4348a67e65e7f2cdedf6ef8cc0ee7a6dcfb02
+
+Count = 86
+Adata = cfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82
+Payload = e39f6225e8eab6cc
+CT = 732943f982df58780532f8c6639e5d6c7b755fcf516724e3
+
+Count = 87
+Adata = 01abcfee196f9d74fcaa7b69ae24a275485c25af93cc2306d56e41e1eb7f5702
+Payload = 6021a00f6d0610a4
+CT = f09781d30733fe107fd7a33828413ebc252dd9d015773524
+
+Count = 88
+Adata = ce1c31e7121c071d89afab5a9676c9e96cac3d89dcae83136bbb6f5ca8f81e5d
+Payload = bbaf0ac4e77ee78d
+CT = 2b192b188d4b0939d3d51368799325ad1c8233fa071bade0
+
+Count = 89
+Adata = bb210ca5bc07e3c5b06f1d0084a5a72125f177d3e56c151221115ae020177739
+Payload = 98a2336549a23a76
+CT = 081412b92397d4c25d1ea568637f773174a7f920a51b1fe1
+
+[Plen = 9]
+
+Key = b23255372455c69244a0210e6a9e13b155a5ec9d6d0900e54a8f4d9f7a255e3a
+Nonce = 274846196d78f0af2df5860231
+
+Count = 90
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d
+CT = f019ae51063239287d896e7127f17d13f98013b420219eb877
+
+Count = 91
+Adata = 162d0033c9ea8d8334d485b29eef727302135a07a934eea5fee6041e9f1f47c1
+Payload = 0d9168eeab3b27ba69
+CT = 9cd5b4f54443433d997cc2cd61da9358b4045fef32f8192cbf
+
+Count = 92
+Adata = 3f4ab57efa32f51a4c00790280e77c0e55b85bbda4f854e242368e9a289b5a81
+Payload = 6287dcffdd5fb97885
+CT = f3c300e43227ddff75d280f0ffdd560fb8915978e3bd6205bb
+
+Count = 93
+Adata = 945d18134c148f164b39fd7c4aef0335045553f6ea690a3b1726418d86f0de00
+Payload = 6e5e01b3fd71d16b9c
+CT = ff1adda81209b5ec6c7dbf90420a1ff2e24bd6303b80cfc199
+
+Count = 94
+Adata = 23af12893431b07c2922ab623aed901c0eaaeb9a24efc55273e96aea4dab7038
+Payload = b51521e689b5247362
+CT = 2451fdfd66cd40f492d741f4329ae7cc77d42bf7e5f2ec5ab6
+
+Count = 95
+Adata = b15a118b3132c20c31e6c9d09acdee0e15fcc59d6f18306442682512d22eb10f
+Payload = 7f973617e710fb76fe
+CT = eed3ea0c08689ff10ec9ffdcc2f36edac14613b1d85baf25a9
+
+Count = 96
+Adata = dcfbeb6490f5fa7eaf917462473a6cec98bebf8f17493fe9b994119a6d5a5457
+Payload = 7e909b6727ac3fd02f
+CT = efd4477cc8d45b57df5a61a28bb10265b26043d7a8dd357713
+
+Count = 97
+Adata = 77e9317294f046f315a0d79e3423f29f7d9ebcd36d6eaa2a3fb2f4500309478c
+Payload = a5075638932b5632f8
+CT = 34438a237c5332b508d321c371ae1fd01bdf3b6c75a597da6e
+
+Count = 98
+Adata = 3aa8f204eb127b547e13873ed0238018394e13686c8734e49e3e629deb352c77
+Payload = c10f15a0de78db8aa3
+CT = 504bc9bb3100bf0d539393d1635bc40ac62405a39155406c47
+
+Count = 99
+Adata = 7f67e6f97c6c258f014d721a4edaaa0ddb3f9f09993276ab7b714ea9356c231d
+Payload = 8294f830cfca42cfbe
+CT = 13d0242b20b226484eff89641e1bd5ad6cc827441b17c45ecf
+
+[Plen = 10]
+
+Key = dbf06366f766e2811ecd5d4384d6d08336adc37e0824d620cf0d9e7fd1e7afa9
+Nonce = b3503ed4e277ed9769b20c10c0
+
+Count = 100
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b22719
+CT = e317df43ab46eb31be7e76f2730d771d56099a0c8d2703d7a24e
+
+Count = 101
+Adata = da77c6d5627a2aa34911bd1f7cc5f8aa68a2c6546adc96a186b9af8e5baac4cf
+Payload = e081c43a07450ce0dfa2
+CT = 2daaebd62095206346c5bcc7a8260ef361dc39fdb776d041f0d4
+
+Count = 102
+Adata = 134d2d9726400d09dd3521326f96fbef993ddc0c4088770057b0f8d70356456f
+Payload = c381d2ae5e72fc82324a
+CT = 0eaafd4279a2d001ab2d19f0cbb0899f221aac9762f2650f8058
+
+Count = 103
+Adata = 0d065dfde1de1f21784c7869eb566c977f807cfbd53578f4616995b51d7dc045
+Payload = 737f4d00c54ddca80eec
+CT = be5462ece29df02b978b3dc92a9bd26b9653e5917359c331fcff
+
+Count = 104
+Adata = 95c54d187f2415535451cbb9cb35869749b171f7043216ce6886dd77baeecf60
+Payload = 4e9e251ebbbbe5dbc8ff
+CT = 83b50af29c6bc958519891dda72c27d272561e00f7041845d998
+
+Count = 105
+Adata = 0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5ce773dd4c67ca967cd691b
+Payload = 0db72b281ab4046d15a6
+CT = c09c04c43d6428ee8cc1928ac628758ad58fc1b5a768d4722848
+
+Count = 106
+Adata = ad840bc55654762e5eba0e4a9e7998992d990a06d70da1b1ca922ef193dab19a
+Payload = 4f7b4f38ff1ba4df5a59
+CT = 825060d4d8cb885cc33ed11dad4dc8b265a53cf0bdd85c5f15f4
+
+Count = 107
+Adata = 911e9876ea98e1bcf710d8fd05b5bf000ea317d926b41b6015998ee1462ab615
+Payload = 58ce55379ef24b72d6d6
+CT = 95e57adbb92267f14fb18eb659a5a7084be48d099467da4395df
+
+Count = 108
+Adata = 3f68a4fb4043bcf9b6d277c97e11365d949c705bd6679c6f0aaf52e62330ad79
+Payload = a219028a953ce1544835
+CT = 6f322d66b2eccdd7d1523b2b2583fd117cec47b1c84d3863159e
+
+Count = 109
+Adata = 02f32242cba6204319075ea8ce806a57845355ae73e6b875955df510096ebff9
+Payload = 83b0ee9a52252c456105
+CT = 4e9bc17675f500c6f8625456eb2b6a2d35c649a84051f843153c
+
+[Plen = 11]
+
+Key = 4dd555bd3a5253a90b68b5d4d46bd050340ee07ddad3a72048c657b5d76bb207
+Nonce = bdb1b82ba864893c2ee8f7426c
+
+Count = 110
+Adata = 9bcc5848e928ba0068f7a867e79e83a6f93593354a8bfcfc306aeeb9821c1da1
+Payload = 8015c0f07a7acd4b1cbdd2
+CT = 8e9f80c726980b3d42e43a6512a0481255b729a10f9edb5f07c60c
+
+Count = 111
+Adata = c2e75952ab49216f305e3776865791ce877cef8c0229ca97561787093fddf1d8
+Payload = c97b62a719720b44b7779c
+CT = c7f122904590cd32e92e748c514444f00ffdb80a4bb7e9eb651946
+
+Count = 112
+Adata = c76a3ff4e6d1f742dd845be2d74c1a9b08e418909b15077deb20373ef55caf91
+Payload = cb7c17ef62464ecc8008f6
+CT = c5f657d83ea488bade511edb609dfc1929ac1ba5753fc83bf945b7
+
+Count = 113
+Adata = bdb69f99f9a144b9ad88c6cfd8ffb8304c201de9b2818552ce6379e6042c1951
+Payload = 893a690cc5221de597d0e8
+CT = 87b0293b99c0db93c9890053b74283296d0fca83b262915289163c
+
+Count = 114
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf0
+CT = 8e79a41300dc6d60b1d21888a34955893059d66549795b3ac2105c
+
+Count = 115
+Adata = a9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5
+Payload = 641c6914920a79943dca39
+CT = 6a962923cee8bfe26393d1377c4e2f20aaa872a9a0b1d1d7f56df0
+
+Count = 116
+Adata = f0c2cc5a1b4c4cbe839338fa0d7a343514801302aef2403530605cf4f44d2811
+Payload = 2286a1eddd80737a724ca9
+CT = 2c0ce1da8162b50c2c15415545aa0c1dd11551891ae553d3a91908
+
+Count = 117
+Adata = 9842922499ad4d487488b3731f48765efe0b4eb59e7b491ba5f6636f09ed564d
+Payload = d8c63e7d7d332198249c0c
+CT = d64c7e4a21d1e7ee7ac5e4d9e07ec5806360843676ef27d811b246
+
+Count = 118
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf
+CT = 450bc07a2b989fc0ff5e27483b8727c5753ede25e1fab0d86963be
+
+Count = 119
+Adata = 2c186c5c3463a4a8bad771feb71e2973c4f6dede2529827707bf4fa40672660f
+Payload = dfc762466fa84c27326e0e
+CT = d14d2271334a8a516c37e64b5c3c1dc577ee8fcf6ef3ebc0783430
+
+[Plen = 12]
+
+Key = d3ad8cda9a0d91a205c4c05665728bb255d50a83403c9ab9243fcbbe95ae7906
+Nonce = 0b5f69697eb1af24e8e6fcb605
+
+Count = 120
+Adata = ea26ea68facdac3c75ba0cdf7b1ad703c9474af83b3fbfc58e548d776b2529b9
+Payload = a203aeb635e195bc33fd42fa
+CT = 62666297a809c982b50722bd56bc555899345e0404b2938edf33168e
+
+Count = 121
+Adata = 0b32069fc7e676f229f1037d3026c93eef199913e426efd786b524ce1dbde543
+Payload = aac414fbad945a49ae178103
+CT = 6aa1d8da307c067728ede1449b15447c904b671824c2ca24c4fc7ad4
+
+Count = 122
+Adata = 7a8658302e5181552292aa56e8209de63b5d86934167549b0d936202681757e1
+Payload = 7ee0ce371329192618e3cda0
+CT = be8502168ec145189e19ade7ea13850e99ef9300c65f5abc9419d13a
+
+Count = 123
+Adata = 4f05600950664d5190a2ebc29c9edb89c20079a4d3e6bc3b27d75e34e2fa3d02
+Payload = b0a1af969a95025385b251af
+CT = 70c463b7077d5e6d034831e8486c93c31bbedc9e5ffa2f4154bceea9
+
+Count = 124
+Adata = 4530e4dc6a4c3733b8ab7e77e384223cc1a8c179fb66818c08aca47e5c705d89
+Payload = 9f6c6d60110fd3782bdf49b0
+CT = 5f09a1418ce78f46ad2529f7f18b556e7da59fd2549dc57a17bf64f8
+
+Count = 125
+Adata = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381c5439b098ff978b01b
+Payload = 90958d7f458d98c48cbb464c
+CT = 50f0415ed865c4fa0a41260b30aad3a838680cbd313004685a5510c5
+
+Count = 126
+Adata = f6df267e5cbc9d2a67b1c0fd762f891ee3b7c435884cb87d8228091b34aeddae
+Payload = 9f7ae892e5662803408d4d06
+CT = 5f1f24b3788e743dc6772d411d57b89ed0c91251aed37a6ca68a50c7
+
+Count = 127
+Adata = 4372e152b1afd99c7f87c8a51dbc3a5c14c49d04ea1c482a45dfbcda54972912
+Payload = 817074e351455f23cb67883d
+CT = 4115b8c2ccad031d4d9de87ad79a3b0feea16ff5fbca16211ea6fdd9
+
+Count = 128
+Adata = 82b6cd1c6618c42ba74e746075dc28700333578131ca6fde6971d2f0c6e31e6a
+Payload = 1b7da3835e074fdf62f1eb3c
+CT = db186fa2c3ef13e1e40b8b7b49f22737c4b2f9fa0a7e3dd4b067fbaa
+
+Count = 129
+Adata = a5422e53975e43168726677930f6d3e13281bdbd13c67c168340ed67e45d15b0
+Payload = 57473e7a105c806867379194
+CT = 9722f25b8db4dc56e1cdf1d3ef43a48dbea8c1547455ad0197af88a2
+
+[Plen = 13]
+
+Key = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b1cfc90a4a9cb06df
+Nonce = 55b59eb434dd1ba3723ee0dc72
+
+Count = 130
+Adata = 9b1d85384cb6f47c0b13514a303d4e1d95af4c6442691f314a401135f07829ec
+Payload = 8714eb9ecf8bdb13e919de40f9
+CT = ba6063824d314aa3cbab14b8c54c6520dac0f073856d9b9010b7857736
+
+Count = 131
+Adata = fa17c693d0997140fbc521d39e042d8e08388106874207ca81c85f45c035d6e6
+Payload = a0837676e091213890dc6e0a34
+CT = 9df7fe6a622bb088b26ea4f20820a423dd30796b6016baff106aaef206
+
+Count = 132
+Adata = 27663597b389b78e96c785ca2f5510c8963a5561d2b0b24c4dcdf8e58562c12c
+Payload = b8a2ce7e051b8d094ec43f2a7f
+CT = 85d6466287a11cb96c76f5d2436032bc79c4aef1f74da25e92b0aa7f8a
+
+Count = 133
+Adata = d8f1a83371487d611ce704e0a6731f97a933c43569690022fce33cb5aecdc0a7
+Payload = 9e4103ab1dfb77ae3494507332
+CT = a3358bb79f41e61e16269a8b0e658123d2e5bb324c7ead8897f8e32b0a
+
+Count = 134
+Adata = 05c57aab99f94b315cf8bdd2d6b54440c097fe33c62a96b98b1568cdee4ce62c
+Payload = fb3e3d1b6394d2daebf121f8ac
+CT = c64ab507e12e436ac943eb0090270758ab09f93fa3ba7d7a2aa8eac789
+
+Count = 135
+Adata = 1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef1434
+Payload = 549ba26a299391538b56ce4bd7
+CT = 69ef2a76ab2900e3a9e404b3eb2293813f1bcb96564f772e9308e42b2d
+
+Count = 136
+Adata = 9f5cf9149f556124d6bb4e3e243cca1502c02682709392cc2ec7eb262fd4d479
+Payload = 287f31e69880823df7798c7970
+CT = 150bb9fa1a3a138dd5cb46814c81877380d5cf097c2fb5177750f8b53a
+
+Count = 137
+Adata = 1a49aaea6fc6fae01a57d2fc207ef9f623dfd0bc2cf736c4a70aaaa0af5dafd3
+Payload = 040d18b128ae4a1935f9509266
+CT = 397990adaa14dba9174b9a6a5acf42c75787edc62a180568c6ef56545d
+
+Count = 138
+Adata = f29a0b2c602ff2cacb587292db301182e6c76c5110b97ca8b706198f0e1dbc26
+Payload = 92441cbe8d70820870bb01ad63
+CT = af3094a20fca13b85209cb555f56d47a0631f2038103e3904b556ba7a5
+
+Count = 139
+Adata = 01fcf5fef50e36175b0510874ea50a4d2005ad5e40e5889b61417700d827251e
+Payload = f11d814df217de96333dee1cbf
+CT = cc69095170ad4f26118f24e4835be15b7ae24edccd0b0934e3af513ed3
+
+[Plen = 14]
+
+Key = 3ae5be5904bae62609ac525e2d1cad90133447573d7b608975a6a2b16cb2efc0
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+
+Count = 140
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f38983
+CT = 37a346bc4909965c5497838251826385a52c68914e9d1f63fd297ee6e7ed
+
+Count = 141
+Adata = 52f6a10a022e5ee57eda3fcf53dcf0d922e9a3785b39fad9498327744f2852e4
+Payload = 23fe445efa5bcb318cc85e2ad1ac
+CT = 81c90102c44e7cc9cee2de5b09ad364b603de6afbc2d96d00510894ccbe7
+
+Count = 142
+Adata = d236e3841b9556b32dbd02886724d053a9b8488c5ad1b466b06482a62b79ebb6
+Payload = 762fdc3e0c30c7ecf2ec8808bb79
+CT = d418996232257014b0c6087963781a4321c2ddbc35ce4864457d611219e9
+
+Count = 143
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+Payload = b6813d5fe8afa68d646c197337a2
+CT = 14b67803d6ba117526469902efa3296e55efebb17fe145cdca9b31ea7bcc
+
+Count = 144
+Adata = 7f291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4090e94b3ef5fd4
+Payload = 4ce8b6578537215224eb9398c011
+CT = eedff30bbb2296aa66c113e9181059270a0510e7cc1b599705853af2144d
+
+Count = 145
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f38f50bd
+CT = 3c88d63806415da4d58e73fe88bcb55847573bf21e946ce9bdc5f569e3ff
+
+Count = 146
+Adata = 5a44ff94f817c7c028a8f3db35a4d01364d2598432469f09ded86e5127d42d35
+Payload = da989cc7d375ed5fac4d7f938d74
+CT = 78afd99bed605aa7ee67ffe25575b8a61c5687ea02f0276824b8316b76f1
+
+Count = 147
+Adata = 2a755e362373ef27a911c4d93ca07bc97135645442ad7ad6a8ef98146c71e9d7
+Payload = 6fbab5a0f98e21e4d15904af5948
+CT = cd8df0fcc79b961c937384de8149a07ee02791011129fcacffcfb1bf4145
+
+Count = 148
+Adata = f7988873f45a5de314e5381d3f14d8f8c48c9b649bf3e745ed5dc882d507da58
+Payload = b610349e8b370a7c195598573637
+CT = 142771c2b522bd845b7f1826ee36d34204b1ce23f5f58a8eb7cf1fa8cfa7
+
+Count = 149
+Adata = 95d2c8502e28ab3ee2cac52e975c3e7bccb1a93acc33d9c32786f66d6268d198
+Payload = 1d969fd81dab5ced3e6ee70be3bf
+CT = bfa1da8423beeb157c44677a3bbe9c618bb88bbcefb008a5ea6bed4ff949
+
+[Plen = 15]
+
+Key = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Nonce = a5c1b146c82c34b2e6ebeceb58
+
+Count = 150
+Adata = 5e60b02b26e2d5f752eb55ea5f50bb354a6f01b800cea5c815ff0030b8c7d475
+Payload = 54be71705e453177b53c92bbf2ab13
+CT = 788db949697b8cd9abbc74ed9aa40cd6852dc829469368491149d6bb140071
+
+Count = 151
+Adata = 210c04632341fbfc185bfe3cbf6fe272bbe971104173bcb11419b35ab3aaf200
+Payload = 22197f9ad14591e7a6d5f8b18c969a
+CT = 0e2ab7a3e67b2c49b8551ee7e4998556940dc5a7e44bf10234806d00a012b5
+
+Count = 152
+Adata = d3a205dd017e79a67400a937a20ef049f4c40d73311731f03ab857a3f93bd458
+Payload = 096b2f530933c1273304a6ad423726
+CT = 2558e76a3e0d7c892d8440fb2a38390898f7dbde25b0b70d335df71a06987b
+
+Count = 153
+Adata = 0c9b3ba4faf5fc2f310ad1bab06c4ca13474b714feeffb6ad615c1b850bbd6a3
+Payload = d44fdfd9da3a63c1083afe574e91bf
+CT = f87c17e0ed04de6f16ba1801269ea02fd10d1f21b6b963c05aeda8eb09e272
+
+Count = 154
+Adata = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841528cccb79fd791b3
+Payload = 8d836acc13ed83c2b2c706415c9679
+CT = a1b0a2f524d33e6cac47e0173499664491d23d90ff55abca17e9d943b98c7f
+
+Count = 155
+Adata = 69dc21eb6f295b12ba493ee8fe6c40d78af946067ce772db316a3cbf00d3c521
+Payload = 2a68e3fe746f593c1b97cb637079c3
+CT = 065b2bc74351e49205172d351876dc9616886c6b2adc97db5a673846b6662c
+
+Count = 156
+Adata = 095eb52135dc6d9c1f56a2571c1389852482e7aa3edc245a3904a0449db24a70
+Payload = 39799b001ed2c334c269acb0f2328c
+CT = 154a533929ec7e9adce94ae69a3d932441dcae1760db90379bd354fa99164e
+
+Count = 157
+Adata = efd7270e0396392fde8b0ddaab00544cbbd504f4d97d4e90d749d1946de90dcb
+Payload = 42143a2b9e1d0b354df3264d08f7b6
+CT = 6e27f212a923b69b5373c01b60f8a9c7c7deb28bdcf84886ef843216b94449
+
+Count = 158
+Adata = 8bc181ce2e66294e803a8dc3834958b5f173bc2123c0726e31f3fca25b622ed6
+Payload = a3dcf26327059a4245b79a38bb8db6
+CT = 8fef3a5a103b27ec5b377c6ed382a935061ae3cd892ba63c44b809d6d29421
+
+Count = 159
+Adata = c39ec70c2c71633ae0dccc41477ac32e47638c885cf59f34ebd4a096d32f91f9
+Payload = 3d54883449ecca8f153436c25a0a01
+CT = 1167400d7ed277210bb4d09432051e3c9ae69a4c59ff8e251c2fe022d065a9
+
+[Plen = 16]
+
+Key = ee8ce187169779d13e443d6428e38b38b55dfb90f0228a8a4e62f8f535806e62
+Nonce = 121642c4218b391c98e6269c8a
+
+Count = 160
+Adata = 718d13e47522ac4cdf3f828063980b6d452fcdcd6e1a1904bf87f548a5fd5a05
+Payload = d15f98f2c6d670f55c78a06648332bc9
+CT = cc17bf8794c843457d899391898ed22a6f9d28fcb64234e1cd793c4144f1da50
+
+Count = 161
+Adata = a371ca29b92ed676bab5dfc4d78631bb6d9bb23a29f822907084a1f0fe17721f
+Payload = 60d55a8d5ab591a51e87fdf6aaa2ad25
+CT = 7d9d7df808aba2153f76ce016b1f54c68b55bbe42d8c97504b97c34a5f16e6a6
+
+Count = 162
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2
+CT = d6b93591a99b14dc6ff85768fc5fdc51017d8706acd676ae99e93d5312a4113c
+
+Count = 163
+Adata = eebd2bbf1e9f6d817cd8062a6a9680e7f10464eefeb50b07cb46b14b9b3fcb2c
+Payload = 865b89aa38ee1b5a3ce56620307e8937
+CT = 9b13aedf6af028ea1d1455d7f1c370d45982f0fe5d951a8c62c87894657301e4
+
+Count = 164
+Adata = 72863362612f146699f6b2f6ec3688f2ca6cb1505af7a309c91c1933e34d516a
+Payload = a8efc37d1b8b51f2a47b21dd14da383d
+CT = b5a7e40849956242858a122ad567c1de5addfddbb59f4985947fb3a9ab56333e
+
+Count = 165
+Adata = 9c9efc6593f96207678db813608f2b8bc33ed1bef974ed77ed7b6e74b621b819
+Payload = d9b0eaaff786165f882f41a98dbc0c35
+CT = c4f8cddaa59825efa9de725e4c01f5d6b651053516673402a57538db1a9ce7e9
+
+Count = 166
+Adata = dc482a051b58d8a3904d3af37c37b51983f634a504451bbba6f77d71337f8e78
+Payload = df49d972b6ebbbb18ee975ac635d847e
+CT = c201fe07e4f58801af18465ba2e07d9d86d772b1a1991b7be6589bbccad36171
+
+Count = 167
+Adata = 51ef065a43caa23faf750b02a41ad6ba701aeb8058f6d8738d6f6b005bec7f60
+Payload = 78318aa5cd16699b77bdcea2fc9d1d20
+CT = 6579add09f085a2b564cfd553d20e4c3569387a1a6bcc826e94012670820576e
+
+Count = 168
+Adata = 88e2a74d2920c89c6a101f5f06d0624a6d5eabd9bdb51395ee3983934c55c73d
+Payload = 8e20d65d02dd9a64379f75b6d8328f2d
+CT = 9368f12850c3a9d4166e4641198f76cee9c788b4aae9b2c6caf0c44aa9bd2ed0
+
+Count = 169
+Adata = ada3ed7db2dabbfbc441ef68a5656e628d6d5bd6c1574369688497179a77601a
+Payload = 97e8d8513af41b97801de98cc4269096
+CT = 8aa0ff2468ea2827a1ecda7b059b6975f1df0f01944641a1b04d753e6ab8d3cc
+
+[Plen = 17]
+
+Key = 7da6ef35ad594a09cb74daf27e50a6b30d6b4160cf0de41ee32bbf2a208b911d
+Nonce = 98a32d7fe606583e2906420297
+
+Count = 170
+Adata = 217d130408a738e6a833931e69f8696960c817407301560bbe5fbd92361488b4
+Payload = b0053d1f490809794250d856062d0aaa92
+CT = a6341ee3d60eb34a8a8bc2806d50dd57a3f628ee49a8c2005c7d07d354bf80994d
+
+Count = 171
+Adata = 4ae414bc888a42141d3060c71c2dbbffd425b6a952806982271a8e756b3c9e24
+Payload = 51eb190c6a9f46e8ec1628b090795470c0
+CT = 47da3af0f599fcdb24cd3266fb04838df13c1c5755a5a240c33b2b890a486aac8b
+
+Count = 172
+Adata = 7b7f78ae1a5ee96fdc49dacd71be1a6ac09a6a162d44dea0172886eca5674e46
+Payload = 25144e807e389bb0e45b6dc25558caf61a
+CT = 33256d7ce13e21832c8077143e251d0b2b4cfca1c19abf447d7bc0898d61885144
+
+Count = 173
+Adata = 03f31c6143b77f6ad44749e2256306b8bf82242f2821fad4075b09b388ba81ca
+Payload = dbe1ee14abfe2ecf4edf6db206cf9886ce
+CT = cdd0cde834f894fc860477646db24f7bff229cc7a390867a245dcb7c434f1db347
+
+Count = 174
+Adata = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa001d553375cc63f8a2
+Payload = db6df31f12bf552f81deff5fa2a373fc22
+CT = cd5cd0e38db9ef1c4905e589c9dea401135361b539f9fe0fb7842907c2326aef63
+
+Count = 175
+Adata = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a7b9bb2bd99392c8a
+Payload = ff2a97b49fcc6a50d4549c979d53ccc51f
+CT = e91bb44800cad0631c8f8641f62e1b382e8ed10943929e7d7bf798b2ae8371aae5
+
+Count = 176
+Adata = 4d1513478fc1fb0a18eb6d2a9324fefbd975ecd1b409025de826bc397462acc1
+Payload = 73ddfa0185200a890b7690a7e3986d8818
+CT = 65ecd9fd1a26b0bac3ad8a7188e5ba7529f92b9e49ab83f113f8949dc9e4a36e0d
+
+Count = 177
+Adata = b26a7ff61bfe94864249af7cc9b4a723627dd4463f5a22f0ca6063769522eab7
+Payload = 5c7604f9ac8fdf30ee5820e5aeb75b65d7
+CT = 4a4727053389650326833a33c5ca8c98e6d0e53223adff22a08e3dddf66fff23e3
+
+Count = 178
+Adata = 960f9a85cfbfb6eab223a4139c72ce926a680ea8e8ecc3088cf123de659ad310
+Payload = d44fdfd9da3a63c1083afe574e91bf01c9
+CT = c27efc25453cd9f2c0e1e48125ec68fcf833f49a42521a7a2367f91bfcc2180b7c
+
+Count = 179
+Adata = 3718467effb5d5dc009aaefce84d8cb4fe8f80eb608f4c678f5d0de02ea11e59
+Payload = bb515dc227abb9acad8fefaa14771bb77b
+CT = ad607e3eb8ad039f6554f57c7f0acc4a4ac08bd395c6807223311070659f550934
+
+[Plen = 18]
+
+Key = 0786706f680c27b792d054faa63f499a8e6b5ddb90502946235bf74c022d772c
+Nonce = f61ef1c8c10a863efeb4a1de86
+
+Count = 180
+Adata = 67874c808600a27fcab34d6f69cc5c730831ad4589075dd82479823cb9b41dc3
+Payload = 6a26677836d65bd0d35a027d278b2534e7df
+CT = d1c1f3c60603359c7d6a707f05ecb2296f8e52f2210b7a798ad5c778ee7cfd7fe6e0
+
+Count = 181
+Adata = e0c27cddf919d3092d9a34766c89a5ae6dcf39fe954d1e6f1a70ddf96805def4
+Payload = 4021ff104ff1dbd91e46db249fd82198b0a1
+CT = fbc66bae7f24b595b076a926bdbfb68538f00923bb5a347af13df12f234fca5f03ef
+
+Count = 182
+Adata = 7ae9eca03f616ab39ebb3be26b848842b4aa584e5c8e5695065ad5af34951175
+Payload = 6a681f164efce199a787bccff223b8ae1a98
+CT = d18f8ba87e298fd509b7cecdd0442fb392c9d03ed7bffac83e890caceb6903d9cab5
+
+Count = 183
+Adata = b47c9bc4eb01c74f5db2e6a293bef80db18c58cf06feef7ee0f8a7a9a51c22bb
+Payload = 7861dac338ba3f8274dca04c8c6f92b6d44c
+CT = c3864e7d086f51cedaecd24eae0805ab5c1d4dd8f30870025b2bd1e2a2511574d3e7
+
+Count = 184
+Adata = f6afd661f218c7426b92ee53e65d14898cd0c78a7e594fcc6ac0e3fb5cab1c9c
+Payload = a3f0473c620d2739d5ba4f7156f88d0fb669
+CT = 1817d38252d849757b8a3d73749f1a123e386046d17f337f3cb49884d94995edbdc9
+
+Count = 185
+Adata = d3802911e341577046cfc61d9043b4af059fb4bef3c6a2ff46ccdcb05670af37
+Payload = 07c535d9456a6ff1e41321150d16dae3f7a3
+CT = bc22a16775bf01bd4a2353172f714dfe7ff25fdc77b43bca254d6459263cdfed8fbb
+
+Count = 186
+Adata = db60720db67a60ca286fe744d46173c231fbcc7deb4c9b0d87d52a2247e06b74
+Payload = 5ee220720a896249efdab2ce418318bb5ebf
+CT = e505b4cc3a5c0c0541eac0cc63e48fa6d6eedd1a1d36c8164c55d55dbf0ff1e9517a
+
+Count = 187
+Adata = 57f70ba5493265b30491decc726354e2065e7971a2efd56db9cf0f79b1d76859
+Payload = 98e4eb0361c8bf40bcbe0539b0850e4c35ff
+CT = 23037fbd511dd10c128e773b92e29951bdaeb476e2ca48fd52bec0539b00744a8a07
+
+Count = 188
+Adata = 4a29b9ad548964942f87f28ba267ec0d0e8f72c73b3823ee57693dd63c2605c1
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72
+CT = c4e0d10096f1178ca63ebcc70c5056fea523fad68c62b81d62f2d490ae74f5bb1465
+
+Count = 189
+Adata = acbd2e9911b3218a230d9db5086d91dccac3fc93fc64b0f4a15d56954906b2b7
+Payload = e99ed2ac6c38e033061b5d85f3e77dd72518
+CT = 527946125ced8e7fa82b2f87d180eacaad4913b15d8000266c61ba5aec898eb35b52
+
+[Plen = 19]
+
+Key = bac55f9847d93325bf5071c220c0a3dfeb38f214292d47b4acb7b0a597fe056f
+Nonce = 05b50c458adbba16c55fcc454d
+
+Count = 190
+Adata = 89ad6ae1e550975eaa916a62615e6b6a66366a17a7e06380a95ea5cdcc1d3302
+Payload = c1a994dc198f5676ea85801cd27cc8f47267ec
+CT = 7c9b138177590edaafec4728c4663e77458ffbe3243faec177de4a2e4a293952073e43
+
+Count = 191
+Adata = dfddb719d00398bf48a6cefd27736389e654a93b8595cd5ac446af1996e0f161
+Payload = 791e232bfb42fb18197adc1967da1a83f70168
+CT = c42ca4769594a3b45c131b2d71c0ec00c0e97f8422f736fc435687634d42254b22fd99
+
+Count = 192
+Adata = 58ef310997dcaf067dd217274921504da6dbf0428a2b48a65fe8a02c616ac306
+Payload = 3d4127942459bb8682e662dfc862467582fa68
+CT = 8073a0c94a8fe32ac78fa5ebde78b0f6b5127f38a96e68ef7dbaef1b460cc0980eacd4
+
+Count = 193
+Adata = 511e5d5e100b595f6b20e791830bca37e23f7b785e482a58405bffe7a632a5b8
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd6
+CT = b343016147b47ce03873efc86345faf0d223c15c5c702a82d468929227502e4e35796f
+
+Count = 194
+Adata = e48dfaa53b6807ea6f01d8dca67960b9f321f7851f324459a9bf61fe0be73abb
+Payload = e0f1cd013e6aea4fa484fc3fa35d348b1a2399
+CT = 5dc34a5c50bcb2e3e1ed3b0bb547c2082dcb8e89188c0940182dd99a902d158c5b0810
+
+Count = 195
+Adata = c12c0423fe36e4c88775dd00b4af267b85b7dd2a37a742a3156923c8917c97a3
+Payload = b1cc1946b4fc1dbd033254cdf536f61e9f9cd7
+CT = 0cfe9e1bda2a4511465b93f9e32c009da874c015849acbb7af1892790300bb84fb0558
+
+Count = 196
+Adata = 4255f8af18df7237e0abe98421aec9634443561752d893aaffe76380e829ef32
+Payload = 87284658928208e3bddca83e3ceb13708d88d4
+CT = 3a1ac105fc54504ff8b56f0a2af1e5f3ba60c3e75aaf3077ac6dfb5454851ec3910de6
+
+Count = 197
+Adata = ab83567833d2f3461b5fbecc0e366694bb5ea00933b2b3e792ec3aefe20325df
+Payload = bdb79f931ef3035a33bdd1b032fd9de8f6b2ba
+CT = 008518ce70255bf676d4168424e76b6bc15aade70f42e3e1f2b5bb58433bd11f5dea1f
+
+Count = 198
+Adata = bd1446ba3185d1c16551730947c22142142caa8cc1c540e89ab734ec297401bc
+Payload = 1f9c3a8eb8bc59f3869e10f73883aa8f8990cb
+CT = a2aebdd3d66a015fc3f7d7c32e995c0cbe78dc564f6248cefe5fc7cfb547c90a558925
+
+Count = 199
+Adata = b87577755d2d9489194f6f7cfabf267dc3433a9c91954e81beb72c5e06870922
+Payload = 5f28809181f9a889894da8d6fe1fde6cce354a
+CT = e21a07ccef2ff025cc246fe2e80528eff9dd5db52249d812f7f235afa0732e984e91b2
+
+[Plen = 20]
+
+Key = 8beedeb85d42c2a7fa6f7237b05acb197dd8e1672471ac878064fe5319eab876
+Nonce = 8479bdfad28ebe781e9c01a3f6
+
+Count = 200
+Adata = 7aebdfd955d6e8a19a701d387447a4bdd59a9382156ab0c0dcd37b89419d6eff
+Payload = 7b125c3b9612a8b554913d0384f4795c90cd387c
+CT = 6cc611d816b18c6847b348e46a4119465104254a04e2dfeeeac9c3255f6227704848d5b2
+
+Count = 201
+Adata = d119f300fbd74e754a200ea2c3f9fabc1466d02078c84245db693eef3f5672a6
+Payload = 8b013f5782d5d1af8dbd451a4202866095dac975
+CT = 9cd572b40276f5729e9f30fdacb7e67a5413d44338d48329997c5981d678b5e24a6f01b0
+
+Count = 202
+Adata = d6204303b86acf62d5ab860ca70161288ede56e3cf017c08dca56fd2d6f8f6fe
+Payload = b2b1d82a5523b72ea366a680922ed3a4624536c4
+CT = a56595c9d58093f3b044d3677c9bb3bea38c2bf2a77e3ab68e0a73519591a33ed098b758
+
+Count = 203
+Adata = 8557e22eb4529b43f16b1f8ae47c714ac8a2c827c1408a47704778b4c5b52601
+Payload = f8c4eb4285d3d7744da52775bb44ca436a3154f7
+CT = ef10a6a10570f3a95e87529255f1aa59abf849c1cff6c24251c2fb7b8604dfa10c60ef4a
+
+Count = 204
+Adata = 8c1a4187efbb3d38332f608f2c8bbe64247d9afa2281ced56c586ecb4ab7a85e
+Payload = 6e7fe35fa39c937a0e6b3a8c072e218650f42b8d
+CT = 79abaebc233fb7a71d494f6be99b419c913d36bb6c3c39f915d081d34559179869b32d81
+
+Count = 205
+Adata = a41bb1f256228302cd0548ae2148ff42774d18c2d6d3e38b36bc4938da13bac3
+Payload = 917b467d841850fc6e648f1bc298a7f9f1ee38ca
+CT = 86af0b9e04bb74217d46fafc2c2dc7e3302725fc9389a6a6a74c6eb0e1f87562469f2082
+
+Count = 206
+Adata = b0b024e20c4f75a6dad54c21a9edbce846792e957878b1c8ed2d916c757e2b3c
+Payload = 2b4314fe1a6bfa786b7cfc13fbee861b348efbf6
+CT = 3c97591d9ac8dea5785e89f4155be601f547e6c03bed3a2f5dfdbfcc0d7ac26c88d1962c
+
+Count = 207
+Adata = 42153925c46fc9d5d328312d62f59bb99fdc4ac479a3386d5f88fefd4b32f577
+Payload = e19fa7f83c79920cbff45c41a9dee8fc99e97396
+CT = f64bea1bbcdab6d1acd629a6476b88e658206ea035ea1d99be344fa1467ee91c73bbca67
+
+Count = 208
+Adata = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711a08da6acd42299fe
+Payload = 53e0475cf492b3d39dad600f5c58eb0bd0021554
+CT = 44340abf7431970e8e8f15e8b2ed8b1111cb08627936ec10a81b36768b606e9a38b2f4c5
+
+Count = 209
+Adata = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a7977eda6de045878
+Payload = c119a383d9a3d4bff4270a1d22076b346db5f61c
+CT = d6cdee605900f062e7057ffaccb20b2eac7ceb2a11575ae03ea8a57bbe4a67c060367b74
+
+[Plen = 21]
+
+Key = c3a0c126cad581012151c25cf85a44472c23f83b6095b6004f4f32cd60ec2db2
+Nonce = 94ab51ce75db8b046d6ab92830
+
+Count = 210
+Adata = 2a243246bfe5b5ab05f51bf5f401af52d5bbaa2549cf57a18e197597fe15dd8c
+Payload = 73b09d18554471309141aa33b687f9248b50fe3154
+CT = b7e8264ca70fd2a4fb76f20a8ad5da3c37f5893fb12abeeaef1187f815ca481ed8ddd3dd37
+
+Count = 211
+Adata = 0595306eb7441622a49800edee0134492d82320707fceba902af2e0c95fe634a
+Payload = b64d00f3a4df754fa4ee6376922fb67ccce0c6209f
+CT = 7215bba75694d6dbced93b4fae7d95647045b12e7accc2b55011dbe92ce7619e0ad48b4ccf
+
+Count = 212
+Adata = bd439dbefec589e120fb4f9825b315bf86523b85c61791cd4da4c8d474ba2714
+Payload = 2b11d1ac74ffe701ec733d32085b1054132726e622
+CT = ef496af886b444958644650b3409334caf8251e8c71e8b1f4d70d8f4c7df4f22847d36b394
+
+Count = 213
+Adata = cfebe1cf82267394065bcecfada6709c6c35a3ac835644f560d4c9a8c1848364
+Payload = a88f22424643a523aa3d7d88f4364f1290f49dd0a2
+CT = 6cd79916b40806b7c00a25b1c8646c0a2c51eade47a85e76a9d07b7b361ca56d53c34cda50
+
+Count = 214
+Adata = 7a37255b682766a0bfecf78e5162528885a339174c2a49325739d2bd8877e64f
+Payload = c81427bc84c6a3cfefd4c4cb210fe82212977e1947
+CT = 0c4c9ce8768d005b85e39cf21d5dcb3aae320917a2fddb010e7508ad03ad287068ecee6020
+
+Count = 215
+Adata = 619f2ae80070e278615466a3fd6c9acb7b510c5679bed7038889c77e78d8bd32
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447
+CT = ec9c6d8acc67468feeac4b64a0af139c4c46625aa2ddea785e6c470c52c4fdf432fd78b66e
+
+Count = 216
+Adata = b2571e56f66a857daffbdc99370ceddd4a7bed3867d600cc797000a3b7b57a9d
+Payload = 4c88151cafef75832bacef43a06e862349d56b67ee
+CT = 88d0ae485da4d617419bb77a9c3ca53bf5701c690b91232cfbd7ffff252498b35274fb2995
+
+Count = 217
+Adata = db409636e3e3bcd606a91aeb7592009896f9ad2c4cc6b7f578e6ad59c0f8fa22
+Payload = 572855e22ce89bc2bcf09cb15a1765d99973449d61
+CT = 9370eeb6dea33856d6c7c488664546c125d633938472b2c50e5e391ad104f9ee33b94f2872
+
+Count = 218
+Adata = 62c89a835721207a182968c516dc8be45774ec846e8dcab9ab8611888f2a76a8
+Payload = 89ce46b3de3afaf2518d419b1a2ac24cabca269a96
+CT = 4d96fde72c7159663bba19a22678e154176f5194732d69c5d6db1b130102af3dae0690673b
+
+Count = 219
+Adata = 33f30ddd83002eea50fd4a8fae39d0980a04160a22ac88b755ac050f1d1f8639
+Payload = edf1682a626e9fbf3d57bb260e0876c6f92ba5b114
+CT = 29a9d37e90253c2b5760e31f325a55de458ed2bff1489903365970c2673c9fd457e1077aad
+
+[Plen = 22]
+
+Key = 9cdebaeee8690b68751070691f49593668a6de12d3a948b38ddbd3f75218b2d4
+Nonce = af1a97d43151f5ea9c48ad36a3
+
+Count = 220
+Adata = f5353fb6bfc8f09d556158132d6cbb97d9045eacdc71f782bcef62d258b1950a
+Payload = 3cbb08f133270e4454bcaaa0f20f6d63c38b6572e766
+CT = 3966930a2ae8fdd8f40e7007f3fde0bd6eb48a46e6d26eef83da9f6384b1a2bda10790dadb3f
+
+Count = 221
+Adata = e3a1555ffe5f34bb43c4a2dae9019b19f1e44a45fb577d495d2a57097612448d
+Payload = 946e86795c332031e2d1ee09d3d4a101fb6800d00911
+CT = 91b31d8245fcd3ad426334aed2262cdf5657efe408a5587bdd120a7d08cd3841cb117af444fb
+
+Count = 222
+Adata = 9c5d43c1a1269cde199509a1eff67cc83a1759b71c9e7a6ee99f76b98c6e23a6
+Payload = b76ce2ab0065ba1c0a754494991c8c452cb416f18ab1
+CT = b2b1795019aa4980aac79e3398ee019b818bf9c58b0545b32f81dcf03e2bcc2aaf62ad366e97
+
+Count = 223
+Adata = b07452a7900a289b91b2771dfdd5108852536659aa259def7b41e38f80bd03ab
+Payload = a3e0d8d0784155bfc45769c52711d4fa68e8bc390c20
+CT = a63d432b618ea62364e5b36226e35924c5d7530d0d94fea17d78533bc9e022dbfb460afdf499
+
+Count = 224
+Adata = 6b30f55c3101540523a92380390f3f84632f42962061b2724cde78ac39809397
+Payload = 6e6a88abbb52a709b47365ad6aa8016fa9a03a9bd834
+CT = 6bb71350a29d549514c1bf0a6b5a8cb1049fd5afd98056defc6dcaeec80b1c639350ab6f1fde
+
+Count = 225
+Adata = 9fc62d14f8b7a6026509275cff80312ff1ade2b5d9c274cb72a506a571439fc1
+Payload = eba1810d537041821121aeff8e0914ac26a550072c8c
+CT = ee7c1af64abfb21eb19374588ffb99728b9abf332d389d37b7251fb8c0ef2b37c36d51219d0f
+
+Count = 226
+Adata = 6b9389cc42113d639fd2b40cbc732ae0dc7c14513b88b36b45a6ea5a06fe4d2b
+Payload = dfc6692cd2442e5ff1f918c8812a27f81d107d16a12f
+CT = da1bf2d7cb8bddc3514bc26f80d8aa26b02f9222a09bd279d9da4437c8a2a252436508134c56
+
+Count = 227
+Adata = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad166c77952a50318bd
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae
+CT = 9f0ea330e4d4a17a0ef3a2575ff28bfcd9c75f865f1a63943543bc1c5f5991ecc5964a288f79
+
+Count = 228
+Adata = e98b710c47a4d12a73cd8aa2613fc2910c16f4195ea7f15650132493521d19be
+Payload = 9f5a05db89e0e336da066ce81b79ad9be1d0ec4fb7b8
+CT = 9a879e20902f10aa7ab4b64f1a8b20454cef037bb60c0a49ee2b7ceddcbd28abb24b77d5edee
+
+Count = 229
+Adata = 527817316fc48b105f8ab178dd2db1fefa09c50461aa9d8bdf3c03482343bbf9
+Payload = 58f31e5770070a5d4031fb795dc2d298561d3559960d
+CT = 5d2e85ac69c8f9c1e08321de5c305f46fb22da6d97b9b099a68cfa3572d974e03232e09f37fb
+
+[Plen = 23]
+
+Key = d34264a12c35cdd67ac105e2826b071e46f8131d1e325f8e0ae80a6447375135
+Nonce = 3891e308b9f44c5b5a8b59004a
+
+Count = 230
+Adata = 0cda000ed754456a844c9ed61843deea9dadf5e723ea1448057712996d660f8c
+Payload = 79ac1a6a9eca5e07ce635bfd666ef72b16f3f2e140d56c
+CT = 1abcc9b1649deaa0bfa7dcd23508282d9c50ca7fee72486950608d7bcb39dcf03a2cab01587f61
+
+Count = 231
+Adata = 3fb6ddb76809b8e6d703347664ef00a365955124c603900d5c8d4ff476138252
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f
+CT = 15c1fde7b60a2dac84a74125f7ff4154132eb0e139e05b1c4fb40e5c8bc37152a173d4bbb18c3e
+
+Count = 232
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab4a5667c472c98b2626
+Payload = a027c28fbe22111fd4c8a226cfe8531c16d7790d561eca
+CT = c33711544475a5b8a50c25099c8e8c1a9c744193f8b9ee019c359008adae3070b5a543ead0effb
+
+Count = 233
+Adata = 7a459aadb48f1a528edae71fcf698b84ed64dc0e18cc23f27ab47eeabeaf833f
+Payload = fa597e37c26c38694abdcf450f9edc529160fa0d651979
+CT = 9949adec383b8cce3b79486a5cf803541bc3c293cbbe5dbd099ab134756b90746762a92a4a9f7f
+
+Count = 234
+Adata = 484207909dec4c35929ebe82fcacf20d2af6d850bd69364ebac9557adeadfbd4
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a0
+CT = fd5c59724fdd3a0cb49cefbda632cf063e9c2f470ef684fa4f6adfec85d055310107ba89198afa
+
+Count = 235
+Adata = 88b5448372548e6aab1b262630a28a471d285514703f1bdb10c695850e18fe6d
+Payload = 7d9582cf9e3bb9ee34dce965f56b08e716589486b0641c
+CT = 1e855114646c0d4945186e4aa60dd7e19cfbac181ec338915d23eb2e952afcc89fbddb567d9d75
+
+Count = 236
+Adata = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb38842d7795d830d2e
+Payload = 5a387e7cc22491fc556fe6a0c060b4911d01f0c11f801e
+CT = 3928ada73873255b24ab618f93066b9797a2c85fb1273aaad6c31828314e24198f005955ca8f5e
+
+Count = 237
+Adata = 2aa7a28da38c42fda2e578d9d6340cd8e80b9b32047c3db296d0640d517b0872
+Payload = 87946e910059cbaf48df63b220f397049c65ca10cd1920
+CT = e484bd4afa0e7f08391be49d7395480216c6f28e63be04e531ebbadccfe47182b41904bbfebcfe
+
+Count = 238
+Adata = 3382051c268891da04e6ca73adcead4029f6a1593be4acfe3968e7351a6a2fb5
+Payload = c62f67d208f1c8ffd5d57df9de15ef54f97fbc07d1630a
+CT = a53fb409f2a67c58a411fad68d73305273dc84997fc42e7c582414154236c09ee704cf4a5de411
+
+Count = 239
+Adata = c352828b1920e53bbb60f2ea6a5f15639659e6f3243405c26f6e48628d5519a9
+Payload = 697e73eaaf562d31bdbf7ce9e78c7426fe1c87e421def9
+CT = 0a6ea03155019996cc7bfbc6b4eaab2074bfbf7a8f79dd57c9990029c89d1b37988745fa5737a3
+
+[Plen = 24]
+
+Key = 4ad98dbef0fb2a188b6c49a859c920967214b998435a00b93d931b5acecaf976
+Nonce = 00d772b07788536b688ff2b84a
+
+Count = 240
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75b8af7746d4e570c848
+CT = f28ec535c2d834963c85814ec4173c0b8983dff8dc4a2d4e0f73bfb28ad42aa8f75f549a93594dd4
+
+Count = 241
+Adata = 1ae8108f216defea65d9426da8f8746a3ae408e563d62203063d49bf7e0d6bdf
+Payload = 2b223932fb2fd8433e4b1af9e8234a824569a141f6c96a69
+CT = 4546c70127abacf84a87e513b8b90331639d386dcff38f6f4de907a59c5e4d3f21e1348d7cdf92b6
+
+Count = 242
+Adata = 460f08114b1015fe8b7a9b5dd1b9e6a3d28367c4bd15f29b13c02a8cb9a53968
+Payload = 4d57cbe4a7e780d4ed17267d5ebc91750c2f0209e0444bd2
+CT = 233335d77b63f46f99dbd9970e26d8c62adb9b25d97eaed4ff4239544e2f354d6c6837cd9c23b884
+
+Count = 243
+Adata = 860f4428259d9c5b17698cc95363db6cfee603258582e3a3e8feb886599d4ac4
+Payload = fda8665f87c618646a89c7abdca275fd10c31453ad4b9c99
+CT = 93cc986c5b426cdf1e4538418c383c4e36378d7f9471799f3f6c6f7cc494201069344e2d6d41bd9b
+
+Count = 244
+Adata = 1b43c482f83780c21583f88e5afcf6938edd20f21b74d895161b60c27a6a42f0
+Payload = 98104fd3f3413ad1f57ef4912cb50097dca379a58c47b0d2
+CT = f674b1e02fc54e6a81b20b7b7c2f4924fa57e089b57d55d43787a15352cfceb028202c8730beaa7a
+
+Count = 245
+Adata = b082ccd964617c27a5607b7324faad237ee53acfc18c35502dbf7c1937a9dfcb
+Payload = b46b343e64d2d70e0bd909dbb3f6bedf7e4adc74321be526
+CT = da0fca0db856a3b57f15f631e36cf76c58be45580b210020f3a0ca3da647eb31893e867956097983
+
+Count = 246
+Adata = b8539ba93ef17254ec1d8d62e8f4eae4d41ee1e75345bf90c9cbb26c63bce501
+Payload = 8e12620bb575e6b167b085255b2b5631ff28e04cbef8826d
+CT = e0769c3869f1920a137c7acf0bb11f82d9dc796087c2676be663fbbebbc251b9f1760afa49e89e71
+
+Count = 247
+Adata = b6b09463b5ef5ead1f17f4021693a0d8452e98dcbb8e7590f9fde6394970a6f8
+Payload = 792aaa23b923d1b53173fe19853b9aa402a301d48529873e
+CT = 174e541065a7a50e45bf01f3d5a1d317245798f8bc136238da90cd87e9d9ca5d85430a150e682752
+
+Count = 248
+Adata = 390f6de14d5e1f2f78dbe757c00b89209d0cf8bc48cbbea035779f93de357905
+Payload = ddc5b4e48970ebd72869be6998e9103c014475e8ae6ea29c
+CT = b3a14ad755f49f6c5ca54183c873598f27b0ecc49754479afc0cc4601afb61efa7059cfe49ec9dde
+
+Count = 249
+Adata = 1d75c9e7acb09932db332498d30f82e4009025cb1827047c59a8f97812b568a4
+Payload = d2b66096c475a77648c27235e6972ba8f18761330d3c6adf
+CT = bcd29ea518f1d3cd3c0e8ddfb60d621bd773f81f34068fd9cf7474962c3602dcfcb50039f43e3d6f
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp
new file mode 100644
index 0000000000..a05492b485
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 43b1a6bc8d0d22d6d1ca95c18593cca5
+Nonce = 9882578e750b9682c6ca7f8f86
+
+Count = 0
+Adata = 2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f
+Payload = a2b381c7d1545c408fe29817a21dc435a154c87256346b05
+CT = cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677
+
+Count = 1
+Adata = 79db716e6b0b1627890d378c4560eba7871883d94527be3454dc3c257ea93556
+Payload = 47f4cdd574264f48716d02d616cf27c759fdf787cdcd43b1
+CT = 292ea1643d2c1ddc36b9c0b3c38cb9eb4765f8ef70e84431676e2df1
+
+Count = 2
+Adata = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32c3f9ca6bf6fb2c4a
+Payload = 5eadeaec29561244ede706b6eb30a1c371d74450a105c3f9
+CT = 3077865d605c40d0aa33c4d33e733fef6f4f4b381c20c479eb1321a1
+
+Count = 3
+Adata = 02e5a1306f612bdec098458cff3e691d93f050ba11ba627355dc7029d2cea5ab
+Payload = aac9fb69fed114c62db65090947096a2f5c85c271c6a6d53
+CT = c41397d8b7db46526a6292f54133088eeb50534fa14f6ad3dd8cb4ca
+
+Count = 4
+Adata = 25144e807e389bb0e45b6dc25558caf61a2263869c4d0e4079d07674d7091110
+Payload = fb6e8d38ce38a8c1e710f3a33c682e6dabf055fb33fe75f8
+CT = 95b4e1898732fa55a0c431c6e92bb041b5685a938edb7278b659a844
+
+Count = 5
+Adata = be303c1ed9327ad88dae7cb5930b5a786d4f5477ef9370a9fdb56501964cb8fa
+Payload = 87d81389a6062e8ed501ea964c2fe35b2d3de9fd676c04f7
+CT = e9027f38ef0c7c1a92d528f3996c7d7733a5e695da490377e9e5e005
+
+Count = 6
+Adata = 46dfb8f3e06c3f168e5ac9b341e7710d7b9c6a19b32389eafb58036de0a27756
+Payload = e1bd9095fa9bb811e4054643feea3eac13fb57b43a0502a0
+CT = 8f67fc24b391ea85a3d184262ba9a0800d6358dc87200520c9fc48e0
+
+Count = 7
+Adata = 19eb03c35c352b79e8c32fa40bb9759b0565e04a6c18519ace346e2e9987a250
+Payload = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe0
+CT = fc2db09395b1b4d64d1ef25e00c57b8e51d431b19e83ec60ac73022c
+
+Count = 8
+Adata = efa6ddd6fb8e4480a0f64414694e5f9e7f2e9b97cbe9cd145b65173d072ab001
+Payload = cecdf831c4044c8fe149e4cd579a1aecf222bf8e9dadba09
+CT = a01794808d0e1e1ba69d26a882d984c0ecbab0e62088bd895dc8d581
+
+Count = 9
+Adata = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0622fccda2e251c97
+Payload = 7cfb0973ea13dedc33ef6728db90f47559273ea6d3cd4db6
+CT = 122165c2a3198c48743ba54d0ed36a5947bf31ce6ee84a36b941b65b
+
+[Tlen = 6]
+
+Key = 44e89189b815b4649c4e9b38c4275a5a
+Nonce = 374c83e94384061ac01963f88d
+
+Count = 10
+Adata = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e3eaa9f4535718a08
+Payload = 8db6ae1eb959963931d1c5224f29ef50019d2b0db7f5f76f
+CT = df952dce0f843374d33da94c969eff07b7bc2418ca9ee01e32bc2ffa8600
+
+Count = 11
+Adata = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb463312b3c772ec308
+Payload = bde3fc83287ddd1227bdab4305102c94d885412eb332bf6b
+CT = efc07f539ea0785fc551c72ddca73cc36ea44e3bce59a81a8b847d3a0c98
+
+Count = 12
+Adata = ab153b0a8933f2eb0d721621c86de0cfe100d13e09654824b09d54277912c79d
+Payload = 82176e573c6070faa08d18b5957f119bb1ff51d744b04240
+CT = d034ed878abdd5b7426174db4cc801cc07de5ec239db5531fb4f9d559a8e
+
+Count = 13
+Adata = b22aba8d3e9f4b4bf006e26062de15daf94597731a6009129bfd12957877b1ce
+Payload = bcfc4485eaf225d945146374b737cdf5301c7738ea9f142a
+CT = eedfc7555c2f8094a7f80f1a6e80dda2863d782d97f4035b1e09ff3d6a6c
+
+Count = 14
+Adata = eb80a43c5986deee6925d7c6d53cbdcbe11194843ea133f72d3590d8e8363efa
+Payload = aa182e3ec4fb2f7a905c03582b2ee100ab81a9a311a778bc
+CT = f83badee72268a3772b06f36f299f1571da0a6b66ccc6fcdb60ba1175f1b
+
+Count = 15
+Adata = 3ee186594f110fb788a8bf8aa8be5d4ad52d6e3bd5f406f080d9df0d7553a851
+Payload = 8ad6db8216af16bfda3261a220d078cc98c8ad134e4a80ca
+CT = d8f55852a072b3f238de0dccf967689b2ee9a206332197bb4a75860f3dd6
+
+Count = 16
+Adata = d36fc18b5b12662ff5f6ea55af7c7a82d25d386220e399a85a590b1505c0dcd5
+Payload = a65d24bd1ab92d8d294d654423412860e113c976f12ed76b
+CT = f47ea76dac6488c0cba1092afaf638375732c6638c45c01a00cf106d70a4
+
+Count = 17
+Adata = f0028503e7cd54474c56dc8b2416fe41f416eed73c63ddd141bdd51a0f8fe49c
+Payload = 6e9dc61dd9cf19a6eebc10c9b51c13970636de2c9ea33592
+CT = 3cbe45cd6f12bceb0c507ca76cab03c0b017d139e3c822e3c0193a87ddfb
+
+Count = 18
+Adata = 9a58a226a578bda012dbd7d04b11c879179aaaa36c6145418586cb103360c6c2
+Payload = b526896c11e514b5b4c26351859e2a33800fefd6fd9e6d1a
+CT = e7050abca738b1f8562e0f3f5c293a64362ee0c380f57a6b444d9b63ffab
+
+Count = 19
+Adata = c015fb08540755a8a8adc387d60553478667158964202eb2d25e28efd94c8c76
+Payload = 88907b639f3fd07f40bf6b9b6334b11b2852557975721bf3
+CT = dab3f8b329e27532a25307f5ba83a14c9e735a6c08190c82c339ba21fcf7
+
+[Tlen = 8]
+
+Key = 368f35a1f80eaaacd6bb136609389727
+Nonce = 842a8445847502ea77363a16b6
+
+Count = 20
+Adata = 34396dfcfa6f742aea7040976bd596497a7a6fa4fb85ee8e4ca394d02095b7bf
+Payload = 1cccd55825316a94c5979e049310d1d717cdfb7624289dac
+CT = 1a58094f0e8c6035a5584bfa8d1009c5f78fd2ca487ff222f6d1d897d6051618
+
+Count = 21
+Adata = 25865c1b89f1973bfa680d8458df35a56993a7e81e407e061794004068e481ab
+Payload = 36004342dd74e7966692a848b2c11e1fc311eac9d9cef616
+CT = 30949f55f6c9ed37065d7db6acc1c60d2353c375b5999998ceca422687f41550
+
+Count = 22
+Adata = e6209480da9e49172ba58a9048f2f1b0349030e8e7a79dcdf295eecd613f401a
+Payload = e81f4fb360bcae372d8be3f32655a29bc10a2f31876173cc
+CT = ee8b93a44b01a4964d44360d38557a892148068deb361c42d2b981fc741f2591
+
+Count = 23
+Adata = 112c969882e685b4ae1ee6b67f680e6a1d9d840e627d12118f991c1a3d71314c
+Payload = 27d6443e729d35d7a0690fcb7fe0b20892875f60b5d8763a
+CT = 2142982959203f76c0a6da3561e06a1a72c576dcd98f19b4a1fd47cd41fcf013
+
+Count = 24
+Adata = 73ef62870c50faca5d4e6c6ec45fa7b54bf79ed229fcf1fc8c79c9c09596039b
+Payload = 6c17ad5496dfccde8b877630e1e582dab52aaabe385a321f
+CT = 6a837143bd62c67feb48a3ceffe55ac855688302540d5d9143eb86ffa6958d71
+
+Count = 25
+Adata = b537f0f2981405f6069b401966656461b3516a32d181777121a60cea537e7cef
+Payload = dc4a1e39561f14321238272adff8b74a4e770c0a0c864a52
+CT = dadec22e7da21e9372f7f2d4c1f86f58ae3525b660d125dc1dfc38975c948d29
+
+Count = 26
+Adata = 96bd747ccdcd5fa6cd920514a2f38203e82ee9c7ec6e88080e9f6e2a6a812b0d
+Payload = c51958d7d7d39906b14d4ebb574db881355ec3e6b41838dd
+CT = c38d84c0fc6e93a7d1829b45494d6093d51cea5ad84f575320a48ee3845d9e7a
+
+Count = 27
+Adata = 690d6a2377314fc2f7dd06ae401e3585c79faf648a7af358ae4ef615669222eb
+Payload = 9eaf24f84e8818e286410de321d65ffbf25d1a14073c60da
+CT = 983bf8ef65351243e68ed81d3fd687e9121f33a86b6b0f54884188f946c9a317
+
+Count = 28
+Adata = 748dc83299a43033239ad2fef2dc3d72b76a38ca127607cef72de94a56d5e5c0
+Payload = 71c8eb0079559a306e236c49b7ce1b6cfe26c7888733eb7e
+CT = 775c371752e890910eecb9b7a9cec37e1e64ee34eb6484f00ae2dd33327f8459
+
+Count = 29
+Adata = 35a49535684637f67573fb0b4fdc1bdd8a57650a1d8f29b866fa552a6e0cdf91
+Payload = f09569906381138cc49e3fc2384c5d33c34abd3d617c487b
+CT = f601b587483c192da451ea3c264c8521230894810d2b27f5c50821a48b93d0ca
+
+[Tlen = 10]
+
+Key = 996a09a652fa6c82eae8be7886d7e75e
+Nonce = a8b3eb68f205a46d8f632c3367
+
+Count = 30
+Adata = c71620d0477c8137b77ec5c72ced4df3a1e987fd9af6b5b10853f0526d876cd5
+Payload = 84cdd7380f47524b86168ed95386faa402831f22045183d0
+CT = a7fbf9dd1b099ed3acf6bcbd0b6f7cae57bee99f9d084f826d86e69c07f053d1a607
+
+Count = 31
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5350c88bc165d
+Payload = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee4
+CT = 5d8d2bf2555a96a3876721710bdeda67bef6387370ee52b694af9359a96acfb31a4a
+
+Count = 32
+Adata = 5cab3b84687070956916c11cab0ceea61adb6ea1f909be63d73df96fbfa3a9f4
+Payload = 35a29c1bcbe2182f34fe05f09dfb9ac4a496f95819ef11ec
+CT = 1694b2fedfacd4b71e1e3794c5121ccef1ab0fe580b6ddbe36d3920d1012bf093a5c
+
+Count = 33
+Adata = 6d440b44a069a6967f8750c3b4f8118798fe32d2eaa696ccc7f24e16d6366753
+Payload = a0e21d971876ae4048a61b43a3ac07c685005a20bccbe6ec
+CT = 83d433720c3862d862462927fb4581ccd03dac9d25922abec23025c1776811647f99
+
+Count = 34
+Adata = 06904325b8c6fc2b5a0412ba8062cd48d3af51beacb5ced9e2bdf8d0e056b738
+Payload = 8d333ed7d4b208e794e1673f6df692caee4e3a00fc49115e
+CT = ae051032c0fcc47fbe01555b351f14c0bb73ccbd6510dd0c6efeeaed29e65f1a8908
+
+Count = 35
+Adata = e5049e1c32f0a000024882e4fca9b77adb6c87fdbad96d0c8e97bdb8f46789dc
+Payload = 4189351b5caea375a0299e81c621bf434b6b97da68ad44be
+CT = 62bf1bfe48e06fed8ac9ace59ec839491e566167f1f488ec70d42f84a5411dfa43f9
+
+Count = 36
+Adata = 6f0be1905d1b5b607574ad93a1e7b4a536020fc6798acae862253916a0562707
+Payload = 5a063a24410b3d265c9a32a027cb2382a52bb8e35db15b98
+CT = 793014c15545f1be767a00c47f22a588f0164e5ec4e897caadd2256112d1f7d04934
+
+Count = 37
+Adata = a90f9f55ef22f5e6c542ed3573a9ab67d9c3b6775587fc2be70817479347ce00
+Payload = 0b72cb09a444be2d7b34cf9997fc5b885851d7e6092008b4
+CT = 2844e5ecb00a72b551d4fdfdcf15dd820d6c215b9079c4e6e187f5f37e8a5029ca4e
+
+Count = 38
+Adata = 4dd64fd7d8b571704cddabef854c51691ace4c30de74bfecad42eaed65284ebf
+Payload = ce2d996c9a4cf85edb888822773e03179feeb9e4b0928d6a
+CT = ed1bb7898e0234c6f168ba462fd7851dcad34f5929cb4138fbbb92009435f9ab6691
+
+Count = 39
+Adata = 75f4031d2e5098a9ea3eaa20c2423fbc1705ea18289efb96e311f3fefc153b67
+Payload = aa182e3ec4fb2f7a905c03582b2ee100ab81a9a311a778bc
+CT = 892e00dbd0b5e3e2babc313c73c7670afebc5f1e88feb4ee3cae38db7cc9d577b0ed
+
+[Tlen = 12]
+
+Key = 3ee186594f110fb788a8bf8aa8be5d4a
+Nonce = 44f705d52acf27b7f17196aa9b
+
+Count = 40
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1
+CT = b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0d6965f5aa6e31302a9cc2b36
+
+Count = 41
+Adata = 78230f73f9c0150f630eca4cd679818551d449db82e665d8dc25fc53ebc11293
+Payload = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab
+CT = 674eb2ea64f03498f9398f0b109d358ff42eae86122bd4aa6356e2548a22e7cbee3b89d4
+
+Count = 42
+Adata = c09191a7d2fca98fca486f8843f275a78d57b8c9a6d330d5652ba641f928c6d8
+Payload = adf51386b3cc133ea9d18e679fe4bbf10ea780b7bed57d6a
+CT = ce3003e66c253a4b04a1de85530497874bbb8c985189336b35516f170a2aada38d1d94eb
+
+Count = 43
+Adata = ea46cc1a7ba5afaa6176f8dedc049283d2ac38fa74ef37ea1fc575328033b222
+Payload = f660a28551416b2f8e21466ba99daee280a91740d98219cf
+CT = 95a5b2e58ea8425a23511689657d8294c5b51b6f36de57ceea2d3237788a02ff15258351
+
+Count = 44
+Adata = 3093b74eb088bdd59999629d59509920938f4feabbd29df8e0b44364c8b55244
+Payload = b9a96f0e4c6dea8861e888bdd693b300017718da958aaa00
+CT = da6c7f6e9384c3fdcc98d85f1a739f76446b14f57ad6e40165fb6719509987930d350890
+
+Count = 45
+Adata = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adbad3f6b3bec8571838
+Payload = cc4acdbd34ec9b7cbc3e23a53e0627c2a7c63206f3e0298d
+CT = af8fddddeb05b209114e7347f2e60bb4e2da3e291cbc678c8ecdf173444c334cfda5b22b
+
+Count = 46
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c8c91525377c130accce0bc
+Payload = ed75d28be4794ad81bbc0f26a11c5466f23c0270d2d7b8f8
+CT = 8eb0c2eb3b9063adb6cc5fc46dfc7810b7200e5f3d8bf6f92221c860022d92b0f961c3e6
+
+Count = 47
+Adata = ac1adca686e1d129142c49f26b52941d037d8052b8a27d5215b7ffcfd2202481
+Payload = b8234b8bd34d9c6ceffebbb85722764e7d37e43c495256e0
+CT = dbe65beb0ca4b519428eeb5a9bc25a38382be813a60e18e11c73d6a695afc704228ed7a1
+
+Count = 48
+Adata = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+Payload = 790134a8db83f2da35dde832c3ae45ec62aff0274495d6e7
+CT = 1ac424c8046adbaf98adb8d00f4e699a27b3fc08abc998e6bf1e81950e44c63183a679d7
+
+Count = 49
+Adata = 1340ac7ff04dd7450afc13f8fa52df6d526c744a2dc2f76b0aadf284da270508
+Payload = 21ea2f778cf37aa02fea30e855c20a77909548da4ee7eb61
+CT = 422f3f17531a53d5829a600a99222601d58944f5a1bba560c2c3a1876e49a47a9b44b737
+
+[Tlen = 14]
+
+Key = 7b2d52a5186d912cf6b83ace7740ceda
+Nonce = f47be3a2b019d1beededf5b80c
+
+Count = 50
+Adata = 76cf3522aff97a44b4edd0eef3b81e3ab3cd1ccc93a767a133afd508315f05ed
+Payload = ea384b081f60bb450808e0c20dc2914ae14a320612c3e1e8
+CT = 79070f33114a980dfd48215051e224dfd01471ac293242afddb36e37da1ee8a88a77d7f12cc6
+
+Count = 51
+Adata = 41aa11ec55980609482575b97eee172590ff545d5798fd4246313da3fdbbcda6
+Payload = 811d54bad842a8b92b96fc03b4fff8b5f1939fd3a49876dc
+CT = 12221081d6688bf1ded63d91e8df4d20c0cddc799f69d59ba850b0116f3269b5e44e57de7166
+
+Count = 52
+Adata = dedfb02e93b975270f50cffa3351c85975a7b21fd89bbb921c40c1e5310e6702
+Payload = 8bbf87b490020b863fc596a8d169d79c0cb3506e1f1f5aa2
+CT = 1880c38f9e2828ceca85573a8d4962093ded13c424eef9e50f053627bd0c90714820c4fbe5ec
+
+Count = 53
+Adata = a727ed3d13331ee6a224ae4b73f0ccb04b997fcf88533a1f57e9b055275de92b
+Payload = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a
+CT = e1abeaaf3bac4aba58e477de4e7b9118c6a0c56c4aaf982df865a77d66f1232cd7e36af3d1be
+
+Count = 54
+Adata = 6704dc39a259152d2dc3f08b8799ffecf4e1bc38ce5b77c71cc293c6664ef2dd
+Payload = 48033c46389f6221fb9cdda1ecb8fc25fdec6afe4eaa5fd0
+CT = db3c787d36b541690edc1c33b09849b0ccb22954755bfc97e1fba154f6b166549d0d6bb9b573
+
+Count = 55
+Adata = 6cba004dfb5e5d9e1433bf1223039ae1d2df89cd2db68f550327a22c8f946ae9
+Payload = 01acc909b7d3bb3b3e1f72845f05238d2e1d9162976d3bd2
+CT = 92938d32b9f99873cb5fb316032596181f43d2c8ac9c9895c485e9e28ae33959f8acbb640fbf
+
+Count = 56
+Adata = dd5799710523aa1da0b1209fab1e6f2ed177444ed3880d462deebbd5f774c621
+Payload = 3706def87786e49baec2d13407865286cb4e05908cac430f
+CT = a4399ac379acc7d35b8210a65ba6e713fa10463ab75de0488ef976fa9bda9544ed94ef266ed2
+
+Count = 57
+Adata = 5d7505ff863d218f6822150455b977ad2df3c02be094f6832ee68872b1ae7a01
+Payload = f38d4b225d9b80a0c5fadc61476aef419ad3d18937d8661f
+CT = 60b20f1953b1a3e830ba1df31b4a5ad4ab8d92230c29c5580caadf1dbd07515e3bfb6992e2cd
+
+Count = 58
+Adata = 796b62c7abf797de7f6bad8bf5d549688ccb7ada62fff9469c14b08208b07a8a
+Payload = 993bb3a85f67f6c1a809d8094ee80e2ad9b694063af2fdb3
+CT = 0a04f793514dd5895d49199b12c8bbbfe8e8d7ac01035ef4733ad369e4a067b7976c9d6d0456
+
+Count = 59
+Adata = 84fd27557aeb283282366083e3586f3a59691ccd0d43ec81c4e5f4e85715eba8
+Payload = 1286506be19fb865a288b09dda8af4323567cd9a66e08643
+CT = 81b91450efb59b2d57c8710f86aa41a704398e305d11250439860d66891f32ce0a09788f5899
+
+[Tlen = 16]
+
+Key = 4189351b5caea375a0299e81c621bf43
+Nonce = 48c0906930561e0ab0ef4cd972
+
+Count = 60
+Adata = 40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951
+Payload = 4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef
+CT = 26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9
+
+Count = 61
+Adata = ac8dde7ba60e4ba226eecb0a789b1c4673ddffe8f371464389f52f767004f0a6
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1ff831cfc51ae62ea29b0791941972254cd0b846294d7be196363d27b9e11fee55111b273399f5ff
+
+Count = 62
+Adata = 8f2777ec4930f7e349c3bd4830120cebdd896db9d8a33d34f101672024bd737f
+Payload = c641cf589020b94026ae5ac0bfdc29822cc13862a54614c7
+CT = a5b1771213628c2e0868dd128117af092a98c4bebaf3cc9ef741e15ad9b2f5ab864ad94d3f9de562
+
+Count = 63
+Adata = a87426f83bf91bd3c3556bf859cd97f51c92609879f02dbca9c7ae637a3fbf05
+Payload = d204994c128d6204ef2939c22572daa56c12df2e4d3e33e9
+CT = b1f4210691cf576ac1efbe101bb95c2e6a4b23f2528bebb0652a083ea1b43b7da026692c7aa796d7
+
+Count = 64
+Adata = 7ff9ca86f820e4d57995d450611009ffaa726e6fbe4ce1558ca1e775daed9ec2
+Payload = aff9bb0238689255f54cd5fdebe6d3dff5f5604ab8d77038
+CT = cc090348bb2aa73bdb8a522fd52d5554f3ac9c96a762a861057e0faa2711cfa1e3da5499f9a1ee0b
+
+Count = 65
+Adata = faa6b7f8c6e076b5e5b981119b7ec2e0b9c73da4064f9704e303d5792f59674b
+Payload = 95d2cf30b6174b17278ad9f44079a2199082dab917f89763
+CT = f622777a35557e79094c5e267eb2249296db2665084d4f3a90b39704d8913391ebd3424117b93b68
+
+Count = 66
+Adata = b553e65640c1ad0d2ff748c5b2af9d970c74131cff4fa73384a33dfec056332e
+Payload = aaa53244520e157c4890a0e62100a12daa84f9be710242d7
+CT = c9558a0ed14c2012665627341fcb27a6acdd05626eb79a8ed0a6cb58733be0a3b608afdf78eaa70c
+
+Count = 67
+Adata = a9be73668b94bc6a212744522a0adff03d49fd495daadaf6cd32f4ca25ebc2b5
+Payload = 1066b96c3c44301073717520ea5c07adbac7759b88d52154
+CT = 73960126bf06057e5db7f2f2d4978126bc9e89479760f90daf20ce64e6a821e39ca96aded43f0875
+
+Count = 68
+Adata = 8b516c47e6630b2c31d8eefd8ba152d7315582a3f4d3f0e0eb2984a365b434db
+Payload = b5969813d0f892febe64ed52d429cc737b5df8d5e0c63207
+CT = d666205953baa79090a26a80eae24af87d040409ff73ea5ecf4699d23f5fc6742bffebbd16858f6e
+
+Count = 69
+Adata = 8ad3e84edbe7d9305848746cbd0f769bce47d5ae4609513210e54cd3b984db1f
+Payload = daa90a2de3937e7942e6711f165a89b9e077fe322cab597d
+CT = b959b26760d14b176c20f6cd28910f32e62e02ee331e81243713601bb16dc91af84ac19ebd43a1ec
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp
new file mode 100644
index 0000000000..75b0c429f6
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 11fd45743d946e6d37341fec49947e8c70482494a8f07fcc
+Nonce = c6aeebcb146cfafaae66f78aab
+
+Count = 0
+Adata = 7dc8c52144a7cb65b3e5a846e8fd7eae37bf6996c299b56e49144ebf43a1770f
+Payload = ee7e6075ba52846de5d6254959a18affc4faf59c8ef63489
+CT = 137d9da59baf5cbfd46620c5f298fc766de10ac68e774edf1f2c5bad
+
+Count = 1
+Adata = edb8834974b02fc9ab29b4b3c49683426124e729b44e43cde4ab9bb1b30b5531
+Payload = d05410f42d4759f8cab3884785cf8f60ecbf902e525b92e8
+CT = 2d57ed240cba812afb038dcb2ef6f9e945a46f7452dae8be24285996
+
+Count = 2
+Adata = 8baf194e81e47a6ca82ca51b488339d014a0a494007793aa5201ac72fc3f808d
+Payload = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c
+CT = 2633df3f6d2b52301ae01015efb688a4730e3088e2d84b0a6c510570
+
+Count = 3
+Adata = c0b55acc7fbfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028470953
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72a6b3864da44a
+CT = 8204b86e87d9a11239becb49850eb76a846959e986ccde1cb418cfd2
+
+Count = 4
+Adata = 9dc672e64c468242ddeec318c71f9b8cbaa14639eba3c861acfc26463fb7d5d7
+Payload = 263dbe1bd5e9d9b29b316fe36ec8bb10f64543b4921c01f6
+CT = db3e43cbf4140160aa816a6fc5f1cd995f5ebcee929d7ba03e5b5794
+
+Count = 5
+Adata = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0183dc578ed976f92
+Payload = 22dbba2b1a39074ddac736767ebdedc37e4208b233e03b34
+CT = dfd847fb3bc4df9feb7733fad5849b4ad759f7e833614162f63b4847
+
+Count = 6
+Adata = ed2898d0bcb34eebf98b5279bc3e8a20214321a7e23bc55b2b7613b1a9b94f2c
+Payload = f0f1235ee88d04de3f3d1489ec6b28b285a6a4fbb344911a
+CT = 0df2de8ec970dc0c0e8d110547525e3b2cbd5ba1b3c5eb4c7ab29a40
+
+Count = 7
+Adata = 50c4a285d6a4e64efceb288b82e7c8277307cf1eaa4b8b9294f97a1c38926a60
+Payload = 0e50aa6a3079c0b8d61e51c3bd93b592a03719acb9f0252e
+CT = f35357ba1184186ae7ae544f16aac31b092ce6f6b9715f7868f40ff6
+
+Count = 8
+Adata = b48a16fb9a065d3aeb2bdf1860e4b0f1348c8f13cd00b1729ff8c19e4e9724f3
+Payload = 82f39f5207afcfd677a7544579f2b888a1eabdee4e835924
+CT = 7ff0628226521704461751c9d2cbce0108f142b44e022372ceeff92c
+
+Count = 9
+Adata = d92b80544f29aba52496e2c9a0aa4adeb89820be321cfd2f0a53585a15d04c7f
+Payload = bc3b08eec6506d1497572f901f0e5f3e9854b40b0f992d08
+CT = 4138f53ee7adb5c6a6e72a1cb43729b7314f4b510f18575e619c1124
+
+[Tlen = 6]
+
+Key = 146a163bbf10746e7c1201546ba46de769be23f9d7cc2c80
+Nonce = f5827e51707d8d64bb522985bb
+
+Count = 10
+Adata = 599b12ebd3347a5ad098772c44c49eed954ec27c3ba6206d899ddaabca23a762
+Payload = 473b6600559aefb67f7976f0a5cc744fb456efd86f615648
+CT = 26d2be30e171439d54a0fec291c6024d1de09d61b44f53258ba1360406f9
+
+Count = 11
+Adata = 3a8423feb661db30542dc3cfb596280429397f80755a4bc8d4d941d03b61aacc
+Payload = 7edfce3dedd65a8592aec2bfc7a751e2360f3137941fc960
+CT = 1f36160d593df6aeb9774a8df3ad27e09fb9438e4f31cc0db5e5938e8c75
+
+Count = 12
+Adata = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17330744d401d2875b
+Payload = a9fb3ebba43c273cacbf0f7187030c69172f31382e9e059b
+CT = c812e68b10d78b1787668743b3097a6bbe994381f5b000f694f534b76f0b
+
+Count = 13
+Adata = 6546d9a90e0e763679d5469a1bcffcc4f18f35f50c7714d14c7329b76ce7984e
+Payload = a7573e5b7dd7f4ce9e4480f603c14145a27f7c7a9246a3cf
+CT = c6bee66bc93c58e5b59d08c437cb37470bc90ec34968a6a23c6c025faa1b
+
+Count = 14
+Adata = 7f398ff0d47e2c0fccd8a16cc9e79b4813abac42e346fa33ba033956f798d6ac
+Payload = 84370557e0bbf74fd0a4533185adfe202d9fa9d622bba72f
+CT = e5dedd6754505b64fb7ddb03b1a788228429db6ff995a242ae0f88d836be
+
+Count = 15
+Adata = d0f46fb37d516cc957aaefd3be2a8bede885330a8edb96f3e5e0ab8cd03a8c59
+Payload = 029575400bd3f2621c7d9ca9b6a09ea6f776968b19dc3f3e
+CT = 637cad70bf385e4937a4149b82aae8a45ec0e432c2f23a5366d09f64b4c2
+
+Count = 16
+Adata = 4abaa4260c864572e12553c5aabfe62e4e7038490d4ba160119fc5d646780cc6
+Payload = 448be3821d94452425fae41a06457260a2666e890fa94954
+CT = 25623bb2a97fe90f0e236c28324f04620bd01c30d4874c39677fd479c852
+
+Count = 17
+Adata = 686e0578eadd19583291a01e11a29fc95a2c156da100dd85429ad58ba65440c6
+Payload = aebfe3e15a876412ec9df714f1afa898e69004c1ef25732b
+CT = cf563bd1ee6cc839c7447f26c5a5de9a4f267678340b7646bbc332573774
+
+Count = 18
+Adata = e3d29f970667286a81586aa02bb490c72d8bb3a308eafec5da0d105fddd1a157
+Payload = 08b2ce5f7296016e86d02f8c7952d746703ee4f0429b8df3
+CT = 695b166fc67dad45ad09a7be4d58a144d988964999b5889e33171a8ccec1
+
+Count = 19
+Adata = 9e2ea8eb7f56087ee506925648661eeefffd643a056cd4f4fc5cc23172b5c637
+Payload = e73d7d23736db17cca816ab2440062a8051177d47feb514e
+CT = 86d4a513c7861d57e158e280700a14aaaca7056da4c55423bc8299cc9f95
+
+[Tlen = 8]
+
+Key = bdf277af2226f03ec1a0ba7a8532ade6aea9b3d519fe2d38
+Nonce = cc3c596be884e7caed503315c0
+
+Count = 20
+Adata = 4d6546167b3ed55f01c62bd384e02e1039c0d67ef7abe33291fecb136272f73b
+Payload = 0ff89eff92a530b66684cd75a39481e7e069a7d05e89b692
+CT = 6ef66a52c866bd5df20ec5096de92167ad83cab0e095ad0c778a299f1224f10c
+
+Count = 21
+Adata = 95722ef5e0cf9f482e4c359f1fd6b9efe2b6e0630413c40285b8958c31188ca4
+Payload = b1ea02e3721e44c327443fcf4b424cce19afbb9e8cf06b76
+CT = d0e4f64e28ddc928b3ce37b3853fec4e5445d6fe32ec70e8a5c2c6b097a04d50
+
+Count = 22
+Adata = f7b76a2a4fe0a1b07a6b193b4600aec02360eb35853d88fe8a4f31a8dda48ad9
+Payload = c1f9c7b2e0ba712b4d2b32e4693b145228213999703767fc
+CT = a0f7331fba79fcc0d9a13a98a746b4d265cb54f9ce2b7c62f62e74c2312f9243
+
+Count = 23
+Adata = 406f39cb77b8d8c63f7797d184b6ebde819af7d48de5003538c022fe96b841ce
+Payload = ebf3a717546199c6f6b14efe8888613ca7e075e8290b277c
+CT = 8afd53ba0ea2142d623b468246f5c1bcea0a188897173ce2f1cb228ffd2ff8e6
+
+Count = 24
+Adata = 3dd3110703a95b05b9b9cff92ab7244e6c6dcb4509522c305d5d33e03f1b0b60
+Payload = a0e317b790870e6703e6077dfb8ea327c12e29a17107284c
+CT = c1ede31aca44838c976c0f0135f303a78cc444c1cf1b33d21f38e2d280a8f3ff
+
+Count = 25
+Adata = 044ae4064156b6ebc0921cb2c3c607976339f824d4dc6902eac66910dce086b2
+Payload = 8a16990690717dc16eea24da39878a2ee7c1579976e5b173
+CT = eb186dabcab2f02afa602ca6f7fa2aaeaa2b3af9c8f9aaedafbcf46b4e75bb11
+
+Count = 26
+Adata = 5479cc7f92460ff7a3e500f76d70e3036c44300005058b5517e3f64ad41b46b3
+Payload = 1e7e51f0fa9a33ed618c26f5e37754df0f7de7778882c26c
+CT = 7f70a55da059be06f5062e892d0af45f42978a17369ed9f2fac11c84d08e918e
+
+Count = 27
+Adata = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a16414085469effe1c
+Payload = 3ef1f4c438dce131990ba536d7a6166022ae7de4a436f87c
+CT = 5fff0069621f6cda0d81ad4a19dbb6e06f4410841a2ae3e2b50cb871173d9bb8
+
+Count = 28
+Adata = 52742be3969830ba9c2bce26c98c2fb44ac881ec55c85627b2c94ba17b0de8cf
+Payload = 3c7b4a68dfb766e24739f14932563fb81f24591f0e31e895
+CT = 5d75bec58574eb09d3b3f935fc2b9f3852ce347fb02df30b4ce29627efbc3523
+
+Count = 29
+Adata = e16e5dc034719e5d815f937b672cf34d5d420a3945c8f73645241779d2bec150
+Payload = 03038acd2d8351e4e5aa308e554abfcd0d0334d8f864ec60
+CT = 620d7e607740dc0f712038f29b371f4d40e959b84678f7fe095168ed90827db2
+
+[Tlen = 10]
+
+Key = 62f8eba1c2c5f66215493a6fa6ae007aae5be92f7880336a
+Nonce = 15769753f503aa324f4b0e8ee0
+
+Count = 30
+Adata = 1bc05440ee3e34d0f25e90ca1ecbb555d0fb92b311621d171be6f2b719923d23
+Payload = f5522e3405d9b77cbf3257db2b9675e618e8744a0ee03f0f
+CT = b9103942dbbb93e15086751c9bb0a3d33112b55f95b7d4f32ff0bb90a8879812683f
+
+Count = 31
+Adata = 25c32770a299020d8500d8a4b5d7621e4379dbd6ef34a9aceefd4055ea6144f5
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2528ef51c80
+CT = 84fd032911998b4b22ae6e9cdccb2835a356734715a2f77c6982d0796e1bd1cc9879
+
+Count = 32
+Adata = cba0e0140f094e17652ea6f64c26f69dd9429bfefb41aaf104c38f3f6501f4f9
+Payload = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe
+CT = b4c32ef32bf9d619528ca02f29ec4d52d2b3ae2b2cda9542fe08edf50e05d4d85faf
+
+Count = 33
+Adata = a846d0f56eb963b308ab8f697adca378ab6ccf9f739edcd7f5db197b2ffa99ac
+Payload = 72862d82d940748d54369e3143192453069b80d10f32e569
+CT = 3ec43af407225010bb82bcf6f33ff2662f6141c494650e95800ae2523c5f161ed96f
+
+Count = 34
+Adata = 1dc5f6d6103ed2ae7f4ecd7b1bae4d5b9c0adef9100527b1737e1cf57f1175ef
+Payload = 46f2199305ff4e1f21a89d96d3902c54939f52278ba7aa0e
+CT = 0ab00ee5db9d6a82ce1cbf5163b6fa61ba65933210f041f234a29547607846bc9834
+
+Count = 35
+Adata = 8c28bcb9c31191c347dd64e552af5aff500e6e6f39e866351dd7065501a2837d
+Payload = 18c38c41a4e70c3f7362249ea329059b0e026bce7ae976b0
+CT = 54819b377a8528a29cd60659130fd3ae27f8aadbe1be9d4c95f73957e86152df56bd
+
+Count = 36
+Adata = 1081afd5bf9f1a87169973ebdca85c2b69598154673d7ca9d6e2f63d52030fc1
+Payload = c89e388dd6124c41251e7422b420a71e4618f5cf9f0a63fc
+CT = 84dc2ffb087068dccaaa56e50406712b6fe234da045d8800b2b028cd785f4f964069
+
+Count = 37
+Adata = 079bc543c966734fa70814139ba8051271ee1c4f701579013c427f8efb141db7
+Payload = 68449bc3f6c8bd8f3a46a8e147522d979948c88ca791d204
+CT = 24068cb528aa9912d5f28a26f774fba2b0b209993cc639f8fd3ef357e5e69f504c95
+
+Count = 38
+Adata = e7094697b78d20174ec3c97a48abcf67c2ba6790b4db5fda82b454becd2a25ef
+Payload = 330088153204c3d5de7744047b60887c8c044e4eeaae4bab
+CT = 7f429f63ec66e74831c366c3cb465e49a5fe8f5b71f9a057e092ed15d1a074306a9e
+
+Count = 39
+Adata = f8d64ce2aa66e67de0f2fa584dec858983333b0570882ab628419bcee541395a
+Payload = 893c5c45db989bd39485caa05ed700bb17c526b426edf4ba
+CT = c57e4b3305fabf4e7b31e867eef1d68e3e3fe7a1bdba1f46afaad39e9183b2970027
+
+[Tlen = 12]
+
+Key = 5a5667197f46b8027980d0a3166c0a419713d4df0629a860
+Nonce = 6236b01079d180fce156fbaab4
+
+Count = 40
+Adata = 29bdf65b29394d363d5243d4249bad087520f8d733a763daa1356be458d487e5
+Payload = d0e4024d6e33daafc011fe463545ed20f172872f6f33cefa
+CT = 479f3d408bfa00d1cd1c8bf11a167ce7ae4bcdb011f04e38733013b8ebe5e92b1917640c
+
+Count = 41
+Adata = 314f069dd4ac5aa3fdc2a74e83daa1d5d18330cd3b90684a9260bb48f5626d49
+Payload = 9ebd994a9af0cb94552ffd749fdd97f75a1ebd0ad3de3a9a
+CT = 09c6a6477f3911ea582288c3b08e06300527f795ad1dba58425a1bad4381dc84fee903e3
+
+Count = 42
+Adata = 3aa7f30ac5bfbcb3f8de7c5e76269c608fbc76361d215e78abc0e308ddc3528f
+Payload = 590a27721a36987d1ffa15f23c6ca5cc556dfcfa6993a2fb
+CT = ce71187fffff420312f76045133f340b0a54b66517502239efcb43c6aaec88b51d0a378b
+
+Count = 43
+Adata = 5630345f662df248886f771b2b77cc0cbdc8fe4cc4a6cde52b1ea4e5d946cebe
+Payload = 65f4b3a00c1c1ef39445a69b2150b034705410140ff9dad0
+CT = f28f8cade9d5c48d9948d32c0e0321f32f6d5a8b713a5a12b9a60374d9304316e2fc50d9
+
+Count = 44
+Adata = 38ee97f0dc635c7416a024e3af5c95dd1d496db8a5a5c3bcc20b9093ca906dfb
+Payload = 0edea2afaeaf650704d2c6c6622aad82169807c983c17309
+CT = 99a59da24b66bf7909dfb3714d793c4549a14d56fd02f3cb07611163d6b0f1734292ed8c
+
+Count = 45
+Adata = ea3b3f3c5b28f7d48af2ccf97083937baccb0a6b1a041080a73b15b9640ccf44
+Payload = b80175a03dff1b10078ded64ed759e5453e3bc0657c68590
+CT = 2f7a4aadd836c16e0a8098d3c2260f930cdaf69929050552edefbcbb51d9d607b7b2e8f8
+
+Count = 46
+Adata = 287f31e69880823df7798c7970c0e42e600bf567ad78f5d559d0182d570c03cb
+Payload = 531c1e721e185f58b2c654b9098ce0c1338bab4149c7bef7
+CT = c467217ffbd18526bfcb210e26df71066cb2e1de37043e35f2b6d4dc8afae25ff400d73d
+
+Count = 47
+Adata = 1d4579c9410cc34ade1352ed433e0d4faaaa28200e359bcb4140d35939b3a792
+Payload = cead1c5af16ca89bc0821775f8cba8c25620a03dfd27d6f1
+CT = 59d6235714a572e5cd8f62c2d79839050919eaa283e4563319cd80c1ce0f9ed40f1e9dec
+
+Count = 48
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f28e3f8faaa76fcad4
+CT = 294910550a6e22b8876e2bbcb39de635d106c535d9ac4a16e53d5aeccfb4a6837b79a625
+
+Count = 49
+Adata = ec6857533675b5ed8d4315b0d5f59c826f3ccb2d0bd6f604bd54f7c9542123ce
+Payload = c222374d366baf2d0301340582aa056c04441ac766065ab1
+CT = 55590840d3a275530e0c41b2adf994ab5b7d505818c5da73385e080bf29ae097c328789a
+
+[Tlen = 14]
+
+Key = d2d4482ea8e98c1cf309671895a16610152ce283434bca38
+Nonce = 6ee177d48f59bd37045ec03731
+
+Count = 50
+Adata = 9ef2d0d556d05cf9d1ee9dab9b322a389c75cd4e9dee2c0d08eea961efce8690
+Payload = 78168e5cc3cddf4b90d5bc11613465030903e0196f1fe443
+CT = e2324a6d5643dfc8aea8c08cbbc245494a3dcbcb800c797c3abcdb0563978785bf7fd71c6c1f
+
+Count = 51
+Adata = 6f99d9ce00a4be502a5d2c76a07b914d56f49a1592c1ee2e46e11b3c9da0d083
+Payload = 3c3992cac792e019720d38f768beac3deb6a43e7e1f59f20
+CT = a61d56fb521ce09a4c70446ab2488c77a85468350ee6021fcb0e8ec0879db8ffa59125eac239
+
+Count = 52
+Adata = deae66f68bb18178d1bc0734f19fd3ab390049c2ca083a159f5c078fcb4f0a38
+Payload = 8eaae72e532943d66ce8250c6b434d299b6afbf8e2b4f8b1
+CT = 148e231fc6a7435552955991b1b56d63d854d02a0da7658e664a2d992f7cf821e19bb7d4dff8
+
+Count = 53
+Adata = e2d592cb412e65f9044257d78e7491f9f80c8b08102c2d5da20535cef74ad8c8
+Payload = 1b8096b79ace8c6ee5dbd8735f1287aa2c94865f382dc2da
+CT = 81a452860f408ceddba6a4ee85e4a7e06faaad8dd73e5fe546a4a816b709a55db450ac249c5c
+
+Count = 54
+Adata = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2aae7b3b7a4634437
+Payload = 014f15219463ac22820ba6a1fa04d7f686003ef24004da67
+CT = 9b6bd11001edaca1bc76da3c20f2f7bcc53e1520af174758fbebbdb2e35ebf682f7fe30996bc
+
+Count = 55
+Adata = de6ea86d3641d916c4394fdd31e6a50194993d6ef1d3dfd9fffca20b2f58107d
+Payload = cc8c855a4c122046916bdcf8089eba3ddb80483e201c7102
+CT = 56a8416bd99c20c5af16a065d2689a7798be63eccf0fec3deee137bb5b1e7385aa1bd5d69831
+
+Count = 56
+Adata = 87b937b1d36e8a9ab33a1d3eed617030923acaabc7e620dfcb3c388936030fc6
+Payload = 3fb7d1f17e7e36d5d4b816cc6db11d1d85848c577fdfe938
+CT = a59315c0ebf03656eac56a51b7473d57c6baa78590cc74079b13b729c70e1fa89c43a05a544b
+
+Count = 57
+Adata = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5f7f1a60cf4e16278
+Payload = 268fe424d6db30f680c10fe2684707a0778069958e9a3bf7
+CT = bcab201543553075bebc737fb2b127ea34be42476189a6c82d900340d90dc4f09a7171d331d6
+
+Count = 58
+Adata = e13e0c9cef1f86160a75ccb131586370b0edabbf8b3b63f21f3a6fee072dd926
+Payload = 9d64de7161895884e7fa3d6e9eb996e7ebe511b01fe19cd4
+CT = 07401a40f4075807d98741f3444fb6ada8db3a62f0f201ebe4ad0d90322ed2813a3343029e93
+
+Count = 59
+Adata = d4cd69b26ea43596278b8caec441fedcf0d729d4e0c27ed1332f48871c96e958
+Payload = e4abe343f98a2df09413c3defb85b56a6d34dba305dcce46
+CT = 7e8f27726c042d73aa6ebf43217395202e0af071eacf53790065601bb59972c35b580852e684
+
+[Tlen = 16]
+
+Key = a7177fd129674c6c91c1c89f4408139afe187026b8114893
+Nonce = 31bb28f0e1e63c36ca3959dd18
+
+Count = 60
+Adata = 2529a834668187213f5342a1f3deea0dc2765478c7d71c9c21b9eb1351a5f6cb
+Payload = 2cea0f7304860a4f40a28c8b890db60f3891b9982478495e
+CT = 5bb7aa6ab9c02a5712d62343fbe61f774e598d6b87545612380ea23dcffc9574f672bca92e306411
+
+Count = 61
+Adata = a4dbf26802b2dba1bf828f57618fd197d3e60b6efc9d884f965ce3b43e1dc008
+Payload = 2baf3d378942bd44f67fb787def50aaf446bf15c56243484
+CT = 5cf2982e34049d5ca40b184fac1ea3d732a3c5aff5082bc8b93605b46a8a6a9c7e02cb8feac67af4
+
+Count = 62
+Adata = cbd1302c9fffe29fe882838236f64fe9d9ba35db5499e90f0faa35f34c7490f2
+Payload = a0639aa4e7a8bda4e9e096d17c1c47d3786010fabe9c72d2
+CT = d73e3fbd5aee9dbcbb9439190ef7eeab0ea824091db06d9e82e411c052c0a025ab15767b0242ebf7
+
+Count = 63
+Adata = b6112eb8299b28445aca8f72e7170a1cd8bbfee4d2145fbe8d49c6af8831c4d4
+Payload = e2d78ce5df9284c045b84df33f551211ddccf7bb14cd4529
+CT = 958a29fc62d4a4d817cce23b4dbebb69ab04c348b7e15a65ab58a892f7142414d3f7cf10925a403a
+
+Count = 64
+Adata = c70a9fb811894b73e445b78db7a931705a181f3a8730341cbb50eaff43572c6e
+Payload = c3f1e735a6741aa481ad577a98dbac1f03cc80ea0dae1b94
+CT = b4ac422c1b323abcd3d9f8b2ea3005677504b419ae8204d8b5b3ce6bae6ecb060289508d6e9212fe
+
+Count = 65
+Adata = c7cbda495a7dc1d91837f652a9d084df9b717e99b29bf1ab7f6c17b3341ecd6c
+Payload = db8cd5d76e459afce765e07da98f4ac58231224238c293c7
+CT = acd170ced303bae4b5114fb5db64e3bdf4f916b19bee8c8ba16229a91a2298ffe104f9c032720abb
+
+Count = 66
+Adata = 4bd3a656796cb1fa87976f3a93471e33dd1209ce33d7a28aaca4d17c99d78c94
+Payload = fd66aebc94f2513b1b9218396b08c63a869b9c4dd0752a91
+CT = 8a3b0ba529b4712349e6b7f119e36f42f053a8be735935ddb9cacc4fdb44402971a0eee7f1ad90d7
+
+Count = 67
+Adata = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f45605ab734b24498
+Payload = 5831e9a6af0234d051ffd17a14b8e3c8da95067ab767901b
+CT = 2f6c4cbf124414c8038b7eb266534ab0ac5d3289144b8f5713306e7f0a61d4b3da372db669321143
+
+Count = 68
+Adata = f8f04f12174b5205866515ce3775bd8e11d50d8b96142be0c347a773379fb928
+Payload = 248a4969621cf291bec7f0d76d80b7f019d4eb002a22c46a
+CT = 53d7ec70df5ad289ecb35f1f1f6b1e886f1cdff3890edb2609726d3a3d04005dc13629658624d05b
+
+Count = 69
+Adata = 4ecd7c2188fb9cfc84a9ee2fab29ccbbd48a574ec20f1959eedfe96887fe0eb3
+Payload = 68f36fd96de8c57210f6f41da5b67d68533d722c604dda62
+CT = 1faecac0d0aee56a42825bd5d75dd41025f546dfc361c52e8631fb934e918210097f3cefc7f3b0ee
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp
new file mode 100644
index 0000000000..dbe86fbb71
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 9074b1ae4ca3342fe5bf6f14bcf2f27904f0b15179d95a654f61e699692e6f71
+Nonce = 2e1e0132468500d4bd47862563
+
+Count = 0
+Adata = 3c5f5404370abdcb1edde99de60d0682c600b034e063b7d3237723da70ab7552
+Payload = 239029f150bccbd67edbb67f8ae456b4ea066a4beee065f9
+CT = 9c8d5dd227fd9f81237601830afee4f0115636c8e5d5fd743cb9afed
+
+Count = 1
+Adata = ab91d1aa072947d22f0dc322355a022fe7f0747f4a184b48446bd27999ef01fe
+Payload = 25a43fd8bf241d67dab9e3c106cd27b71fd45a87b9254a53
+CT = 9ab94bfbc86549308714543d86d795f3e4840604b210d2de169d7775
+
+Count = 2
+Adata = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b10a85eed1bf63a30c
+Payload = e63d8303fa5c51550e417e77ec1ec647c9e2a853cab00fee
+CT = 5920f7208d1d050253ecc98b6c04740332b2f4d0c1859763b9c2e299
+
+Count = 3
+Adata = 8587324c1ff6712aed8af134744de5df1f88c5d2cb33f4f888af9fd39eb8e813
+Payload = f27548ec1608d3b8a5bdcbccb7e09cf4b5c29d3661b13a61
+CT = 4d683ccf614987eff8107c3037fa2eb04e92c1b56a84a2ec02f73205
+
+Count = 4
+Adata = 58820fb68ba1cd73b05a6698b4394ba1b13e8e296480f5afe1154d9b8536007c
+Payload = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c
+CT = 53a004b2046f1d97a910151ab22f580740a894f004a0c7114e1dd81b
+
+Count = 5
+Adata = f3034031933e7807d47140cf5c7794e42a228a522a83883b0765b57a411bad85
+Payload = 3002c6fb49497c7d1d06e1bd4edd57a9e54bbbb74e948c79
+CT = 8f1fb2d83e08282a40ab5641cec7e5ed1e1be73445a114f446525bc4
+
+Count = 6
+Adata = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4795ca03ca4661d2fc35b8c
+Payload = 214acfb2613b266f2929d43c7666f3a23e61423061cdbec3
+CT = 9e57bb91167a7238748463c0f67c41e6c5311eb36af8264e651844a3
+
+Count = 7
+Adata = 968a302a27624c304e894633af600c3cc7c614b7da3af0bf2d3f239c7605338a
+Payload = 9c575d592a9622c014c1303329757a65a414a9ed0c1b1b3f
+CT = 234a297a5dd77697496c87cfa96fc8215f44f56e072e83b249fd550d
+
+Count = 8
+Adata = 9011231ec382ecaaae57f34de1ac6bbb50741014a978160ce59c60491e64f30d
+Payload = 426a4c83793abdcff5e2a99e161785dc27c6168a329ee465
+CT = fd7738a00e7be998a84f1e62960d3798dc964a0939ab7ce84137defa
+
+Count = 9
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = e04006b68c83a5dd4ceac3cde238e48895ae17728fdc7bbe
+CT = 5f5d7295fbc2f18a11477431622256cc6efe4bf184e9e33356a4953f
+
+[Tlen = 6]
+
+Key = 8596a69890b0e47d43aeeca54b52029331da06fae63aa3249faaca94e2605feb
+Nonce = 20442e1c3f3c88919c39978b78
+
+Count = 10
+Adata = 4e0d3aa502bd03fe1761b167c4e0df1d228301d3ebaa4a0281becd813266e255
+Payload = f0b065da6ecb9ddcab855152d3b4155037adfa758ba96070
+CT = d6a0f377f7c1b14dcdba729cae5271b027e71cc7850173ec265867a29eb3
+
+Count = 11
+Adata = aeef2d1e3d3c9920a4fdb5f9d963b88e78a5d0edae531e3b55e702ed609d9a3c
+Payload = f2a8855e34854656df0776e80255ad1d125841c727201509
+CT = d4b813f3ad8f6ac7b93855267fb3c9fd0212a7752988069566e89a72dc0e
+
+Count = 12
+Adata = 3051ffb19862370bc46ca94a8eb906a660d539b18e965583e95acc149190e3e9
+Payload = 20955a0ca3c9c10d4055406ec12226130ecdaf195b08d65e
+CT = 0685cca13ac3ed9c266a63a0bcc442f31e8749ab55a0c5c2dff4f6257e06
+
+Count = 13
+Adata = aafa45a107d909756b4a1956d5228b50316fc5852afdeecf401fa2a71aabea46
+Payload = 246b60d17ea70deb1380fbf4bd767d88f53069b0f4136511
+CT = 027bf67ce7ad217a75bfd83ac0901968e57a8f02fabb768def0017c9acc1
+
+Count = 14
+Adata = ccdeab6a28b1b9e9f0c67116a91f2215b229d0edcd35d696db2bcf54e77db743
+Payload = 5b735697c5577ee0e352cf6a1495c490d6f7e97c3898f0ee
+CT = 7d63c03a5c5d5271856deca46973a070c6bd0fce3630e372c73969437912
+
+Count = 15
+Adata = 33a1e7d4820ed6a76a6dab90b4ba830888caf12a262e4eb6d75a505b2207de36
+Payload = 1170416faf81896c7f00815f53c2be5f7246d4794895b4b1
+CT = 3760d7c2368ba5fd193fa2912e24dabf620c32cb463da72dd7cb3721fcdd
+
+Count = 16
+Adata = 3df3edd9fc93be9960b5a632e2847b30b10187c8f83de5b45fcb2e3ed475569a
+Payload = 556765ffe5c46015cbd8194e32abc41e8f711773e2bcac90
+CT = 7377f3527cce4c84ade73a804f4da0fe9f3bf1c1ec14bf0c82183448e643
+
+Count = 17
+Adata = 4cb8663a1a934b6b27cbc1ed3040fbb99fbb6812f8ca35ff73cc13feeb483af7
+Payload = 3070e269f3e87cd82af3896895a5dd6fbfa9898279e0f73b
+CT = 166074c46ae250494cccaaa6e843b98fafe36f307748e4a76069901b5e3a
+
+Count = 18
+Adata = 876df130c01d0b9b8ebe43e71046c365e13124169026876d50d7e155f0299676
+Payload = dd18d40728c561e24e6e54834348dde5683f067baf8df469
+CT = fb0842aab1cf4d732851774d3eaeb9057875e0c9a125e7f56d65c2b005d4
+
+Count = 19
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 7064a2491f716f4a2969815e4a281a54690ced9f794b264e
+CT = 567434e4867b43db4f56a29037ce7eb479460b2d77e335d275b37e9fb9e9
+
+[Tlen = 8]
+
+Key = bae73483de27b581a7c13f178a6d7bda168c1b4a1cb9180512a13e3ab914eb61
+Nonce = daf54faef6e4fc7867624b76f2
+
+Count = 20
+Adata = 7022eaa52c9da821da72d2edd98f6b91dfe474999b75b34699aeb38465f70c1c
+Payload = 28ef408d57930086011b167ac04b866e5b58fe6690a0b9c3
+CT = 356367c6cee4453658418d9517f7c6faddcd7c65aef460138cf050f48c505151
+
+Count = 21
+Adata = a61b6c1f0293a7c35520abf158a995e5ae59b43ec5f38ff6fd6529970c9f83ac
+Payload = 1c5ad37d2a55afbc390b27cde0c42d6651fe191239bfaa27
+CT = 01d6f436b322ea0c6051bc2237786df2d76b9b1107eb73f76bca352f92f383e1
+
+Count = 22
+Adata = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a41f9fe5648f02fba
+Payload = 6efe6652d46a84166d30befe2fbee0795e9475b401eedd60
+CT = 737241194d1dc1a6346a2511f802a0edd801f7b73fba04b014fd7c84052208d9
+
+Count = 23
+Adata = 151110a9ce7e44e5d76d9cad53c1819317527fcd169051f01c6a3efcc06ea999
+Payload = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc5
+CT = 483bb6a5d025dc2136a959ddacf5d001ad7e52a1e4ce1615c3ebc7214b9eef31
+
+Count = 24
+Adata = 0ba1210696d735eebc13b609d0ec33bc740805105dd82f065b82892b931f1e6d
+Payload = 794a86f5b20d344ad86fd5523d08f1864737be57731440c2
+CT = 64c6a1be2b7a71fa81354ebdeab4b112c1a23c544d409912eff08182f8a00f13
+
+Count = 25
+Adata = 5a3b71b0fdecce8bd759d3d72321b5c3e882c82627c14e0b59cc8c6d191f243f
+Payload = efa6ddd6fb8e4480a0f64414694e5f9e7f2e9b97cbe9cd14
+CT = f22afa9d62f90130f9acdffbbef21f0af9bb1994f5bd14c46894be1f8fa14538
+
+Count = 26
+Adata = 5d344c5b94695a66192b6692e420c8eaa3cb482502be837b2a0a91b787fbe48e
+Payload = 561dd3bf419ae33ff521a43898cf12c6a5c6163eec22abc1
+CT = 4b91f4f4d8eda68fac7b3fd74f7352522353943dd2767211f4393bca514c3336
+
+Count = 27
+Adata = 08344486df2b2f9a6880a03503a3986c485f067c480c31a51607553b875f91fa
+Payload = 6d3596f25401f2e3b099613236f1d88a2f3d8edc1f04bc0c
+CT = 70b9b1b9cd76b753e9c3fadde14d981ea9a80cdf215065dcb708ffd04c8c2da0
+
+Count = 28
+Adata = 9d0824a4dc7e67326c5b68a6ea99cb68298a2af2cc1952351454b038f6270603
+Payload = c563a43e4cc0f93d955432f68287e63400a7fdcae738ba84
+CT = d8ef8375d5b7bc8dcc0ea919553ba6a086327fc9d96c63541511d7d684d58762
+
+Count = 29
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 18c5865b414b2a06b4d71ab9550985b4f3c3d7817e8a8d7c
+CT = 0549a110d83c6fb6ed8d815682b5c5207556558240de54acef0919c5f5daf093
+
+[Tlen = 10]
+
+Key = d5b321b0ac2fedce0933d57d12195c7b9941f4caa95529125ed21c41fac43374
+Nonce = b35fb2262edfa14938a0fba03e
+
+Count = 30
+Adata = ba762bbda601d711e2dfc9dbe3003d39df1043ca845612b8e9dc9ff5c5d06ec4
+Payload = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb
+CT = 97027de5effd82c58f8dbfb909d7696fbe2d54916262912001a4d765bc1c95c90a95
+
+Count = 31
+Adata = 77a685958ca801dbcbf346d6bac72662d3870899d7bcdef6665d57bacd4e558f
+Payload = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f9
+CT = 3f3db715e088ac4a39f557a300b4673996bec3c3129dec22288aecb4c38c2391c21d
+
+Count = 32
+Adata = 3a54d3e14bbd0549570ef12425c4b36fd25382d56b68e217bc711ab1625fe9bb
+Payload = e5151262cafdd2f4dea187372dacb9e5975065572446f2a5
+CT = 18b185e1a8f65b3ce979aa5e8c621955b76da8572456c97edb4bd2cb1f1222e0d64f
+
+Count = 33
+Adata = 5c7604f9ac8fdf30ee5820e5aeb75b65d7855e5d2ff9ccf021640707bf1f53e8
+Payload = 1fe786f52daab92a6aa5f43263bed74153d90579a34bceff
+CT = e24311764fa130e25d7dd95bc27077f173e4c879a35bf5249283c1a61e9113462325
+
+Count = 34
+Adata = 42b8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+Payload = 56c3130c5af210b5bcf7c58b968fc75fc92b9c339efb7aee
+CT = ab67848f38f9997d8b2fe8e2374167efe91651339eeb4135bd3ffe1b1051ec3206db
+
+Count = 35
+Adata = c5a369a8291f4278e797ff11ea5e777d69df3b9c0c32d46150ed4b3e2c3defdd
+Payload = daa716f3cd1e008b46318ec90d976c3fbf88c3ff73cf0052
+CT = 27038170af15894371e9a3a0ac59cc8f9fb50eff73df3b8910d5d255f193b29eb961
+
+Count = 36
+Adata = 63bdceb36a032d3e0e81b4e98ad9861e2c708cef4e870c5b88a87ecc24449be3
+Payload = 42477d7d44881dabccfce52efb8a2cc917b182a23b71fb49
+CT = bfe3eafe26839463fb24c8475a448c79378c4fa23b61c0924e524729fb06212508e6
+
+Count = 37
+Adata = b7f8e7b66726e07c3c73d74135f068bb8025c9da9ba70affb9ed9a69675f0eef
+Payload = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c9309
+CT = fa501b5f70a1aed9a865d0cd4dc96ed048f4e6a7ba8ca8d2222af86d91fb6a2b09d3
+
+Count = 38
+Adata = 09891ed14f4488069cd6a5744061e06f8ff8d1bc87b10448b3fbfc1a4e327787
+Payload = e2e7002b769fb5b4201053457158147d99b0d5147f3acac2
+CT = 1f4397a814943c7c17c87e2cd096b4cdb98d18147f2af1194cddcb65a76c40698017
+
+Count = 39
+Adata = 8f9786940943752c536548497f9dae2bd8d677b8bbcb0121a9c9f3c399b62e4b
+Payload = 86be1d1949fe03b8b80ef7abb3e27394273d7b76d7697f0e
+CT = 7b1a8a9a2bf58a708fd6dac2122cd3240700b676d77944d5ddb42d504b6fc47d6575
+
+[Tlen = 12]
+
+Key = 7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d
+Nonce = dde2a362ce81b2b6913abc3095
+
+Count = 40
+Adata = 404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695
+Payload = 7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb
+CT = 353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd2927a053c9244d3217a7ad05
+
+Count = 41
+Adata = e9ed05813262fbe769c1104d8ba5c836dbd229a22a681de3565d17ac1129f96b
+Payload = fdf5a5fb377bb52ad07a971c6a9da3e1a68d279be9ac4ed7
+CT = b67b754b5fc1c80d23f26f5e6f5df9ee9880de7b69d2e3c11c000c9d88f047ca198c4e65
+
+Count = 42
+Adata = f246f1e948c81c98ea13f03dd8eea878449d0c3d5b5fe87c633bbe0106fcb899
+Payload = e5e6b57e74ce7afbde3697e2a69d61ca615aa3dfd32fe31f
+CT = ae6865ce1c7407dc2dbe6fa0a35d3bc55f575a3f53514e095c09878f1a963b795b29f4dd
+
+Count = 43
+Adata = e4683285695348ff04a61d51d90b868dfe4cf6ea246544727adeaeface571d57
+Payload = ef2c3a6bb8602d290045854a5f223e6f43bfd0bb9278fa88
+CT = a4a2eadbd0da500ef3cd7d085ae264607db2295b1206579e807d196d2628df1c384816f7
+
+Count = 44
+Adata = 42695369dbd69f07b46db282653704c34106aad82efdcc99b452598b5353f904
+Payload = beda29c7fe15c73ee5bef96485eb8c9e3cd3ea7ee633ef45
+CT = f554f97796afba1916360126802bd69102de139e664d4253961c666279394e1e28cf1b02
+
+Count = 45
+Adata = 58c3ce3906633475441229cfcdf05e02ff3738ae8d1b255974f431b3309ed41e
+Payload = 419c96ba8142b27e3377716358c97a8a636d7fe8403165e1
+CT = 0a12460ae9f8cf59c0ff89215d0920855d608608c04fc8f764efe624dd6c6f8b8cdc76e3
+
+Count = 46
+Adata = a9c06d8029f8da31629c3a6ddceb6009220a69fc614af1c231ae8702b3a85d6e
+Payload = 69bb441a7640f77e124d66af45a0e9f646658a838dfcb957
+CT = 223594aa1efa8a59e1c59eed4060b3f9786873630d8214410ef4b71970b9f80087533cf7
+
+Count = 47
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = a45b755658d38bdea57d1faae21d75428a17f2c74a33d2d5
+CT = efd5a5e63069f6f956f5e7e8e7dd2f4db41a0b27ca4d7fc36e27dfbf1ff7f08d1b213848
+
+Count = 48
+Adata = 421533453c8129fc8e681c68b9d7371adb0a19442ede7accd185129fcb7db648
+Payload = 2c3e28b61cede08121e80ee08c4f1f19dabb19add9d2dc8a
+CT = 67b0f80674579da6d260f6a2898f4516e4b6e04d59ac719ca48d1a0b815139fa28652d94
+
+Count = 49
+Adata = 55351bc7ddbc6b668d435088f1f9cf6f53caae16d4292b14bc0deec20f393ba0
+Payload = 81fa7fd41ba267bcbdf024cef1543b041cadd96b62a7cf1f
+CT = ca74af6473181a9b4e78dc8cf494610b22a0208be2d962091301c87a2a94df147c8cce4c
+
+[Tlen = 14]
+
+Key = 5c8b59d3e7986c277d5ad51e4a2233251076809ebf59463f47cd10b4aa951f8c
+Nonce = 21ff892b743d661189e205c7f3
+
+Count = 50
+Adata = f1e0af185180d2eb63e50e37ba692647cac2c6a149d70c81dbd34685ed78feaa
+Payload = 138ee53b1914d3322c2dd0a4e02faab2236555131d5eea08
+CT = 5b2f3026f30fdd50accc40ddd093b7997f23d7c6d3c8bc425f82c828413643b8794494cb5236
+
+Count = 51
+Adata = 45c5c284836414407268d7c8a89a0146759cfc92242004027d58d0828fad74e7
+Payload = fe3df84ee9b237f9edd77a5b8af96bc3e184579ac9c6e246
+CT = b69c2d5303a9399b6d36ea22ba4576e8bdc2d54f0750b40c6db5c92de5fb3aafba9537795e17
+
+Count = 52
+Adata = a41ea42692eac0914fef35e58409007342cef027de141223ffb46da7f58df034
+Payload = e0f5c02f9f84e57fada3f3575f1b1a748f360e0ea781b7b8
+CT = a8541532759feb1d2d42632e6fa7075fd3708cdb6917e1f21af6cf931ac943fd3affa6ad6fd1
+
+Count = 53
+Adata = 17dae00f2a9417780ecfef98f290a5ca9b17c873a9149cd81c18bd33164a0405
+Payload = 3a77a2ec5a1be6cbfbbfaab3e65427cb38d6798b132ff5c7
+CT = 72d677f1b000e8a97b5e3acad6e83ae06490fb5eddb9a38d38a3f09c56ae653be49b355fb938
+
+Count = 54
+Adata = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda2749b42f00744e50
+Payload = d0628b26019dad84de628d9dabf42cfb195165a369c22b49
+CT = 98c35e3beb86a3e65e831de49b4831d04517e776a7547d03974deec7ce2e1f296890bee795cb
+
+Count = 55
+Adata = f4fc5acff75d404849675b813cf7adcaeb8f3d56cb9a54a083f8ec07feb666bb
+Payload = 10b5ec41036e4bc5d61728e8811b520b7080c2177c122cbd
+CT = 5814395ce97545a756f6b891b1a74f202cc640c2b2847af798a3bc56f900bee7e8271c6dab22
+
+Count = 56
+Adata = ba051d1bc19b9a27520834fa3977b6413a319c9a52c8785e3e9594bd4265d911
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = 2c2b519cd6b2748dca56713ade95b1921a7e04b53f18e03be6623d80c677633a9e4f999bb885
+
+Count = 57
+Adata = f5c629299d18901c8c34c42e8fc29a70c377c160fdea4a6068a36867707575f7
+Payload = 3ead49ed0b41de79c829098d034b666bce052d79bf1f56db
+CT = 760c9cf0e15ad01b48c899f433f77b409243afac71890091c65b88ff4fdd9b8187f7d71ba04b
+
+Count = 58
+Adata = da486fd2953a72838e67e1909ed4042df67c355b648a45bcd2cc1ba610659e76
+Payload = 4543457c8fdf463c4bf8515a762cdc83d9aaa887d3eaa2af
+CT = 0de2906165c4485ecb19c1234690c1a885ec2a521d7cf4e5727c3404564ed41528973d389c7c
+
+Count = 59
+Adata = a0b1d3600f6eba910a11537d61fa12184959f1c3ae386570cbbc9106f7a7ba07
+Payload = 22071ef5d204417f99bc2faf53ecc4c6cf795e77805633ee
+CT = 6aa6cbe8381f4f1d195dbfd66350d9ed933fdca24ec065a446ecb536703a7a97928f80fcc7cf
+
+[Tlen = 16]
+
+Key = 60823b64e0b2da3a7eb772bd5941c534e6ff94ea96b564e2b38f82c78bb54522
+Nonce = 48526f1bffc97dd65e42906983
+
+Count = 60
+Adata = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Payload = a8be794613835c4366e75817d228438f011a2ec8a86f9797
+CT = cc3efe04d84a4ec5cb6a6c28dc2c2d386a359d9550dbdec963ddd56464aed6d0613159d1aa181dcb
+
+Count = 61
+Adata = b3ff11e57eeab41bc597622c770c9eea333e178d5bd5689c6a30011187a965b8
+Payload = 7590769380dc91832da023798dfdd447b9f7adaa09d7e2d0
+CT = 1110f1d14b158305802d174683f9baf0d2d81ef7f163ab8e7c1273765bc5bfdeca429cc8ebd8aca2
+
+Count = 62
+Adata = 2a953a081c5d52bc500c9c12f56cd2aab5c920d73098335baa5d947100cb3411
+Payload = 30e4de5e8c275677f8f4f7bbf9d101f96b38d79968ea028c
+CT = 5464591c47ee44f15579c384f7d56f4e001764c4905e4bd2886229c09b986bee3a8a3025c150d3a3
+
+Count = 63
+Adata = 99cc9d1b3db79640dfdc4423af3ded03c329f7ba5b6b509269c10e59519053b8
+Payload = 852698f6ab4aa794b3d657c4a2ca7b9c8bfb5fc9b4ad0aca
+CT = e1a61fb46083b5121e5b63fbacce152be0d4ec944c19439480cd04041918c4071ea5ac263f36c544
+
+Count = 64
+Adata = b76aef71eaf03c2d0dc0623e90596fcb0bc4dbbed1d5bb24c8af37d778863e5b
+Payload = cd337fcf362d301d66916c7097bdeb31df8206e00f7ac106
+CT = a9b3f88dfde4229bcb1c584f99b98586b4adb5bdf7ce8858f001d6002eafaec49c472acdfaedf1de
+
+Count = 65
+Adata = 42a718d892e229a1807b74bd730fb15500ac4a790392100aef362cd7628d5806
+Payload = 0041a0cf48fcf870b21db6107cfd9ef91e409afc7562ffa7
+CT = 64c1278d8335eaf61f90822f72f9f04e756f29a18dd6b6f975d86cde91b6610496c3bb5276238741
+
+Count = 66
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = fcc74ef1908dbcab9b05c76ee5a9941cdef933d433c0d25f
+CT = 9847c9b35b44ae2d3688f351ebadfaabb5d68089cb749b01db7d9f10e75d1b213beae0e0230dd82b
+
+Count = 67
+Adata = d330fc1ca406dd9528e9281aa1a3cdf013b698c14a4e55371e7539c9f6867dd4
+Payload = 611dade00cec14743be4e035cafe7507df5fb94b278875b1
+CT = 059d2aa2c72506f29669d40ac4fa1bb0b4700a16df3c3cefc63ba64291e73e6349ed089a53564291
+
+Count = 68
+Adata = 06bbadd5d22d1796d88415d7a4b024313f243bd0f58aafc75bb554a691d7e54f
+Payload = b67b5dd7f90ecd48a45853cb193e0d9702d78898f07e831d
+CT = d2fbda9532c7dfce09d567f4173a632069f83bc508caca43ac4d7bd964a2f9e2303df688dd0513da
+
+Count = 69
+Adata = 54da66d406f2d98edd999b673ef44d46ffd196091c8b7582ac2ed6bf13dc648f
+Payload = d092dc436c41836bdb815e473bc6a1906f37624e73b494f9
+CT = b4125b01a78891ed760c6a7835c2cf270418d1138b00dda7b4cd237cd9a7c9d93b9cc0f171818dae
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip
new file mode 100644
index 0000000000..34bb67b1ac
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip
Binary files differ
diff --git a/lib/crypto/test/crypto_bench.spec b/lib/crypto/test/crypto_bench.spec
new file mode 100644
index 0000000000..b9a26d94db
--- /dev/null
+++ b/lib/crypto/test/crypto_bench.spec
@@ -0,0 +1,3 @@
+{suites, "../crypto_test", [
+ crypto_bench_SUITE
+ ]}.
diff --git a/lib/crypto/test/crypto_bench_SUITE.erl b/lib/crypto/test/crypto_bench_SUITE.erl
new file mode 100644
index 0000000000..c66a27f0c8
--- /dev/null
+++ b/lib/crypto/test/crypto_bench_SUITE.erl
@@ -0,0 +1,400 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(crypto_bench_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct_event.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+suite() -> [%%{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]},
+ {timetrap,{minutes,2}}
+ ].
+
+all() ->
+ [
+ {group, textblock_256}
+ ].
+
+groups() ->
+ [
+ {textblock_256, [], [
+ {group, ciphers_128},
+ {group, ciphers_256}
+ ]},
+
+ {ciphers_128, [{repeat, 5}], [
+ block,
+ stream
+ ]},
+
+ {ciphers_256, [{repeat, 5}], [
+ block,
+ stream,
+ chacha
+ ]}
+ ].
+
+%%%----------------------------------------------------------------
+%%%
+init_per_suite(Config0) ->
+ try crypto:start() of
+ _ ->
+ [{_,_,Info}] = crypto:info_lib(),
+ ct:comment("~s",[Info]),
+ ct:pal("Crypto version: ~p~n~n~p",[Info,crypto:supports()]),
+ Config1 = measure_openssl_aes_cbc([128,256], Config0),
+ calibrate([{sec_goal,10} | Config1])
+
+ catch _:_ ->
+ {fail, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ application:stop(crypto).
+
+%%%----------------------------------------------------------------
+%%%
+init_per_group(Group, Config) ->
+ case atom_to_list(Group) of
+ "ciphers_"++KeySizeStr ->
+ KeySize = list_to_integer(KeySizeStr),
+ [{key_size,KeySize} | Config];
+
+ "textblock_"++BlockSizeStr ->
+ BlockSize = list_to_integer(BlockSizeStr),
+ [{block_size,BlockSize} | Config];
+
+ _ ->
+ Config
+ end.
+
+end_per_group(_Group, Config) ->
+ Config.
+
+
+measure_openssl_aes_cbc(KeySizes, Config) ->
+ BLno_acc = [baseline(aes_cbc, KeySize, false) || KeySize <- KeySizes],
+ ct:pal("Non-accelerated baseline encryption time [µs/block]:~n~p", [BLno_acc]),
+ BLacc = [baseline(aes_cbc, KeySize, true) || KeySize <- KeySizes],
+ ct:pal("Possibly accelerated baseline encryption time [µs/block]:~n~p", [BLacc]),
+ [{acc,BLacc},
+ {no_acc,BLno_acc} | Config].
+
+calibrate(Config) ->
+ Secs = proplists:get_value(sec_goal, Config, 10),
+ {_,Empty} = data(empty, 0, 0),
+ {Ne,Te} = run1(Secs*3000, Empty),
+ report(["Overhead"], Te/Ne),
+ [{overhead,Te/Ne} | Config].
+
+%%%================================================================
+%%%
+%%%
+block(Config) ->
+ run_cryptos([aes_cbc, aes_gcm, aes_ccm],
+ Config).
+
+stream(Config) ->
+ run_cryptos([aes_ctr],
+ Config).
+
+chacha(Config) ->
+ run_cryptos([chacha20, chacha20_poly1305],
+ Config).
+
+
+%%%================================================================
+%%%
+%%%
+
+run_cryptos(Cryptos, Config) ->
+ KeySize = proplists:get_value(key_size, Config),
+ BlockSize = proplists:get_value(block_size, Config),
+ MilliSecGoal = 1000*proplists:get_value(sec_goal,Config),
+ OverHead = proplists:get_value(overhead, Config, 0),
+ [try
+ TimePerOpBrutto = run(Crypto,KeySize,BlockSize,MilliSecGoal),
+ %% ct:pal("Brutto: ~p Overhead: ~p (~.2f %) Netto: ~p",
+ %% [TimePerOpBrutto, OverHead, 100*OverHead/TimePerOpBrutto,TimePerOpBrutto - OverHead]),
+ TimePerOpBrutto - OverHead
+ of
+ TimePerOp -> % µs
+ %% First, Report speed of encrypting blocks of 1000. [blocks/sec]
+ ReportUnit = 1000,
+ Label = [fmt(Crypto)," key:",KeySize," block:",BlockSize],
+ report(Label,
+ (BlockSize/ReportUnit)*1000000/TimePerOp
+ ),
+
+ EffCrypto = case Crypto of
+ X -> X
+ end,
+ %% Percent of accelerated speed
+ case find_value([acc,{EffCrypto,KeySize},BlockSize], Config) of
+ undefined ->
+ ok;
+ TimePerOpBaseAcc ->
+ report(["Percent of acc OpenSSL "|Label],
+ 100*TimePerOpBaseAcc/TimePerOp % Percent of base *speed*
+ )
+ end,
+
+ %% Percent of non-accelerated speed
+ case find_value([no_acc,{EffCrypto,KeySize},BlockSize], Config) of
+ undefined ->
+ ok;
+ TimePerOpBaseNoAcc ->
+ report(["Percent of noacc OpenSSL "|Label],
+ 100*TimePerOpBaseNoAcc/TimePerOp % Percent of base *speed*
+ )
+ end
+ catch
+ _:_ ->
+ ct:pal("~p unsupported",[{Crypto,KeySize,BlockSize}])
+ end
+ || Crypto <- Cryptos,
+ supported(Crypto)
+ ].
+
+
+run(Crypto, KeySize, BlockSize, MilliSecGoal) ->
+ {_Type, Funs} = data(Crypto, KeySize, BlockSize),
+ {Nc,Tc} = run1(MilliSecGoal, Funs),
+ Tc/Nc.
+
+fmt(X) -> X.
+
+
+find_value(KeyPath, PropList, Default) ->
+ try find_value(KeyPath, PropList)
+ of
+ undefined -> Default
+ catch
+ error:function_clause -> Default
+ end.
+
+find_value(KeyPath, PropList) ->
+ lists:foldl(fun(K, L) when is_list(L) -> proplists:get_value(K,L);
+ (_, _) -> undefined
+ end, PropList, KeyPath).
+
+%%%================================================================
+%%%
+%%%
+funs({block, {Type, Key, IV, Block}}) ->
+ {fun() -> ok end,
+ fun(_) -> crypto:block_encrypt(Type, Key, IV, Block) end,
+ fun(_) -> ok end};
+
+funs({stream, {Type, Key, IV, Block}}) ->
+ {fun() -> {crypto:stream_init(Type, Key, IV),ok} end,
+ fun({Ctx,_}) -> crypto:stream_encrypt(Ctx, Block) end,
+ fun(_) -> ok end}.
+
+
+data(aes_cbc, KeySize, BlockSize) ->
+ Type = case KeySize of
+ 128 -> aes_cbc128;
+ 256 -> aes_cbc256
+ end,
+ Key = mk_bin(KeySize div 8),
+ IV = mk_bin(16),
+ Block = mk_bin(BlockSize),
+ {Type, funs({block, {Type, Key, IV, Block}})};
+
+data(aes_gcm, KeySize, BlockSize) ->
+ Type = aes_gcm,
+ Key = mk_bin(KeySize div 8),
+ IV = mk_bin(12),
+ Block = mk_bin(BlockSize),
+ AAD = <<01,02,03,04>>,
+ {Type, funs({block, {Type, Key, IV, {AAD,Block,16}}})};
+
+data(aes_ccm, KeySize, BlockSize) ->
+ Type = aes_ccm,
+ Key = mk_bin(KeySize div 8),
+ IV = mk_bin(12),
+ Block = mk_bin(BlockSize),
+ AAD = <<01,02,03,04>>,
+ {Type, funs({block, {Type, Key, IV, {AAD,Block,12}}})};
+
+data(aes_ctr, KeySize, BlockSize) ->
+ Type = aes_ctr,
+ Key = mk_bin(KeySize div 8),
+ IV = mk_bin(16),
+ Block = mk_bin(BlockSize),
+ {Type, funs({stream, {Type, Key, IV, Block}})};
+
+data(chacha20_poly1305, 256=KeySize, BlockSize) ->
+ Type = chacha20_poly1305,
+ Key = mk_bin(KeySize div 8),
+ IV = mk_bin(16),
+ AAD = <<01,02,03,04>>,
+ Block = mk_bin(BlockSize),
+ {Type, funs({block, {Type, Key, IV, {AAD,Block}}})};
+
+data(chacha20, 256=KeySize, BlockSize) ->
+ Type = chacha20,
+ Key = mk_bin(KeySize div 8),
+ IV = mk_bin(16),
+ Block = mk_bin(BlockSize),
+ {Type, funs({stream, {Type, Key, IV, Block}})};
+
+data(empty, 0, 0) ->
+ {undefined,
+ {fun() -> ok end,
+ fun(X) -> X end,
+ fun(_) -> ok end}}.
+
+%%%================================================================
+%%%
+%%%
+run1(MilliSecGoal, Funs) ->
+ Parent = self(),
+ Pid = spawn(fun() ->
+ {Fi,Fu,Ff} = Funs,
+ Ctx0 = Fi(),
+ erlang:garbage_collect(),
+ T0 = start_time(),
+ {N,Ctx} = loop(Fu, Ctx0, 0),
+ T = elapsed_time(T0),
+ Ff(Ctx),
+ Parent ! {result,N,microseconds(T)}
+ end),
+ Pid ! go,
+ receive
+ after MilliSecGoal ->
+ Pid ! stop
+ end,
+ receive
+ {result,N,MicroSecs} ->
+ {N,MicroSecs}
+ end.
+
+
+loop(F, Ctx, N) ->
+ receive
+ stop ->
+ {N, Ctx}
+ after 0 ->
+ loop(F, F(Ctx), N+1)
+ end.
+
+%%%----------------------------------------------------------------
+report(LabelList, Value) ->
+ Label = report_chars(lists:concat(LabelList)),
+ ct:pal("ct_event:notify ~p: ~p", [Label, Value]),
+ ct_event:notify(
+ #event{name = benchmark_data,
+ data = [{name, Label},
+ {value,Value}]}).
+
+report_chars(Cs) ->
+ [case C of
+ $- -> $_;
+ _ -> C
+ end || C <- Cs].
+
+%%%----------------------------------------------------------------
+supported(Algorithm) ->
+ lists:member(Algorithm,
+ [A || {_,As} <- crypto:supports(), A <- As]
+ ).
+
+%%%----------------------------------------------------------------
+start_time() ->
+ erlang:system_time().
+
+elapsed_time(StartTime) ->
+ erlang:system_time() - StartTime.
+
+microseconds(Time) ->
+ erlang:convert_time_unit(Time, native, microsecond).
+
+%%%----------------------------------------------------------------
+
+%% Example output:
+%% +DT:aes-128-cbc:3:16
+%% +R:135704772:aes-128-cbc:2.980000
+%% +DT:aes-128-cbc:3:64
+%% +R:36835089:aes-128-cbc:3.000000
+%% +DT:aes-128-cbc:3:256
+%% +R:9398616:aes-128-cbc:3.000000
+%% +DT:aes-128-cbc:3:1024
+%% +R:2355683:aes-128-cbc:2.990000
+%% +DT:aes-128-cbc:3:8192
+%% +R:294508:aes-128-cbc:2.990000
+%% +H:16:64:256:1024:8192
+%% +F:22:aes-128-cbc:728616225.50:785815232.00:802015232.00:806762338.46:806892821.40
+
+baseline(Crypto, KeySize, EVP) ->
+ Spec=
+ case {Crypto,KeySize} of
+ {aes_cbc, 128} -> "aes-128-cbc";
+ {aes_cbc, 256} -> "aes-256-cbc"
+ end,
+ {{Crypto,KeySize}, baseline(Spec, EVP)}.
+
+baseline(Spec, EVP) ->
+ Cmd =
+ case EVP of
+ true -> "openssl speed -mr -evp " ++ Spec;
+ false-> "openssl speed -mr " ++ Spec
+ end,
+ get_base_values(string:tokens(os:cmd(Cmd),"\n"), Spec, []).
+
+
+get_base_values(["+DT:"++Sdt,
+ "+R:"++Sr
+ |T], Crypto, Acc) ->
+ [Crypto0,_GoalSecs0,BlockSize0] = string:tokens(Sdt, ":"),
+ [Nblocks0,Crypto0,RealSecs0] = string:tokens(Sr, ":"),
+ Crypto = fix_possible_space_bug(Crypto0),
+ RealSecs = list_to_float(RealSecs0),
+ BlockSize = list_to_integer(BlockSize0),
+ Nblocks = list_to_integer(Nblocks0),
+ get_base_values(T, Crypto, [{BlockSize, 1000000*RealSecs/Nblocks} | Acc]);
+
+get_base_values([_|T], Crypto, Acc) ->
+ get_base_values(T, Crypto, Acc);
+
+get_base_values([], _, Acc) ->
+ lists:sort(Acc).
+
+fix_possible_space_bug(S) -> lists:concat(lists:join("-",string:tokens(S,"- "))).
+
+%%%----------------------------------------------------------------
+mk_bin(Size) when Size =< 256 ->
+ list_to_binary(lists:seq(0,Size-1));
+
+mk_bin(Size) when 1024 =< Size ->
+ B = mk_bin(Size div 4),
+ Brest = mk_bin(Size rem 4),
+ <<B/binary, B/binary, B/binary, B/binary, Brest/binary>>;
+
+mk_bin(Size) when 256 < Size ->
+ B = mk_bin(Size div 2),
+ Brest = mk_bin(Size rem 2),
+ <<B/binary, B/binary, Brest/binary>>.
+
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
index f708d7272d..869db516b4 100644
--- a/lib/crypto/test/engine_SUITE.erl
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -39,6 +39,10 @@ all() ->
get_all_possible_methods,
engine_load_all_methods,
engine_load_some_methods,
+ multiple_engine_load,
+ engine_list,
+ get_id_and_name,
+ engine_by_id,
bad_arguments,
unknown_engine,
pre_command_fail_bad_value,
@@ -46,12 +50,15 @@ all() ->
failed_engine_init,
ctrl_cmd_string,
ctrl_cmd_string_optional,
- {group, engine_stored_key}
+ ensure_load,
+ {group, engine_stored_key},
+ {group, engine_fakes_rsa}
].
groups() ->
[{engine_stored_key, [],
- [sign_verify_rsa,
+ [
+ sign_verify_rsa,
sign_verify_dsa,
sign_verify_ecdsa,
sign_verify_rsa_pwd,
@@ -66,15 +73,25 @@ groups() ->
get_pub_from_priv_key_rsa_pwd_bad_pwd,
get_pub_from_priv_key_dsa,
get_pub_from_priv_key_ecdsa
- ]}].
+ ]},
+ {engine_fakes_rsa, [], [sign_verify_rsa_fake
+ ]}
+ ].
init_per_suite(Config) ->
- case crypto:info_lib() of
- [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}] ->
+ case {os:type(), crypto:info_lib()} of
+ {_, [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}]} ->
{skip, "Problem with engine on OpenSSL 1.0.1s-freebsd"};
- Res ->
- ct:log("crypto:info_lib() -> ~p\n", [Res]),
+
+ {{unix,darwin}, _} ->
+ {skip, "Engine unsupported on Darwin"};
+
+ {{win32,_}, _} ->
+ {skip, "Engine unsupported on Windows"};
+
+ {OS, Res} ->
+ ct:log("crypto:info_lib() -> ~p\nos:type() -> ~p", [Res,OS]),
try crypto:start() of
ok ->
Config;
@@ -90,32 +107,45 @@ end_per_suite(_Config) ->
%%--------------------------------------------------------------------
init_per_group(engine_stored_key, Config) ->
- case load_storage_engine(Config) of
+ group_load_engine(Config, [engine_method_rsa]);
+init_per_group(engine_fakes_rsa, Config) ->
+ case crypto:info_lib() of
+ [{<<"OpenSSL">>,LibVer,_}] when is_integer(LibVer), LibVer >= 16#10100000 ->
+ group_load_engine(Config, []);
+ _ ->
+ {skip, "Too low OpenSSL cryptolib version"}
+ end;
+init_per_group(_Group, Config0) ->
+ Config0.
+
+
+group_load_engine(Config, ExcludeMthds) ->
+ case load_storage_engine(Config, ExcludeMthds) of
{ok, E} ->
KeyDir = key_dir(Config),
[{storage_engine,E}, {storage_dir,KeyDir} | Config];
{error, notexist} ->
{skip, "OTP Test engine not found"};
{error, notsup} ->
- {skip, "Engine not supported on this OpenSSL version"};
+ {skip, "Engine not supported on this SSL version"};
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"};
Other ->
ct:log("Engine load failed: ~p",[Other]),
{fail, "Engine load failed"}
- end;
-init_per_group(_Group, Config0) ->
- Config0.
+ end.
+
-end_per_group(engine_stored_key, Config) ->
+
+
+
+end_per_group(_, Config) ->
case proplists:get_value(storage_engine, Config) of
undefined ->
ok;
E ->
ok = crypto:engine_unload(E)
- end;
-end_per_group(_, _) ->
- ok.
+ end.
%%--------------------------------------------------------------------
init_per_testcase(_Case, Config) ->
@@ -132,11 +162,12 @@ get_all_possible_methods() ->
get_all_possible_methods(Config) when is_list(Config) ->
try
List = crypto:engine_get_all_methods(),
+ true = erlang:is_list(List),
ct:log("crypto:engine_get_all_methods() -> ~p\n", [List]),
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
engine_load_all_methods()->
@@ -149,13 +180,12 @@ engine_load_all_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
{ok, E} ->
@@ -181,7 +211,7 @@ engine_load_all_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -195,21 +225,20 @@ engine_load_some_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
EngineMethods = crypto:engine_get_all_methods() --
- [engine_method_dh,engine_method_rand,
+ [engine_method_dh, engine_method_rand,
engine_method_ciphers, engine_method_store,
engine_method_pkey_meths, engine_method_pkey_asn1_meths],
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[],
EngineMethods) of
- {ok, E} ->
+ {ok, E} ->
case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
ct:fail(fail_to_load_engine_still_original);
@@ -232,7 +261,168 @@ engine_load_some_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+multiple_engine_load()->
+ [{doc, "Use a dummy md5 engine that does not implement md5"
+ "but rather returns a static binary to test that crypto:engine_load "
+ "functions works when called multiple times."}].
+
+multiple_engine_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ {ok, E1} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ {ok, E2} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E2),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E1),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_list()->
+ [{doc, "Test add and remove engine ID to the SSL internal engine list."}].
+
+engine_list(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ EngineList0 = crypto:engine_list(),
+ false = lists:member(<<"MD5">>, EngineList0),
+ ok = crypto:engine_add(E),
+ [<<"MD5">>] = lists:subtract(crypto:engine_list(), EngineList0),
+ ok = crypto:engine_remove(E),
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+get_id_and_name()->
+ [{doc, "Test fetching id and name from an engine."}].
+
+get_id_and_name(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ <<"MD5">> = crypto:engine_get_id(E),
+ <<"MD5 test engine">> = crypto:engine_get_name(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_by_id()->
+ [{doc, "Test fetching a new reference the the engine when the"
+ "engine id is added to the SSL engine list."}].
+
+engine_by_id(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_by_id(<<"MD5">>) of
+ {error,bad_engine_id} ->
+ ok;
+ {ok, _} ->
+ ct:fail(fail_engine_found)
+ end,
+ ok = crypto:engine_add(E),
+ {ok, _E1} = crypto:engine_by_id(<<"MD5">>),
+ ok = crypto:engine_remove(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -246,9 +436,12 @@ bad_arguments(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
try
crypto:engine_load(fail_engine, [], [])
+ of
+ X1 ->
+ ct:fail("1 Got ~p",[X1])
catch
error:badarg ->
ok
@@ -260,6 +453,11 @@ bad_arguments(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[])
+ of
+ {error,bad_engine_id} ->
+ throw(dynamic_engine_unsupported);
+ X2 ->
+ ct:fail("2 Got ~p",[X2])
catch
error:badarg ->
ok
@@ -270,13 +468,20 @@ bad_arguments(Config) when is_list(Config) ->
{'ID', <<"MD5">>},
<<"LOAD">>],
[])
+ of
+ {error,bad_engine_id} -> % should have happend in the previous try...catch end!
+ throw(dynamic_engine_unsupported);
+ X3 ->
+ ct:fail("3 Got ~p",[X3])
catch
error:badarg ->
ok
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"};
+ throw:dynamic_engine_unsupported ->
+ {skip, "Dynamic Engine not supported"}
end
end.
@@ -289,7 +494,7 @@ unknown_engine(Config) when is_list(Config) ->
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_value() ->
@@ -311,7 +516,7 @@ pre_command_fail_bad_value(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_key() ->
@@ -334,9 +539,9 @@ pre_command_fail_bad_key(Config) when is_list(Config) ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
failed_engine_init()->
@@ -352,18 +557,20 @@ failed_engine_init(Config) when is_list(Config) ->
[{<<"SO_PATH">>, Engine},
{<<"ID">>, <<"MD5">>}],
[]) of
- {error, add_engine_failed} ->
+ {error, engine_init_failed} ->
ok;
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
+%% Test the optional flag in ctrl comands
ctrl_cmd_string()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
ctrl_cmd_string(Config) when is_list(Config) ->
@@ -377,22 +584,22 @@ ctrl_cmd_string(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {ok, E} ->
case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>) of
ok ->
+ ok = crypto:engine_unload(E),
ct:fail(fail_ctrl_cmd_should_fail);
- {error,ctrl_cmd_failed} ->
- ok
- end,
- ok = crypto:engine_unload(E);
+ {error,ctrl_cmd_failed} ->
+ ok = crypto:engine_unload(E)
+ end;
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
ctrl_cmd_string_optional()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
@@ -407,22 +614,64 @@ ctrl_cmd_string_optional(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {ok, E} ->
case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>, true) of
ok ->
- ok;
- _ ->
+ ok = crypto:engine_unload(E);
+ Err ->
+ ct:log("Error: ~p",[Err]),
+ ok = crypto:engine_unload(E),
ct:fail(fail_ctrl_cmd_string)
- end,
- ok = crypto:engine_unload(E);
+ end;
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+ensure_load()->
+ [{doc, "Test the special ensure load function."}].
+
+ensure_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
+ {ok, E} ->
+ {ok, _E1} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:ensure_engine_unloaded(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
%%%----------------------------------------------------------------
%%% Pub/priv key storage tests. Thoose are for testing the crypto.erl
@@ -435,6 +684,14 @@ sign_verify_rsa(Config) ->
key_id => key_id(Config, "rsa_public_key.pem")},
sign_verify(rsa, sha, Priv, Pub).
+sign_verify_rsa_fake(Config) ->
+ %% Use fake engine rsa implementation
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key.pem")},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key.pem")},
+ sign_verify_fake(rsa, sha256, Priv, Pub).
+
sign_verify_dsa(Config) ->
Priv = #{engine => engine_ref(Config),
key_id => key_id(Config, "dsa_private_key.pem")},
@@ -467,7 +724,7 @@ sign_verify_rsa_pwd_bad_pwd(Config) ->
_ -> {fail, "PWD prot pubkey sign succeded with no pwd!"}
catch
error:badarg -> ok
- end.
+ end.
priv_encrypt_pub_decrypt_rsa(Config) ->
Priv = #{engine => engine_ref(Config),
@@ -540,7 +797,7 @@ get_pub_from_priv_key_rsa_pwd_no_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded although no pwd!"}
end.
@@ -556,7 +813,7 @@ get_pub_from_priv_key_rsa_pwd_bad_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded with bad pwd!"}
end.
@@ -590,17 +847,22 @@ get_pub_from_priv_key_ecdsa(Config) ->
ct:log("ecdsa Pub = ~p",[Pub]),
sign_verify(ecdsa, sha, Priv, Pub)
end.
-
+
%%%================================================================
%%% Help for engine_stored_pub_priv_keys* test cases
%%%
-load_storage_engine(_Config) ->
+load_storage_engine(Config) ->
+ load_storage_engine(Config, []).
+
+load_storage_engine(_Config, ExcludeMthds) ->
case crypto:get_test_engine() of
{ok, Engine} ->
try crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
<<"LOAD">>],
- [])
+ [],
+ crypto:engine_get_all_methods() -- ExcludeMthds
+ )
catch
error:notsup ->
{error, notsup}
@@ -658,10 +920,47 @@ sign_verify(Alg, Sha, KeySign, KeyVerify) ->
true ->
PlainText = <<"Hej på dig">>,
Signature = crypto:sign(Alg, Sha, PlainText, KeySign),
- case crypto:verify(Alg, Sha, PlainText, Signature, KeyVerify) of
- true -> ok;
- _ -> {fail, "Sign-verify error"}
+ case is_fake(Signature) of
+ true ->
+ ct:pal("SIG ~p ~p size ~p~n~p",[Alg,Sha,size(Signature),Signature]),
+ {fail, "Faked RSA impl used!!"};
+ false ->
+ case crypto:verify(Alg, Sha, PlainText, Signature, KeyVerify) of
+ true -> ok;
+ _ -> {fail, "Sign-verify error"}
+ end
end;
false ->
{skip, lists:concat([Alg," is not supported by cryptolib"])}
end.
+
+
+%%% Use fake engine rsa implementation
+sign_verify_fake(Alg, Sha, KeySign, KeyVerify) ->
+ case pubkey_alg_supported(Alg) of
+ true ->
+ PlainText = <<"Fake me!">>,
+ Signature = crypto:sign(Alg, Sha, PlainText, KeySign),
+ case is_fake(Signature) of
+ true ->
+ case crypto:verify(Alg, Sha, PlainText, Signature, KeyVerify) of
+ true -> ok;
+ _ -> {fail, "Sign-verify error"}
+ end;
+ false ->
+ ct:pal("SIG ~p ~p size ~p~n~p",[Alg,Sha,size(Signature),Signature]),
+ {fail, "Faked impl not used"}
+ end;
+ false ->
+ {skip, lists:concat([Alg," is not supported by cryptolib"])}
+ end.
+
+
+is_fake(Sig) -> is_fake(Sig, 0).
+
+is_fake(<<>>, _) -> true;
+is_fake(<<B,Rest/binary>>, B) -> is_fake(Rest, B+1);
+is_fake(_, _) -> false.
+
+
+
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index cc34c20ac6..0a3d9f45e4 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 4.3
+CRYPTO_VSN = 4.4.2
diff --git a/lib/debugger/doc/src/Makefile b/lib/debugger/doc/src/Makefile
index 4a25006ee0..49b5a4be57 100644
--- a/lib/debugger/doc/src/Makefile
+++ b/lib/debugger/doc/src/Makefile
@@ -99,6 +99,7 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
@@ -113,8 +114,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
$(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
$(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- ($(CP) -rf $(HTMLDIR) "$(RELSYSDIR)/doc")
+ $(INSTALL_DIR_DATA) $(HTMLDIR) "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
$(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
$(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
diff --git a/lib/debugger/doc/src/debugger.xml b/lib/debugger/doc/src/debugger.xml
index 1ecdbcd064..77285095e7 100644
--- a/lib/debugger/doc/src/debugger.xml
+++ b/lib/debugger/doc/src/debugger.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>debugger</module>
+ <module since="">debugger</module>
<modulesummary>Erlang Debugger.</modulesummary>
<description>
<p>Erlang Debugger for debugging and testing of Erlang programs.</p>
@@ -36,10 +36,10 @@
<funcs>
<func>
- <name>start()</name>
- <name>start(File)</name>
- <name>start(Mode)</name>
- <name>start(Mode, File)</name>
+ <name since="">start()</name>
+ <name since="">start(File)</name>
+ <name since="">start(Mode)</name>
+ <name since="">start(Mode, File)</name>
<fsummary>Start Debugger.</fsummary>
<type>
<v>Mode = local | global</v>
@@ -60,7 +60,7 @@
</func>
<func>
- <name>quick(Module, Name, Args)</name>
+ <name since="">quick(Module, Name, Args)</name>
<fsummary>Debug a process.</fsummary>
<type>
<v>Module = Name = atom()</v>
diff --git a/lib/debugger/doc/src/i.xml b/lib/debugger/doc/src/i.xml
index 628b91e9e4..06b0eb876a 100644
--- a/lib/debugger/doc/src/i.xml
+++ b/lib/debugger/doc/src/i.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>i</module>
+ <module since="">i</module>
<modulesummary>Debugger/Interpreter Interface.</modulesummary>
<description>
<p>The <c>i</c> module provides short forms for some of
@@ -51,7 +51,7 @@
<funcs>
<func>
- <name>im() -> pid()</name>
+ <name since="">im() -> pid()</name>
<fsummary>Start a graphical monitor.</fsummary>
<desc>
<p>Starts a new graphical monitor. This is the Monitor window,
@@ -63,10 +63,10 @@
</func>
<func>
- <name>ii(AbsModules) -> ok</name>
- <name>ii(AbsModule) -> {module, Module} | error</name>
- <name>ini(AbsModules) -> ok</name>
- <name>ini(AbsModule) -> {module, Module} | error</name>
+ <name since="">ii(AbsModules) -> ok</name>
+ <name since="">ii(AbsModule) -> {module, Module} | error</name>
+ <name since="">ini(AbsModules) -> ok</name>
+ <name since="">ini(AbsModule) -> {module, Module} | error</name>
<fsummary>Interpret a module.</fsummary>
<type>
<v>AbsModules = [AbsModule]</v>
@@ -84,8 +84,8 @@
</func>
<func>
- <name>iq(AbsModule) -> ok</name>
- <name>inq(AbsModule) -> ok</name>
+ <name since="">iq(AbsModule) -> ok</name>
+ <name since="">inq(AbsModule) -> ok</name>
<fsummary>Stop interpreting a module.</fsummary>
<type>
<v>AbsModule = Module | File</v>
@@ -100,7 +100,7 @@
</func>
<func>
- <name>il() -> ok</name>
+ <name since="">il() -> ok</name>
<fsummary>Make a printout of all interpreted modules</fsummary>
<desc>
<p>Makes a printout of all interpreted modules.
@@ -110,7 +110,7 @@
</func>
<func>
- <name>ip() -> ok</name>
+ <name since="">ip() -> ok</name>
<fsummary>Print the current status of all interpreted
processes.</fsummary>
<desc>
@@ -119,7 +119,7 @@
</func>
<func>
- <name>ic() -> ok</name>
+ <name since="">ic() -> ok</name>
<fsummary>Clear information about processes executing interpreted
code.</fsummary>
<desc>
@@ -129,8 +129,8 @@
</func>
<func>
- <name>iaa(Flags) -> true</name>
- <name>iaa(Flags, Function) -> true</name>
+ <name since="">iaa(Flags) -> true</name>
+ <name since="">iaa(Flags, Function) -> true</name>
<fsummary>Set when and how to attach to a process.</fsummary>
<type>
<v>Flags = [init | break | exit]</v>
@@ -148,7 +148,7 @@
</func>
<func>
- <name>ist(Flag) -> true</name>
+ <name since="">ist(Flag) -> true</name>
<fsummary>Set how to save call frames.</fsummary>
<type>
<v>Flag = all | no_tail | false</v>
@@ -160,7 +160,7 @@
</func>
<func>
- <name>ia(Pid) -> ok | no_proc</name>
+ <name since="">ia(Pid) -> ok | no_proc</name>
<fsummary>Attache to a process.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -172,7 +172,7 @@
</func>
<func>
- <name>ia(X,Y,Z) -> ok | no_proc</name>
+ <name since="">ia(X,Y,Z) -> ok | no_proc</name>
<fsummary>Attache to a process.</fsummary>
<type>
<v>X = Y = Z = int()</v>
@@ -184,7 +184,7 @@
</func>
<func>
- <name>ia(Pid, Function) -> ok | no_proc</name>
+ <name since="">ia(Pid, Function) -> ok | no_proc</name>
<fsummary>Attache to a process.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -199,7 +199,7 @@
</func>
<func>
- <name>ia(X,Y,Z, Function) -> ok | no_proc</name>
+ <name since="">ia(X,Y,Z, Function) -> ok | no_proc</name>
<fsummary>Attache to a process.</fsummary>
<type>
<v>X = Y = Z = int()</v>
@@ -217,7 +217,7 @@
</func>
<func>
- <name>ib(Module, Line) -> ok | {error, break_exists}</name>
+ <name since="">ib(Module, Line) -> ok | {error, break_exists}</name>
<fsummary>Create a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -229,7 +229,7 @@
</func>
<func>
- <name>ib(Module, Name, Arity) -> ok | {error, function_not_found}
+ <name since="">ib(Module, Name, Arity) -> ok | {error, function_not_found}
</name>
<fsummary>Create breakpoints in the specified function.</fsummary>
<type>
@@ -243,7 +243,7 @@
</func>
<func>
- <name>ir() -> ok</name>
+ <name since="">ir() -> ok</name>
<fsummary>Delete all breakpoints.</fsummary>
<desc>
<p>Deletes all breakpoints.</p>
@@ -251,7 +251,7 @@
</func>
<func>
- <name>ir(Module) -> ok</name>
+ <name since="">ir(Module) -> ok</name>
<fsummary>Delete all breakpoints in a module.</fsummary>
<type>
<v>Module = atom()</v>
@@ -262,7 +262,7 @@
</func>
<func>
- <name>ir(Module, Line) -> ok</name>
+ <name since="">ir(Module, Line) -> ok</name>
<fsummary>Delete a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -274,7 +274,7 @@
</func>
<func>
- <name>ir(Module, Name, Arity) -> ok | {error, function_not_found}
+ <name since="">ir(Module, Name, Arity) -> ok | {error, function_not_found}
</name>
<fsummary>Delete breakpoints from the specified function.</fsummary>
<type>
@@ -288,7 +288,7 @@
</func>
<func>
- <name>ibd(Module, Line) -> ok</name>
+ <name since="">ibd(Module, Line) -> ok</name>
<fsummary>Make a breakpoint inactive.</fsummary>
<type>
<v>Module = atom()</v>
@@ -300,7 +300,7 @@
</func>
<func>
- <name>ibe(Module, Line) -> ok</name>
+ <name since="">ibe(Module, Line) -> ok</name>
<fsummary>Make a breakpoint active.</fsummary>
<type>
<v>Module = atom()</v>
@@ -312,7 +312,7 @@
</func>
<func>
- <name>iba(Module, Line, Action) -> ok</name>
+ <name since="">iba(Module, Line, Action) -> ok</name>
<fsummary>Set the trigger action of a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -326,7 +326,7 @@
</func>
<func>
- <name>ibc(Module, Line, Function) -> ok</name>
+ <name since="">ibc(Module, Line, Function) -> ok</name>
<fsummary>Set the conditional test of a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -348,7 +348,7 @@
</func>
<func>
- <name>ipb() -> ok</name>
+ <name since="">ipb() -> ok</name>
<fsummary>Print all existing breakpoints.</fsummary>
<desc>
<p>Prints all existing breakpoints.</p>
@@ -356,7 +356,7 @@
</func>
<func>
- <name>ipb(Module) -> ok</name>
+ <name since="">ipb(Module) -> ok</name>
<fsummary>Print all existing breakpoints in a module.</fsummary>
<type>
<v>Module = atom()</v>
@@ -367,7 +367,7 @@
</func>
<func>
- <name>iv() -> atom()</name>
+ <name since="">iv() -> atom()</name>
<fsummary>Return the current version number of the interpreter.
</fsummary>
<desc>
@@ -377,7 +377,7 @@
</func>
<func>
- <name>help() -> ok</name>
+ <name since="">help() -> ok</name>
<fsummary>Print help text.</fsummary>
<desc>
<p>Prints help text.</p>
diff --git a/lib/debugger/doc/src/int.xml b/lib/debugger/doc/src/int.xml
index 31e9dfe923..a0078714e6 100644
--- a/lib/debugger/doc/src/int.xml
+++ b/lib/debugger/doc/src/int.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>int</module>
+ <module since="">int</module>
<modulesummary>Interpreter Interface.</modulesummary>
<description>
<p>The Erlang interpreter provides mechanisms for breakpoints and
@@ -94,10 +94,10 @@
<funcs>
<func>
- <name>i(AbsModule) -> {module,Module} | error</name>
- <name>i(AbsModules) -> ok</name>
- <name>ni(AbsModule) -> {module,Module} | error</name>
- <name>ni(AbsModules) -> ok</name>
+ <name since="">i(AbsModule) -> {module,Module} | error</name>
+ <name since="">i(AbsModules) -> ok</name>
+ <name since="">ni(AbsModule) -> {module,Module} | error</name>
+ <name since="">ni(AbsModules) -> ok</name>
<fsummary>Interpret a module.</fsummary>
<type>
<v>AbsModules = [AbsModule]</v>
@@ -144,8 +144,8 @@
</func>
<func>
- <name>n(AbsModule) -> ok</name>
- <name>nn(AbsModule) -> ok</name>
+ <name since="">n(AbsModule) -> ok</name>
+ <name since="">nn(AbsModule) -> ok</name>
<fsummary>Stop interpreting a module.</fsummary>
<type>
<v>AbsModule = Module | File | [Module | File]</v>
@@ -163,7 +163,7 @@
</func>
<func>
- <name>interpreted() -> [Module]</name>
+ <name since="">interpreted() -> [Module]</name>
<fsummary>Get all interpreted modules.</fsummary>
<type>
<v>Module = atom()</v>
@@ -174,7 +174,7 @@
</func>
<func>
- <name>file(Module) -> File | {error,not_loaded}</name>
+ <name since="">file(Module) -> File | {error,not_loaded}</name>
<fsummary>Get the filename for an interpreted module.</fsummary>
<type>
<v>Module = atom()</v>
@@ -187,7 +187,7 @@
</func>
<func>
- <name>interpretable(AbsModule) -> true | {error,Reason}</name>
+ <name since="">interpretable(AbsModule) -> true | {error,Reason}</name>
<fsummary>Check if a module can be interpreted.</fsummary>
<type>
<v>AbsModule = Module | File</v>
@@ -255,9 +255,9 @@
</func>
<func>
- <name>auto_attach() -> false | {Flags,Function}</name>
- <name>auto_attach(false)</name>
- <name>auto_attach(Flags, Function)</name>
+ <name since="">auto_attach() -> false | {Flags,Function}</name>
+ <name since="">auto_attach(false)</name>
+ <name since="">auto_attach(Flags, Function)</name>
<fsummary>Get and set when and how to attach to a process.</fsummary>
<type>
<v>Flags = [init | break | exit]</v>
@@ -290,8 +290,8 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>stack_trace() -> Flag</name>
- <name>stack_trace(Flag)</name>
+ <name since="">stack_trace() -> Flag</name>
+ <name since="">stack_trace(Flag)</name>
<fsummary>Get and set if and how to save call frames.</fsummary>
<type>
<v>Flag = all | no_tail | false</v>
@@ -322,7 +322,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>break(Module, Line) -> ok | {error,break_exists}</name>
+ <name since="">break(Module, Line) -> ok | {error,break_exists}</name>
<fsummary>Create a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -334,7 +334,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>delete_break(Module, Line) -> ok</name>
+ <name since="">delete_break(Module, Line) -> ok</name>
<fsummary>Delete a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -346,7 +346,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>break_in(Module, Name, Arity) -> ok
+ <name since="">break_in(Module, Name, Arity) -> ok
| {error,function_not_found}</name>
<fsummary>Create breakpoints in the specified function.</fsummary>
<type>
@@ -360,7 +360,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>del_break_in(Module, Name, Arity) -> ok
+ <name since="">del_break_in(Module, Name, Arity) -> ok
| {error,function_not_found}</name>
<fsummary>Delete breakpoints from the specified function.</fsummary>
<type>
@@ -374,8 +374,8 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>no_break() -> ok</name>
- <name>no_break(Module) -> ok</name>
+ <name since="">no_break() -> ok</name>
+ <name since="">no_break(Module) -> ok</name>
<fsummary>Delete all breakpoints.</fsummary>
<desc>
<p>Deletes all breakpoints, or all breakpoints in <c>Module</c>.</p>
@@ -383,7 +383,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>disable_break(Module, Line) -> ok</name>
+ <name since="">disable_break(Module, Line) -> ok</name>
<fsummary>Make a breakpoint inactive.</fsummary>
<type>
<v>Module = atom()</v>
@@ -395,7 +395,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>enable_break(Module, Line) -> ok</name>
+ <name since="">enable_break(Module, Line) -> ok</name>
<fsummary>Make a breakpoint active.</fsummary>
<type>
<v>Module = atom()</v>
@@ -407,7 +407,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>action_at_break(Module, Line, Action) -> ok</name>
+ <name since="">action_at_break(Module, Line, Action) -> ok</name>
<fsummary>Set the trigger action of a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -421,7 +421,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>test_at_break(Module, Line, Function) -> ok</name>
+ <name since="">test_at_break(Module, Line, Function) -> ok</name>
<fsummary>Set the conditional test of a breakpoint.</fsummary>
<type>
<v>Module = atom()</v>
@@ -438,7 +438,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>get_binding(Var, Bindings) -> {value,Value} | unbound</name>
+ <name since="">get_binding(Var, Bindings) -> {value,Value} | unbound</name>
<fsummary>Retrieve a variable binding.</fsummary>
<type>
<v>Var = atom()</v>
@@ -453,8 +453,8 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>all_breaks() -> [Break]</name>
- <name>all_breaks(Module) -> [Break]</name>
+ <name since="">all_breaks() -> [Break]</name>
+ <name since="">all_breaks(Module) -> [Break]</name>
<fsummary>Get all breakpoints.</fsummary>
<type>
<v>Break = {Point,Options}</v>
@@ -474,7 +474,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>snapshot() -> [Snapshot]</name>
+ <name since="">snapshot() -> [Snapshot]</name>
<fsummary>Get information about all processes executing interpreted
code.</fsummary>
<type>
@@ -519,7 +519,7 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>clear() -> ok</name>
+ <name since="">clear() -> ok</name>
<fsummary>Clear information about processes executing interpreted
code.</fsummary>
<desc>
@@ -529,8 +529,8 @@ spawn(Module, Name, [Pid | Args])</pre>
</func>
<func>
- <name>continue(Pid) -> ok | {error,not_interpreted}</name>
- <name>continue(X,Y,Z) -> ok | {error,not_interpreted}</name>
+ <name since="">continue(Pid) -> ok | {error,not_interpreted}</name>
+ <name since="">continue(X,Y,Z) -> ok | {error,not_interpreted}</name>
<fsummary>Resume process execution.</fsummary>
<type>
<v>Pid = pid()</v>
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index 9f7214ac69..395b69973d 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -33,6 +33,21 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 4.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 4.2.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index d62e5915a7..a3cbb497f8 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 4.2.5
+DEBUGGER_VSN = 4.2.6
diff --git a/lib/dialyzer/doc/src/Makefile b/lib/dialyzer/doc/src/Makefile
index 3463b589e6..3ce777392b 100644
--- a/lib/dialyzer/doc/src/Makefile
+++ b/lib/dialyzer/doc/src/Makefile
@@ -91,6 +91,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index e34ffd6def..f5e8337eb1 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -29,7 +29,7 @@
<rev></rev>
<file>dialyzer.xml</file>
</header>
- <module>dialyzer</module>
+ <module since="">dialyzer</module>
<modulesummary>Dialyzer, a DIscrepancy AnaLYZer for ERlang programs.
</modulesummary>
<description>
@@ -472,7 +472,7 @@ dialyzer --plts plt_1 ... plt_n -- files_to_analyze</code>
<funcs>
<func>
- <name>format_warning(Msg) -> string()</name>
+ <name since="">format_warning(Msg) -> string()</name>
<fsummary>Get the string version of a warning message.</fsummary>
<type>
<v>Msg = {Tag, Id, msg()}</v>
@@ -485,8 +485,8 @@ dialyzer --plts plt_1 ... plt_n -- files_to_analyze</code>
</func>
<func>
- <name>gui() -> ok | {error, Msg}</name>
- <name>gui(OptList) -> ok | {error, Msg}</name>
+ <name since="">gui() -> ok | {error, Msg}</name>
+ <name since="">gui(OptList) -> ok | {error, Msg}</name>
<fsummary>Dialyzer GUI version.</fsummary>
<type>
<v>OptList</v>
@@ -539,7 +539,7 @@ WarnOpts :: error_handling
</func>
<func>
- <name>plt_info(string()) -> {'ok', [{atom(), any()}]} | {'error', atom()}</name>
+ <name since="">plt_info(string()) -> {'ok', [{atom(), any()}]} | {'error', atom()}</name>
<fsummary>Return information about the specified PLT.</fsummary>
<desc>
<p>Returns information about the specified PLT.</p>
@@ -547,7 +547,7 @@ WarnOpts :: error_handling
</func>
<func>
- <name>run(OptList) -> Warnings</name>
+ <name since="">run(OptList) -> Warnings</name>
<fsummary>Dialyzer command-line version.</fsummary>
<type>
<v>OptList</v>
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 4ec72eecd9..bc422c43a0 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -32,6 +32,51 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 3.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug that caused Dialyzer to crash when
+ analyzing a contract with a module name differing from
+ the analyzed module's name. The bug was introduced in
+ Erlang/OTP 18. </p>
+ <p>
+ Own Id: OTP-15562 Aux Id: ERL-845 </p>
+ </item>
+ <item>
+ <p> Fix a bug in the handling of the <c>Key</c> argument
+ of <c>lists:{keysearch, keyfind, keymember}</c>. </p>
+ <p>
+ Own Id: OTP-15570</p>
+ </item>
+ <item>
+ <p>Optimize (again) Dialyzer's handling of
+ left-associative use of <c>andalso</c> and <c>orelse</c>
+ in guards.</p>
+ <p>
+ Own Id: OTP-15577 Aux Id: ERL-851, PR-2141, PR-1944 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 3.3.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Optimize Dialyzer's handling of left-associative use
+ of <c>andalso</c> and <c>orelse</c> in guards. </p>
+ <p>
+ Own Id: OTP-15268 Aux Id: ERL-680 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 3.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl
index 5587cf2bdf..c4e3c322e5 100644
--- a/lib/dialyzer/src/dialyzer_codeserver.erl
+++ b/lib/dialyzer/src/dialyzer_codeserver.erl
@@ -347,13 +347,11 @@ get_file_contract(Key, ContDict) ->
lookup_mfa_contract(MFA, #codeserver{contracts = ContDict}) ->
ets_dict_find(MFA, ContDict).
--spec lookup_meta_info(module() | mfa(), codeserver()) -> meta_info().
+-spec lookup_meta_info(module() | mfa(), codeserver()) ->
+ {'ok', meta_info()} | 'error'.
lookup_meta_info(MorMFA, #codeserver{fun_meta_info = FunMetaInfo}) ->
- case ets_dict_find(MorMFA, FunMetaInfo) of
- error -> [];
- {ok, PropList} -> PropList
- end.
+ ets_dict_find(MorMFA, FunMetaInfo).
-spec get_contracts(codeserver()) ->
dict:dict(mfa(), dialyzer_contracts:file_contract()).
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index af7f4385ad..9c36d745c3 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -25,7 +25,7 @@
%% get_contract_signature/1,
is_overloaded/1,
process_contract_remote_types/1,
- store_tmp_contract/5]).
+ store_tmp_contract/6]).
-export_type([file_contract/0, plt_contracts/0]).
@@ -146,18 +146,18 @@ process_contract_remote_types(CodeServer) ->
Mods = dialyzer_codeserver:all_temp_modules(CodeServer),
RecordTable = dialyzer_codeserver:get_records_table(CodeServer),
ExpTypes = dialyzer_codeserver:get_exported_types(CodeServer),
- ContractFun =
- fun({{_M, _F, _A}=MFA, {File, TmpContract, Xtra}}, C0) ->
- #tmp_contract{contract_funs = CFuns, forms = Forms} = TmpContract,
- {NewCs, C2} = lists:mapfoldl(fun(CFun, C1) ->
- CFun(ExpTypes, RecordTable, C1)
- end, C0, CFuns),
- Args = general_domain(NewCs),
- Contract = #contract{contracts = NewCs, args = Args, forms = Forms},
- {{MFA, {File, Contract, Xtra}}, C2}
- end,
ModuleFun =
fun(ModuleName) ->
+ ContractFun =
+ fun({MFA, {File, TmpContract, Xtra}}, C0) ->
+ #tmp_contract{contract_funs = CFuns, forms = Forms} = TmpContract,
+ {NewCs, C2} = lists:mapfoldl(fun(CFun, C1) ->
+ CFun(ExpTypes, RecordTable, C1)
+ end, C0, CFuns),
+ Args = general_domain(NewCs),
+ Contract = #contract{contracts = NewCs, args = Args, forms = Forms},
+ {{MFA, {File, Contract, Xtra}}, C2}
+ end,
Cache = erl_types:cache__new(),
{ContractMap, CallbackMap} =
dialyzer_codeserver:get_temp_contracts(ModuleName, CodeServer),
@@ -474,26 +474,29 @@ insert_constraints([], Map) -> Map.
-type spec_data() :: {TypeSpec :: [_], Xtra:: [_]}.
--spec store_tmp_contract(mfa(), file_line(), spec_data(), contracts(), types()) ->
- contracts().
+-spec store_tmp_contract(module(), mfa(), file_line(), spec_data(),
+ contracts(), types()) -> contracts().
-store_tmp_contract(MFA, FileLine, {TypeSpec, Xtra}, SpecMap, RecordsDict) ->
+store_tmp_contract(Module, MFA, FileLine, {TypeSpec, Xtra}, SpecMap,
+ RecordsDict) ->
%% io:format("contract from form: ~tp\n", [TypeSpec]),
- TmpContract = contract_from_form(TypeSpec, MFA, RecordsDict, FileLine),
+ TmpContract = contract_from_form(TypeSpec, Module, MFA, RecordsDict, FileLine),
%% io:format("contract: ~tp\n", [TmpContract]),
maps:put(MFA, {FileLine, TmpContract, Xtra}, SpecMap).
-contract_from_form(Forms, MFA, RecDict, FileLine) ->
- {CFuns, Forms1} = contract_from_form(Forms, MFA, RecDict, FileLine, [], []),
+contract_from_form(Forms, Module, MFA, RecDict, FileLine) ->
+ {CFuns, Forms1} =
+ contract_from_form(Forms, Module, MFA, RecDict, FileLine, [], []),
#tmp_contract{contract_funs = CFuns, forms = Forms1}.
-contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], MFA, RecDict,
- FileLine, TypeAcc, FormAcc) ->
+contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], Module, MFA,
+ RecDict, FileLine, TypeAcc, FormAcc) ->
TypeFun =
fun(ExpTypes, RecordTable, Cache) ->
{NewType, NewCache} =
try
- from_form_with_check(Form, ExpTypes, MFA, RecordTable, Cache)
+ from_form_with_check(Form, ExpTypes, Module, MFA, RecordTable,
+ Cache)
catch
throw:{error, Msg} ->
{File, Line} = FileLine,
@@ -506,68 +509,74 @@ contract_from_form([{type, _, 'fun', [_, _]} = Form | Left], MFA, RecDict,
end,
NewTypeAcc = [TypeFun | TypeAcc],
NewFormAcc = [{Form, []} | FormAcc],
- contract_from_form(Left, MFA, RecDict, FileLine, NewTypeAcc, NewFormAcc);
+ contract_from_form(Left, Module, MFA, RecDict, FileLine, NewTypeAcc,
+ NewFormAcc);
contract_from_form([{type, _L1, bounded_fun,
[{type, _L2, 'fun', [_, _]} = Form, Constr]}| Left],
- MFA, RecDict, FileLine, TypeAcc, FormAcc) ->
+ Module, MFA, RecDict, FileLine, TypeAcc, FormAcc) ->
TypeFun =
fun(ExpTypes, RecordTable, Cache) ->
{Constr1, VarTable, Cache1} =
- process_constraints(Constr, MFA, RecDict, ExpTypes, RecordTable,
- Cache),
+ process_constraints(Constr, Module, MFA, RecDict, ExpTypes,
+ RecordTable, Cache),
{NewType, NewCache} =
- from_form_with_check(Form, ExpTypes, MFA, RecordTable,
+ from_form_with_check(Form, ExpTypes, Module, MFA, RecordTable,
VarTable, Cache1),
NewTypeNoVars = erl_types:subst_all_vars_to_any(NewType),
{{NewTypeNoVars, Constr1}, NewCache}
end,
NewTypeAcc = [TypeFun | TypeAcc],
NewFormAcc = [{Form, Constr} | FormAcc],
- contract_from_form(Left, MFA, RecDict, FileLine, NewTypeAcc, NewFormAcc);
-contract_from_form([], _MFA, _RecDict, _FileLine, TypeAcc, FormAcc) ->
+ contract_from_form(Left, Module, MFA, RecDict, FileLine, NewTypeAcc,
+ NewFormAcc);
+contract_from_form([], _Mod, _MFA, _RecDict, _FileLine, TypeAcc, FormAcc) ->
{lists:reverse(TypeAcc), lists:reverse(FormAcc)}.
-process_constraints(Constrs, MFA, RecDict, ExpTypes, RecordTable, Cache) ->
- {Init0, NewCache} = initialize_constraints(Constrs, MFA, RecDict, ExpTypes,
- RecordTable, Cache),
+process_constraints(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
+ Cache) ->
+ {Init0, NewCache} = initialize_constraints(Constrs, Module, MFA, RecDict,
+ ExpTypes, RecordTable, Cache),
Init = remove_cycles(Init0),
- constraints_fixpoint(Init, MFA, RecDict, ExpTypes, RecordTable, NewCache).
+ constraints_fixpoint(Init, Module, MFA, RecDict, ExpTypes, RecordTable,
+ NewCache).
-initialize_constraints(Constrs, MFA, RecDict, ExpTypes, RecordTable, Cache) ->
- initialize_constraints(Constrs, MFA, RecDict, ExpTypes, RecordTable,
+initialize_constraints(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
+ Cache) ->
+ initialize_constraints(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
Cache, []).
-initialize_constraints([], _MFA, _RecDict, _ExpTypes, _RecordTable,
+initialize_constraints([], _Module, _MFA, _RecDict, _ExpTypes, _RecordTable,
Cache, Acc) ->
{Acc, Cache};
-initialize_constraints([Constr|Rest], MFA, RecDict, ExpTypes, RecordTable,
- Cache, Acc) ->
+initialize_constraints([Constr|Rest], Module, MFA, RecDict, ExpTypes,
+ RecordTable, Cache, Acc) ->
case Constr of
{type, _, constraint, [{atom, _, is_subtype}, [Type1, Type2]]} ->
VarTable = erl_types:var_table__new(),
{T1, NewCache} =
- final_form(Type1, ExpTypes, MFA, RecordTable, VarTable, Cache),
+ final_form(Type1, ExpTypes, Module, MFA, RecordTable, VarTable, Cache),
Entry = {T1, Type2},
- initialize_constraints(Rest, MFA, RecDict, ExpTypes, RecordTable,
- NewCache, [Entry|Acc]);
+ initialize_constraints(Rest, Module, MFA, RecDict, ExpTypes,
+ RecordTable, NewCache, [Entry|Acc]);
{type, _, constraint, [{atom,_,Name}, List]} ->
N = length(List),
throw({error,
io_lib:format("Unsupported type guard ~tw/~w\n", [Name, N])})
end.
-constraints_fixpoint(Constrs, MFA, RecDict, ExpTypes, RecordTable, Cache) ->
+constraints_fixpoint(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
+ Cache) ->
VarTable = erl_types:var_table__new(),
{VarTab, NewCache} =
- constraints_to_dict(Constrs, MFA, RecDict, ExpTypes, RecordTable,
+ constraints_to_dict(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
VarTable, Cache),
- constraints_fixpoint(VarTab, MFA, Constrs, RecDict, ExpTypes,
+ constraints_fixpoint(VarTab, Module, MFA, Constrs, RecDict, ExpTypes,
RecordTable, NewCache).
-constraints_fixpoint(OldVarTab, MFA, Constrs, RecDict, ExpTypes,
+constraints_fixpoint(OldVarTab, Module, MFA, Constrs, RecDict, ExpTypes,
RecordTable, Cache) ->
{NewVarTab, NewCache} =
- constraints_to_dict(Constrs, MFA, RecDict, ExpTypes, RecordTable,
+ constraints_to_dict(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
OldVarTab, Cache),
case NewVarTab of
OldVarTab ->
@@ -578,19 +587,23 @@ constraints_fixpoint(OldVarTab, MFA, Constrs, RecDict, ExpTypes,
FinalConstrs = maps:fold(Fun, [], NewVarTab),
{FinalConstrs, NewVarTab, NewCache};
_Other ->
- constraints_fixpoint(NewVarTab, MFA, Constrs, RecDict, ExpTypes,
+ constraints_fixpoint(NewVarTab, Module, MFA, Constrs, RecDict, ExpTypes,
RecordTable, NewCache)
end.
-final_form(Form, ExpTypes, MFA, RecordTable, VarTable, Cache) ->
- from_form_with_check(Form, ExpTypes, MFA, RecordTable, VarTable, Cache).
+final_form(Form, ExpTypes, Module, MFA, RecordTable, VarTable, Cache) ->
+ from_form_with_check(Form, ExpTypes, Module, MFA, RecordTable, VarTable,
+ Cache).
-from_form_with_check(Form, ExpTypes, MFA, RecordTable, Cache) ->
+from_form_with_check(Form, ExpTypes, Module, MFA, RecordTable, Cache) ->
VarTable = erl_types:var_table__new(),
- from_form_with_check(Form, ExpTypes, MFA, RecordTable, VarTable, Cache).
+ from_form_with_check(Form, ExpTypes, Module, MFA, RecordTable, VarTable,
+ Cache).
-from_form_with_check(Form, ExpTypes, MFA, RecordTable, VarTable, Cache) ->
- Site = {spec, MFA},
+from_form_with_check(Form, ExpTypes, Module, MFA, RecordTable, VarTable,
+ Cache) ->
+ {_, F, A} = MFA,
+ Site = {spec, {Module, F, A}},
C1 = erl_types:t_check_record_fields(Form, ExpTypes, Site, RecordTable,
VarTable, Cache),
%% The check costs some time, and with the assumption that contracts
@@ -598,22 +611,22 @@ from_form_with_check(Form, ExpTypes, MFA, RecordTable, VarTable, Cache) ->
%% erl_types:t_from_form_check_remote(Form, ExpTypes, MFA, RecordTable),
erl_types:t_from_form(Form, ExpTypes, Site, RecordTable, VarTable, C1).
-constraints_to_dict(Constrs, MFA, RecDict, ExpTypes, RecordTable,
+constraints_to_dict(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
VarTab, Cache) ->
{Subtypes, NewCache} =
- constraints_to_subs(Constrs, MFA, RecDict, ExpTypes, RecordTable,
+ constraints_to_subs(Constrs, Module, MFA, RecDict, ExpTypes, RecordTable,
VarTab, Cache, []),
{insert_constraints(Subtypes), NewCache}.
-constraints_to_subs([], _MFA, _RecDict, _ExpTypes, _RecordTable,
+constraints_to_subs([], _Module, _MFA, _RecDict, _ExpTypes, _RecordTable,
_VarTab, Cache, Acc) ->
{Acc, Cache};
-constraints_to_subs([{T1, Form2}|Rest], MFA, RecDict, ExpTypes, RecordTable,
- VarTab, Cache, Acc) ->
+constraints_to_subs([{T1, Form2}|Rest], Module, MFA, RecDict, ExpTypes,
+ RecordTable, VarTab, Cache, Acc) ->
{T2, NewCache} =
- final_form(Form2, ExpTypes, MFA, RecordTable, VarTab, Cache),
+ final_form(Form2, ExpTypes, Module, MFA, RecordTable, VarTab, Cache),
NewAcc = [{subtype, T1, T2}|Acc],
- constraints_to_subs(Rest, MFA, RecDict, ExpTypes, RecordTable,
+ constraints_to_subs(Rest, Module, MFA, RecDict, ExpTypes, RecordTable,
VarTab, NewCache, NewAcc).
%% Replaces variables with '_' when necessary to break up cycles among
@@ -898,6 +911,7 @@ is_remote_types_related(Contract, CSig, Sig, MFA, RecDict) ->
t_from_forms_without_remote([{FType, []}], MFA, RecDict) ->
Site = {spec, MFA},
+ %% FIXME
Type1 = erl_types:t_from_form_without_remote(FType, Site, RecDict),
{ok, erl_types:subst_all_vars_to_any(Type1)};
t_from_forms_without_remote([{_FType, _Constrs}], _MFA, _RecDict) ->
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index abd89034f3..310301ee0b 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -450,8 +450,9 @@ get_spec_info([{Contract, Ln, [{Id, TypeSpec}]}|Left],
error ->
SpecData = {TypeSpec, Xtra},
NewActiveMap =
- dialyzer_contracts:store_tmp_contract(MFA, {File, Ln}, SpecData,
- ActiveMap, RecordsMap),
+ dialyzer_contracts:store_tmp_contract(ModName, MFA, {File, Ln},
+ SpecData, ActiveMap,
+ RecordsMap),
{NewSpecMap, NewCallbackMap} =
case Contract of
spec -> {NewActiveMap, CallbackMap};
@@ -599,24 +600,32 @@ collect_attribute([], _Tag, _File) ->
-spec is_suppressed_fun(mfa(), codeserver()) -> boolean().
is_suppressed_fun(MFA, CodeServer) ->
- lookup_fun_property(MFA, nowarn_function, CodeServer).
+ lookup_fun_property(MFA, nowarn_function, CodeServer, false).
-spec is_suppressed_tag(mfa() | module(), dial_warn_tag(), codeserver()) ->
boolean().
is_suppressed_tag(MorMFA, Tag, Codeserver) ->
- not lookup_fun_property(MorMFA, Tag, Codeserver).
-
-lookup_fun_property({M, _F, _A}=MFA, Property, CodeServer) ->
- MFAPropList = dialyzer_codeserver:lookup_meta_info(MFA, CodeServer),
- case proplists:get_value(Property, MFAPropList, no) of
- mod -> false; % suppressed in function
- func -> true; % requested in function
- no -> lookup_fun_property(M, Property, CodeServer)
+ not lookup_fun_property(MorMFA, Tag, Codeserver, true).
+
+lookup_fun_property({M, _F, _A}=MFA, Property, CodeServer, NoInfoReturn) ->
+ case dialyzer_codeserver:lookup_meta_info(MFA, CodeServer) of
+ error ->
+ lookup_fun_property(M, Property, CodeServer, NoInfoReturn);
+ {ok, MFAPropList} ->
+ case proplists:get_value(Property, MFAPropList, no) of
+ mod -> false; % suppressed in function
+ func -> true; % requested in function
+ no -> lookup_fun_property(M, Property, CodeServer, NoInfoReturn)
+ end
end;
-lookup_fun_property(M, Property, CodeServer) when is_atom(M) ->
- MPropList = dialyzer_codeserver:lookup_meta_info(M, CodeServer),
- proplists:is_defined(Property, MPropList).
+lookup_fun_property(M, Property, CodeServer, NoInfoReturn) when is_atom(M) ->
+ case dialyzer_codeserver:lookup_meta_info(M, CodeServer) of
+ error ->
+ NoInfoReturn;
+ {ok, MPropList} ->
+ proplists:is_defined(Property, MPropList)
+ end.
%% ============================================================================
%%
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/para b/lib/dialyzer/test/opaque_SUITE_data/results/para
index 37b5b7b44e..eca445315c 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/para
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/para
@@ -29,5 +29,6 @@ para4.erl:74: Attempt to test for equality between a term of type para4_adt:int(
para4.erl:79: Attempt to test for equality between a term of type para4_adt:int(2 | 3 | 4) and a term of opaque type para4_adt:int(5 | 6 | 7)
para4.erl:84: Attempt to test for equality between a term of type para4_adt:un(3 | 4) and a term of opaque type para4_adt:un(1 | 2)
para4.erl:89: Attempt to test for equality between a term of type para4_adt:tup({_,_}) and a term of opaque type para4_adt:tup(tuple())
+para4.erl:94: Attempt to test for equality between a term of type para4_adt:t(#{1=>'a'}) and a term of opaque type para4_adt:t(#{2=>'b'})
para5.erl:13: Attempt to test for inequality between a term of type para5_adt:dd(atom()) and a term of opaque type para5_adt:d()
para5.erl:8: The test para5_adt:d() =:= para5_adt:d() can never evaluate to 'true'
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para4.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para4.erl
index b9794672a9..8cd049169d 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/para/para4.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para4.erl
@@ -88,6 +88,11 @@ adt_tt13() ->
I2 = adt_tup2(),
I1 =:= I2. % opaque attempt
+adt_tt14() ->
+ I1 = adt_map(),
+ I2 = adt_map2(),
+ I1 =:= I2.
+
y3() ->
{a, 3}.
@@ -132,3 +137,9 @@ adt_tup() ->
adt_tup2() ->
para4_adt:tup2().
+
+adt_map() ->
+ para4_adt:map().
+
+adt_map2() ->
+ para4_adt:map2().
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para4_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para4_adt.erl
index 407dd198a7..06a6c22677 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/para/para4_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para4_adt.erl
@@ -8,6 +8,8 @@
-export([tup/0, tup2/0]).
+-export([map/0, map2/0]).
+
-export_type([t/1, y/1, int/1, tup/1, un/1]).
-type ai() :: atom() | integer().
@@ -106,3 +108,13 @@ tup() ->
tup2() ->
foo:tup2().
+
+-spec map() -> t(#{2 => b}).
+
+map() ->
+ foo:map().
+
+-spec map2() -> t(#{1 => a}).
+
+map2() ->
+ foo:map2().
diff --git a/lib/dialyzer/test/small_SUITE_data/results/left_assoc b/lib/dialyzer/test/small_SUITE_data/results/left_assoc
new file mode 100644
index 0000000000..58cdad29de
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/left_assoc
@@ -0,0 +1,2 @@
+
+left_assoc.erl:93: The variable __@2 can never match since previous clauses completely covered the type binary()
diff --git a/lib/dialyzer/test/small_SUITE_data/results/spec_other_module b/lib/dialyzer/test/small_SUITE_data/results/spec_other_module
new file mode 100644
index 0000000000..ab2e35cf55
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/spec_other_module
@@ -0,0 +1,2 @@
+
+spec_other_module.erl:7: Contract for function that does not exist: lists:flatten/1
diff --git a/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl
new file mode 100644
index 0000000000..0250e4ab49
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl
@@ -0,0 +1,96 @@
+-module(left_assoc).
+
+%% As pointed out in ERL-680, analyzing guards with short circuit
+%% operators becomes very slow as the number of left associations
+%% grows.
+
+-spec from_iso8601('Elixir.String':t(), 'Elixir.Calendar':calendar()) ->
+ {ok, t()} | {error, atom()}.
+
+-export_type([t/0]).
+
+-type t() ::
+ #{'__struct__' := 'Elixir.Date',
+ calendar := 'Elixir.Calendar':calendar(),
+ day := 'Elixir.Calendar':day(),
+ month := 'Elixir.Calendar':month(),
+ year := 'Elixir.Calendar':year()}.
+
+-export([from_iso8601/1,
+ from_iso8601/2]).
+
+from_iso8601(__@1) ->
+ from_iso8601(__@1, 'Elixir.Calendar.ISO').
+
+from_iso8601(<<45/integer,_rest@1/binary>>, _calendar@1) ->
+ case raw_from_iso8601(_rest@1, _calendar@1) of
+ {ok,#{year := _year@1} = _date@1} ->
+ {ok,_date@1#{year := - _year@1}};
+ __@1 ->
+ __@1
+ end;
+from_iso8601(<<_rest@1/binary>>, _calendar@1) ->
+ raw_from_iso8601(_rest@1, _calendar@1).
+
+raw_from_iso8601(_string@1, _calendar@1) ->
+ case _string@1 of
+ <<_y1@1/integer,
+ _y2@1/integer,
+ _y3@1/integer,
+ _y4@1/integer,
+ 45/integer,
+ _m1@1/integer,
+ _m2@1/integer,
+ 45/integer,
+ _d1@1/integer,
+ _d2@1/integer>>
+ when
+ ((((((((((((((_y1@1 >= 48
+ andalso
+ _y1@1 =< 57)
+ andalso
+ _y2@1 >= 48)
+ andalso
+ _y2@1 =< 57)
+ andalso
+ _y3@1 >= 48)
+ andalso
+ _y3@1 =< 57)
+ andalso
+ _y4@1 >= 48)
+ andalso
+ _y4@1 =< 57)
+ andalso
+ _m1@1 >= 48)
+ andalso
+ _m1@1 =< 57)
+ andalso
+ _m2@1 >= 48)
+ andalso
+ _m2@1 =< 57)
+ andalso
+ _d1@1 >= 48)
+ andalso
+ _d1@1 =< 57)
+ andalso
+ _d2@1 >= 48)
+ andalso
+ _d2@1 =< 57 ->
+ {ok,
+ #{year => (_y1@1 - 48) * 1000 + (_y2@1 - 48) * 100
+ +
+ (_y3@1 - 48) * 10
+ +
+ (_y4@1 - 48),
+ month => (_m1@1 - 48) * 10 + (_m2@1 - 48),
+ day => (_d1@1 - 48) * 10 + (_d2@1 - 48),
+ calendar => _calendar@1,
+ '__struct__' => 'Elixir.Date'}};
+ __@1 ->
+ case __@1 of
+ _ ->
+ {error,invalid_format};
+ __@2 ->
+ error({with_clause,__@2})
+ end
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/lists_key_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/lists_key_bug.erl
new file mode 100644
index 0000000000..ad5cf3c503
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/lists_key_bug.erl
@@ -0,0 +1,75 @@
+-module(lists_key_bug).
+
+%% OTP-15570
+
+-export([is_1/1, is_2/1, i/1, t1/0, t2/0, im/0]).
+
+%% int_set([3])
+is_1(V) ->
+ K = ikey(V),
+ case lists:keyfind(K, 1, [{<<"foo">>, bar}]) of
+ false ->
+ a;
+ {_, _} ->
+ b
+ end.
+
+ikey(1) ->
+ 3;
+ikey(2) ->
+ <<"foo">>.
+
+%% int_set([3, 5])
+is_2(V) ->
+ K = iskey(V),
+ case lists:keyfind(K, 1, [{<<"foo">>, bar}]) of
+ false ->
+ a;
+ {_, _} ->
+ b
+ end.
+
+iskey(1) ->
+ 12;
+iskey(2) ->
+ 14;
+iskey(3) ->
+ <<"foo">>.
+
+%% integer()
+i(V) ->
+ K = intkey(V),
+ case lists:keyfind(K, 1, [{9.0, foo}]) of
+ false ->
+ a;
+ {_, _} ->
+ b
+ end.
+
+intkey(K) when is_integer(K) ->
+ K + 9999.
+
+t1() ->
+ case lists:keyfind({17}, 1, [{{17.0}, true}]) of
+ false ->
+ a;
+ {_, _} ->
+ b
+ end.
+
+t2() ->
+ case lists:keyfind({17.0}, 1, [{{17}, true}]) of
+ false ->
+ a;
+ {_, _} ->
+ b
+ end.
+
+%% Note: #{1.0 => a} =/= #{1 => a}.
+im() ->
+ case lists:keyfind(#{1.0 => a}, 1, [{#{1 => a}, foo}]) of
+ false ->
+ a;
+ {_, _} ->
+ b
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/spec_other_module.erl b/lib/dialyzer/test/small_SUITE_data/src/spec_other_module.erl
new file mode 100644
index 0000000000..b36742b1bd
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/spec_other_module.erl
@@ -0,0 +1,7 @@
+-module(spec_other_module).
+
+%% OTP-15562 and ERL-845. Example provided by Kostis.
+
+-type deep_list(A) :: [A | deep_list(A)].
+
+-spec lists:flatten(deep_list(A)) -> [A].
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index 7240b66fb5..7221993963 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 3.3
+DIALYZER_VSN = 3.3.2
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
index 7a7546fc4d..7c7fbeafef 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -77,6 +77,7 @@ clean_man:
clean_html:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index dfa4c803ed..85522c99b2 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd" [
- <!ENTITY spawn_opt
+ <!ENTITY spawn_opt2
'<seealso marker="erts:erlang#spawn_opt-2">erlang:spawn_opt/2</seealso>'>
+ <!ENTITY spawn_opt5
+ '<seealso marker="erts:erlang#spawn_opt-5">erlang:spawn_opt/5</seealso>'>
<!ENTITY nodes
'<seealso marker="erts:erlang#nodes-0">erlang:nodes/0</seealso>'>
<!ENTITY make_ref
@@ -21,7 +23,7 @@
<copyright>
<year>2011</year>
-<year>2017</year>
+<year>2019</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -55,7 +57,7 @@ limitations under the License.
<!-- ===================================================================== -->
<!-- ===================================================================== -->
-<module>diameter</module>
+<module since="OTP R14B03">diameter</module>
<modulesummary>Main API of the diameter application.</modulesummary>
<description>
@@ -1384,12 +1386,22 @@ the same peer.</p>
</item>
<tag>
-<marker id="spawn_opt"/><c>{spawn_opt, [term()]}</c></tag>
+<marker id="spawn_opt"/><c>{spawn_opt, [term()] | {M,F,A}}</c></tag>
<item>
<p>
-Options passed to &spawn_opt; when spawning a process for an
-incoming Diameter request.
-Options <c>monitor</c> and <c>link</c> are ignored.</p>
+An options list passed to &spawn_opt2; to spawn a handler process for an
+incoming Diameter request on the local node, or an MFA that returns
+the pid of a handler process.</p>
+
+<p>
+Options <c>monitor</c> and <c>link</c> are ignored in the list-valued
+case.
+An MFA is applied with an additional term prepended to its argument
+list, and should return either the pid of the handler process that
+invokes <c>diameter_traffic:request/1</c> on the term in order to
+process the request, or the atom <c>discard</c>.
+The handler process need not be local, but diameter must be started on
+the remote node.</p>
<p>
Defaults to the empty list.</p>
@@ -1574,7 +1586,7 @@ identifies the configuration.</p>
<!-- ===================================================================== -->
<func>
-<name>add_transport(SvcName, {connect|listen, [Opt]})
+<name since="OTP R14B03">add_transport(SvcName, {connect|listen, [Opt]})
-> {ok, Ref} | {error, Reason}</name>
<fsummary>Add transport capability to a service.</fsummary>
<type>
@@ -1624,7 +1636,7 @@ its transports.</p>
<!-- ===================================================================== -->
<func>
-<name>call(SvcName, App, Request, [Opt]) -> Answer | ok | {error, Reason}</name>
+<name since="OTP R14B03">call(SvcName, App, Request, [Opt]) -> Answer | ok | {error, Reason}</name>
<fsummary>Send a Diameter request message.</fsummary>
<type>
<v>SvcName = &service_name;</v>
@@ -1730,7 +1742,7 @@ transport connection.</p>
<!-- ===================================================================== -->
<func>
-<name>origin_state_id() -> &dict_Unsigned32;</name>
+<name since="OTP R14B03">origin_state_id() -> &dict_Unsigned32;</name>
<fsummary>Returns a reasonable Origin-State-Id.</fsummary>
<desc>
<p>
@@ -1748,7 +1760,7 @@ at the time the diameter application was started.</p>
<!-- ===================================================================== -->
<func>
-<name>remove_transport(SvcName, Pred) -> ok | {error, Reason}</name>
+<name since="OTP R14B03">remove_transport(SvcName, Pred) -> ok | {error, Reason}</name>
<fsummary>Remove previously added transports.</fsummary>
<type>
<v>SvcName = &service_name;</v>
@@ -1795,7 +1807,7 @@ configured on the transport.</p>
<!-- ===================================================================== -->
<func>
-<name>service_info(SvcName, Info) -> term()</name>
+<name since="OTP R14B03">service_info(SvcName, Info) -> term()</name>
<fsummary>Return information about a started service.</fsummary>
<type>
<v>SvcName = &service_name;</v>
@@ -2114,7 +2126,7 @@ For example:</p>
<!-- ===================================================================== -->
<func>
-<name>services() -> [SvcName]</name>
+<name since="OTP R14B03">services() -> [SvcName]</name>
<fsummary>Return the list of started services.</fsummary>
<type>
<v>SvcName = &service_name;</v>
@@ -2129,7 +2141,7 @@ Return the list of started services.</p>
<!-- ===================================================================== -->
<func>
-<name>session_id(Ident) -> &dict_OctetString;</name>
+<name since="OTP R14B03">session_id(Ident) -> &dict_OctetString;</name>
<fsummary>Return a value for a Session-Id AVP.</fsummary>
<type>
<v>Ident = &dict_DiameterIdentity;</v>
@@ -2148,7 +2160,7 @@ the message containing the returned value will be sent.</p>
<!-- ===================================================================== -->
<func>
-<name>start() -> ok | {error, Reason}</name>
+<name since="OTP R14B03">start() -> ok | {error, Reason}</name>
<fsummary>Start the diameter application.</fsummary>
<desc>
<p>
@@ -2164,7 +2176,7 @@ file, not by calling <c>start/0</c> explicitly.</p>
<!-- ===================================================================== -->
<func>
-<name>start_service(SvcName, Options) -> ok | {error, Reason}</name>
+<name since="OTP R14B03">start_service(SvcName, Options) -> ok | {error, Reason}</name>
<fsummary>Start a Diameter service.</fsummary>
<type>
<v>SvcName = &service_name;</v>
@@ -2194,7 +2206,7 @@ necessarily the case.</p>
<!-- ===================================================================== -->
<func>
-<name>stop() -> ok | {error, Reason}</name>
+<name since="OTP R14B03">stop() -> ok | {error, Reason}</name>
<fsummary>Stop the diameter application.</fsummary>
<desc>
<p>
@@ -2208,7 +2220,7 @@ Stop the diameter application.</p>
<!-- ===================================================================== -->
<func>
-<name>stop_service(SvcName) -> ok | {error, Reason}</name>
+<name since="OTP R14B03">stop_service(SvcName) -> ok | {error, Reason}</name>
<fsummary>Stop a Diameter service.</fsummary>
<type>
<v>SvcName = &service_name;</v>
@@ -2236,7 +2248,7 @@ be called to remove transport configuration.</p>
<!-- ===================================================================== -->
<func>
-<name>subscribe(SvcName) -> true</name>
+<name since="OTP R14B03">subscribe(SvcName) -> true</name>
<fsummary>Subscribe to event messages.</fsummary>
<type>
<v>SvcName = &service_name;</v>
@@ -2258,7 +2270,7 @@ reception of all transport-related events.</p>
<!-- ===================================================================== -->
<func>
-<name>unsubscribe(SvcName) -> true</name>
+<name since="OTP R14B03">unsubscribe(SvcName) -> true</name>
<fsummary>Unsubscribe to event messages.</fsummary>
<type>
<v>SvcName = &service_name;</v>
diff --git a/lib/diameter/doc/src/diameter_app.xml b/lib/diameter/doc/src/diameter_app.xml
index aa334beb21..82e3d449ef 100644
--- a/lib/diameter/doc/src/diameter_app.xml
+++ b/lib/diameter/doc/src/diameter_app.xml
@@ -44,7 +44,7 @@ limitations under the License.
</header>
-<module>diameter_app</module>
+<module since="OTP R14B03">diameter_app</module>
<modulesummary>
Callback module of a Diameter application.</modulesummary>
@@ -180,7 +180,7 @@ process.</p>
<funcs>
<func>
-<name>Mod:peer_up(SvcName, Peer, State) -> NewState</name>
+<name since="OTP R14B03">Mod:peer_up(SvcName, Peer, State) -> NewState</name>
<fsummary>Invoked when a transport connection has been established</fsummary>
<type>
<v>SvcName = &mod_service_name;</v>
@@ -215,7 +215,7 @@ handled independently of &peer_up; and &peer_down;.</p>
</func>
<func>
-<name>Mod:peer_down(SvcName, Peer, State) -> NewState</name>
+<name since="OTP R14B03">Mod:peer_down(SvcName, Peer, State) -> NewState</name>
<fsummary>Invoked when a transport connection has been lost.</fsummary>
<type>
<v>SvcName = &mod_service_name;</v>
@@ -234,7 +234,7 @@ candidate in &pick_peer; callbacks.</p>
</func>
<func>
-<name>Mod:pick_peer(LocalCandidates, RemoteCandidates, SvcName, State)
+<name since="OTP R14B03">Mod:pick_peer(LocalCandidates, RemoteCandidates, SvcName, State)
-> Selection | false</name>
<fsummary>Select a target peer for an outgoing request.</fsummary>
<type>
@@ -311,7 +311,7 @@ or &peer_down; callback.</p>
</func>
<func>
-<name>Mod:prepare_request(Packet, SvcName, Peer) -> Action</name>
+<name since="OTP R14B03">Mod:prepare_request(Packet, SvcName, Peer) -> Action</name>
<fsummary>Return a request for encoding and transport.</fsummary>
<type>
<v>Packet = &packet;</v>
@@ -363,7 +363,7 @@ discarded}</c>.</p>
</func>
<func>
-<name>Mod:prepare_retransmit(Packet, SvcName, Peer) -> Action</name>
+<name since="OTP R14B03">Mod:prepare_retransmit(Packet, SvcName, Peer) -> Action</name>
<fsummary>Return a request for encoding and retransmission.</fsummary>
<type>
<v>Packet = &packet;</v>
@@ -393,7 +393,7 @@ discarded}</c>.</p>
</func>
<func>
-<name>Mod:handle_answer(Packet, Request, SvcName, Peer) -> Result</name>
+<name since="OTP R14B03">Mod:handle_answer(Packet, Request, SvcName, Peer) -> Result</name>
<fsummary>Receive an answer message from a peer.</fsummary>
<type>
<v>Packet = &packet;</v>
@@ -437,7 +437,7 @@ The &mod_application_opt;
</func>
<func>
-<name>Mod:handle_error(Reason, Request, SvcName, Peer) -> Result</name>
+<name since="OTP R14B03">Mod:handle_error(Reason, Request, SvcName, Peer) -> Result</name>
<fsummary>Return an error from a outgoing request.</fsummary>
<type>
<v>Reason = timeout | failover | term()</v>
@@ -465,7 +465,7 @@ not selected.</p>
</func>
<func>
-<name>Mod:handle_request(Packet, SvcName, Peer) -> Action</name>
+<name since="OTP R14B03">Mod:handle_request(Packet, SvcName, Peer) -> Action</name>
<fsummary>Receive an incoming request.</fsummary>
<type>
<v>Packet = &packet;</v>
diff --git a/lib/diameter/doc/src/diameter_codec.xml b/lib/diameter/doc/src/diameter_codec.xml
index 0a34dd7ec7..0384ad2913 100644
--- a/lib/diameter/doc/src/diameter_codec.xml
+++ b/lib/diameter/doc/src/diameter_codec.xml
@@ -46,7 +46,7 @@ limitations under the License.
<file>diameter_codec.xml</file>
</header>
-<module>diameter_codec</module>
+<module since="OTP R15B03">diameter_codec</module>
<modulesummary>Decode and encode of Diameter messages.</modulesummary>
<description>
@@ -346,7 +346,7 @@ question, as documented in &man_transport;.</p>
<funcs>
<func>
-<name>decode(Mod, Bin) -> Pkt</name>
+<name since="OTP R15B03">decode(Mod, Bin) -> Pkt</name>
<fsummary>Decode a Diameter message.</fsummary>
<type>
<v>Mod = &dictionary;</v>
@@ -362,7 +362,7 @@ Decode a Diameter message.</p>
</func>
<func>
-<name>encode(Mod, Msg) -> Pkt</name>
+<name since="OTP R15B03">encode(Mod, Msg) -> Pkt</name>
<fsummary>Encode a Diameter message.</fsummary>
<type>
<v>Mod = &dictionary;</v>
diff --git a/lib/diameter/doc/src/diameter_make.xml b/lib/diameter/doc/src/diameter_make.xml
index 112355816f..57e83bbca1 100644
--- a/lib/diameter/doc/src/diameter_make.xml
+++ b/lib/diameter/doc/src/diameter_make.xml
@@ -45,7 +45,7 @@ limitations under the License.
<file>diameter_make.xml</file>
</header>
-<module>diameter_make</module>
+<module since="OTP R14B03">diameter_make</module>
<modulesummary>Diameter dictionary compilation.</modulesummary>
<description>
@@ -67,7 +67,7 @@ interface.</p>
<funcs>
<func>
-<name>codec(File :: iolist() | binary(), [Opt]) -> ok
+<name since="OTP R15B">codec(File :: iolist() | binary(), [Opt]) -> ok
| {ok, [Out]}
| {error, Reason}</name>
<fsummary>Compile a dictionary file into Erlang source.</fsummary>
@@ -186,7 +186,7 @@ A returned error reason can be converted into a readable string using
<!-- ===================================================================== -->
<func>
-<name>format(Parsed) -> iolist()</name>
+<name since="OTP R16B03">format(Parsed) -> iolist()</name>
<fsummary>Format a parsed dictionary.</fsummary>
<desc>
<p>
@@ -198,7 +198,7 @@ dictionary format.</p>
<!-- ===================================================================== -->
<func>
-<name>flatten(Parsed) -> term()</name>
+<name since="OTP R16B03">flatten(Parsed) -> term()</name>
<fsummary>Flatten a parsed dictionary.</fsummary>
<desc>
@@ -214,7 +214,7 @@ The return value is also a parsed dictionary.</p>
<!-- ===================================================================== -->
<func>
-<name>format_error(Reason) -> string()</name>
+<name since="OTP 17.0">format_error(Reason) -> string()</name>
<fsummary>Turn an error reason into a readable string.</fsummary>
<desc>
diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml
index 62e958870e..2cf924ee6b 100644
--- a/lib/diameter/doc/src/diameter_sctp.xml
+++ b/lib/diameter/doc/src/diameter_sctp.xml
@@ -47,7 +47,7 @@ limitations under the License.
<file>diameter_sctp.xml</file>
</header>
-<module>diameter_sctp</module>
+<module since="OTP R14B03">diameter_sctp</module>
<modulesummary>Diameter transport over SCTP.</modulesummary>
<description>
@@ -67,7 +67,7 @@ and implements the behaviour documented in
<funcs>
<func>
-<name>start({Type, Ref}, Svc, [Opt])
+<name since="OTP R14B03">start({Type, Ref}, Svc, [Opt])
-> {ok, Pid, [LAddr]} | {error, Reason}</name>
<fsummary>Start a transport process.</fsummary>
<type>
diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml
index 9f84eeb9fd..fe0cb2d067 100644
--- a/lib/diameter/doc/src/diameter_tcp.xml
+++ b/lib/diameter/doc/src/diameter_tcp.xml
@@ -57,7 +57,7 @@ limitations under the License.
<file>diameter_tcp.xml</file>
</header>
-<module>diameter_tcp</module>
+<module since="OTP R14B03">diameter_tcp</module>
<modulesummary>Diameter transport over TCP.</modulesummary>
<description>
@@ -83,7 +83,7 @@ before configuring TLS capability on diameter transports.</p>
<funcs>
<func>
-<name>start({Type, Ref}, Svc, [Opt])
+<name since="OTP R14B03">start({Type, Ref}, Svc, [Opt])
-> {ok, Pid}
| {ok, Pid, [LAddr]}
| {error, Reason}</name>
diff --git a/lib/diameter/doc/src/diameter_transport.xml b/lib/diameter/doc/src/diameter_transport.xml
index 294e8a8864..0a8ef321c6 100644
--- a/lib/diameter/doc/src/diameter_transport.xml
+++ b/lib/diameter/doc/src/diameter_transport.xml
@@ -14,7 +14,8 @@
<erlref>
<header>
<copyright>
-<year>2011</year><year>2016</year>
+<year>2011</year>
+<year>2019</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,7 +44,7 @@ limitations under the License.
<file>diameter_transport.xml</file>
</header>
-<module>diameter_transport</module>
+<module since="OTP R14B03">diameter_transport</module>
<modulesummary>Diameter transport interface.</modulesummary>
<description>
@@ -94,7 +95,7 @@ and has the binary() to send in its <c>bin</c> field.</p>
<funcs>
<func>
-<name>Mod:start({Type, Ref}, Svc, Config)
+<name since="OTP R14B03">Mod:start({Type, Ref}, Svc, Config)
-> {ok, Pid}
| {ok, Pid, LAddrs}
| {error, Reason}</name>
@@ -174,10 +175,13 @@ its parent.</p>
<taglist>
-<tag><c>{diameter, {send, &message;}}</c></tag>
+<tag><c>{diameter, {send, &message; | false}}</c></tag>
<item>
<p>
-An outbound Diameter message.</p>
+An outbound Diameter message.
+The atom <c>false</c> can only be received when request
+acknowledgements have been requests: see the <c>ack</c> message
+below.</p>
</item>
<tag><c>{diameter, {close, Pid}}</c></tag>
@@ -246,6 +250,27 @@ A <c>LocalAddr</c> list has the same semantics as one returned from
&start;.</p>
</item>
+<tag><c>{diameter, ack}</c></tag>
+<item>
+<p>
+Request acknowledgements of unanswered requests.
+A transport process should send this once before passing incoming
+Diameter messages into diameter.
+As a result, every Diameter request passed into diameter with a
+<c>recv</c> message (below) will be answered with a
+<c>send</c> message (above), either a &message; for the transport
+process to send or the atom <c>false</c> if the request has been
+discarded or otherwise not answered.</p>
+
+<p>
+This is to allow a transport process to keep count of the number
+of incoming request messages that have not yet been answered or
+discarded, to allow it to regulate the amount of incoming traffic.
+Both diameter_tcp and diameter_sctp request acknowledgements when a
+<c>message_cb</c> is configured, turning send/recv message into
+callbacks that can be used to regulate traffic.</p>
+</item>
+
<tag><c>{diameter, {recv, &message;}}</c></tag>
<item>
<p>
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index 3232c3380a..8dcba93273 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -43,6 +43,78 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix inadvertently broad monitor that resulted in
+ gen_server cast messages to hidden nodes from module
+ diameter_dist.</p>
+ <p>
+ Own Id: OTP-15768</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix failure of incoming answer message with faulty
+ Experimental-Result-Code. Failure to decode the AVP
+ resulted in an uncaught exception, with no no
+ handle_answer/error callback as a consequence.</p>
+ <p>
+ Own Id: OTP-15569 Aux Id: ERIERL-302 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add spawn_opt MFA configuration to allow a callback to
+ spawn a handler process for an incoming Diameter request
+ on an an arbitrary node. Module diameter_dist provides a
+ route_session/2 that can be used to distribute requests
+ based on Session-Id, although this module is currently
+ only documented in the module itself and may change.</p>
+ <p>
+ Own Id: OTP-15398</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix function_clause when sending an outgoing request
+ after DPA has been sent in response to an incoming DPR.
+ The caused the diameter_peer_fsm gen_server associated
+ with the peer connection to fail, which could then result
+ in the transport connection being reset before the peer
+ closed it upon reception of DPA.</p>
+ <p>
+ Own Id: OTP-15198 Aux Id: ERIERL-213 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 2.1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -58,6 +130,24 @@ first.</p>
</section>
+<section><title>diameter 2.1.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix failure of incoming answer message with faulty
+ Experimental-Result-Code. Failure to decode the AVP
+ resulted in an uncaught exception, with no no
+ handle_answer/error callback as a consequence.</p>
+ <p>
+ Own Id: OTP-15569 Aux Id: ERIERL-302 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 2.1.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index b90b794611..7f172e1fa1 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -365,7 +365,7 @@ call(SvcName, App, Message) ->
| {connect_timer, 'Unsigned32'()}
| {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}
| {watchdog_config, [{okay|suspect, non_neg_integer()}]}
- | {spawn_opt, list()}.
+ | {spawn_opt, list() | mfa()}.
%% Options passed to start_service/2
diff --git a/lib/diameter/src/base/diameter_callback.erl b/lib/diameter/src/base/diameter_callback.erl
index d04a416bef..3bcf550cd8 100644
--- a/lib/diameter/src/base/diameter_callback.erl
+++ b/lib/diameter/src/base/diameter_callback.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -70,7 +70,7 @@
-module(diameter_callback).
-%% Default callbacks when no aleternate is specified.
+%% Default callbacks when no alternate is specified.
-export([peer_up/3,
peer_down/3,
pick_peer/4,
diff --git a/lib/diameter/src/base/diameter_dist.erl b/lib/diameter/src/base/diameter_dist.erl
new file mode 100644
index 0000000000..ed23152b8b
--- /dev/null
+++ b/lib/diameter/src/base/diameter_dist.erl
@@ -0,0 +1,535 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(diameter_dist).
+
+-behaviour(gen_server).
+
+%%
+%% Implements callbacks that can be configured as a spawn_opt
+%% transport configuration, to be able to distribute incoming Diameter
+%% requests to handler processes (local or remote) in various ways.
+%%
+
+%% spawn_opt callbacks
+-export([spawn_local/2,
+ spawn_local/1,
+ route_session/2,
+ route_session/1]).
+
+%% signal availability for handling incoming requests to route_sesssion/2
+-export([attach/1,
+ detach/1]).
+
+%% consistent hashing
+-export([hash/3, %% for use as default MFA in route_session/2 options map
+ hash/2]). %% arbitrary key/values
+
+-include_lib("diameter/include/diameter.hrl").
+
+%% server start
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_info/2,
+ handle_cast/2,
+ handle_call/3,
+ code_change/3,
+ terminate/2]).
+
+-type request() :: tuple(). %% callback argument from diameter_traffic
+
+-define(SERVER, ?MODULE). %% server monitoring node connections
+
+%% Maps a node name binary to the corresponding atom. Used by
+%% route_session/2 to map the optional value of a Session-Id to
+%% node().
+-define(NODE_TABLE, diameter_dist_node).
+
+%% Maps a diameter:service_name() to a node() that has called attach/1
+%% to declare its willingness to handle incoming requests for the
+%% service. Use by route_session/2 in case the optional value mapping
+%% has failed.
+-define(SERVICE_TABLE, diameter_dist_service).
+
+-define(B(A), atom_to_binary(A, utf8)).
+-define(ORCOND(List), list_to_tuple(['orelse', false | List])).
+-define(HASH(T), erlang:phash2(T, 16#100000000)).
+
+%% spawn_local/2
+%%
+%% Callback that is equivalent to an options list. That is, the
+%% following are equivalent when passed as options to
+%% diameter:add_transport/2.
+%%
+%% {spawn_opt, Opts}
+%% {spawn_opt, {diameter_dist, spawn_local, [Opts]}}
+
+-spec spawn_local(ReqT :: request(), Opts :: list())
+ -> pid().
+
+spawn_local(ReqT, Opts) ->
+ spawn_opt(diameter_traffic, request, [ReqT], Opts).
+
+%% spawn_local/1
+
+spawn_local(ReqT) ->
+ spawn_local(ReqT, []).
+
+%% route_session/2
+%%
+%% Callback that maps the Session-Id of an incoming request to a
+%% handler node.
+%%
+%% With an options list, maps an id whose optional value is the name
+%% of a connected node to the same node, to handle the case that the
+%% session id has been returned from diameter:session_id/1; otherwise
+%% to a node that has called diameter_dist:attach/1 using the
+%% consistent hashing provided by hash/3, or to the local node() if a
+%% session id could not be extracted or there are no attached nodes. A
+%% handler process is spawned on the selected node using
+%% erlang:spawn_opt/4.
+%%
+%% Different behaviour can be configured by supplying an options map
+%% of the following form:
+%%
+%% #{search => non_neg_integer(),
+%% id => [binary()],
+%% default => discard | local | mfa(),
+%% dispatch => list() | mfa()}
+%%
+%% The search member limits the number of AVPs that are examined in
+%% the message (from the front), to avoid searching entire message in
+%% case it's known that peers follow RFC 6733's recommendation that
+%% Session-Id be placed at the head of a message. The default is to
+%% search the entire message.
+%%
+%% The id member restricts the optional value mapping to session ids
+%% whose DiamterIdentity is one of those specified. Set this to the
+%% list of Diameter identities advertised by the service in question
+%% (typically one) to ensure that only locally generated session ids
+%% are mapped; or to the empty list to disable the mapping.
+%%
+%% The default member determines where to handle a message whose
+%% Session-Id isn't found or whose optional value isn't mapped to the
+%% name of a connected node. The atom local says the local node, an
+%% MFA is invoked on Session-Id | false, the name of the diameter
+%% service, and the message binary, and should return either a node()
+%% or false to discard the message. Defaults to {diameter_dist, hash, []}.
+%%
+%% The dispatch member determines how the pid() of the request handler
+%% process is retrieved. An MFA is applied to a previously selected
+%% node(), and the module, function, and arguments list to apply in
+%% the handler process to handle the request, the MFA being supplied
+%% by diameter, and returns pid() | discard. A list is equivalent to
+%% {erlang, spawn_opt, []}. Defaults to [].
+%%
+%% This can be used with search = 0 to route on something other than
+%% Session-Id, but this is probably no simpler than just implementing
+%% an own spawn_opt callback. (Except with the default dispatch possibly.)
+%%
+%% Note that if the peer is also implemented with OTP diameter and
+%% generating session ids with diameter:session_id/1 then
+%% route_session/2 can map an optional value to a local node that
+%% happens to have the same name as one of the peer's nodes. This
+%% could lead to an uneven distribution; for example, if the peer
+%% nodes are a subset of the local nodes. In practice, it's typically
+%% known if it's peers or the local node originating sessions; if the
+%% former then setting id = [] disables the optional value mapping, if
+%% the latter then setting default = local disables the hashing.
+-spec route_session(ReqT :: request(), Opts)
+ -> discard
+ | pid()
+ when Opts :: pos_integer() %% aka #{search => N}
+ | list() %% aka #{dispatch => Opts}
+ | #{search => non_neg_integer(), %% limit number of examined AVPs
+ id => [binary()], %% restrict optional value map on DiamIdent
+ default => local %% handle locally
+ | discard
+ | mfa(), %% return node() | false
+ dispatch => list() %% spawn options
+ | mfa()}. %% (Node, M, F, A) -> pid() | discard
+
+route_session(ReqT, Opts) ->
+ {_, Bin} = Info = diameter_traffic:request_info(ReqT),
+ Sid = session_id(avps(Bin), search(Opts)),
+ Node = default(node_of_session_id(Sid, Opts), Sid, Opts, Info),
+ dispatch(Node, ReqT, dispatch(Opts)).
+
+%% avps/1
+
+avps(<<_:20/binary, Bin/binary>>) ->
+ Bin;
+
+avps(_) ->
+ false.
+
+%% dispatch/3
+
+dispatch(false, _, _) ->
+ discard;
+
+dispatch(Node, ReqT, {M,F,A}) ->
+ apply(M, F, [Node, diameter_traffic, request, [ReqT] | A]);
+
+dispatch(Node, ReqT, Opts) ->
+ spawn_opt(Node, diameter_traffic, request, [ReqT], Opts).
+
+%% route_session/1
+
+route_session(ReqT) ->
+ route_session(ReqT, []).
+
+%% node_of_session_id/2
+%%
+%% Return the node name encoded as optional value in a Session-Id,
+%% assuming the id has been created with diameter:session_id/0. Lookup
+%% the node name to ensure we don't convert arbitrary binaries to
+%% atom.
+
+node_of_session_id([Id, _, _, Bin], #{id := Ids}) ->
+ lists:member(Id, Ids) andalso nodemap(Bin);
+
+node_of_session_id([_, _, _, Bin], _) ->
+ nodemap(Bin);
+
+node_of_session_id(_, _) ->
+ false.
+
+%% nodemap/1
+
+nodemap(Bin) ->
+ try
+ ets:lookup_element(?NODE_TABLE, Bin, 2)
+ catch
+ error: badarg -> false
+ end.
+
+%% session_id/2
+
+session_id(_, 0) -> %% give up
+ false;
+
+%% Session-Id = Command Code 263, V-bit = 0.
+session_id(<<263:32, 0:1, _:7, Len:24, _/binary>> = Bin, _) ->
+ case Bin of
+ <<Avp:Len/binary, _/binary>> ->
+ <<_:8/binary, Sid/binary>> = Avp,
+ split(Sid);
+ _ ->
+ false
+ end;
+
+%% Jump to the next AVP. This is potentially costly for a message with
+%% many AVPs and no Session-Id, which an attacker is prone to send.
+%% 8.8 or RFC 6733 says that Session-Id SHOULD (but not MUST) appear
+%% immediately following the Diameter Header, so there is no
+%% guarantee.
+session_id(<<_:40, Len:24, _/binary>> = Bin, N) ->
+ Pad = (4 - (Len rem 4)) rem 4,
+ case Bin of
+ <<_:Len/binary, _:Pad/binary, Rest/binary>> ->
+ session_id(Rest, if N == infinity -> N; true -> N-1 end);
+ _ ->
+ false
+ end;
+
+session_id(_, _) ->
+ false.
+
+%% split/1
+%%
+%% Split a Session-Id at no more than three semicolons: the optional
+%% value (if any) follows the third. binary:split/2 does better than
+%% matching character by character, especially when the pattern is
+%% compiled.
+
+split(Bin) ->
+ split(3, Bin, pattern()).
+
+%% split/3
+
+split(0, Bin, _) ->
+ [Bin];
+
+split(N, Bin, Pattern) ->
+ [H|T] = binary:split(Bin, Pattern),
+ [H | case T of
+ [] ->
+ T;
+ [Rest] ->
+ split(N-1, Rest, Pattern)
+ end].
+
+%% pattern/0
+%%
+%% Since this is being called in a watchdog process, compile the
+%% pattern once and maintain it in the process dictionary.
+
+pattern() ->
+ case get(?MODULE) of
+ undefined ->
+ CP = binary:compile_pattern(<<$;>>), %% tuple
+ put(?MODULE, CP),
+ CP;
+ CP ->
+ CP
+ end.
+
+%% dispatch/1
+
+dispatch(#{} = Opts) ->
+ maps:get(dispatch, Opts, []);
+
+dispatch(Opts)
+ when is_list(Opts) ->
+ Opts;
+
+dispatch(_) ->
+ [].
+
+%% search/1
+%%
+%% Bound number of AVPs examined when looking for Session-Id.
+
+search(#{search := N})
+ when is_integer(N), 0 =< N ->
+ N;
+
+search(N)
+ when is_integer(N), 0 =< N ->
+ N;
+
+search(_) ->
+ infinity.
+
+%% default/3
+%%
+%% Choose a node when Session-Id lookup has failed.
+
+default(false, _, #{default := discard}, _) ->
+ false;
+
+default(false, _, #{default := local}, _) ->
+ node();
+
+default(false, Sid, #{default := {M,F,A}}, Info) ->
+ {ServiceName, Bin} = Info,
+ apply(M, F, [Sid, ServiceName, Bin | A]); %% node() | false
+
+default(false, Sid, _, Info) -> %% aka {?MODULE, hash, []}
+ {ServiceName, Bin} = Info,
+ hash(Sid, ServiceName, Bin);
+
+default(Node, _, _, _) ->
+ Node.
+
+%% ===========================================================================
+
+%% hash/3
+%%
+%% Consistent hashing of Session-Id to an attached node, or the local
+%% node if Session-Id = false or no attached nodes.
+
+hash(Sid, ServiceName, _) ->
+ case false /= Sid andalso attached(ServiceName) of
+ [_|_] = Nodes ->
+ hash(Sid, Nodes);
+ _ ->
+ node()
+ end.
+
+%% hash/2
+%%
+%% Consistent hashing on arbitrary key/values. Returns false if the
+%% list is empty.
+
+%% No key or no values.
+hash(_, []) ->
+ false;
+
+%% Not much choice.
+hash(_, [Value]) ->
+ Value;
+
+%% Hash on a circle and choose the closest predecessor.
+hash(Key, Values) ->
+ Hash = ?HASH(Key),
+ tl(lists:foldl(fun(V,A) ->
+ choose(Hash, [?HASH({Key, V}) | V], A)
+ end,
+ false, %% < list()
+ Values)).
+
+%% choose/3
+
+choose(Hash, [Hash1 | _] = T, [Hash2 | _])
+ when Hash1 =< Hash, Hash < Hash2 ->
+ T;
+
+choose(Hash, [Hash1 | _], [Hash2 | _] = T)
+ when Hash2 =< Hash, Hash < Hash1 ->
+ T;
+
+choose(_, T1, T2) ->
+ max(T1, T2).
+
+%% ===========================================================================
+
+%% attach/1
+%%
+%% Register the local node as a handler of incoming requests for the
+%% specified services when using the route_session/2 spawn_opt
+%% callback.
+
+attach(ServiceNames) ->
+ abcast({attach, node(), ServiceNames}).
+
+%% detach/1
+%%
+%% Deregister the local node as a handler of incoming requests.
+
+detach(ServiceNames) ->
+ abcast({detach, node(), ServiceNames}).
+
+%% abcast/1
+
+abcast(T) ->
+ gen_server:abcast([node() | nodes()], ?SERVER, T),
+ ok.
+
+%% attached/1
+
+attached(ServiceName) ->
+ try
+ ets:lookup_element(?SERVICE_TABLE, ServiceName, 2)
+ catch
+ error: badarg -> []
+ end.
+
+%% cast/2
+
+cast(Node, T) ->
+ gen_server:cast({?SERVER, Node}, T).
+
+%% attach/2
+
+attach(Node, S) ->
+ case sets:to_list(S) of
+ [] ->
+ ok;
+ Services ->
+ cast(Node, {attach, node(), Services})
+ end.
+
+%% ===========================================================================
+
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, _Args = [], _Opts = []).
+
+%% init/1
+%%
+%% Maintain [node() | nodes()] in a table that maps from binary-valued
+%% names, so we can lookup the corresponding atoms rather than convert
+%% binaries that aren't necessarily node names.
+
+init([]) ->
+ ets:new(?NODE_TABLE, [set, named_table]),
+ ets:new(?SERVICE_TABLE, [bag, named_table]),
+ ok = net_kernel:monitor_nodes(true, [{node_type, visible},
+ nodedown_reason]),
+ ets:insert(?NODE_TABLE, [{?B(N), N} || N <- [node() | nodes()]]),
+ abcast({attach, node()}),
+ {ok, sets:new()}.
+
+%% handle_call/3
+
+handle_call(_, _From, S) ->
+ {reply, nok, S}.
+
+%% handle_cast/2
+
+%% Remote node is asking which services the local node wants to handle.
+handle_cast({attach, Node}, S)
+ when Node /= node() ->
+ attach(Node, S),
+ {noreply, S};
+
+%% Node wants to handle incoming requests ...
+handle_cast({attach, Node, ServiceNames}, S) ->
+ ets:insert(?SERVICE_TABLE, [{N, Node} || N <- ServiceNames]),
+ {noreply, case node() of
+ Node ->
+ sets:union(S, sets:from_list(ServiceNames));
+ _ ->
+ S
+ end};
+
+%% ... or not.
+handle_cast({detach, Node, ServiceNames}, S) ->
+ ets:select_delete(?SERVICE_TABLE, [{{'$1', Node},
+ [?ORCOND([{'==', '$1', {const, N}}
+ || N <- ServiceNames])],
+ [true]}]),
+ {noreply, case node() of
+ Node ->
+ sets:subtract(S, sets:from_list(ServiceNames));
+ _ ->
+ S
+ end};
+
+handle_cast(_, S) ->
+ {noreply, S}.
+
+%% handle_info/2
+
+handle_info({nodeup, Node, _}, S) ->
+ ets:insert(?NODE_TABLE, {?B(Node), Node}),
+ cast(Node, {attach, node()}), %% ask which services remote node handles
+ attach(Node, S), %% say which service local node handles
+ {noreply, S};
+
+handle_info({nodedown, Node, _}, S) ->
+ ets:delete(?NODE_TABLE, ?B(Node)),
+ ets:select_delete(?SERVICE_TABLE, [{{'_', Node}, [], [true]}]),
+ {noreply, S};
+
+handle_info(_, S) ->
+ {noreply, S}.
+
+%% terminate/2
+
+terminate(_, _) ->
+ ok.
+
+%% code_change/3
+
+%% Old code inadvertently monitored all nodes: start a new
+%% subscription and remove the old one.
+code_change(_OldVsn, State, "2.2") ->
+ ok = net_kernel:monitor_nodes(true, [{node_type, visible},
+ nodedown_reason]),
+ ok = net_kernel:monitor_nodes(false, [{node_type, all},
+ nodedown_reason]),
+ {ok, State};
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index d110a3015e..564448de48 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/diameter/src/base/diameter_misc_sup.erl b/lib/diameter/src/base/diameter_misc_sup.erl
index 343688be23..fec5a41b5c 100644
--- a/lib/diameter/src/base/diameter_misc_sup.erl
+++ b/lib/diameter/src/base/diameter_misc_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
diameter_stats, %% statistics counter management
diameter_reg, %% service/property publishing
diameter_peer, %% remote peer manager
+ diameter_dist, %% request distribution
diameter_config]). %% configuration/restart
%% start_link/0
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index d99f11a697..cf5e7f21d3 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -901,7 +901,7 @@ outgoing(#diameter_packet{header = #diameter_header{is_request = false}}
ok;
%% Outgoing request: discard.
-outgoing(Msg, #state{dpr = {_,_,_}}) ->
+outgoing(Msg, #state{}) ->
invalid(false, send_after_dpr, header(Msg)).
header(#diameter_packet{header = H}) ->
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index d2856ae530..8423e30269 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,8 +42,12 @@
peer_up/1,
peer_down/1]).
+%% towards diameter_dist
+-export([request_info/1]).
+
%% internal
-export([send/1, %% send from remote node
+ request/1, %% process request in handler process
init/1]). %% monitor process start
-include_lib("diameter/include/diameter.hrl").
@@ -232,7 +236,7 @@ incr_rc(Dir, Pkt, TPid, MsgDict, AppDict, Dict0) ->
-spec receive_message(pid(), Route, #diameter_packet{}, module(), RecvData)
-> pid() %% request handler
| boolean() %% answer, known request or not
- | discard %% request discarded by MFA
+ | discard %% request discarded
when Route :: {Handler, RequestRef, TPid}
| Ack,
RecvData :: {[SpawnOpt], #recvdata{}},
@@ -252,7 +256,8 @@ receive_message(TPid, Route, Pkt, Dict0, RecvData) ->
recv(true, Ack, TPid, Pkt, Dict0, T)
when is_boolean(Ack) ->
{Opts, RecvData} = T,
- spawn_request(Ack, TPid, Pkt, Dict0, RecvData, Opts);
+ AppT = find_app(TPid, Pkt, RecvData),
+ ack(Ack, TPid, spawn_request(AppT, Opts, Ack, TPid, Pkt, Dict0, RecvData));
%% ... answer to known request ...
recv(false, {Pid, Ref, TPid}, _, Pkt, Dict0, _) ->
@@ -274,58 +279,73 @@ recv(false, false, TPid, Pkt, _, _) ->
incr(TPid, {{unknown, 0}, recv, discarded}),
false.
-%% spawn_request/6
+%% spawn_request/7
+
+spawn_request(false, _, _, _, _, _, _) -> %% no transport
+ discard;
-%% An MFA should return a pid() or the atom 'discard'. The latter
-%% results in an acknowledgment back to the transport process when
-%% appropriate, to ensure that send/recv callbacks can count
-%% outstanding requests. Acknowledgement is implicit if the
+%% An MFA should return the pid() of a process in which the argument
+%% fun in applied, or the atom 'discard' if the fun is not applied.
+%% The latter results in an acknowledgment back to the transport
+%% process when appropriate, to ensure that send/recv callbacks can
+%% count outstanding requests. Acknowledgement is implicit if the
%% handler process dies (in a handle_request callback for example).
-spawn_request(Ack, TPid, Pkt, Dict0, RecvData, {M,F,A}) ->
- ReqF = fun() ->
- ack(Ack, TPid, recv_request(Ack, TPid, Pkt, Dict0, RecvData))
- end,
- ack(Ack, TPid, apply(M, F, [ReqF | A]));
+spawn_request(AppT, {M,F,A}, Ack, TPid, Pkt, Dict0, RecvData) ->
+ %% Term to pass to request/1 in an appropriate process. Module
+ %% diameter_dist implements callbacks.
+ ReqT = {Pkt, AppT, Ack, TPid, Dict0, RecvData},
+ apply(M, F, [ReqT | A]);
%% A spawned process acks implicitly when it dies, so there's no need
%% to handle 'discard'.
-spawn_request(Ack, TPid, Pkt, Dict0, RecvData, Opts) ->
+spawn_request(AppT, Opts, Ack, TPid, Pkt, Dict0, RecvData) ->
spawn_opt(fun() ->
- recv_request(Ack, TPid, Pkt, Dict0, RecvData)
+ recv_request(Ack, TPid, Pkt, Dict0, RecvData, AppT)
end,
Opts).
+%% request_info/1
+%%
+%% Limited request information for diameter_dist.
+
+request_info({Pkt, _AppT, _Ack, _TPid, _Dict0, RecvData} = _ReqT) ->
+ {RecvData#recvdata.service_name, Pkt#diameter_packet.bin}.
+
+%% request/1
+%%
+%% Called from a handler process chosen by a transport spawn_opt MFA
+%% to process an incoming request.
+
+request({Pkt, AppT, Ack, TPid, Dict0, RecvData} = _ReqT) ->
+ ack(Ack, TPid, recv_request(Ack, TPid, Pkt, Dict0, RecvData, AppT)).
+
%% ack/3
ack(Ack, TPid, RC) ->
- RC == discard andalso Ack andalso (TPid ! {send, false}),
+ RC == discard
+ andalso Ack
+ andalso (TPid ! {send, false}),
RC.
%% ---------------------------------------------------------------------------
-%% recv_request/5
+%% recv_request/6
%% ---------------------------------------------------------------------------
-spec recv_request(Ack :: boolean(),
TPid :: pid(),
#diameter_packet{},
Dict0 :: module(),
- #recvdata{})
+ #recvdata{},
+ AppT :: {#diameter_app{}, #diameter_caps{}}
+ | #diameter_caps{}) %% no suitable app
-> ok %% answer was sent
- | discard %% or not
- | false. %% no transport
-
-recv_request(Ack,
- TPid,
- #diameter_packet{header = #diameter_header{application_id = Id}}
- = Pkt,
- Dict0,
- #recvdata{peerT = PeerT,
- apps = Apps,
- counters = Count}
- = RecvData) ->
+ | discard. %% or not
+
+recv_request(Ack, TPid, Pkt, Dict0, RecvData, AppT) ->
Ack andalso (TPid ! {handler, self()}),
- case diameter_service:find_incoming_app(PeerT, TPid, Id, Apps) of
+ case AppT of
{#diameter_app{id = Aid, dictionary = AppDict} = App, Caps} ->
+ Count = RecvData#recvdata.counters,
Count andalso incr(recv, Pkt, TPid, AppDict),
DecPkt = decode(Aid, AppDict, RecvData, Pkt),
Count andalso incr_error(recv, DecPkt, TPid, AppDict),
@@ -349,11 +369,20 @@ recv_request(Ack,
Dict0,
RecvData,
DecPkt,
- [[]]);
- false = No -> %% transport has gone down
- No
+ [[]])
end.
+%% find_app/3
+%%
+%% Lookup the application of a received Diameter request on the node
+%% on which it's received.
+
+find_app(TPid,
+ #diameter_packet{header = #diameter_header{application_id = Id}},
+ #recvdata{peerT = PeerT,
+ apps = Apps}) ->
+ diameter_service:find_incoming_app(PeerT, TPid, Id, Apps).
+
%% decode/4
decode(Id, Dict, #recvdata{codec = Opts}, Pkt) ->
@@ -1925,6 +1954,8 @@ get_avp(Dict, Name, [#diameter_header{} | Avps]) ->
A = find_avp(Code, Vid, Avps),
avp_decode(Dict, Name, ungroup(A))
catch
+ {diameter_gen, _} -> %% faulty Grouped AVP
+ undefined;
error: _ ->
undefined
end;
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index 3389f11937..bb2a4a8e92 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,7 +58,11 @@
{"2.1.1", [{restart_application, diameter}]}, %% 20.1.2
{"2.1.2", [{restart_application, diameter}]}, %% 20.1.3
{"2.1.3", [{restart_application, diameter}]}, %% 20.2
- {"2.1.4", [{restart_application, diameter}]} %% 20.3
+ {"2.1.4", [{restart_application, diameter}]}, %% 20.3
+ {"2.1.4.1", [{restart_application, diameter}]}, %% 20.3.8.19
+ {"2.1.5", [{restart_application, diameter}]}, %% 21.0
+ {"2.1.6", [{restart_application, diameter}]}, %% 21.1
+ {"2.2", [{update, diameter_dist, {advanced, "2.2"}}]} %% 21.3
],
[
{"0.9", [{restart_application, diameter}]},
@@ -98,6 +102,10 @@
{"2.1.1", [{restart_application, diameter}]},
{"2.1.2", [{restart_application, diameter}]},
{"2.1.3", [{restart_application, diameter}]},
- {"2.1.4", [{restart_application, diameter}]}
+ {"2.1.4", [{restart_application, diameter}]},
+ {"2.1.4.1", [{restart_application, diameter}]},
+ {"2.1.5", [{restart_application, diameter}]},
+ {"2.1.6", [{restart_application, diameter}]},
+ {"2.2", [{restart_application, diameter}]}
]
}.
diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk
index bb86de016a..d16292bb88 100644
--- a/lib/diameter/src/modules.mk
+++ b/lib/diameter/src/modules.mk
@@ -1,7 +1,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2017. All Rights Reserved.
+# Copyright Ericsson AB 2010-2019. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ RT_MODULES = \
base/diameter_config \
base/diameter_config_sup \
base/diameter_codec \
+ base/diameter_dist \
base/diameter_gen \
base/diameter_lib \
base/diameter_misc_sup \
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index da059fa7d6..e5e766d2a0 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -92,9 +92,9 @@
-type connect_option() :: {raddr, inet:ip_address()}
| {rport, pos_integer()}
- | {ssl_options, true | [ssl:connect_option()]}
+ | {ssl_options, true | [ssl:tls_client_option()]}
| option()
- | ssl:connect_option()
+ | ssl:tls_client_option()
| gen_tcp:connect_option().
-type match() :: inet:ip_address()
@@ -102,9 +102,9 @@
| [match()].
-type listen_option() :: {accept, match()}
- | {ssl_options, true | [ssl:listen_option()]}
+ | {ssl_options, true | [ssl:tls_server_option()]}
| option()
- | ssl:listen_option()
+ | ssl:tls_server_option()
| gen_tcp:listen_option().
-type option() :: {port, non_neg_integer()}
diff --git a/lib/diameter/test/diameter_dist_SUITE.erl b/lib/diameter/test/diameter_dist_SUITE.erl
new file mode 100644
index 0000000000..b2e4c35b9a
--- /dev/null
+++ b/lib/diameter/test/diameter_dist_SUITE.erl
@@ -0,0 +1,332 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between two Diameter nodes, the server being
+%% spread across three Erlang nodes.
+%%
+
+-module(diameter_dist_SUITE).
+
+-export([suite/0,
+ all/0]).
+
+%% testcases
+-export([enslave/1, enslave/0,
+ ping/1,
+ start/1,
+ connect/1,
+ send/1,
+ stop/1, stop/0]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-export([call/1]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc6733.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(CLIENT, 'CLIENT').
+-define(SERVER, 'SERVER').
+-define(REALM, "erlang.org").
+-define(DICT, diameter_gen_base_rfc6733).
+-define(ADDR, {127,0,0,1}).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host),
+ [{'Origin-Host', Host ++ [$.|?REALM]},
+ {'Origin-Realm', ?REALM},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Auth-Application-Id', [?DICT:id()]},
+ {'Origin-State-Id', origin()},
+ {spawn_opt, {diameter_dist, route_session, [#{id => []}]}},
+ {sequence, fun sequence/0},
+ {string_decode, false},
+ {application, [{dictionary, ?DICT},
+ {module, ?MODULE},
+ {request_errors, callback},
+ {answer_errors, callback}]}]).
+
+-define(SUCCESS, 2001).
+-define(BUSY, 3004).
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
+-define(MOVED, ?'DIAMETER_BASE_TERMINATION-CAUSE_USER_MOVED').
+-define(TIMEOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_SESSION_TIMEOUT').
+
+-define(L, atom_to_list).
+-define(A, list_to_atom).
+
+%% The order here is significant and causes the server to listen
+%% before the clients connect. The server listens on the first node,
+%% and distributes requests to the other two.
+-define(NODES, [{server0, ?SERVER},
+ {server1, ?SERVER},
+ {server2, ?SERVER},
+ {client, ?CLIENT}]).
+
+%% Options to ct_slave:start/2.
+-define(TIMEOUTS, [{T, 15000} || T <- [boot_timeout,
+ init_timeout,
+ start_timeout]]).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 60}}].
+
+all() ->
+ [enslave,
+ ping,
+ start,
+ connect,
+ send,
+ stop].
+
+%% ===========================================================================
+%% start/stop testcases
+
+%% enslave/1
+%%
+%% Start four slave nodes, three to implement a Diameter server,
+%% one to implement a client.
+
+enslave() ->
+ [{timetrap, {seconds, 30*length(?NODES)}}].
+
+enslave(Config) ->
+ Here = filename:dirname(code:which(?MODULE)),
+ Ebin = filename:join([Here, "..", "ebin"]),
+ Dirs = [Here, Ebin],
+ Nodes = [{N,S} || {M,S} <- ?NODES, N <- [slave(M, Dirs)]],
+ ?util:write_priv(Config, nodes, [{N,S} || {{N,ok},S} <- Nodes]),
+ [] = [{T,S} || {{_,E} = T, S} <- Nodes, E /= ok].
+
+slave(Name, Dirs) ->
+ add_pathsa(Dirs, ct_slave:start(Name, ?TIMEOUTS)).
+
+add_pathsa(Dirs, {ok, Node}) ->
+ {Node, rpc:call(Node, code, add_pathsa, [Dirs])};
+add_pathsa(_, No) ->
+ {No, error}.
+
+%% ping/1
+%%
+%% Ensure the server nodes are connected so that diameter_dist can attach.
+
+ping({S, Nodes}) ->
+ ?SERVER = S,
+ [N || {N,_} <- Nodes,
+ node() /= N,
+ pang <- [net_adm:ping(N)]];
+
+ping(Config) ->
+ Nodes = lists:droplast(?util:read_priv(Config, nodes)),
+ [] = [{N,RC} || {N,S} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, ping, [{S,Nodes}])],
+ RC /= []].
+
+%% start/1
+%%
+%% Start diameter services.
+
+start(SvcName)
+ when is_atom(SvcName) ->
+ ok = diameter:start(),
+ ok = diameter:start_service(SvcName, ?SERVICE((?L(SvcName))));
+
+start(Config) ->
+ Nodes = ?util:read_priv(Config, nodes),
+ [] = [{N,RC} || {N,S} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, start, [S])],
+ RC /= ok].
+
+sequence() ->
+ sequence(sname()).
+
+sequence(client) ->
+ {0,32};
+sequence(Server) ->
+ "server" ++ N = ?L(Server),
+ {list_to_integer(N), 30}.
+
+origin() ->
+ origin(sname()).
+
+origin(client) ->
+ 99;
+origin(Server) ->
+ "server" ++ N = ?L(Server),
+ list_to_integer(N).
+
+%% connect/1
+%%
+%% Establish one connection from the client, terminated on the first
+%% server node, the others handling requests.
+
+connect({?SERVER, Config, [{Node, _} | _]}) ->
+ if Node == node() -> %% server0
+ ?util:write_priv(Config, lref, {Node, ?util:listen(?SERVER, tcp)});
+ true ->
+ diameter_dist:attach([?SERVER])
+ end,
+ ok;
+
+connect({?CLIENT, Config, _}) ->
+ ?util:connect(?CLIENT, tcp, ?util:read_priv(Config, lref)),
+ ok;
+
+connect(Config) ->
+ Nodes = ?util:read_priv(Config, nodes),
+ [] = [{N,RC} || {N,S} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, connect, [{S, Config, Nodes}])],
+ RC /= ok].
+
+%% stop/1
+%%
+%% Stop the slave nodes.
+
+stop() ->
+ [{timetrap, {seconds, 30*length(?NODES)}}].
+
+stop(_Config) ->
+ [] = [{N,E} || {N,_} <- ?NODES,
+ {error, _, _} = E <- [ct_slave:stop(N)]].
+
+%% ===========================================================================
+%% traffic testcases
+
+%% send/1
+%%
+%% Send 100 requests and ensure the node name sent as User-Name isn't
+%% the node terminating transport.
+
+send(Config) ->
+ send(Config, 100, dict:new()).
+
+%% send/2
+
+send(Config, 0, Dict) ->
+ [{Server0, _} | _] = ?util:read_priv(Config, nodes) ,
+ Node = atom_to_binary(Server0, utf8),
+ {false, _} = {dict:is_key(Node, Dict), dict:to_list(Dict)};
+
+send(Config, N, Dict) ->
+ #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'User-Name' = [ServerNode]}
+ = send(Config, str(?LOGOUT)),
+ true = is_binary(ServerNode),
+ send(Config, N-1, dict:update_counter(ServerNode, 1, Dict)).
+
+%% ===========================================================================
+
+str(Cause) ->
+ #diameter_base_STR{'Destination-Realm' = ?REALM,
+ 'Auth-Application-Id' = ?DICT:id(),
+ 'Termination-Cause' = Cause}.
+
+%% send/2
+
+send(Config, Req) ->
+ {Node, _} = lists:last(?util:read_priv(Config, nodes)),
+ rpc:call(Node, ?MODULE, call, [Req]).
+
+%% call/1
+
+call(Req) ->
+ diameter:call(?CLIENT, ?DICT, Req, []).
+
+%% sname/0
+
+sname() ->
+ ?A(hd(string:tokens(?L(node()), "@"))).
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+pick_peer([Peer], [], ?CLIENT, _State) ->
+ {ok, Peer}.
+
+%% prepare_request/3
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}) ->
+ #diameter_packet{msg = Req}
+ = Pkt,
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+ {send, Req#diameter_base_STR{'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'Session-Id' = diameter:session_id(OH)}}.
+
+%% prepare_retransmit/3
+
+prepare_retransmit(_, ?CLIENT, _) ->
+ discard.
+
+%% handle_answer/5
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ #diameter_packet{msg = Rec, errors = []} = Pkt,
+ Rec.
+
+%% handle_error/5
+
+handle_error(Reason, _Req, ?CLIENT, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+handle_request(Pkt, ?SERVER, {_, Caps}) ->
+ #diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId}}
+ = Pkt,
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'User-Name' = [atom_to_binary(node(), utf8)]}}.
diff --git a/lib/diameter/test/diameter_distribution_SUITE.erl b/lib/diameter/test/diameter_distribution_SUITE.erl
index 5146f68ff1..5fe02284ae 100644
--- a/lib/diameter/test/diameter_distribution_SUITE.erl
+++ b/lib/diameter/test/diameter_distribution_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -76,6 +76,7 @@
{share_peers, peers()},
{use_shared_peers, peers()},
{restrict_connections, false},
+ {spawn_opt, {diameter_dist, spawn_local, []}},
{sequence, fun sequence/0},
{application, [{dictionary, ?DICT},
{module, ?MODULE},
@@ -125,7 +126,7 @@ all() ->
%% enslave/1
%%
%% Start four slave nodes, one to implement a Diameter server,
-%% two three to implement a client.
+%% three to implement a client.
enslave() ->
[{timetrap, {seconds, 30*length(?NODES)}}].
@@ -331,6 +332,8 @@ prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, {_, client0}) ->
'Origin-Realm' = OR,
'Session-Id' = diameter:session_id(OH)}}.
+%% prepare_retransmit/4
+
prepare_retransmit(Pkt, ?CLIENT, _, {_, client0}) ->
#diameter_packet{msg = #diameter_base_STR{'Termination-Cause' = ?MOVED}}
= Pkt, %% assert
diff --git a/lib/diameter/test/diameter_pool_SUITE.erl b/lib/diameter/test/diameter_pool_SUITE.erl
index 97c16940ff..a36a4fa17a 100644
--- a/lib/diameter/test/diameter_pool_SUITE.erl
+++ b/lib/diameter/test/diameter_pool_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,6 +51,7 @@
{'Auth-Application-Id', [0]}, %% common
{'Acct-Application-Id', [3]}, %% accounting
{restrict_connections, false},
+ {spawn_opt, {diameter_dist, route_session, []}},
{application, [{alias, common},
{dictionary, diameter_gen_base_rfc6733},
{module, diameter_callback}]},
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 434aef01dd..47b00c25a2 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -539,8 +539,7 @@ add_transports(Config) ->
++ [{unordered, unordered()} || T == sctp],
[{capabilities_cb, fun capx/2},
{pool_size, 8}
- | server_apps()]
- ++ [{spawn_opt, {erlang, spawn, []}} || CS]),
+ | server_apps()]),
Cs = [?util:connect(CN,
[T, {sender, CS} | client_opts(T)],
LRef,
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index 0c73adca12..90b0a25d5f 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -1,7 +1,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2017. All Rights Reserved.
+# Copyright Ericsson AB 2010-2019. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ MODULES = \
diameter_codec_test \
diameter_config_SUITE \
diameter_compiler_SUITE \
+ diameter_dist_SUITE \
diameter_distribution_SUITE \
diameter_dpr_SUITE \
diameter_event_SUITE \
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 3081034df9..a8fbca5bc8 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 2.1.5
+DIAMETER_VSN = 2.2.1
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/edoc/doc/src/Makefile b/lib/edoc/doc/src/Makefile
index 71de42795a..aba94a6802 100644
--- a/lib/edoc/doc/src/Makefile
+++ b/lib/edoc/doc/src/Makefile
@@ -114,6 +114,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index 2ef941b06d..145856bcaa 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -32,6 +32,37 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.10</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Print a helpful message explaining that adding
+ <c>{preprocess, true}</c> can help if reading a source
+ file fails. </p>
+ <p>
+ Own Id: OTP-15605 Aux Id: ERL-841 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Edoc 0.9.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.9.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl
index b641118c5d..e9d62d3283 100644
--- a/lib/edoc/src/edoc.erl
+++ b/lib/edoc/src/edoc.erl
@@ -578,7 +578,7 @@ read_source(Name, Opts0) ->
Opts = expand_opts(Opts0),
case read_source_1(Name, Opts) of
{ok, Forms} ->
- check_forms(Forms, Name),
+ check_forms(Forms, Name, Opts),
Forms;
{error, R} ->
edoc_report:error({"error reading file '~ts'.",
@@ -692,13 +692,19 @@ fll([T | L], LastLine, Ts) ->
fll(L, _LastLine, Ts) ->
lists:reverse(L, Ts).
-check_forms(Fs, Name) ->
+check_forms(Fs, Name, Opts) ->
Fun = fun (F) ->
case erl_syntax:type(F) of
error_marker ->
case erl_syntax:error_marker_info(F) of
{L, M, D} ->
- edoc_report:error(L, Name, {format_error, M, D});
+ edoc_report:error(L, Name, {format_error, M, D}),
+ case proplists:get_bool(preprocess, Opts) of
+ true ->
+ ok;
+ false ->
+ helpful_message(Name)
+ end;
Other ->
edoc_report:report(Name, "unknown error in "
"source code: ~w.", [Other])
@@ -710,6 +716,11 @@ check_forms(Fs, Name) ->
end,
lists:foreach(Fun, Fs).
+helpful_message(Name) ->
+ Ms = ["If the error is caused by too exotic macro",
+ "definitions or uses of macros, adding option",
+ "{preprocess, true} can help. See also edoc(3)."],
+ lists:foreach(fun(M) -> edoc_report:report(Name, M, []) end, Ms).
%% @spec get_doc(File::filename()) -> {ModuleName, edoc_module()}
%% @equiv get_doc(File, [])
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index bea9277e1f..b6e1422623 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.9.3
+EDOC_VSN = 0.10
diff --git a/lib/eldap/doc/src/Makefile b/lib/eldap/doc/src/Makefile
index aff1da4a9a..bf1eca267a 100644
--- a/lib/eldap/doc/src/Makefile
+++ b/lib/eldap/doc/src/Makefile
@@ -89,6 +89,7 @@ debug opt valgrind:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/eldap/doc/src/eldap.xml b/lib/eldap/doc/src/eldap.xml
index f2c7889e58..790a2f4e26 100644
--- a/lib/eldap/doc/src/eldap.xml
+++ b/lib/eldap/doc/src/eldap.xml
@@ -28,7 +28,7 @@
<date>2000-06-20</date>
<rev>B</rev>
</header>
- <module>eldap</module>
+ <module since="OTP R15B01">eldap</module>
<modulesummary>LDAP Client</modulesummary>
<description>
<p>This module provides a client api to the Lightweight Directory Access Protocol (LDAP).
@@ -103,7 +103,7 @@
<funcs>
<func>
- <name>open([Host]) -> {ok, Handle} | {error, Reason}</name>
+ <name since="OTP R15B01">open([Host]) -> {ok, Handle} | {error, Reason}</name>
<fsummary>Open a connection to an LDAP server.</fsummary>
<type>
<v>Handle = handle()</v>
@@ -113,7 +113,7 @@
</desc>
</func>
<func>
- <name>open([Host], [Option]) -> {ok, Handle} | {error, Reason}</name>
+ <name since="OTP R15B01">open([Host], [Option]) -> {ok, Handle} | {error, Reason}</name>
<fsummary>Open a connection to an LDAP server.</fsummary>
<type>
<v>Handle = handle()</v>
@@ -129,7 +129,7 @@
</desc>
</func>
<func>
- <name>close(Handle) -> ok</name>
+ <name since="OTP R15B01">close(Handle) -> ok</name>
<fsummary>Shutdown the connection.</fsummary>
<type>
<v>Handle = handle()</v>
@@ -140,14 +140,14 @@
</desc>
</func>
<func>
- <name>start_tls(Handle, Options) -> return_value()</name>
+ <name since="OTP R16B03">start_tls(Handle, Options) -> return_value()</name>
<fsummary>Upgrade a connection to TLS.</fsummary>
<desc>
<p>Same as start_tls(Handle, Options, infinity)</p>
</desc>
</func>
<func>
- <name>start_tls(Handle, Options, Timeout) -> return_value()</name>
+ <name since="OTP R16B03">start_tls(Handle, Options, Timeout) -> return_value()</name>
<fsummary>Upgrade a connection to TLS.</fsummary>
<type>
<v>Handle = handle()</v>
@@ -176,7 +176,7 @@
</desc>
</func>
<func>
- <name>simple_bind(Handle, Dn, Password) -> return_value()</name>
+ <name since="OTP R15B01">simple_bind(Handle, Dn, Password) -> return_value()</name>
<fsummary>Authenticate the connection.</fsummary>
<type>
<v>Handle = handle()</v>
@@ -188,7 +188,7 @@
</desc>
</func>
<func>
- <name>add(Handle, Dn, [Attribute]) -> return_value()</name>
+ <name since="OTP R15B01">add(Handle, Dn, [Attribute]) -> return_value()</name>
<fsummary>Add an entry.</fsummary>
<type>
<v>Handle = handle()</v>
@@ -209,7 +209,7 @@
</desc>
</func>
<func>
- <name>delete(Handle, Dn) -> return_value()</name>
+ <name since="OTP R15B01">delete(Handle, Dn) -> return_value()</name>
<fsummary>Delete an entry.</fsummary>
<type>
<v>Dn = string()</v>
@@ -223,7 +223,7 @@
</func>
<func>
- <name>mod_add(Type, [Value]) -> modify_op()</name>
+ <name since="OTP R15B01">mod_add(Type, [Value]) -> modify_op()</name>
<fsummary>Create a modification operation.</fsummary>
<type>
<v>Type = string()</v>
@@ -232,7 +232,7 @@
<desc> <p> Create an add modification operation.</p> </desc>
</func>
<func>
- <name>mod_delete(Type, [Value]) -> modify_op()</name>
+ <name since="OTP R15B01">mod_delete(Type, [Value]) -> modify_op()</name>
<fsummary>Create a modification operation.</fsummary>
<type>
<v>Type = string()</v>
@@ -241,7 +241,7 @@
<desc> <p> Create a delete modification operation.</p> </desc>
</func>
<func>
- <name>mod_replace(Type, [Value]) -> modify_op()</name>
+ <name since="OTP R15B01">mod_replace(Type, [Value]) -> modify_op()</name>
<fsummary>Create a modification operation.</fsummary>
<type>
<v>Type = string()</v>
@@ -251,7 +251,7 @@
</func>
<func>
- <name>modify(Handle, Dn, [ModifyOp]) -> return_value()</name>
+ <name since="OTP R15B01">modify(Handle, Dn, [ModifyOp]) -> return_value()</name>
<fsummary>Modify an entry.</fsummary>
<type>
<v>Dn = string()</v>
@@ -267,7 +267,7 @@
</desc>
</func>
<func>
- <name>modify_password(Handle, Dn, NewPasswd) -> return_value() | {ok, GenPasswd}</name>
+ <name since="OTP 18.0">modify_password(Handle, Dn, NewPasswd) -> return_value() | {ok, GenPasswd}</name>
<fsummary>Modify the password of a user.</fsummary>
<type>
<v>Dn = string()</v>
@@ -278,7 +278,7 @@
</desc>
</func>
<func>
- <name>modify_password(Handle, Dn, NewPasswd, OldPasswd) -> return_value() | {ok, GenPasswd}</name>
+ <name since="OTP 18.0">modify_password(Handle, Dn, NewPasswd, OldPasswd) -> return_value() | {ok, GenPasswd}</name>
<fsummary>Modify the password of a user.</fsummary>
<type>
<v>Dn = string()</v>
@@ -307,7 +307,7 @@
</desc>
</func>
<func>
- <name>modify_dn(Handle, Dn, NewRDN, DeleteOldRDN, NewSupDN) -> return_value()</name>
+ <name since="OTP R15B01">modify_dn(Handle, Dn, NewRDN, DeleteOldRDN, NewSupDN) -> return_value()</name>
<fsummary>Modify the DN of an entry.</fsummary>
<type>
<v>Dn = string()</v>
@@ -327,7 +327,7 @@
</desc>
</func>
<func>
- <name>search(Handle, SearchOptions) -> {ok, #eldap_search_result{}} | {ok, {referral,referrals()}} | {error, Reason}</name>
+ <name since="OTP R15B01">search(Handle, SearchOptions) -> {ok, #eldap_search_result{}} | {ok, {referral,referrals()}} | {error, Reason}</name>
<fsummary>Search the Directory</fsummary>
<type>
<v>SearchOptions = #eldap_search{} | [SearchOption]</v>
@@ -354,44 +354,44 @@
</func>
<func>
- <name>baseObject() -> scope()</name>
+ <name since="OTP R15B01">baseObject() -> scope()</name>
<fsummary>Create search scope.</fsummary>
<desc> <p> Search baseobject only.</p> </desc>
</func>
<func>
- <name>singleLevel() -> scope()</name>
+ <name since="OTP R15B01">singleLevel() -> scope()</name>
<fsummary>Create search scope.</fsummary>
<desc> <p> Search the specified level only, i.e. do not recurse.</p> </desc>
</func>
<func>
- <name>wholeSubtree() -> scope()</name>
+ <name since="OTP R15B01">wholeSubtree() -> scope()</name>
<fsummary>Create search scope.</fsummary>
<desc> <p> Search the entire subtree.</p> </desc>
</func>
<func>
- <name>neverDerefAliases() -> dereference()</name>
+ <name since="OTP R15B01">neverDerefAliases() -> dereference()</name>
<fsummary>Create search option.</fsummary>
<desc> <p>Never derefrence aliases, treat aliases as entries.</p> </desc>
</func>
<func>
- <name>derefAlways() -> dereference()</name>
+ <name since="OTP R15B01">derefAlways() -> dereference()</name>
<fsummary>Create search option.</fsummary>
<desc> <p>Always derefrence aliases.</p> </desc>
</func>
<func>
- <name>derefInSearching() -> dereference()</name>
+ <name since="OTP R15B01">derefInSearching() -> dereference()</name>
<fsummary>Create search option.</fsummary>
<desc> <p>Derefrence aliases only when searching.</p> </desc>
</func>
<func>
- <name>derefFindingBaseObj() -> dereference()</name>
+ <name since="OTP R15B01">derefFindingBaseObj() -> dereference()</name>
<fsummary>Create search option.</fsummary>
<desc> <p>Derefrence aliases only in finding the base.</p> </desc>
</func>
<func>
- <name>present(Type) -> filter()</name>
+ <name since="OTP R15B01">present(Type) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Type = string()</v>
@@ -399,7 +399,7 @@
<desc> <p>Create a filter which filters on attribute type presence.</p> </desc>
</func>
<func>
- <name>substrings(Type, [SubString]) -> filter()</name>
+ <name since="OTP R15B01">substrings(Type, [SubString]) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Type = string()</v>
@@ -409,7 +409,7 @@
<desc> <p>Create a filter which filters on substrings.</p> </desc>
</func>
<func>
- <name>equalityMatch(Type, Value) -> filter()</name>
+ <name since="OTP R15B01">equalityMatch(Type, Value) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Type = string()</v>
@@ -418,7 +418,7 @@
<desc> <p>Create a equality filter.</p> </desc>
</func>
<func>
- <name>greaterOrEqual(Type, Value) -> filter()</name>
+ <name since="OTP R15B01">greaterOrEqual(Type, Value) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Type = string()</v>
@@ -427,7 +427,7 @@
<desc> <p>Create a greater or equal filter.</p> </desc>
</func>
<func>
- <name>lessOrEqual(Type, Value) -> filter()</name>
+ <name since="OTP R15B01">lessOrEqual(Type, Value) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Type = string()</v>
@@ -436,7 +436,7 @@
<desc> <p>Create a less or equal filter.</p> </desc>
</func>
<func>
- <name>approxMatch(Type, Value) -> filter()</name>
+ <name since="OTP R15B01">approxMatch(Type, Value) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Type = string()</v>
@@ -445,7 +445,7 @@
<desc> <p>Create a approximation match filter.</p> </desc>
</func>
<func>
- <name>extensibleMatch(MatchValue, OptionalAttrs) -> filter()</name>
+ <name since="OTP 17.4">extensibleMatch(MatchValue, OptionalAttrs) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>MatchValue = string()</v>
@@ -459,7 +459,7 @@
<p>creates a filter which performs a <c>caseExactMatch</c> on the attribute <c>sn</c> and matches with the value <c>"Bar"</c>. The default value of <c>dnAttributes</c> is <c>false</c>.</p> </desc>
</func>
<func>
- <name>'and'([Filter]) -> filter()</name>
+ <name since="OTP R15B01">'and'([Filter]) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Filter = filter()</v>
@@ -467,7 +467,7 @@
<desc> <p>Creates a filter where all <c>Filter</c> must be true.</p> </desc>
</func>
<func>
- <name>'or'([Filter]) -> filter()</name>
+ <name since="OTP R15B01">'or'([Filter]) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Filter = filter()</v>
@@ -475,7 +475,7 @@
<desc> <p>Create a filter where at least one of the <c>Filter</c> must be true.</p> </desc>
</func>
<func>
- <name>'not'(Filter) -> filter()</name>
+ <name since="OTP R15B01">'not'(Filter) -> filter()</name>
<fsummary>Create search filter option.</fsummary>
<type>
<v>Filter = filter()</v>
diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml
index ef7dda510c..975a25d7a8 100644
--- a/lib/eldap/doc/src/notes.xml
+++ b/lib/eldap/doc/src/notes.xml
@@ -31,6 +31,57 @@
</header>
<p>This document describes the changes made to the Eldap application.</p>
+<section><title>Eldap 1.2.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Back port of bug fix ERL-893 from OTP-22 and document
+ enhancements that will solve dialyzer warnings for users
+ of the ssl application.</p>
+ <p>
+ This change also affects public_key, eldap (and inet
+ doc).</p>
+ <p>
+ Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eldap 1.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A race condition at close could cause the eldap client to
+ exit with a badarg message as cause.</p>
+ <p>
+ Own Id: OTP-15342 Aux Id: ERIERL-242 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eldap 1.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eldap 1.2.4</title>
<section><title>Improvements and New Features</title>
@@ -46,6 +97,22 @@
</section>
+<section><title>Eldap 1.2.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A race condition at close could cause the eldap client to
+ exit with a badarg message as cause.</p>
+ <p>
+ Own Id: OTP-15342 Aux Id: ERIERL-242 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eldap 1.2.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -61,6 +128,22 @@
</section>
+<section><title>Eldap 1.2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A race condition at close could cause the eldap client to
+ exit with a badarg message as cause.</p>
+ <p>
+ Own Id: OTP-15342 Aux Id: ERIERL-242 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eldap 1.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -337,4 +420,3 @@
<p>New application. </p>
</section>
</chapter>
-
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
index 2b84872b92..9b7e254dfe 100644
--- a/lib/eldap/src/eldap.erl
+++ b/lib/eldap/src/eldap.erl
@@ -957,11 +957,20 @@ do_modify_dn_0(Data, Entry, NewRDN, DelOldRDN, NewSup, Controls) ->
do_unbind(Data) ->
Req = "",
log2(Data, "unbind request = ~p (has no reply)~n", [Req]),
- send_request(Data#eldap.fd, Data, Data#eldap.id, {unbindRequest, Req}),
- case Data#eldap.using_tls of
- true -> ssl:close(Data#eldap.fd);
- false -> gen_tcp:close(Data#eldap.fd)
- end,
+ _ = case Data#eldap.using_tls of
+ true ->
+ send_request(Data#eldap.fd, Data, Data#eldap.id, {unbindRequest, Req}),
+ ssl:close(Data#eldap.fd);
+ false ->
+ OldTrapExit = process_flag(trap_exit, true),
+ catch send_request(Data#eldap.fd, Data, Data#eldap.id, {unbindRequest, Req}),
+ catch gen_tcp:close(Data#eldap.fd),
+ receive
+ {'EXIT', _From, _Reason} -> ok
+ after 0 -> ok
+ end,
+ process_flag(trap_exit, OldTrapExit)
+ end,
{no_reply, Data#eldap{binddn = (#eldap{})#eldap.binddn,
passwd = (#eldap{})#eldap.passwd,
fd = (#eldap{})#eldap.fd,
@@ -1121,7 +1130,7 @@ ldap_closed_p(Data, Emsg) when Data#eldap.using_tls == true ->
%% Check if the SSL socket seems to be alive or not
case catch ssl:sockname(Data#eldap.fd) of
{error, _} ->
- ssl:close(Data#eldap.fd),
+ _ = ssl:close(Data#eldap.fd),
{error, ldap_closed};
{ok, _} ->
{error, Emsg};
diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk
index f2b3cd47f2..7f03fbd1b2 100644
--- a/lib/eldap/vsn.mk
+++ b/lib/eldap/vsn.mk
@@ -1 +1 @@
-ELDAP_VSN = 1.2.4
+ELDAP_VSN = 1.2.7
diff --git a/lib/erl_docgen/doc/src/Makefile b/lib/erl_docgen/doc/src/Makefile
index a9110e4635..d6d2550425 100644
--- a/lib/erl_docgen/doc/src/Makefile
+++ b/lib/erl_docgen/doc/src/Makefile
@@ -106,6 +106,7 @@ html: gifs examples $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/erl_docgen/doc/src/docgen_xml_check.xml b/lib/erl_docgen/doc/src/docgen_xml_check.xml
index 68253edef7..8d6dceef43 100644
--- a/lib/erl_docgen/doc/src/docgen_xml_check.xml
+++ b/lib/erl_docgen/doc/src/docgen_xml_check.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>docgen_xml_check</module>
+ <module since="OTP R15B">docgen_xml_check</module>
<modulesummary>Validate XML documentation source code</modulesummary>
<description>
<p><c>docgen_xml_check</c> contains functions for validating XML
@@ -39,7 +39,7 @@
<funcs>
<func>
- <name>validate(File) -> ok | error | {error, badfile}</name>
+ <name since="OTP R15B">validate(File) -> ok | error | {error, badfile}</name>
<fsummary>Validate XML source code.</fsummary>
<type>
<v>File = string()</v>
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 7a09b62351..54f0a36b27 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -31,7 +31,47 @@
</header>
<p>This document describes the changes made to the <em>erl_docgen</em> application.</p>
- <section><title>Erl_Docgen 0.8</title>
+ <section><title>Erl_Docgen 0.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The HTML reference documentation shows the OTP version
+ where modules and functions were first introduced.
+ Versions older than R13B04 are not shown.</p>
+ <p>
+ Own Id: OTP-15460</p>
+ </item>
+ <item>
+ <p>
+ Make html documentation of C functions with many
+ arguments more readable.</p>
+ <p>
+ Own Id: OTP-15637 Aux Id: PR-2160 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Indexing for the online search function has been
+ corrected for CREF documents.</p>
+ <p>
+ Own Id: OTP-14406</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.8</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css
index 34c6befb0e..17d9f8dd56 100644
--- a/lib/erl_docgen/priv/css/otp_doc.css
+++ b/lib/erl_docgen/priv/css/otp_doc.css
@@ -71,6 +71,39 @@ a:visited { color: #1b6ec2; text-decoration: none }
}
.bold_code { font-family: mono, Courier, monospace; font-weight: bold }
+
+/* Invisible table for function specs,
+ * just to get since-version out in right margin */
+.func-table, .func-tr, .func-td, .cfunc-td, .func-since-td {
+ width: 200%;
+ border: 0;
+ padding: 0;
+ margin: 0;
+}
+
+.func-tr:nth-child(n) {
+ background: inherit /* turn off zebra striped rows */
+}
+
+.func-td {
+ width: 50%;
+}
+
+.cfunc-td {
+ width: 50%;
+ padding-left: 100px;
+ text-indent: -100px;
+}
+
+.func-since-td {
+ width: 50%;
+ padding-left: 1em
+}
+
+.func-td:hover {
+ background-color: #f5f5f5;
+}
+
.code {
font-family: mono, Courier, monospace;
font-weight: normal;
@@ -283,3 +316,9 @@ a > .code {
.func-types-title{
font-size: 1em;
}
+
+.since{
+ color: gray;
+ font-weight: normal;
+ font-size: small;
+} \ No newline at end of file
diff --git a/lib/erl_docgen/priv/dtd/cref.dtd b/lib/erl_docgen/priv/dtd/cref.dtd
index 5ccd98ed89..d392081807 100644
--- a/lib/erl_docgen/priv/dtd/cref.dtd
+++ b/lib/erl_docgen/priv/dtd/cref.dtd
@@ -30,6 +30,8 @@
<!-- `name' is used in common.refs.dtd and must therefore
be defined in each *ref. dtd -->
<!ELEMENT name (ret,nametext) >
+<!ATTLIST name since CDATA #IMPLIED>
+
<!ELEMENT ret (#PCDATA) >
<!ELEMENT nametext (#PCDATA) >
diff --git a/lib/erl_docgen/priv/dtd/erlref.dtd b/lib/erl_docgen/priv/dtd/erlref.dtd
index 78d6771f52..8202ea5a4d 100644
--- a/lib/erl_docgen/priv/dtd/erlref.dtd
+++ b/lib/erl_docgen/priv/dtd/erlref.dtd
@@ -25,6 +25,7 @@
<!ELEMENT erlref (header,module,modulesummary,description,
(section|funcs|datatypes)*,authors?) >
<!ELEMENT module (#PCDATA) >
+<!ATTLIST module since CDATA #IMPLIED>
<!ELEMENT modulesummary (#PCDATA) >
<!-- `name' is used in common.refs.dtd and must therefore
@@ -34,4 +35,5 @@
arity CDATA #IMPLIED
clause_i CDATA #IMPLIED
anchor CDATA #IMPLIED
+ since CDATA #IMPLIED
n_vars CDATA #IMPLIED>
diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl
index b496614854..6bce577f08 100644
--- a/lib/erl_docgen/priv/xsl/db_eix.xsl
+++ b/lib/erl_docgen/priv/xsl/db_eix.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2016. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -199,11 +199,34 @@
<xsl:template name="name">
<xsl:param name="lastfuncsblock"/>
+ <xsl:variable name="signature">
+ <xsl:variable name="signature1">
+ <xsl:choose>
+ <xsl:when test="ancestor::cref">
+ <xsl:value-of
+ select="normalize-space(nametext)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of
+ select="normalize-space(substring-before(., '->'))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($signature1) > 0">
+ <xsl:value-of select="$signature1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="normalize-space(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
<xsl:variable name="tmpstring">
- <xsl:value-of select="substring-before(substring-after(., '('), '->')"/>
+ <xsl:value-of select="substring-after($signature, '(')"/>
</xsl:variable>
- <xsl:variable name="ustring">
+ <xsl:variable name="argstring">
<xsl:choose>
<xsl:when test="string-length($tmpstring) > 0">
<xsl:call-template name="remove-paren">
@@ -219,10 +242,19 @@
</xsl:variable>
<xsl:variable name="arity">
- <xsl:call-template name="calc-arity">
- <xsl:with-param name="string" select="substring-before($ustring, ')')"/>
- <xsl:with-param name="no-of-pars" select="0"/>
- </xsl:call-template>
+ <xsl:choose>
+ <xsl:when
+ test="string-length(substring-before(., '->')) > 0">
+ <xsl:call-template name="calc-arity">
+ <xsl:with-param
+ name="string"
+ select="substring-before($argstring, ')')"/>
+ <xsl:with-param name="no-of-pars" select="0"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+
</xsl:variable>
<xsl:variable name="fname">
@@ -250,10 +282,18 @@
</xsl:variable>
<xsl:text> {"</xsl:text><xsl:value-of select="$fname"/>
+ <xsl:text>", "</xsl:text>
+ <xsl:call-template name="escape-doublequotes">
+ <xsl:with-param name="string" select="$signature"/>
+ </xsl:call-template>
<xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
- <xsl:text>(</xsl:text><xsl:value-of select="normalize-space($tmpstring)"/>
- <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
- <xsl:text>-</xsl:text><xsl:value-of select="$arity"/><xsl:text>"}</xsl:text>
+ <xsl:choose>
+ <xsl:when test="string-length($arity) > 0">
+ <xsl:text>-</xsl:text><xsl:value-of select="$arity"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:text>"}</xsl:text>
<xsl:choose>
<xsl:when test="($lastfuncsblock = 'true') and (position() = last())">
@@ -345,6 +385,27 @@
</xsl:template>
+ <xsl:template name="escape-doublequotes">
+ <xsl:param name="string"/>
+ <xsl:param name="pPat">"</xsl:param>
+ <xsl:param name="pRep">\"</xsl:param>
+
+ <xsl:choose>
+ <xsl:when test="not(contains($string, $pPat))">
+ <xsl:copy-of select="$string"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="substring-before($string, $pPat)"/>
+ <xsl:copy-of select="$pRep"/>
+ <xsl:call-template name="escape-doublequotes">
+ <xsl:with-param
+ name="string"
+ select="substring-after($string, $pPat)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- default content handling -->
<xsl:template match="text()"/>
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index a0a922216b..c9be926e1e 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -191,6 +191,7 @@
<xsl:variable name="name" select="@name"/>
<xsl:variable name="arity" select="@arity"/>
<xsl:variable name="anchor" select="@anchor"/>
+ <xsl:variable name="since" select="@since"/>
<xsl:variable name="spec0">
<xsl:call-template name="find_spec"/>
</xsl:variable>
@@ -225,11 +226,12 @@
<xsl:variable name="global_types" select="ancestor::erlref/datatypes"/>
<xsl:variable name="local_types"
select="../type[string-length(@name) > 0]"/>
- <xsl:apply-templates select="$spec/contract/clause/head">
+ <xsl:apply-templates select="$spec/contract/clause/head">
<xsl:with-param name="ghlink" select="ancestor-or-self::*[@ghlink]/@ghlink"/>
<xsl:with-param name="local_types" select="$local_types"/>
<xsl:with-param name="global_types" select="$global_types"/>
- </xsl:apply-templates>
+ <xsl:with-param name="since" select="$since"/>
+ </xsl:apply-templates>
</xsl:when>
</xsl:choose>
</xsl:template>
@@ -238,19 +240,32 @@
<xsl:param name="ghlink"/>
<xsl:param name="local_types"/>
<xsl:param name="global_types"/>
+ <xsl:param name="since"/>
<xsl:variable name="id" select="concat(concat(concat(concat(../../../name,'-'),../../../arity),'-'),generate-id(.))"/>
- <div class="bold_code func-head"
- onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';"
- onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';">
- <xsl:call-template name="ghlink">
- <xsl:with-param name="ghlink" select="$ghlink"/>
- <xsl:with-param name="id" select="$id"/>
- </xsl:call-template>
- <xsl:apply-templates mode="local_type">
- <xsl:with-param name="local_types" select="$local_types"/>
- <xsl:with-param name="global_types" select="$global_types"/>
- </xsl:apply-templates>
- </div>
+ <table class="func-table">
+ <tr class="func-tr">
+ <td class="func-td">
+ <div class="bold_code func-head"
+ onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';"
+ onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';">
+ <xsl:call-template name="ghlink">
+ <xsl:with-param name="ghlink" select="$ghlink"/>
+ <xsl:with-param name="id" select="$id"/>
+ </xsl:call-template>
+ <xsl:apply-templates mode="local_type">
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:apply-templates>
+ </div>
+ </td>
+ <td class="func-since-td">
+ <xsl:if test="string-length($since) > 0">
+ <span class="since"><xsl:value-of select="$since"/>
+ </span>
+ </xsl:if>
+ </td>
+ </tr>
+ </table>
</xsl:template>
<!-- The *last* <name name="..." arity=".."/> -->
@@ -1884,6 +1899,16 @@
<xsl:with-param name="partnum" select="$partnum"/>
</xsl:apply-templates>
</div>
+ <!-- Since -->
+ <xsl:if test="string-length(../module/@since) > 0">
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Since</xsl:with-param>
+ </xsl:call-template>
+ <div class="REFBODY module-since">
+ Module <xsl:value-of select="../module"/> was introduced in
+ <xsl:value-of select="../module/@since"/>.
+ </div>
+ </xsl:if>
</xsl:template>
<!-- Lib -->
@@ -2030,11 +2055,10 @@
<xsl:template match="func">
<xsl:param name="partnum"/>
- <p><xsl:apply-templates select="name"/>
- <xsl:apply-templates
- select="name[string-length(@arity) > 0 and position()=last()]"
- mode="types"/>
- </p>
+ <xsl:apply-templates select="name"/>
+ <xsl:apply-templates
+ select="name[string-length(@arity) > 0 and position()=last()]"
+ mode="types"/>
<xsl:apply-templates select="fsummary|type|desc">
<xsl:with-param name="partnum" select="$partnum"/>
@@ -2093,19 +2117,22 @@
<xsl:choose>
<xsl:when test="ancestor::cref">
- <span class="bold_code bc-7">
- <xsl:call-template name="title_link">
- <xsl:with-param name="link" select="substring-before(nametext, '(')"/>
- <xsl:with-param name="title">
- <xsl:value-of select="ret"/>
- <xsl:call-template name="maybe-space-after-ret">
- <xsl:with-param name="s" select="ret"/>
- </xsl:call-template>
- <xsl:value-of select="nametext"/>
- </xsl:with-param>
- </xsl:call-template>
- </span>
- <br/>
+ <table class="func-table">
+ <tr class="func-tr">
+ <td class="cfunc-td">
+ <span class="bold_code bc-7">
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="link" select="substring-before(nametext, '(')"/>
+ </xsl:call-template>
+ </span>
+ </td>
+ <td class="func-since-td">
+ <xsl:if test="string-length(@since) > 0">
+ <span class="since"><xsl:value-of select="@since"/></span>
+ </xsl:if>
+ </td>
+ </tr>
+ </table>
</xsl:when>
<xsl:when test="ancestor::erlref">
<xsl:variable name="fname">
@@ -2136,14 +2163,25 @@
</div>
</xsl:when>
<xsl:otherwise>
- <div class="bold_code fun-type">
- <xsl:call-template name="title_link">
- <xsl:with-param name="link" select="concat(concat($fname,'-'),$arity)"/>
- <xsl:with-param name="title">
- <xsl:apply-templates/>
- </xsl:with-param>
- </xsl:call-template>
- </div>
+ <table class="func-table">
+ <tr class="func-tr">
+ <td class="func-td">
+ <div class="bold_code fun-type">
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="link" select="concat(concat($fname,'-'),$arity)"/>
+ <xsl:with-param name="title">
+ <xsl:apply-templates/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </div>
+ </td>
+ <td class="func-since-td">
+ <xsl:if test="string-length(@since) > 0">
+ <span class="since"><xsl:value-of select="@since"/></span>
+ </xsl:if>
+ </td>
+ </tr>
+ </table>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
@@ -2154,18 +2192,6 @@
</xsl:template>
- <xsl:template name="maybe-space-after-ret">
- <xsl:param name="s"/>
- <xsl:variable name="last_char"
- select="substring($s, string-length($s), 1)"/>
- <xsl:choose>
- <xsl:when test="$last_char != '*'">
- <xsl:text> </xsl:text>
- </xsl:when>
- </xsl:choose>
- </xsl:template>
-
-
<!-- Type -->
<xsl:template match="type">
<xsl:param name="partnum"/>
@@ -2219,7 +2245,7 @@
</xsl:template>
<xsl:template name="title_link">
- <xsl:param name="title"/>
+ <xsl:param name="title" select="'APPLY'"/>
<xsl:param name="link" select="erl:to-link(title)"/>
<xsl:param name="ghlink" select="ancestor-or-self::*[@ghlink][position() = 1]/@ghlink"/>
<xsl:variable name="id" select="concat(concat($link,'-'), generate-id(.))"/>
@@ -2229,7 +2255,16 @@
<xsl:with-param name="id" select="$id"/>
<xsl:with-param name="ghlink" select="$ghlink"/>
</xsl:call-template>
- <a class="title_link" name="{$link}" href="#{$link}"><xsl:value-of select="$title"/></a>
+ <a class="title_link" name="{$link}" href="#{$link}">
+ <xsl:choose>
+ <xsl:when test="$title = 'APPLY'">
+ <xsl:apply-templates/> <!-- like <ret> and <nametext> -->
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$title"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </a>
</span>
</xsl:template>
@@ -2659,4 +2694,46 @@
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
+ <xsl:template match="ret">
+ <xsl:value-of select="."/>
+ <xsl:variable name="last_char" select="substring(., string-length(.), 1)"/>
+ <xsl:if test="$last_char != '*'">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="nametext">
+ <xsl:value-of select="substring-before(.,'(')"/>
+ <xsl:text>(</xsl:text>
+ <xsl:variable name="arglist" select="substring-after(.,'(')"/>
+ <xsl:choose>
+ <xsl:when test="$arglist = ')' or $arglist = 'void)'">
+ <xsl:value-of select="$arglist"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <br/>
+ <xsl:call-template name="cfunc-arglist">
+ <xsl:with-param name="text" select="$arglist"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Format C function argument list with <br> after comma -->
+ <xsl:template name="cfunc-arglist">
+ <xsl:param name="text"/>
+ <xsl:variable name="line" select="normalize-space($text)"/>
+ <xsl:choose>
+ <xsl:when test="contains($line,',')">
+ <xsl:value-of select="substring-before($line,',')"/>,<br/>
+ <xsl:call-template name="cfunc-arglist">
+ <xsl:with-param name="text" select="substring-after($line,',')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$line"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
</xsl:stylesheet>
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 0b24604daa..6321f229dd 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1 +1 @@
-ERL_DOCGEN_VSN = 0.8
+ERL_DOCGEN_VSN = 0.9
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index a155ceef7e..747750c1fb 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -82,6 +82,15 @@ AC_ARG_ENABLE(threads,
esac ],
[ threads_disabled=maybe ])
+AC_ARG_ENABLE(mask-real-errno,
+[ --disable-mask-real-errno do not mask real 'errno'],
+[ case "$enableval" in
+ no) mask_real_errno=no ;;
+ *) mask_real_errno=yes ;;
+ esac ],
+[ mask_real_errno=yes ])
+
+
dnl ----------------------------------------------------------------------
dnl Checks for programs
dnl ----------------------------------------------------------------------
@@ -100,6 +109,10 @@ AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(void *)
AC_CHECK_SIZEOF(long long)
+if test $mask_real_errno = yes; then
+ AC_DEFINE(EI_HIDE_REAL_ERRNO, 1, [Define if 'errno' should not be exposed as is in 'erl_errno'])
+fi
+
dnl We set EI_64BIT mode when long is 8 bytes, this makes things
dnl work on windows and unix correctly
if test $ac_cv_sizeof_long = 8; then
@@ -158,7 +171,7 @@ AC_CHECK_LIB([socket], [getpeername])
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/param.h sys/socket.h sys/select.h sys/time.h unistd.h sys/types.h])
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/param.h sys/socket.h sys/select.h sys/time.h unistd.h sys/types.h sys/uio.h])
# Checks for typedefs, structures, and compiler characteristics.
# fixme AC_C_CONST & AC_C_VOLATILE needed for Windows?
@@ -193,7 +206,7 @@ AC_CHECK_FUNCS([dup2 gethostbyaddr gethostbyname \
gethostbyaddr_r \
gethostbyname_r gethostname writev \
gethrtime gettimeofday inet_ntoa memchr memmove memset select \
- socket strchr strerror strrchr strstr uname])
+ socket strchr strerror strrchr strstr uname sysconf])
AC_CHECK_FUNC(res_gethostbyname, [],
AC_CHECK_LIB(resolv, res_gethostbyname)
)
@@ -255,6 +268,7 @@ AC_SUBST(EI_THREADS)
case "$threads_disabled" in
no|maybe)
LM_CHECK_THR_LIB
+ ETHR_CHK_GCC_ATOMIC_OPS([])
case "$THR_LIB_NAME" in
"")
@@ -268,7 +282,7 @@ case "$threads_disabled" in
EI_THREADS="true"
THR_DEFS="$THR_DEFS -D_WIN32_WINNT=0x0600 -DWINVER=0x0600"
;;
- pthread)
+ pthread)
EI_THREADS="true"
;;
*)
diff --git a/lib/erl_interface/doc/src/Makefile b/lib/erl_interface/doc/src/Makefile
index 8ef7e9648c..507a84a453 100644
--- a/lib/erl_interface/doc/src/Makefile
+++ b/lib/erl_interface/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2017. All Rights Reserved.
+# Copyright Ericsson AB 1998-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -100,6 +100,7 @@ debug opt:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index 9502fb1ee7..179dbbd966 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -124,7 +124,7 @@ typedef enum {
<funcs>
<func>
- <name><ret>int</ret><nametext>ei_decode_atom(const char *buf, int *index, char *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_atom(const char *buf, int *index, char *p)</nametext></name>
<fsummary>Decode an atom.</fsummary>
<desc>
<p>Decodes an atom from the binary format. The <c>NULL</c>-terminated
@@ -134,7 +134,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_atom_as(const char *buf, int *index, char *p, int plen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result)</nametext></name>
+ <name since="OTP R16B"><ret>int</ret><nametext>ei_decode_atom_as(const char *buf, int *index, char *p, int plen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result)</nametext></name>
<fsummary>Decode an atom.</fsummary>
<desc>
<p>Decodes an atom from the binary format. The <c>NULL</c>-terminated
@@ -158,7 +158,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_bignum(const char *buf, int *index, mpz_t obj)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_bignum(const char *buf, int *index, mpz_t obj)</nametext></name>
<fsummary>Decode a GMP arbitrary precision integer.</fsummary>
<desc>
<p>Decodes an integer in the binary format to a GMP
@@ -168,7 +168,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_binary(const char *buf, int *index, void *p, long *len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_binary(const char *buf, int *index, void *p, long *len)</nametext></name>
<fsummary>Decode a binary.</fsummary>
<desc>
<p>Decodes a binary from the binary format. Parameter
@@ -180,7 +180,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_boolean(const char *buf, int *index, int *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_boolean(const char *buf, int *index, int *p)</nametext></name>
<fsummary>Decode a boolean.</fsummary>
<desc>
<p>Decodes a boolean value from the binary format.
@@ -190,7 +190,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_char(const char *buf, int *index, char *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_char(const char *buf, int *index, char *p)</nametext></name>
<fsummary>Decode an 8-bit integer between 0-255.</fsummary>
<desc>
<p>Decodes a char (8-bit) integer between 0-255 from the binary format.
@@ -203,7 +203,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_double(const char *buf, int *index, double *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_double(const char *buf, int *index, double *p)</nametext></name>
<fsummary>Decode a double.</fsummary>
<desc>
<p>Decodes a double-precision (64-bit) floating
@@ -212,7 +212,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_ei_term(const char* buf, int* index, ei_term* term)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_ei_term(const char* buf, int* index, ei_term* term)</nametext></name>
<fsummary>Decode a term, without previous knowledge of type.</fsummary>
<desc>
<p>Decodes any term, or at least tries to. If the term
@@ -233,8 +233,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_fun(const char *buf, int *index, erlang_fun *p)</nametext></name>
- <name><ret>void</ret><nametext>free_fun(erlang_fun* f)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_fun(const char *buf, int *index, erlang_fun *p)</nametext></name>
+ <name since=""><ret>void</ret><nametext>free_fun(erlang_fun* f)</nametext></name>
<fsummary>Decode a fun.</fsummary>
<desc>
<p>Decodes a fun from the binary format. Parameter
@@ -248,7 +248,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_list_header(const char *buf, int *index, int *arity)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_list_header(const char *buf, int *index, int *arity)</nametext></name>
<fsummary>Decode a list.</fsummary>
<desc>
<p>Decodes a list header from the binary
@@ -265,7 +265,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_long(const char *buf, int *index, long *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_long(const char *buf, int *index, long *p)</nametext></name>
<fsummary>Decode integer.</fsummary>
<desc>
<p>Decodes a long integer from the binary format.
@@ -275,7 +275,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_longlong(const char *buf, int *index, long long *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_longlong(const char *buf, int *index, long long *p)</nametext></name>
<fsummary>Decode integer.</fsummary>
<desc>
<p>Decodes a GCC <c>long long</c> or Visual C++
@@ -286,7 +286,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_map_header(const char *buf, int *index, int *arity)</nametext></name>
+ <name since="OTP 17.0"><ret>int</ret><nametext>ei_decode_map_header(const char *buf, int *index, int *arity)</nametext></name>
<fsummary>Decode a map.</fsummary>
<desc>
<p>Decodes a map header from the binary
@@ -299,7 +299,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_pid(const char *buf, int *index, erlang_pid *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_pid(const char *buf, int *index, erlang_pid *p)</nametext></name>
<fsummary>Decode a <c>pid</c>.</fsummary>
<desc>
<p>Decodes a process identifier (pid) from the binary format.</p>
@@ -307,7 +307,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_port(const char *buf, int *index, erlang_port *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_port(const char *buf, int *index, erlang_port *p)</nametext></name>
<fsummary>Decode a port.</fsummary>
<desc>
<p>Decodes a port identifier from the binary format.</p>
@@ -315,7 +315,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_ref(const char *buf, int *index, erlang_ref *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_ref(const char *buf, int *index, erlang_ref *p)</nametext></name>
<fsummary>Decode a reference.</fsummary>
<desc>
<p>Decodes a reference from the binary format.</p>
@@ -323,7 +323,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_string(const char *buf, int *index, char *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_string(const char *buf, int *index, char *p)</nametext></name>
<fsummary>Decode a string.</fsummary>
<desc>
<p>Decodes a string from the binary format. A
@@ -338,7 +338,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_term(const char *buf, int *index, void *t)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_term(const char *buf, int *index, void *t)</nametext></name>
<fsummary>Decode a <c>ETERM</c>.</fsummary>
<desc>
<p>Decodes a term from the binary format. The term
@@ -352,7 +352,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_trace(const char *buf, int *index, erlang_trace *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_trace(const char *buf, int *index, erlang_trace *p)</nametext></name>
<fsummary>Decode a trace token.</fsummary>
<desc>
<p>Decodes an Erlang trace token from the binary format.</p>
@@ -360,7 +360,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_tuple_header(const char *buf, int *index, int *arity)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_tuple_header(const char *buf, int *index, int *arity)</nametext></name>
<fsummary>Decode a tuple.</fsummary>
<desc>
<p>Decodes a tuple header, the number of elements
@@ -370,7 +370,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_ulong(const char *buf, int *index, unsigned long *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_ulong(const char *buf, int *index, unsigned long *p)</nametext></name>
<fsummary>Decode unsigned integer.</fsummary>
<desc>
<p>Decodes an unsigned long integer from the binary format.
@@ -380,7 +380,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_ulonglong(const char *buf, int *index, unsigned long long *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_ulonglong(const char *buf, int *index, unsigned long long *p)</nametext></name>
<fsummary>Decode unsigned integer.</fsummary>
<desc>
<p>Decodes a GCC <c>unsigned long long</c> or Visual C++
@@ -390,7 +390,7 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_decode_version(const char *buf, int *index, int *version)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_decode_version(const char *buf, int *index, int *version)</nametext></name>
<fsummary>Decode an empty list (<c>nil</c>).</fsummary>
<desc>
<p>Decodes the version magic number for the
@@ -400,10 +400,10 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_atom(char *buf, int *index, const char *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_encode_atom_len(char *buf, int *index, const char *p, int len)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_atom(ei_x_buff* x, const char *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_atom_len(ei_x_buff* x, const char *p, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_atom(char *buf, int *index, const char *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_atom_len(char *buf, int *index, const char *p, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_atom(ei_x_buff* x, const char *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_atom_len(ei_x_buff* x, const char *p, int len)</nametext></name>
<fsummary>Encode an atom.</fsummary>
<desc>
<p>Encodes an atom in the binary format. Parameter <c>p</c>
@@ -415,10 +415,10 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_atom_as(char *buf, int *index, const char *p, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
- <name><ret>int</ret><nametext>ei_encode_atom_len_as(char *buf, int *index, const char *p, int len, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_atom_as(ei_x_buff* x, const char *p, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_atom_len_as(ei_x_buff* x, const char *p, int len, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
+ <name since="OTP R16B"><ret>int</ret><nametext>ei_encode_atom_as(char *buf, int *index, const char *p, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
+ <name since="OTP R16B"><ret>int</ret><nametext>ei_encode_atom_len_as(char *buf, int *index, const char *p, int len, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
+ <name since="OTP R16B"><ret>int</ret><nametext>ei_x_encode_atom_as(ei_x_buff* x, const char *p, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
+ <name since="OTP R16B"><ret>int</ret><nametext>ei_x_encode_atom_len_as(ei_x_buff* x, const char *p, int len, erlang_char_encoding from_enc, erlang_char_encoding to_enc)</nametext></name>
<fsummary>Encode an atom.</fsummary>
<desc>
<p>Encodes an atom in the binary format. Parameter <c>p</c> is the name of the atom with
@@ -435,8 +435,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_bignum(char *buf, int *index, mpz_t obj)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_bignum(ei_x_buff *x, mpz_t obj)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_bignum(char *buf, int *index, mpz_t obj)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_bignum(ei_x_buff *x, mpz_t obj)</nametext></name>
<fsummary>Encode an arbitrary precision integer.</fsummary>
<desc>
<p>Encodes a GMP <c>mpz_t</c> integer to binary format.
@@ -446,8 +446,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_binary(char *buf, int *index, const void *p, long len)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_binary(ei_x_buff* x, const void *p, long len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_binary(char *buf, int *index, const void *p, long len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_binary(ei_x_buff* x, const void *p, long len)</nametext></name>
<fsummary>Encode a binary.</fsummary>
<desc>
<p>Encodes a binary in the binary format. The data is at
@@ -456,8 +456,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_boolean(char *buf, int *index, int p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_boolean(ei_x_buff* x, int p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_boolean(char *buf, int *index, int p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_boolean(ei_x_buff* x, int p)</nametext></name>
<fsummary>Encode a boolean.</fsummary>
<desc>
<p>Encodes a boolean value as the atom <c>true</c> if
@@ -467,8 +467,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_char(char *buf, int *index, char p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_char(ei_x_buff* x, char p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_char(char *buf, int *index, char p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_char(ei_x_buff* x, char p)</nametext></name>
<fsummary>Encode an 8-bit integer between 0-255.</fsummary>
<desc>
<p>Encodes a char (8-bit) as an integer between 0-255 in the binary
@@ -481,8 +481,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_double(char *buf, int *index, double p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_double(ei_x_buff* x, double p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_double(char *buf, int *index, double p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_double(ei_x_buff* x, double p)</nametext></name>
<fsummary>Encode a double float.</fsummary>
<desc>
<p>Encodes a double-precision (64-bit) floating point number in
@@ -493,8 +493,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_empty_list(char* buf, int* index)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_empty_list(ei_x_buff* x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_empty_list(char* buf, int* index)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_empty_list(ei_x_buff* x)</nametext></name>
<fsummary>Encode an empty list (<c>nil</c>).</fsummary>
<desc>
<p>Encodes an empty list. It is often used at the tail of a list.</p>
@@ -502,8 +502,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_fun(char *buf, int *index, const erlang_fun *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_fun(char *buf, int *index, const erlang_fun *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun)</nametext></name>
<fsummary>Encode a fun.</fsummary>
<desc>
<p>Encodes a fun in the binary format. Parameter <c>p</c>
@@ -515,8 +515,8 @@ typedef enum {
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_list_header(char *buf, int *index, int arity)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_list_header(ei_x_buff* x, int arity)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_list_header(char *buf, int *index, int arity)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_list_header(ei_x_buff* x, int arity)</nametext></name>
<fsummary>Encode a list.</fsummary>
<desc>
<p>Encodes a list header, with a specified
@@ -552,8 +552,8 @@ ei_x_encode_empty_list(&amp;x);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_long(char *buf, int *index, long p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_long(ei_x_buff* x, long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_long(char *buf, int *index, long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_long(ei_x_buff* x, long p)</nametext></name>
<fsummary>Encode integer.</fsummary>
<desc>
<p>Encodes a long integer in the binary format.
@@ -563,8 +563,8 @@ ei_x_encode_empty_list(&amp;x);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_longlong(char *buf, int *index, long long p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_longlong(ei_x_buff* x, long long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_longlong(char *buf, int *index, long long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_longlong(ei_x_buff* x, long long p)</nametext></name>
<fsummary>Encode integer.</fsummary>
<desc>
<p>Encodes a GCC <c>long long</c> or Visual C++
@@ -574,8 +574,8 @@ ei_x_encode_empty_list(&amp;x);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_map_header(char *buf, int *index, int arity)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_map_header(ei_x_buff* x, int arity)</nametext></name>
+ <name since="OTP 17.0"><ret>int</ret><nametext>ei_encode_map_header(char *buf, int *index, int arity)</nametext></name>
+ <name since="OTP 17.0"><ret>int</ret><nametext>ei_x_encode_map_header(ei_x_buff* x, int arity)</nametext></name>
<fsummary>Encode a map.</fsummary>
<desc>
<p>Encodes a map header, with a specified arity. The next
@@ -595,8 +595,8 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_pid(char *buf, int *index, const erlang_pid *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_pid(ei_x_buff* x, const erlang_pid *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_pid(char *buf, int *index, const erlang_pid *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_pid(ei_x_buff* x, const erlang_pid *p)</nametext></name>
<fsummary>Encode a pid.</fsummary>
<desc>
<p>Encodes an Erlang process identifier (pid) in the binary
@@ -607,8 +607,8 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_port(char *buf, int *index, const erlang_port *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_port(ei_x_buff* x, const erlang_port *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_port(char *buf, int *index, const erlang_port *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_port(ei_x_buff* x, const erlang_port *p)</nametext></name>
<fsummary>Encode a port.</fsummary>
<desc>
<p>Encodes an Erlang port in the binary format. Parameter
@@ -619,8 +619,8 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_ref(char *buf, int *index, const erlang_ref *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_ref(char *buf, int *index, const erlang_ref *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p)</nametext></name>
<fsummary>Encode a ref.</fsummary>
<desc>
<p>Encodes an Erlang reference in the binary format. Parameter
@@ -631,10 +631,10 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_string(char *buf, int *index, const char *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_encode_string_len(char *buf, int *index, const char *p, int len)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_string(ei_x_buff* x, const char *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_string(char *buf, int *index, const char *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_string_len(char *buf, int *index, const char *p, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_string(ei_x_buff* x, const char *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)</nametext></name>
<fsummary>Encode a string.</fsummary>
<desc>
<p>Encodes a string in the binary format. (A string in Erlang
@@ -645,8 +645,8 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_term(char *buf, int *index, void *t)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_term(ei_x_buff* x, void *t)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_term(char *buf, int *index, void *t)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_term(ei_x_buff* x, void *t)</nametext></name>
<fsummary>Encode an <c>erl_interface</c> term.</fsummary>
<desc>
<p>Encodes an <c>ETERM</c>, as obtained from
@@ -656,8 +656,8 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_trace(char *buf, int *index, const erlang_trace *p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_trace(char *buf, int *index, const erlang_trace *p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p)</nametext></name>
<fsummary>Encode a trace token.</fsummary>
<desc>
<p>Encodes an Erlang trace token in the binary format.
@@ -668,8 +668,8 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_tuple_header(char *buf, int *index, int arity)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_tuple_header(ei_x_buff* x, int arity)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_tuple_header(char *buf, int *index, int arity)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_tuple_header(ei_x_buff* x, int arity)</nametext></name>
<fsummary>Encode a tuple.</fsummary>
<desc>
<p>Encodes a tuple header, with a specified
@@ -687,8 +687,8 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_ulong(char *buf, int *index, unsigned long p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_ulong(ei_x_buff* x, unsigned long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_ulong(char *buf, int *index, unsigned long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_ulong(ei_x_buff* x, unsigned long p)</nametext></name>
<fsummary>Encode unsigned integer.</fsummary>
<desc>
<p>Encodes an unsigned long integer in the binary format.
@@ -698,8 +698,8 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_ulonglong(char *buf, int *index, unsigned long long p)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_ulonglong(ei_x_buff* x, unsigned long long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_ulonglong(char *buf, int *index, unsigned long long p)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_ulonglong(ei_x_buff* x, unsigned long long p)</nametext></name>
<fsummary>Encode unsigned integer.</fsummary>
<desc>
<p>Encodes a GCC <c>unsigned long long</c> or Visual C++
@@ -709,8 +709,8 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_encode_version(char *buf, int *index)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_encode_version(ei_x_buff* x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_encode_version(char *buf, int *index)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_encode_version(ei_x_buff* x)</nametext></name>
<fsummary>Encode version.</fsummary>
<desc>
<p>Encodes a version magic number for the binary format. Must
@@ -719,7 +719,7 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_get_type(const char *buf, const int *index, int *type, int *size)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_get_type(const char *buf, const int *index, int *type, int *size)</nametext></name>
<fsummary>Fetch the type and size of an encoded term.</fsummary>
<desc>
<p>Returns the type in <c>type</c> and size in
@@ -733,8 +733,23 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_print_term(FILE* fp, const char* buf, int* index)</nametext></name>
- <name><ret>int</ret><nametext>ei_s_print_term(char** s, const char* buf, int* index)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_init(void)</nametext></name>
+ <fsummary>Initialize the ei library.</fsummary>
+ <desc>
+ <p>Initialize the <c>ei</c> library. This function should be called once
+ (and only once) before calling any other functionality in the <c>ei</c>
+ library. However, note the exception below.</p>
+ <p>If the <c>ei</c> library is used together with the <c>erl_interface</c>
+ library, this function should <em>not</em> be called directly. It will be
+ called by the <c>erl_init()</c> function which should be used to initialize
+ the combination of the two libraries instead.</p>
+ <p>On success zero is returned. On failure a posix error code is returned.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name since=""><ret>int</ret><nametext>ei_print_term(FILE* fp, const char* buf, int* index)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_s_print_term(char** s, const char* buf, int* index)</nametext></name>
<fsummary>Print a term in clear text.</fsummary>
<desc>
<p>Prints a term, in clear text, to the file
@@ -759,7 +774,7 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>void</ret><nametext>ei_set_compat_rel(release_number)</nametext></name>
+ <name since=""><ret>void</ret><nametext>ei_set_compat_rel(release_number)</nametext></name>
<fsummary>Set the ei library in compatibility mode.</fsummary>
<type>
<v>unsigned release_number;</v>
@@ -794,7 +809,7 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_skip_term(const char* buf, int* index)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_skip_term(const char* buf, int* index)</nametext></name>
<fsummary>Skip a term.</fsummary>
<desc>
<p>Skips a term in the specified buffer;
@@ -815,8 +830,8 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_x_append(ei_x_buff* x, const ei_x_buff* x2)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_append_buf(ei_x_buff* x, const char* buf, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_append(ei_x_buff* x, const ei_x_buff* x2)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_append_buf(ei_x_buff* x, const char* buf, int len)</nametext></name>
<fsummary>Append a buffer at the end.</fsummary>
<desc>
<p>Appends data at the end of buffer <c>x</c>.</p>
@@ -824,8 +839,8 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_x_format(ei_x_buff* x, const char* fmt, ...)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ... )</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_format(ei_x_buff* x, const char* fmt, ...)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ... )</nametext></name>
<fsummary>Format a term from a format string and parameters.</fsummary>
<desc>
<p>Formats a term, given as a string, to a buffer.
@@ -853,7 +868,7 @@ encodes the tuple {numbers,12,3.14159}</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_x_free(ei_x_buff* x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_free(ei_x_buff* x)</nametext></name>
<fsummary>Free a buffer.</fsummary>
<desc>
<p>Frees an <c>ei_x_buff</c> buffer.
@@ -862,8 +877,8 @@ encodes the tuple {numbers,12,3.14159}</pre>
</func>
<func>
- <name><ret>int</ret><nametext>ei_x_new(ei_x_buff* x)</nametext></name>
- <name><ret>int</ret><nametext>ei_x_new_with_version(ei_x_buff* x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_new(ei_x_buff* x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_x_new_with_version(ei_x_buff* x)</nametext></name>
<fsummary>Allocate a new buffer.</fsummary>
<desc>
<p>Allocates a new <c>ei_x_buff</c> buffer. The
diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml
index 607a7cbff4..2dd0a285fe 100644
--- a/lib/erl_interface/doc/src/ei_connect.xml
+++ b/lib/erl_interface/doc/src/ei_connect.xml
@@ -85,20 +85,288 @@
the <c>_tmo</c> suffix.</p>
</section>
+ <section>
+ <marker id="ussi"/>
+ <title>User Supplied Socket Implementation</title>
+ <p>By default <c>ei</c> supplies a TCP/IPv4 socket interface
+ that is used when communicating. The user can however plug in
+ his/her own IPv4 socket implementation. This, for example, in order
+ to communicate over TLS. A user supplied socket implementation
+ is plugged in by passing a
+ <seealso marker="#ei_socket_callbacks">callback structure</seealso>
+ to either
+ <seealso marker="#ei_connect_init"><c>ei_connect_init_ussi()</c></seealso>
+ or
+ <seealso marker="#ei_connect_init"><c>ei_connect_xinit_ussi()</c></seealso>.</p>
+
+ <p>All callbacks in the <c>ei_socket_callbacks</c> structure
+ <em>should</em> return zero on success; and a posix error
+ code on failure.</p>
+
+ <p>The <c>addr</c> argument of the <c>listen</c>, <c>accept</c>,
+ and <c>connect</c> callbacks refer to appropriate address
+ structure for currently used protocol. Currently <c>ei</c>
+ only supports IPv4. That is, at this time <c>addr</c> always
+ points to a <c>struct sockaddr_in</c> structure.</p>
+
+ <p>The <c>ei_socket_callbacks</c> structure may be enlarged in
+ the future. All fields not set, <em>needs</em> to be zeroed out.</p>
+
+ <marker id="ei_socket_callbacks"/>
+ <code type="none"><![CDATA[
+typedef struct {
+ int flags;
+ int (*socket)(void **ctx, void *setup_ctx);
+ int (*close)(void *ctx);
+ int (*listen)(void *ctx, void *addr, int *len, int backlog);
+ int (*accept)(void **ctx, void *addr, int *len, unsigned tmo);
+ int (*connect)(void *ctx, void *addr, int len, unsigned tmo);
+ int (*writev)(void *ctx, const void *iov, int iovcnt, ssize_t *len, unsigned tmo);
+ int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo);
+ int (*read)(void *ctx, char *buf, ssize_t *len, unsigned tmo);
+ int (*handshake_packet_header_size)(void *ctx, int *sz);
+ int (*connect_handshake_complete)(void *ctx);
+ int (*accept_handshake_complete)(void *ctx);
+ int (*get_fd)(void *ctx, int *fd);
+} ei_socket_callbacks;
+ ]]></code>
+
+ <taglist>
+
+ <tag><c>flags</c></tag>
+ <item>
+ <p>Flags informing <c>ei</c> about the behaviour of the
+ callbacks. Flags should be bitwise or:ed together. If no flag,
+ is set, the <c>flags</c> field should contain <c>0</c>. Currently,
+ supported flags:</p>
+ <taglist>
+ <tag><c>EI_SCLBK_FLG_FULL_IMPL</c></tag>
+ <item>
+ <p>
+ If set, the <c>accept()</c>, <c>connect()</c>,
+ <c>writev()</c>, <c>write()</c>, and <c>read()</c> callbacks
+ implements timeouts. The timeout is passed in the <c>tmo</c>
+ argument and is given in milli seconds. Note that the
+ <c>tmo</c> argument to these callbacks differ from the
+ timeout arguments in the <c>ei</c> API. Zero means a zero
+ timeout. That is, poll and timeout immediately unless the
+ operation is successful. <c>EI_SCLBK_INF_TMO</c>
+ (max <c>unsigned</c>) means infinite timeout. The file
+ descriptor is in blocking mode when a callback is called,
+ and it must be in blocking mode when the callback returns.
+ </p>
+ <p>
+ If not set, <c>ei</c> will implement the timeout using
+ <c>select()</c> in order to determine when to call the
+ callbacks and when to time out. The <c>tmo</c> arguments
+ of the <c>accept()</c>, <c>connect()</c>, <c>writev()</c>,
+ <c>write()</c>, and <c>read()</c> callbacks should be
+ ignored. The callbacks may be called in non-blocking mode.
+ The callbacks are not allowed to change between blocking
+ and non-blocking mode. In order for this to work,
+ <c>select()</c> needs to interact with the socket primitives
+ used the same way as it interacts with the ordinary socket
+ primitives. If this is not the case, the callbacks
+ <em>need</em> to implement timeouts and this flag should
+ be set.
+ </p>
+ </item>
+ </taglist>
+ <p>More flags may be introduced in the future.</p>
+ </item>
+
+ <tag><c>int (*socket)(void **ctx, void *setup_ctx)</c></tag>
+ <item>
+ <p>Create a socket and a context for the socket.</p>
+
+ <p>On success it should set <c>*ctx</c> to point to a context for
+ the created socket. This context will be passed to all other
+ socket callbacks. This function will be passed the same
+ <c>setup_context</c> as passed to the preceeding
+ <seealso marker="#ei_connect_init"><c>ei_connect_init_ussi()</c></seealso>
+ or
+ <seealso marker="#ei_connect_init"><c>ei_connect_xinit_ussi()</c></seealso>
+ call.</p>
+
+ <note><p>During the lifetime of a socket, the pointer <c>*ctx</c>
+ <em>has</em> to remain the same. That is, it cannot later be
+ relocated.</p></note>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*close)(void *ctx)</c></tag>
+ <item>
+ <p>Close the socket identified by <c>ctx</c> and destroy the context.</p>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*listen)(void *ctx, void *addr, int *len, int backlog)</c></tag>
+ <item>
+ <p>Bind the socket identified by <c>ctx</c> to a local interface
+ and then listen on it.</p>
+
+ <p>The <c>addr</c> and <c>len</c> arguments are both input and output
+ arguments. When called <c>addr</c> points to an address structure of
+ lenght <c>*len</c> containing information on how to bind the socket.
+ Uppon return this callback should have updated the structure referred
+ by <c>addr</c> with information on how the socket actually was bound.
+ <c>*len</c> should be updated to reflect the size of <c>*addr</c>
+ updated. <c>backlog</c> identifies the size of the backlog for the
+ listen socket.</p>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*accept)(void **ctx, void *addr, int *len, unsigned tmo)</c></tag>
+ <item>
+ <p>Accept connections on the listen socket identified by
+ <c>*ctx</c>.</p>
+
+ <p>When a connection is accepted, a new context for the accepted
+ connection should be created and <c>*ctx</c> should be updated
+ to point to the new context for the accepted connection. When
+ called <c>addr</c> points to an uninitialized address structure
+ of lenght <c>*len</c>. Uppon return this callback should have
+ updated this structure with information about the client address.
+ <c>*len</c> should be updated to reflect the size of <c>*addr</c>
+ updated.
+ </p>
+
+ <p>If the <c>EI_SCLBK_FLG_FULL_IMPL</c> flag has been set,
+ <c>tmo</c> contains timeout time in milliseconds.</p>
+
+ <note><p>During the lifetime of a socket, the pointer <c>*ctx</c>
+ <em>has</em> to remain the same. That is, it cannot later be
+ relocated.</p></note>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*connect)(void *ctx, void *addr, int len, unsigned tmo)</c></tag>
+ <item>
+ <p>Connect the socket identified by <c>ctx</c> to the address
+ identified by <c>addr</c>.</p>
+
+ <p>When called <c>addr</c> points to an address structure of
+ lenght <c>len</c> containing information on where to connect.</p>
+
+ <p>If the <c>EI_SCLBK_FLG_FULL_IMPL</c> flag has been set,
+ <c>tmo</c> contains timeout time in milliseconds.</p>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*writev)(void *ctx, const void *iov, long iovcnt, ssize_t *len, unsigned tmo)</c></tag>
+ <item>
+ <p>Write data on the connected socket identified by <c>ctx</c>.</p>
+
+ <p><c>iov</c> points to an array of <c>struct iovec</c> structures of
+ length <c>iovcnt</c> containing data to write to the socket. On success,
+ this callback should set <c>*len</c> to the amount of bytes successfully
+ written on the socket.</p>
+
+ <p>If the <c>EI_SCLBK_FLG_FULL_IMPL</c> flag has been set,
+ <c>tmo</c> contains timeout time in milliseconds.</p>
+
+ <p>This callback is optional. Set the <c>writev</c> field
+ in the the <c>ei_socket_callbacks</c> structure to <c>NULL</c> if not
+ implemented.</p>
+ </item>
+
+ <tag><c>int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo)</c></tag>
+ <item>
+ <p>Write data on the connected socket identified by <c>ctx</c>.</p>
+
+ <p>When called <c>buf</c> points to a buffer of length <c>*len</c>
+ containing the data to write on the socket. On success, this callback
+ should set <c>*len</c> to the amount of bytes successfully written on
+ the socket.</p>
+
+ <p>If the <c>EI_SCLBK_FLG_FULL_IMPL</c> flag has been set,
+ <c>tmo</c> contains timeout time in milliseconds.</p>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*read)(void *ctx, char *buf, ssize_t *len, unsigned tmo)</c></tag>
+ <item>
+ <p>Read data on the connected socket identified by <c>ctx</c>.</p>
+
+ <p><c>buf</c> points to a buffer of length <c>*len</c> where the
+ read data should be placed. On success, this callback should update
+ <c>*len</c> to the amount of bytes successfully read on the socket.</p>
+
+ <p>If the <c>EI_SCLBK_FLG_FULL_IMPL</c> flag has been set,
+ <c>tmo</c> contains timeout time in milliseconds.</p>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*handshake_packet_header_size)(void *ctx, int *sz)</c></tag>
+ <item>
+ <p>Inform about handshake packet header size to use during the Erlang
+ distribution handshake.</p>
+
+ <p>On success, <c>*sz</c> should be set to the handshake packet header
+ size to use. Valid values are <c>2</c> and <c>4</c>. Erlang TCP
+ distribution use a handshake packet size of <c>2</c> and Erlang TLS
+ distribution use a handshake packet size of <c>4</c>.</p>
+
+ <p>This callback is mandatory.</p>
+ </item>
+
+ <tag><c>int (*connect_handshake_complete)(void *ctx)</c></tag>
+ <item>
+ <p>Called when a locally started handshake has completed successfully.</p>
+
+ <p>This callback is optional. Set the <c>connect_handshake_complete</c> field
+ in the <c>ei_socket_callbacks</c> structure to <c>NULL</c> if not implemented.</p>
+ </item>
+
+ <tag><c>int (*accept_handshake_complete)(void *ctx)</c></tag>
+ <item>
+ <p>Called when a remotely started handshake has completed successfully.</p>
+
+ <p>This callback is optional. Set the <c>accept_handshake_complete</c> field in
+ the <c>ei_socket_callbacks</c> structure to <c>NULL</c> if not implemented.</p>
+ </item>
+
+ <tag><c>int (*get_fd)(void *ctx, int *fd)</c></tag>
+ <item>
+ <p>Inform about file descriptor used by the socket which is identified
+ by <c>ctx</c>.</p>
+
+ <note><p>During the lifetime of a socket, the file descriptor
+ <em>has</em> to remain the same. That is, repeated calls to this
+ callback with the same context <c>should</c> always report the same
+ file descriptor.</p>
+ <p>The file descriptor <em>has</em> to be a real file descriptor.
+ That is, no other operation should be able to get the same file
+ descriptor until it has been released by the <c>close()</c>
+ callback.</p>
+ </note>
+
+ <p>This callback is mandatory.</p>
+ </item>
+ </taglist>
+ </section>
<funcs>
<func>
- <name><ret>struct hostent</ret><nametext>*ei_gethostbyaddr(const char *addr, int len, int type)</nametext></name>
- <name><ret>struct hostent</ret><nametext>*ei_gethostbyaddr_r(const char *addr, int length, int type, struct hostent *hostp, char *buffer, int buflen, int *h_errnop)</nametext></name>
- <name><ret>struct hostent</ret><nametext>*ei_gethostbyname(const char *name)</nametext></name>
- <name><ret>struct hostent</ret><nametext>*ei_gethostbyname_r(const char *name, struct hostent *hostp, char *buffer, int buflen, int *h_errnop)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>ei_gethostbyaddr(const char *addr, int len, int type)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>ei_gethostbyaddr_r(const char *addr, int length, int type, struct hostent *hostp, char *buffer, int buflen, int *h_errnop)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>ei_gethostbyname(const char *name)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>ei_gethostbyname_r(const char *name, struct hostent *hostp, char *buffer, int buflen, int *h_errnop)</nametext></name>
<fsummary>Name lookup functions.</fsummary>
<desc>
<p>Convenience functions for some common name lookup functions.</p>
</desc>
</func>
+
<func>
- <name><ret>int</ret><nametext>ei_accept(ei_cnode *ec, int listensock, ErlConnect *conp)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_accept(ei_cnode *ec, int listensock, ErlConnect *conp)</nametext></name>
<fsummary>Accept a connection from another node.</fsummary>
<desc>
<p>Used by a server process to accept a
@@ -130,7 +398,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>ei_accept_tmo(ei_cnode *ec, int listensock, ErlConnect *conp, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_accept_tmo(ei_cnode *ec, int listensock, ErlConnect *conp, unsigned timeout_ms)</nametext></name>
<fsummary>Accept a connection from another node with optional
time-out.</fsummary>
<desc>
@@ -141,8 +409,16 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>ei_connect(ei_cnode* ec, char *nodename)</nametext></name>
- <name><ret>int</ret><nametext>ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_close_connection(int fd)</nametext></name>
+ <fsummary>Close a connection.</fsummary>
+ <desc>
+ <p>Closes a previously opened connection or listen socket.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name since=""><ret>int</ret><nametext>ei_connect(ei_cnode* ec, char *nodename)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename)</nametext></name>
<fsummary>Establish a connection to an Erlang node.</fsummary>
<desc>
<p>Sets up a connection to an Erlang node.</p>
@@ -192,8 +468,10 @@ fd = ei_xconnect(&ec, &addr, ALIVE);
</func>
<func>
- <name><ret>int</ret><nametext>ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation)</nametext></name>
- <name><ret>int</ret><nametext>ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
<fsummary>Initialize for a connection.</fsummary>
<desc>
<p>Initializes the <c>ec</c> structure, to
@@ -236,6 +514,21 @@ fd = ei_xconnect(&ec, &addr, ALIVE);
<item>
<p><c>thispaddr</c> if the IP address of the host.</p>
</item>
+ <item>
+ <p><c>cbs</c> is a pointer to a
+ <seealso marker="#ei_socket_callbacks">callback structure</seealso>
+ implementing and alternative socket interface.</p>
+ </item>
+ <item>
+ <p><c>cbs_sz</c> is the size of the structure
+ pointed to by <c>cbs</c>.</p>
+ </item>
+ <item>
+ <p><c>setup_context</c> is a pointer to a structure that
+ will be passed as second argument to the <c>socket</c> callback
+ in the <c>cbs</c> structure.</p>
+ </item>
+
</list>
<p>A C-node acting as a server is assigned a creation
number when it calls <c>ei_publish()</c>.</p>
@@ -273,8 +566,8 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned timeout_ms)</nametext></name>
- <name><ret>int</ret><nametext>ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned timeout_ms)</nametext></name>
<fsummary>Establish a connection to an Erlang node with optional
time-out.</fsummary>
<desc>
@@ -286,8 +579,8 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_get_tracelevel(void)</nametext></name>
- <name><ret>void</ret><nametext>ei_set_tracelevel(int level)</nametext></name>
+ <name since="OTP R13B04"><ret>int</ret><nametext>ei_get_tracelevel(void)</nametext></name>
+ <name since="OTP R13B04"><ret>void</ret><nametext>ei_set_tracelevel(int level)</nametext></name>
<fsummary>Get and set functions for tracing.</fsummary>
<desc>
<p>Used to set tracing on the distribution. The levels are different
@@ -299,7 +592,46 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_publish(ei_cnode *ec, int port)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_listen(ei_cnode *ec, int *port, int backlog)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_xlisten(ei_cnode *ec, Erl_IpAddr adr, int *port, int backlog)</nametext></name>
+ <fsummary>Create a listen socket.</fsummary>
+ <desc>
+ <p>Used by a server process to setup a listen socket which
+ later can be used for accepting connections from client processes.
+ </p>
+ <list type="bulleted">
+ <item>
+ <p><c>ec</c> is the C-node structure.</p>
+ </item>
+ <item>
+ <p><c>adr</c> is local interface to bind to.</p>
+ </item>
+ <item>
+ <p><c>port</c> is a pointer to an integer containing the
+ port number to bind to. If <c>*port</c> equals <c>0</c>
+ when calling <c>ei_listen()</c>, the socket will be bound to
+ an ephemeral port. On success, <c>ei_listen()</c> will update
+ the value of <c>*port</c> to the port actually bound to.
+ </p>
+ </item>
+ <item>
+ <p><c>backlog</c> is maximum backlog of pending connections.</p>
+ </item>
+ </list>
+ <p><c>ei_listen</c> will create a socket, bind to a port on the
+ local interface identified by <c>adr</c> (or all local interfaces if
+ <c>ei_listen()</c> is called), and mark the socket as a passive socket
+ (that is, a socket that will be used for accepting incoming connections).
+ </p>
+ <p>
+ On success, a file descriptor is returned which can be used in a call to
+ <c>ei_accept()</c>. On failure, <c>ERL_ERROR</c> is returned and
+ <c>erl_errno</c> is set to <c>EIO</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name since=""><ret>int</ret><nametext>ei_publish(ei_cnode *ec, int port)</nametext></name>
<fsummary>Publish a node name.</fsummary>
<desc>
<p>Used by a server process to register
@@ -336,7 +668,7 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_publish_tmo(ei_cnode *ec, int port, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_publish_tmo(ei_cnode *ec, int port, unsigned timeout_ms)</nametext></name>
<fsummary>Publish a node name with optional time-out.</fsummary>
<desc>
<p>Equivalent to
@@ -346,7 +678,7 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_receive(int fd, unsigned char* bufp, int bufsize)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_receive(int fd, unsigned char* bufp, int bufsize)</nametext></name>
<fsummary>Receive a message.</fsummary>
<desc>
<p>Receives a message consisting of a sequence
@@ -387,7 +719,7 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_receive_encoded(int fd, char **mbufp, int *bufsz, erlang_msg *msg, int *msglen)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_receive_encoded(int fd, char **mbufp, int *bufsz, erlang_msg *msg, int *msglen)</nametext></name>
<fsummary>Obsolete function for receiving a message.</fsummary>
<desc>
<p>This function is retained for compatibility with code
@@ -417,7 +749,7 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_receive_encoded_tmo(int fd, char **mbufp, int *bufsz, erlang_msg *msg, int *msglen, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_receive_encoded_tmo(int fd, char **mbufp, int *bufsz, erlang_msg *msg, int *msglen, unsigned timeout_ms)</nametext></name>
<fsummary>Obsolete function for receiving a message with time-out.
</fsummary>
<desc>
@@ -428,8 +760,8 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
</func>
<func>
- <name><ret>int</ret><nametext>ei_receive_msg(int fd, erlang_msg* msg, ei_x_buff* x)</nametext></name>
- <name><ret>int</ret><nametext>ei_xreceive_msg(int fd, erlang_msg* msg, ei_x_buff* x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_receive_msg(int fd, erlang_msg* msg, ei_x_buff* x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_xreceive_msg(int fd, erlang_msg* msg, ei_x_buff* x)</nametext></name>
<fsummary>Receive a message.</fsummary>
<desc>
<p>Receives a message to the buffer in <c>x</c>.
@@ -493,8 +825,8 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>ei_receive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned imeout_ms)</nametext></name>
- <name><ret>int</ret><nametext>ei_xreceive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_receive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned imeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_xreceive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned timeout_ms)</nametext></name>
<fsummary>Receive a message with optional time-out.</fsummary>
<desc>
<p>Equivalent to <c>ei_receive_msg</c> and <c>ei_xreceive_msg</c>
@@ -504,7 +836,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>ei_receive_tmo(int fd, unsigned char* bufp, int bufsize, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_receive_tmo(int fd, unsigned char* bufp, int bufsize, unsigned timeout_ms)</nametext></name>
<fsummary>Receive a message with optional time-out.</fsummary>
<desc>
<p>Equivalent to
@@ -514,7 +846,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_send(ei_cnode* ec, int fd, char* server_name, char* buf, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_send(ei_cnode* ec, int fd, char* server_name, char* buf, int len)</nametext></name>
<fsummary>Send a message to a registered name.</fsummary>
<desc>
<p>Sends an Erlang term to a registered process.</p>
@@ -546,7 +878,7 @@ if (ei_reg_send(&ec, fd, x.buff, x.index) < 0)
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_send_tmo(ei_cnode* ec, int fd, char* server_name, char* buf, int len, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_send_tmo(ei_cnode* ec, int fd, char* server_name, char* buf, int len, unsigned timeout_ms)</nametext></name>
<fsummary>Send a message to a registered name with optional time-out
</fsummary>
<desc>
@@ -557,9 +889,9 @@ if (ei_reg_send(&ec, fd, x.buff, x.index) < 0)
</func>
<func>
- <name><ret>int</ret><nametext>ei_rpc(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf, int argbuflen, ei_x_buff *x)</nametext></name>
- <name><ret>int</ret><nametext>ei_rpc_to(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf, int argbuflen)</nametext></name>
- <name><ret>int</ret><nametext>ei_rpc_from(ei_cnode *ec, int fd, int timeout, erlang_msg *msg, ei_x_buff *x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_rpc(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf, int argbuflen, ei_x_buff *x)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_rpc_to(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf, int argbuflen)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_rpc_from(ei_cnode *ec, int fd, int timeout, erlang_msg *msg, ei_x_buff *x)</nametext></name>
<fsummary>Remote Procedure Call from C to Erlang.</fsummary>
<desc>
<p>Supports calling Erlang functions on remote nodes.
@@ -658,7 +990,7 @@ if (ei_decode_version(result.buff, &index) < 0
</func>
<func>
- <name><ret>erlang_pid *</ret><nametext>ei_self(ei_cnode *ec)</nametext></name>
+ <name since=""><ret>erlang_pid *</ret><nametext>ei_self(ei_cnode *ec)</nametext></name>
<fsummary>Retrieve the pid of the C-node.</fsummary>
<desc>
<p>Retrieves the pid of the C-node. Every C-node
@@ -671,7 +1003,7 @@ if (ei_decode_version(result.buff, &index) < 0
</func>
<func>
- <name><ret>int</ret><nametext>ei_send(int fd, erlang_pid* to, char* buf, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_send(int fd, erlang_pid* to, char* buf, int len)</nametext></name>
<fsummary>Send a message.</fsummary>
<desc>
<p>Sends an Erlang term to a process.</p>
@@ -692,7 +1024,7 @@ if (ei_decode_version(result.buff, &index) < 0
</func>
<func>
- <name><ret>int</ret><nametext>ei_send_encoded(int fd, erlang_pid* to, char* buf, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_send_encoded(int fd, erlang_pid* to, char* buf, int len)</nametext></name>
<fsummary>Obsolete function to send a message.</fsummary>
<desc>
<p>Works exactly as <c>ei_send</c>, the alternative name is retained for
@@ -702,7 +1034,7 @@ if (ei_decode_version(result.buff, &index) < 0
</func>
<func>
- <name><ret>int</ret><nametext>ei_send_encoded_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_send_encoded_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms)</nametext></name>
<fsummary>Obsolete function to send a message with optional time-out.
</fsummary>
<desc>
@@ -713,7 +1045,7 @@ if (ei_decode_version(result.buff, &index) < 0
</func>
<func>
- <name><ret>int</ret><nametext>ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to, const char *buf, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to, const char *buf, int len)</nametext></name>
<fsummary>Obsolete function to send a message to a registered name.
</fsummary>
<desc>
@@ -741,7 +1073,7 @@ self->num = fd;
</func>
<func>
- <name><ret>int</ret><nametext>ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, const char *buf, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, const char *buf, int len)</nametext></name>
<fsummary>Obsolete function to send a message to a registered name with
time-out.</fsummary>
<desc>
@@ -752,7 +1084,7 @@ self->num = fd;
</func>
<func>
- <name><ret>int</ret><nametext>ei_send_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_send_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms)</nametext></name>
<fsummary>Send a message with optional time-out.</fsummary>
<desc>
<p>Equivalent to
@@ -762,9 +1094,9 @@ self->num = fd;
</func>
<func>
- <name><ret>const char *</ret><nametext>ei_thisnodename(ei_cnode *ec)</nametext></name>
- <name><ret>const char *</ret><nametext>ei_thishostname(ei_cnode *ec)</nametext></name>
- <name><ret>const char *</ret><nametext>ei_thisalivename(ei_cnode *ec)</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>ei_thisnodename(ei_cnode *ec)</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>ei_thishostname(ei_cnode *ec)</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>ei_thisalivename(ei_cnode *ec)</nametext></name>
<fsummary>Retrieve some values.</fsummary>
<desc>
<p>Can be used to retrieve information about
@@ -779,7 +1111,7 @@ self->num = fd;
</func>
<func>
- <name><ret>int</ret><nametext>ei_unpublish(ei_cnode *ec)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_unpublish(ei_cnode *ec)</nametext></name>
<fsummary>Forcefully unpublish a node name.</fsummary>
<desc>
<p>Can be called by a process to unregister a
@@ -802,7 +1134,7 @@ self->num = fd;
</func>
<func>
- <name><ret>int</ret><nametext>ei_unpublish_tmo(ei_cnode *ec, unsigned timeout_ms)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_unpublish_tmo(ei_cnode *ec, unsigned timeout_ms)</nametext></name>
<fsummary>Unpublish a node name with optional time-out.</fsummary>
<desc>
<p>Equivalent to
diff --git a/lib/erl_interface/doc/src/ei_users_guide.xml b/lib/erl_interface/doc/src/ei_users_guide.xml
index 0eed50b50b..2dfd99e35a 100644
--- a/lib/erl_interface/doc/src/ei_users_guide.xml
+++ b/lib/erl_interface/doc/src/ei_users_guide.xml
@@ -162,12 +162,20 @@ $ ld -L/usr/local/otp/lib/erl_interface-3.2.3/
</section>
<section>
- <title>Initializing the Erl_Interface Library</title>
- <p>Before calling any of the other <c>Erl_Interface</c> functions, call
- <c>erl_init()</c> exactly once to initialize the library.
+ <title>Initializing the Libraries</title>
+ <p>
+ Before calling any of the other functions in the <c>erl_interface</c>
+ and <c>ei</c> libraries, call <c>erl_init()</c> exactly once to initialize
+ both libraries.
<c>erl_init()</c> takes two arguments. However, the arguments
- are no longer used by <c>Erl_Interface</c> and are therefore to be
- specified as <c>erl_init(NULL,0)</c>.</p>
+ are no longer used by <c>erl_interface</c> and are therefore to be
+ specified as <c>erl_init(NULL,0)</c>.
+ </p>
+ <p>
+ If you only use the <c>ei</c> library, instead initialize it by calling
+ <c>ei_init()</c> exactly once before calling any other functions in
+ the <c>ei</c> library.
+ </p>
</section>
<section>
diff --git a/lib/erl_interface/doc/src/erl_connect.xml b/lib/erl_interface/doc/src/erl_connect.xml
index 76ef6588c2..139ac9e2f0 100644
--- a/lib/erl_interface/doc/src/erl_connect.xml
+++ b/lib/erl_interface/doc/src/erl_connect.xml
@@ -49,7 +49,7 @@
<funcs>
<func>
- <name><ret>int</ret><nametext>erl_accept(listensock, conp)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_accept(listensock, conp)</nametext></name>
<fsummary>Accept a connection.</fsummary>
<type>
<v>int listensock;</v>
@@ -78,7 +78,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>erl_close_connection(fd)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_close_connection(fd)</nametext></name>
<fsummary>Close a connection to an Erlang node.</fsummary>
<type>
<v>int fd;</v>
@@ -95,8 +95,8 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>erl_connect(node)</nametext></name>
- <name><ret>int</ret><nametext>erl_xconnect(addr, alive)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_connect(node)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_xconnect(addr, alive)</nametext></name>
<fsummary>Establish a connection to an Erlang node.</fsummary>
<type>
<v>char *node, *alive;</v>
@@ -149,8 +149,8 @@ erl_xconnect( &addr , ALIVE );
</func>
<func>
- <name><ret>int</ret><nametext>erl_connect_init(number, cookie, creation)</nametext></name>
- <name><ret>int</ret><nametext>erl_connect_xinit(host, alive, node, addr, cookie, creation)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_connect_init(number, cookie, creation)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_connect_xinit(host, alive, node, addr, cookie, creation)</nametext></name>
<fsummary>Initialize communication.</fsummary>
<type>
<v>int number;</v>
@@ -246,7 +246,7 @@ if (!erl_connect_init(17, "samplecookiestring...", 0))
</func>
<func>
- <name><ret>int</ret><nametext>erl_publish(port)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_publish(port)</nametext></name>
<fsummary>Publish a node name.</fsummary>
<type>
<v>int port;</v>
@@ -277,7 +277,7 @@ if (!erl_connect_init(17, "samplecookiestring...", 0))
</func>
<func>
- <name><ret>int</ret><nametext>erl_receive(fd, bufp, bufsize)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_receive(fd, bufp, bufsize)</nametext></name>
<fsummary>Receive a message.</fsummary>
<type>
<v>int fd;</v>
@@ -316,7 +316,7 @@ if (!erl_connect_init(17, "samplecookiestring...", 0))
</func>
<func>
- <name><ret>int</ret><nametext>erl_receive_msg(fd, bufp, bufsize, emsg)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_receive_msg(fd, bufp, bufsize, emsg)</nametext></name>
<fsummary>Receive and decode a message.</fsummary>
<type>
<v>int fd;</v>
@@ -411,7 +411,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>erl_reg_send(fd, to, msg)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_reg_send(fd, to, msg)</nametext></name>
<fsummary>Send a message to a registered name.</fsummary>
<type>
<v>int fd;</v>
@@ -439,9 +439,9 @@ typedef struct {
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_rpc(fd, mod, fun, args)</nametext></name>
- <name><ret>int</ret><nametext>erl_rpc_from(fd, timeout, emsg)</nametext></name>
- <name><ret>int</ret><nametext>erl_rpc_to(fd, mod, fun, args)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_rpc(fd, mod, fun, args)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_rpc_from(fd, timeout, emsg)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_rpc_to(fd, mod, fun, args)</nametext></name>
<fsummary>Remote Procedure Call.</fsummary>
<type>
<v>int fd, timeout;</v>
@@ -511,7 +511,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>erl_send(fd, to, msg)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_send(fd, to, msg)</nametext></name>
<fsummary>Send a message.</fsummary>
<type>
<v>int fd;</v>
@@ -541,11 +541,11 @@ typedef struct {
</func>
<func>
- <name><ret>const char *</ret><nametext>erl_thisalivename()</nametext></name>
- <name><ret>const char *</ret><nametext>erl_thiscookie()</nametext></name>
- <name><ret>short</ret><nametext>erl_thiscreation()</nametext></name>
- <name><ret>const char *</ret><nametext>erl_thishostname()</nametext></name>
- <name><ret>const char *</ret><nametext>erl_thisnodename()</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>erl_thisalivename()</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>erl_thiscookie()</nametext></name>
+ <name since=""><ret>short</ret><nametext>erl_thiscreation()</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>erl_thishostname()</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>erl_thisnodename()</nametext></name>
<fsummary>Retrieve some values.</fsummary>
<desc>
<p>Retrieves information about
@@ -556,7 +556,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>erl_unpublish(alive)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_unpublish(alive)</nametext></name>
<fsummary>Forcefully unpublish a node name.</fsummary>
<type>
<v>char *alive;</v>
@@ -583,7 +583,7 @@ typedef struct {
</func>
<func>
- <name><ret>int</ret><nametext>erl_xreceive_msg(fd, bufpp, bufsizep, emsg)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_xreceive_msg(fd, bufpp, bufsizep, emsg)</nametext></name>
<fsummary>Receive and decode a message.</fsummary>
<type>
<v>int fd;</v>
@@ -616,10 +616,10 @@ typedef struct {
</func>
<func>
- <name><ret>struct hostent</ret><nametext>*erl_gethostbyaddr(addr, length, type)</nametext></name>
- <name><ret>struct hostent</ret><nametext>*erl_gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, h_errnop)</nametext></name>
- <name><ret>struct hostent</ret><nametext>*erl_gethostbyname(name)</nametext></name>
- <name><ret>struct hostent</ret><nametext>*erl_gethostbyname_r(name, hostp, buffer, buflen, h_errnop)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyaddr(addr, length, type)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, h_errnop)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyname(name)</nametext></name>
+ <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyname_r(name, hostp, buffer, buflen, h_errnop)</nametext></name>
<fsummary>Name lookup functions.</fsummary>
<type>
diff --git a/lib/erl_interface/doc/src/erl_error.xml b/lib/erl_interface/doc/src/erl_error.xml
index 8139c9b343..6fac94e442 100644
--- a/lib/erl_interface/doc/src/erl_error.xml
+++ b/lib/erl_interface/doc/src/erl_error.xml
@@ -47,7 +47,7 @@
<funcs>
<func>
- <name><ret>void</ret><nametext>erl_err_msg(FormatStr, ... )</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_err_msg(FormatStr, ... )</nametext></name>
<fsummary>Non-fatal error, and not system call error.</fsummary>
<type>
<v>const char *FormatStr;</v>
@@ -59,7 +59,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_err_quit(FormatStr, ... )</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_err_quit(FormatStr, ... )</nametext></name>
<fsummary>Fatal error, but not system call error.</fsummary>
<type>
<v>const char *FormatStr;</v>
@@ -73,7 +73,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_err_ret(FormatStr, ... )</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_err_ret(FormatStr, ... )</nametext></name>
<fsummary>Non-fatal system call error.</fsummary>
<type>
<v>const char *FormatStr;</v>
@@ -86,7 +86,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_err_sys(FormatStr, ... )</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_err_sys(FormatStr, ... )</nametext></name>
<fsummary>Fatal system call error.</fsummary>
<type>
<v>const char *FormatStr;</v>
@@ -113,7 +113,7 @@
<funcs>
<func>
- <name><ret>volatile int</ret><nametext>erl_errno</nametext></name>
+ <name since=""><ret>volatile int</ret><nametext>erl_errno</nametext></name>
<fsummary>Variable <c>erl_errno</c> contains the
Erl_Interface error number. You can change the value if you wish.
</fsummary>
diff --git a/lib/erl_interface/doc/src/erl_eterm.xml b/lib/erl_interface/doc/src/erl_eterm.xml
index 9a05196a70..070ed30dfe 100644
--- a/lib/erl_interface/doc/src/erl_eterm.xml
+++ b/lib/erl_interface/doc/src/erl_eterm.xml
@@ -142,7 +142,7 @@
<funcs>
<func>
- <name><ret>ETERM *</ret><nametext>erl_cons(head, tail)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_cons(head, tail)</nametext></name>
<fsummary>Prepend a term to the head of a list.</fsummary>
<type>
<v>ETERM *head;</v>
@@ -181,7 +181,7 @@ erl_free_compound(list);
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_copy_term(term)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_copy_term(term)</nametext></name>
<fsummary>Create a copy of an Erlang term.</fsummary>
<type>
<v>ETERM *term;</v>
@@ -193,7 +193,7 @@ erl_free_compound(list);
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_element(position, tuple)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_element(position, tuple)</nametext></name>
<fsummary>Extract an element from an Erlang tuple.</fsummary>
<type>
<v>int position;</v>
@@ -215,7 +215,7 @@ erl_free_compound(list);
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_hd(list)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_hd(list)</nametext></name>
<fsummary>Extract the first element from a list.</fsummary>
<type>
<v>ETERM *list;</v>
@@ -230,7 +230,7 @@ erl_free_compound(list);
</func>
<func>
- <name><ret>void</ret><nametext>erl_init(NULL, 0)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_init(NULL, 0)</nametext></name>
<fsummary>Initialization routine.</fsummary>
<type>
<v>void *NULL;</v>
@@ -245,7 +245,7 @@ erl_free_compound(list);
</func>
<func>
- <name><ret>int</ret><nametext>erl_iolist_length(list)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_iolist_length(list)</nametext></name>
<fsummary>Return the length of an I/O list.</fsummary>
<type>
<v>ETERM *list;</v>
@@ -262,7 +262,7 @@ erl_free_compound(list);
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_iolist_to_binary(term)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_iolist_to_binary(term)</nametext></name>
<fsummary>Convert an I/O list to a binary.</fsummary>
<type>
<v>ETERM *list;</v>
@@ -289,7 +289,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>char *</ret><nametext>erl_iolist_to_string(list)</nametext></name>
+ <name since=""><ret>char *</ret><nametext>erl_iolist_to_string(list)</nametext></name>
<fsummary>Convert an I/O list to a <c>NULL</c>-terminated string.</fsummary>
<type>
<v>ETERM *list;</v>
@@ -312,7 +312,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>int</ret><nametext>erl_length(list)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_length(list)</nametext></name>
<fsummary>Determine the length of a list.</fsummary>
<type>
<v>ETERM *list;</v>
@@ -328,7 +328,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_atom(string)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_atom(string)</nametext></name>
<fsummary>Create an atom.</fsummary>
<type>
<v>const char *string;</v>
@@ -355,7 +355,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_binary(bptr, size)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_binary(bptr, size)</nametext></name>
<fsummary>Create a binary object.</fsummary>
<type>
<v>char *bptr;</v>
@@ -378,7 +378,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_empty_list()</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_empty_list()</nametext></name>
<fsummary>Create an empty Erlang list.</fsummary>
<desc>
<p>Creates and returns an empty Erlang list.
@@ -388,7 +388,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_estring(string, len)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_estring(string, len)</nametext></name>
<fsummary>Create an Erlang string.</fsummary>
<type>
<v>char *string;</v>
@@ -408,7 +408,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_float(f)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_float(f)</nametext></name>
<fsummary>Create an Erlang float.</fsummary>
<type>
<v>double f;</v>
@@ -426,7 +426,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_int(n)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_int(n)</nametext></name>
<fsummary>Create an Erlang integer.</fsummary>
<type>
<v>int n;</v>
@@ -443,7 +443,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_list(array, arrsize)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_list(array, arrsize)</nametext></name>
<fsummary>Create a list from an array.</fsummary>
<type>
<v>ETERM **array;</v>
@@ -465,7 +465,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_long_ref(node, n1, n2, n3, creation)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_long_ref(node, n1, n2, n3, creation)</nametext></name>
<fsummary>Create an Erlang reference.</fsummary>
<type>
<v>const char *node;</v>
@@ -495,7 +495,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_pid(node, number, serial, creation)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_pid(node, number, serial, creation)</nametext></name>
<fsummary>Create a process identifier.</fsummary>
<type>
<v>const char *node;</v>
@@ -525,7 +525,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_port(node, number, creation)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_port(node, number, creation)</nametext></name>
<fsummary>Create a port identifier.</fsummary>
<type>
<v>const char *node;</v>
@@ -550,7 +550,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_ref(node, number, creation)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_ref(node, number, creation)</nametext></name>
<fsummary>Create an old Erlang reference.</fsummary>
<type>
<v>const char *node;</v>
@@ -578,7 +578,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_string(string)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_string(string)</nametext></name>
<fsummary>Create a string.</fsummary>
<type>
<v>char *string;</v>
@@ -593,7 +593,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_tuple(array, arrsize)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_tuple(array, arrsize)</nametext></name>
<fsummary>Create an Erlang tuple from an array.</fsummary>
<type>
<v>ETERM **array;</v>
@@ -621,7 +621,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_uint(n)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_uint(n)</nametext></name>
<fsummary>Create an unsigned integer.</fsummary>
<type>
<v>unsigned int n;</v>
@@ -638,7 +638,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_mk_var(name)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_mk_var(name)</nametext></name>
<fsummary>Create an Erlang variable.</fsummary>
<type>
<v>char *name;</v>
@@ -653,7 +653,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>int</ret><nametext>erl_print_term(stream, term)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_print_term(stream, term)</nametext></name>
<fsummary>Print an Erlang term.</fsummary>
<type>
<v>FILE *stream;</v>
@@ -672,7 +672,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>void</ret><nametext>erl_set_compat_rel(release_number)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_set_compat_rel(release_number)</nametext></name>
<fsummary>Set the Erl_Interface library in compatibility mode.</fsummary>
<type>
<v>unsigned release_number;</v>
@@ -706,7 +706,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>int</ret><nametext>erl_size(term)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_size(term)</nametext></name>
<fsummary>Return the arity of a tuple or binary.</fsummary>
<type>
<v>ETERM *term;</v>
@@ -723,7 +723,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_tl(list)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_tl(list)</nametext></name>
<fsummary>Extract the tail from a list.</fsummary>
<type>
<v>ETERM *list;</v>
@@ -738,7 +738,7 @@ iohead ::= Binary
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_var_content(term, name)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_var_content(term, name)</nametext></name>
<fsummary>Extract the content of a variable.</fsummary>
<type>
<v>ETERM *term;</v>
diff --git a/lib/erl_interface/doc/src/erl_format.xml b/lib/erl_interface/doc/src/erl_format.xml
index 5b8b7b5e78..b5e895c720 100644
--- a/lib/erl_interface/doc/src/erl_format.xml
+++ b/lib/erl_interface/doc/src/erl_format.xml
@@ -41,7 +41,7 @@
<funcs>
<func>
- <name><ret>ETERM *</ret><nametext>erl_format(FormatStr, ...)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_format(FormatStr, ...)</nametext></name>
<fsummary>Create an Erlang term.</fsummary>
<type>
<v>char *FormatStr;</v>
@@ -81,7 +81,7 @@ erl_format("[{name,~a},{age,~i},{data,~w}]",
</func>
<func>
- <name><ret>int</ret><nametext>erl_match(Pattern, Term)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_match(Pattern, Term)</nametext></name>
<fsummary>Perform pattern matching.</fsummary>
<type>
<v>ETERM *Pattern,*Term;</v>
diff --git a/lib/erl_interface/doc/src/erl_global.xml b/lib/erl_interface/doc/src/erl_global.xml
index 2fa0045adf..72d43e81d5 100644
--- a/lib/erl_interface/doc/src/erl_global.xml
+++ b/lib/erl_interface/doc/src/erl_global.xml
@@ -48,7 +48,7 @@
<funcs>
<func>
- <name><ret>char **</ret><nametext>erl_global_names(fd,count)</nametext></name>
+ <name since=""><ret>char **</ret><nametext>erl_global_names(fd,count)</nametext></name>
<fsummary>Obtain list of global names.</fsummary>
<type>
<v>int fd;</v>
@@ -79,7 +79,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>erl_global_register(fd,name,pid)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_global_register(fd,name,pid)</nametext></name>
<fsummary>Register a name in global.</fsummary>
<type>
<v>int fd;</v>
@@ -103,7 +103,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>erl_global_unregister(fd,name)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_global_unregister(fd,name)</nametext></name>
<fsummary>Unregister a name from global.</fsummary>
<type>
<v>int fd;</v>
@@ -122,7 +122,7 @@
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_global_whereis(fd,name,node)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_global_whereis(fd,name,node)</nametext></name>
<fsummary>Look up a name in global.</fsummary>
<type>
<v>int fd;</v>
diff --git a/lib/erl_interface/doc/src/erl_malloc.xml b/lib/erl_interface/doc/src/erl_malloc.xml
index c0eebc29e9..aae3b7e078 100644
--- a/lib/erl_interface/doc/src/erl_malloc.xml
+++ b/lib/erl_interface/doc/src/erl_malloc.xml
@@ -41,7 +41,7 @@
<funcs>
<func>
- <name><ret>ETERM *</ret><nametext>erl_alloc_eterm(etype)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_alloc_eterm(etype)</nametext></name>
<fsummary>Allocate an ETERM structure.</fsummary>
<type>
<v>unsigned char etype;</v>
@@ -89,7 +89,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_eterm_release(void)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_eterm_release(void)</nametext></name>
<fsummary>Clear the ETERM freelist.</fsummary>
<desc>
<p>Clears the freelist, where blocks are placed when they are
@@ -99,7 +99,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_eterm_statistics(allocated, freed)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_eterm_statistics(allocated, freed)</nametext></name>
<fsummary>Report term allocation statistics.</fsummary>
<type>
<v>long *allocated;</v>
@@ -127,7 +127,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_free(ptr)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_free(ptr)</nametext></name>
<fsummary>Free some memory.</fsummary>
<type>
<v>void *ptr;</v>
@@ -139,7 +139,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_free_array(array, size)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_free_array(array, size)</nametext></name>
<fsummary>Free an array of ETERM structures.</fsummary>
<type>
<v>ETERM **array;</v>
@@ -156,7 +156,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_free_compound(t)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_free_compound(t)</nametext></name>
<fsummary>Free an array of ETERM structures.</fsummary>
<type>
<v>ETERM *t;</v>
@@ -179,7 +179,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_free_term(t)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_free_term(t)</nametext></name>
<fsummary>Free an ETERM structure.</fsummary>
<type>
<v>ETERM *t;</v>
@@ -190,7 +190,7 @@
</func>
<func>
- <name><ret>void</ret><nametext>erl_malloc(size)</nametext></name>
+ <name since=""><ret>void</ret><nametext>erl_malloc(size)</nametext></name>
<fsummary>Allocate some memory.</fsummary>
<type>
<v>long size;</v>
diff --git a/lib/erl_interface/doc/src/erl_marshal.xml b/lib/erl_interface/doc/src/erl_marshal.xml
index 2ad658f78b..1a6d3bb43c 100644
--- a/lib/erl_interface/doc/src/erl_marshal.xml
+++ b/lib/erl_interface/doc/src/erl_marshal.xml
@@ -42,7 +42,7 @@
<funcs>
<func>
- <name><ret>int</ret><nametext>erl_compare_ext(bufp1, bufp2)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_compare_ext(bufp1, bufp2)</nametext></name>
<fsummary>Compare encoded byte sequences.</fsummary>
<type>
<v>unsigned char *bufp1,*bufp2;</v>
@@ -62,8 +62,8 @@
</func>
<func>
- <name><ret>ETERM *</ret><nametext>erl_decode(bufp)</nametext></name>
- <name><ret>ETERM *</ret><nametext>erl_decode_buf(bufpp)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_decode(bufp)</nametext></name>
+ <name since=""><ret>ETERM *</ret><nametext>erl_decode_buf(bufpp)</nametext></name>
<fsummary>Convert a term from Erlang external format.</fsummary>
<type>
<v>unsigned char *bufp;</v>
@@ -102,8 +102,8 @@
</func>
<func>
- <name><ret>int</ret><nametext>erl_encode(term, bufp)</nametext></name>
- <name><ret>int</ret><nametext>erl_encode_buf(term, bufpp)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_encode(term, bufp)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_encode_buf(term, bufpp)</nametext></name>
<fsummary>Convert a term into Erlang external format.</fsummary>
<type>
<v>ETERM *term;</v>
@@ -179,7 +179,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>erl_ext_size(bufp)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_ext_size(bufp)</nametext></name>
<fsummary>Count elements in encoded term.</fsummary>
<type>
<v>unsigned char *bufp;</v>
@@ -190,7 +190,7 @@
</func>
<func>
- <name><ret>unsigned char</ret><nametext>erl_ext_type(bufp)</nametext></name>
+ <name since=""><ret>unsigned char</ret><nametext>erl_ext_type(bufp)</nametext></name>
<fsummary>Determine type of an encoded byte sequence.</fsummary>
<type>
<v>unsigned char *bufp;</v>
@@ -228,7 +228,7 @@
</func>
<func>
- <name><ret>unsigned char *</ret><nametext>erl_peek_ext(bufp, pos)</nametext></name>
+ <name since=""><ret>unsigned char *</ret><nametext>erl_peek_ext(bufp, pos)</nametext></name>
<fsummary>Step over encoded term.</fsummary>
<type>
<v>unsigned char *bufp;</v>
@@ -252,7 +252,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>erl_term_len(t)</nametext></name>
+ <name since=""><ret>int</ret><nametext>erl_term_len(t)</nametext></name>
<fsummary>Determine encoded size of term.</fsummary>
<type>
<v>ETERM *t;</v>
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 5b81f795b2..1f95382704 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -31,6 +31,139 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.11.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>erl_interface</c>/<c>ei</c> refused to use node names
+ with an alive name (the part of the node name preceding
+ the @ sign) longer than 63 characters and a host name
+ longer than 64 characters. The total amount of characters
+ allowed in a node name (alivename@hostname) was thus
+ limited to 128 characters. These limits applied both to
+ the own node name as well as node names of other nodes.
+ Ordinary Erlang nodes limit the node name length to 256
+ characters, which meant that you could not communicate
+ with certain Erlang nodes due to their node name used.</p>
+ <p>
+ <c>erl_interface</c>/<c>ei</c> now allow the total amount
+ of characters in a node name to be up to 256 characters.
+ These characters may be distributed between alive name
+ and host name in whatever way needed. That is, the
+ maximum amount of characters in the alive name may be 254
+ and the maximum amount of characters in the host name may
+ be 254, but in total the node name must not exceed 256
+ characters.</p>
+ <p>
+ Own Id: OTP-15781 Aux Id: ERIERL-356 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.11.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix handling of Makefile dependencies so that parallel
+ make works properly.</p>
+ <p>
+ Own Id: OTP-15757</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.11.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed two bugs in the <c>erl_call</c> program. A missing
+ initialization (introduced in <c>erl_interface-3.11</c>)
+ which either caused a crash or failure to connect to or
+ start a node, and an incorrectly calculated timeout which
+ could cause failure to start an erlang node. These bugs
+ only caused failures on some platforms.</p>
+ <p>
+ Own Id: OTP-15676 Aux Id: OTP-15442, ERL-881 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.11</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Support for plugin of a <seealso
+ marker="ei_connect#ussi">user supplied socket
+ implementation</seealso> has been added.</p>
+ <p>
+ Own Id: OTP-15442 Aux Id: ERIERL-258 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.10.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make <c>ei_connect</c> and friends also accept state
+ <c>ok_simultaneous</c> during handshake, which means the
+ other node has initiated a connection setup that will be
+ cancelled in favor of this connection.</p>
+ <p>
+ Own Id: OTP-15161 Aux Id: ERIERL-191 </p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in <c>ei_receive_msg</c>,
+ <c>ei_xreceive_msg</c>, <c>ei_receive_msg_tmo</c> and
+ <c>ei_xreceive_msg_tmo</c>. The <c>x-&gt;index</c> was
+ set to entire buffer size instead of the number of bytes
+ actually received.</p>
+ <p>
+ Own Id: OTP-15171</p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in <c>ei_connect_init</c> which could be
+ provoked if called by concurrent threads.
+ <c>ei_connect_init</c> called posix interface
+ <c>gethostbyname</c> which is documented as not thread
+ safe.</p>
+ <p>
+ Own Id: OTP-15191</p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in erl_compare_ext() ignoring the tail of lists
+ of otherwise equal content. Example: <c>[a | b]</c> and
+ <c>[a | c]</c> compared equal and <c>{[a], b}</c> and
+ <c>{[a], c}</c> compared equal.</p>
+ <p>
+ Own Id: OTP-15277 Aux Id: PR-1929 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -69,6 +202,24 @@
</section>
+<section><title>Erl_Interface 3.10.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make <c>ei_connect</c> and friends also accept state
+ <c>ok_simultaneous</c> during handshake, which means the
+ other node has initiated a connection setup that will be
+ cancelled in favor of this connection.</p>
+ <p>
+ Own Id: OTP-15161 Aux Id: ERIERL-191 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/doc/src/registry.xml b/lib/erl_interface/doc/src/registry.xml
index 6d70fb3475..1c90c5c9dd 100644
--- a/lib/erl_interface/doc/src/registry.xml
+++ b/lib/erl_interface/doc/src/registry.xml
@@ -44,7 +44,7 @@
<funcs>
<func>
- <name><ret>int</ret><nametext>ei_reg_close(reg)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_close(reg)</nametext></name>
<fsummary>Close a registry.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -59,7 +59,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_delete(reg,key)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_delete(reg,key)</nametext></name>
<fsummary>Delete an object from the registry.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -85,7 +85,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_dump(fd,reg,mntab,flags)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_dump(fd,reg,mntab,flags)</nametext></name>
<fsummary>Back up a registry to Mnesia.</fsummary>
<type>
<v>int fd;</v>
@@ -125,7 +125,7 @@
</func>
<func>
- <name><ret>double</ret><nametext>ei_reg_getfval(reg,key)</nametext></name>
+ <name since=""><ret>double</ret><nametext>ei_reg_getfval(reg,key)</nametext></name>
<fsummary>Get a floating point object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -151,7 +151,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_getival(reg,key)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_getival(reg,key)</nametext></name>
<fsummary>Get an integer object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -177,7 +177,7 @@
</func>
<func>
- <name><ret>const void *</ret><nametext>ei_reg_getpval(reg,key,size)</nametext></name>
+ <name since=""><ret>const void *</ret><nametext>ei_reg_getpval(reg,key,size)</nametext></name>
<fsummary>Get a binary object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -207,7 +207,7 @@
</func>
<func>
- <name><ret>const char *</ret><nametext>ei_reg_getsval(reg,key)</nametext></name>
+ <name since=""><ret>const char *</ret><nametext>ei_reg_getsval(reg,key)</nametext></name>
<fsummary>Get a string object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -232,7 +232,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_getval(reg,key,flags,v,...)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_getval(reg,key,flags,v,...)</nametext></name>
<fsummary>Get any object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -278,7 +278,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_markdirty(reg,key)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_markdirty(reg,key)</nametext></name>
<fsummary>Mark an object as dirty.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -305,7 +305,7 @@
</func>
<func>
- <name><ret>ei_reg *</ret><nametext>ei_reg_open(size)</nametext></name>
+ <name since=""><ret>ei_reg *</ret><nametext>ei_reg_open(size)</nametext></name>
<fsummary>Create and open a registry.</fsummary>
<type>
<v>int size;</v>
@@ -326,7 +326,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_purge(reg)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_purge(reg)</nametext></name>
<fsummary>Remove deleted objects.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -346,7 +346,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_resize(reg,newsize)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_resize(reg,newsize)</nametext></name>
<fsummary>Resize a registry.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -363,7 +363,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_restore(fd,reg,mntab)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_restore(fd,reg,mntab)</nametext></name>
<fsummary>Restore a registry from Mnesia.</fsummary>
<type>
<v>int fd;</v>
@@ -399,7 +399,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_setfval(reg,key,f)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_setfval(reg,key,f)</nametext></name>
<fsummary>Assign a floating point object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -424,7 +424,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_setival(reg,key,i)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_setival(reg,key,i)</nametext></name>
<fsummary>Assign an integer object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -448,7 +448,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_setpval(reg,key,p,size)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_setpval(reg,key,p,size)</nametext></name>
<fsummary>Assign a binary object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -479,7 +479,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_setsval(reg,key,s)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_setsval(reg,key,s)</nametext></name>
<fsummary>Assign a string object.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -507,7 +507,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_setval(reg,key,flags,v,...)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_setval(reg,key,flags,v,...)</nametext></name>
<fsummary>Assign a value to any object type.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -552,7 +552,7 @@
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_stat(reg,key,obuf)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_stat(reg,key,obuf)</nametext></name>
<fsummary>Get object information.</fsummary>
<type>
<v>ei_reg *reg;</v>
@@ -590,7 +590,7 @@ struct ei_reg_stat {
</func>
<func>
- <name><ret>int</ret><nametext>ei_reg_tabstat(reg,obuf)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_reg_tabstat(reg,obuf)</nametext></name>
<fsummary>Get registry information.</fsummary>
<type>
<v>ei_reg *reg;</v>
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index 948f89be85..947726208e 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -35,6 +35,9 @@
#include <winsock2.h>
#include <windows.h>
#include <winbase.h>
+typedef LONG_PTR ssize_t; /* Sigh... */
+#else
+#include <sys/types.h> /* ssize_t */
#endif
#include <stdio.h> /* Need type FILE */
@@ -188,12 +191,12 @@ extern volatile int __erl_errno;
* library and when using the library we set a value that we use
*/
-#define EI_MAXHOSTNAMELEN 64
-#define EI_MAXALIVELEN 63
#define EI_MAX_COOKIE_SIZE 512
#define MAXATOMLEN (255 + 1)
#define MAXATOMLEN_UTF8 (255*4 + 1)
-#define MAXNODELEN EI_MAXALIVELEN+1+EI_MAXHOSTNAMELEN
+#define EI_MAXHOSTNAMELEN (MAXATOMLEN - 2)
+#define EI_MAXALIVELEN (MAXATOMLEN - 2)
+#define MAXNODELEN MAXATOMLEN
typedef enum {
ERLANG_ASCII = 1,
@@ -286,6 +289,31 @@ typedef struct {
char nodename[MAXNODELEN+1];
} ErlConnect;
+#define EI_SCLBK_INF_TMO (~((unsigned) 0))
+
+#define EI_SCLBK_FLG_FULL_IMPL (1 << 0)
+
+typedef struct {
+ int flags;
+
+ int (*socket)(void **ctx, void *setup_ctx);
+ int (*close)(void *ctx);
+ int (*listen)(void *ctx, void *addr, int *len, int backlog);
+ int (*accept)(void **ctx, void *addr, int *len, unsigned tmo);
+ int (*connect)(void *ctx, void *addr, int len, unsigned tmo);
+ int (*writev)(void *ctx, const void *iov, int iovcnt, ssize_t *len, unsigned tmo);
+ int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo);
+ int (*read)(void *ctx, char *buf, ssize_t *len, unsigned tmo);
+
+ int (*handshake_packet_header_size)(void *ctx, int *sz);
+ int (*connect_handshake_complete)(void *ctx);
+ int (*accept_handshake_complete)(void *ctx);
+ int (*get_fd)(void *ctx, int *fd);
+
+ /* end of version 1 */
+
+} ei_socket_callbacks;
+
typedef struct ei_cnode_s {
char thishostname[EI_MAXHOSTNAMELEN+1];
char thisnodename[MAXNODELEN+1];
@@ -295,6 +323,8 @@ typedef struct ei_cnode_s {
char ei_connect_cookie[EI_MAX_COOKIE_SIZE+1];
short creation;
erlang_pid self;
+ ei_socket_callbacks *cbs;
+ void *setup_context;
} ei_cnode;
typedef struct in_addr *Erl_IpAddr;
@@ -308,7 +338,6 @@ typedef struct ei_x_buff_TAG {
int index;
} ei_x_buff;
-
/* -------------------------------------------------------------------- */
/* Function definitions (listed in same order as documentation) */
/* -------------------------------------------------------------------- */
@@ -322,6 +351,16 @@ int ei_connect_xinit (ei_cnode* ec, const char *thishostname,
Erl_IpAddr thisipaddr, const char *cookie,
const short creation);
+int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name,
+ const char *cookie, short creation,
+ ei_socket_callbacks *cbs, int cbs_sz,
+ void *setup_context);
+int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
+ const char *thisalivename, const char *thisnodename,
+ Erl_IpAddr thisipaddr, const char *cookie,
+ const short creation, ei_socket_callbacks *cbs,
+ int cbs_sz, void *setup_context);
+
int ei_connect(ei_cnode* ec, char *nodename);
int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms);
int ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename);
@@ -348,11 +387,15 @@ int ei_rpc_from(ei_cnode* ec, int fd, int timeout, erlang_msg* msg,
int ei_publish(ei_cnode* ec, int port);
int ei_publish_tmo(ei_cnode* ec, int port, unsigned ms);
+int ei_listen(ei_cnode *ec, int *port, int backlog);
+int ei_xlisten(ei_cnode *ec, Erl_IpAddr adr, int *port, int backlog);
int ei_accept(ei_cnode* ec, int lfd, ErlConnect *conp);
int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms);
int ei_unpublish(ei_cnode* ec);
int ei_unpublish_tmo(const char *alive, unsigned ms);
+int ei_close_connection(int fd);
+
const char *ei_thisnodename(const ei_cnode* ec);
const char *ei_thishostname(const ei_cnode* ec);
const char *ei_thisalivename(const ei_cnode* ec);
@@ -626,6 +669,8 @@ struct ei_reg_tabstat {
};
+int ei_init(void);
+
/* -------------------------------------------------------------------- */
/* XXXXXXXXXXX */
/* -------------------------------------------------------------------- */
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 614e7325a9..2c1a8252ae 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -31,12 +31,11 @@
.PHONY : debug opt release clean distclean depend
-TARGET = @TARGET@
-
# ----------------------------------------------------
# Application version and release dir specification
# ----------------------------------------------------
include ../vsn.mk
+include $(ERL_TOP)/make/target.mk
include $(TARGET)/eidefs.mk
include $(ERL_TOP)/make/output.mk
@@ -417,7 +416,8 @@ MISCSRC = \
misc/eimd5.c \
misc/get_type.c \
misc/show_msg.c \
- misc/ei_compat.c
+ misc/ei_compat.c \
+ misc/ei_init.c
REGISTRYSRC = \
registry/hash_dohash.c \
@@ -780,29 +780,31 @@ $(MDD_OBJDIR)/ei_fake_prog_mdd_cxx$(EXE): prog/ei_fake_prog.c $(MDD_EILIB)
# Create dependency file using gcc -MM
###########################################################################
-depend:
+depend: $(TARGET)/depend.mk
+
+$(TARGET)/depend.mk: $(TARGET)/config.h
$(gen_verbose)
- $(V_colon)@echo "Generating dependency file depend.mk..."
- @echo "# Generated dependency rules" > depend.mk; \
- $(V_CC) $(CFLAGS) -MM $(SOURCES) | \
+ $(V_colon)echo "Generating dependency file depend.mk..."
+ @echo "# Generated dependency rules" > $@
+ $(V_CC) $(CFLAGS) -MM $(SOURCES) | \
sed 's&$(TARGET)&\$$\(TARGET\)&g' | \
- sed 's/^.*:/\$$\(ST_OBJDIR\)\/&/' >> depend.mk; \
- echo >> depend.mk; \
- $(CC) $(CFLAGS) -MM $(SOURCES) | \
+ sed 's/^.*:/\$$\(ST_OBJDIR\)\/&/' >> $@
+ @echo >> $@
+ $(V_CC) $(CFLAGS) -MM $(SOURCES) | \
sed 's&$(TARGET)&\$$\(TARGET\)&g' | \
- sed 's/^.*:/\$$\(MT_OBJDIR\)\/&/' >> depend.mk; \
- echo >> depend.mk; \
- $(CC) $(CFLAGS) -MM $(SOURCES) | \
+ sed 's/^.*:/\$$\(MT_OBJDIR\)\/&/' >> $@
+ @echo >> $@
+ $(V_CC) $(CFLAGS) -MM $(SOURCES) | \
sed 's&$(TARGET)&\$$\(TARGET\)&g' | \
- sed 's/^.*:/\$$\(MD_OBJDIR\)\/&/' >> depend.mk; \
- echo >> depend.mk; \
- $(CC) $(CFLAGS) -MM $(SOURCES) | \
+ sed 's/^.*:/\$$\(MD_OBJDIR\)\/&/' >> $@
+ @echo >> $@
+ $(V_CC) $(CFLAGS) -MM $(SOURCES) | \
sed 's&$(TARGET)&\$$\(TARGET\)&g' | \
- sed 's/^.*:/\$$\(MDD_OBJDIR\)\/&/' >> depend.mk; \
- echo >> depend.mk
+ sed 's/^.*:/\$$\(MDD_OBJDIR\)\/&/' >> $@
+ @echo >> $@
# For some reason this has to be after 'opt' target
-include depend.mk
+-include $(TARGET)/depend.mk
# ----------------------------------------------------
# Release Target
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index f5034ca3e8..95cb10a20c 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -42,10 +42,8 @@
#include <inetLib.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/times.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -55,7 +53,6 @@
#else /* some other unix */
#include <unistd.h>
-#include <sys/types.h>
#include <sys/times.h>
#if TIME_WITH_SYS_TIME
@@ -84,6 +81,7 @@
#include <string.h>
#include <errno.h>
#include <ctype.h>
+#include <stddef.h>
#include "eiext.h"
#include "ei_portio.h"
@@ -98,11 +96,16 @@
#include "ei_epmd.h"
#include "ei_internal.h"
+static int ei_connect_initialized = 0;
int ei_tracelevel = 0;
#define COOKIE_FILE "/.erlang.cookie"
#define EI_MAX_HOME_PATH 1024
+#define EI_SOCKET_CALLBACKS_SZ_V1 \
+ (offsetof(ei_socket_callbacks, get_fd) \
+ + sizeof(int (*)(void *)))
+
/* FIXME why not macro? */
static char *null_cookie = "";
@@ -113,30 +116,51 @@ static int get_home(char *buf, int size);
static unsigned gen_challenge(void);
static void gen_digest(unsigned challenge, char cookie[],
unsigned char digest[16]);
-static int send_status(int fd, char *status, unsigned ms);
-static int recv_status(int fd, unsigned ms);
-static int send_challenge(int fd, char *nodename,
- unsigned challenge, unsigned version, unsigned ms);
-static int recv_challenge(int fd, unsigned *challenge,
- unsigned *version,
- unsigned *flags, ErlConnect *namebuf, unsigned ms);
-static int send_challenge_reply(int fd, unsigned char digest[16],
+static int send_status(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, char *status, unsigned ms);
+static int recv_status(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned ms);
+static int send_challenge(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
+ char *nodename, unsigned challenge,
+ unsigned version, unsigned ms);
+static int recv_challenge(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
+ unsigned *challenge, unsigned *version,
+ unsigned *flags, char *namebuf, unsigned ms);
+static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned char digest[16],
unsigned challenge, unsigned ms);
-static int recv_challenge_reply(int fd,
- unsigned our_challenge,
+static int recv_challenge_reply(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned our_challenge,
char cookie[],
unsigned *her_challenge, unsigned ms);
-static int send_challenge_ack(int fd, unsigned char digest[16], unsigned ms);
-static int recv_challenge_ack(int fd,
- unsigned our_challenge,
+static int send_challenge_ack(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned char digest[16],
+ unsigned ms);
+static int recv_challenge_ack(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned our_challenge,
char cookie[], unsigned ms);
-static int send_name(int fd, char *nodename,
- unsigned version, unsigned ms);
+static int send_name(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
+ char *nodename, unsigned version, unsigned ms);
+
+static int recv_name(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
+ unsigned *version, unsigned *flags, char *namebuf,
+ unsigned ms);
-/* Common for both handshake types */
-static int recv_name(int fd,
- unsigned *version,
- unsigned *flags, ErlConnect *namebuf, unsigned ms);
+static struct hostent*
+dyn_gethostbyname_r(const char *name, struct hostent *hostp, char **buffer_p,
+ int buflen, int *h_errnop);
+
+static void abort_connection(ei_socket_callbacks *cbs, void *ctx);
+static int close_connection(ei_socket_callbacks *cbs, void *ctx, int fd);
+
+static char *
+estr(int e)
+{
+ char *str = strerror(e);
+ if (!str)
+ return "unknown error";
+ return str;
+}
/***************************************************************************
@@ -149,25 +173,208 @@ static int recv_name(int fd,
typedef struct ei_socket_info_s {
int socket;
+ ei_socket_callbacks *cbs;
+ void *ctx;
int dist_version;
ei_cnode cnode; /* A copy, not a pointer. We don't know when freed */
char cookie[EI_MAX_COOKIE_SIZE+1];
} ei_socket_info;
+/***************************************************************************
+ *
+ * XXX
+ *
+ ***************************************************************************/
+
+#ifndef ETHR_HAVE___atomic_compare_exchange_n
+# define ETHR_HAVE___atomic_compare_exchange_n 0
+#endif
+#ifndef ETHR_HAVE___atomic_load_n
+# define ETHR_HAVE___atomic_load_n 0
+#endif
+#ifndef ETHR_HAVE___atomic_store_n
+# define ETHR_HAVE___atomic_store_n 0
+#endif
+
+#if defined(_REENTRANT) \
+ && (!(ETHR_HAVE___atomic_compare_exchange_n & SIZEOF_VOID_P) \
+ || !(ETHR_HAVE___atomic_load_n & SIZEOF_VOID_P) \
+ || !(ETHR_HAVE___atomic_store_n & SIZEOF_VOID_P))
+# undef EI_DISABLE_SEQ_SOCKET_INFO
+# define EI_DISABLE_SEQ_SOCKET_INFO
+#endif
+
+#ifdef __WIN32__
+# undef EI_DISABLE_SEQ_SOCKET_INFO
+# define EI_DISABLE_SEQ_SOCKET_INFO
+#endif
+
+#ifndef EI_DISABLE_SEQ_SOCKET_INFO
+
+#ifdef _REENTRANT
+
+#define EI_ATOMIC_CMPXCHG_ACQ_REL(VARP, XCHGP, NEW) \
+ __atomic_compare_exchange_n((VARP), (XCHGP), (NEW), 0, \
+ __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)
+#define EI_ATOMIC_LOAD_ACQ(VARP) \
+ __atomic_load_n((VARP), __ATOMIC_ACQUIRE)
+#define EI_ATOMIC_STORE_REL(VARP, NEW) \
+ __atomic_store_n((VARP), (NEW), __ATOMIC_RELEASE)
+
+#else /* ! _REENTRANT */
+
+#define EI_ATOMIC_CMPXCHG_ACQ_REL(VARP, XCHGP, NEW) \
+ (*(VARP) == *(XCHGP) \
+ ? ((*(VARP) = (NEW)), !0) \
+ : ((*(XCHGP) = *(VARP)), 0))
+#define EI_ATOMIC_LOAD_ACQ(VARP) (*(VARP))
+#define EI_ATOMIC_STORE_REL(VARP, NEW) (*(VARP) = (NEW))
+
+#endif /* ! _REENTRANT */
+
+#define EI_SOCKET_INFO_SEG_BITS 5
+#define EI_SOCKET_INFO_SEG_SIZE (1 << EI_SOCKET_INFO_SEG_BITS)
+#define EI_SOCKET_INFO_SEG_MASK (EI_SOCKET_INFO_SEG_SIZE - 1)
+
+typedef struct {
+ int max_fds;
+ ei_socket_info *segments[1]; /* Larger in reality... */
+} ei_socket_info_data__;
+
+static ei_socket_info_data__ *socket_info_data = NULL;
+
+static int init_socket_info(int late)
+{
+ int max_fds;
+ int i;
+ size_t segments_len;
+ ei_socket_info_data__ *info_data, *xchg;
+
+ if (EI_ATOMIC_LOAD_ACQ(&socket_info_data) != NULL)
+ return 0; /* Already initialized... */
+
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+ max_fds = sysconf(_SC_OPEN_MAX);
+#else
+ max_fds = 1024;
+#endif
+
+ if (max_fds < 0)
+ return EIO;
+
+ segments_len = ((max_fds-1)/EI_SOCKET_INFO_SEG_SIZE + 1);
+
+ info_data = malloc(sizeof(ei_socket_info_data__)
+ + (sizeof(ei_socket_info *)*(segments_len-1)));
+ if (!info_data)
+ return ENOMEM;
+
+ info_data->max_fds = max_fds;
+ for (i = 0; i < segments_len; i++)
+ info_data->segments[i] = NULL;
+
+ xchg = NULL;
+ if (!EI_ATOMIC_CMPXCHG_ACQ_REL(&socket_info_data, &xchg, info_data))
+ free(info_data); /* Already initialized... */
+
+ return 0;
+}
+
+static int put_ei_socket_info(int fd, int dist_version, char* cookie, ei_cnode *ec,
+ ei_socket_callbacks *cbs, void *ctx)
+{
+ int six;
+ ei_socket_info *seg, *si;
+ int socket;
+
+ if (fd < 0 || socket_info_data->max_fds <= fd)
+ return -1;
+
+ socket = fd;
+ six = fd >> EI_SOCKET_INFO_SEG_BITS;
+ seg = EI_ATOMIC_LOAD_ACQ(&socket_info_data->segments[six]);
+
+ if (!seg) {
+ ei_socket_info *xchg;
+ int i;
+ seg = malloc(sizeof(ei_socket_info)*EI_SOCKET_INFO_SEG_SIZE);
+ if (!seg)
+ return -1;
+ for (i = 0; i < EI_SOCKET_INFO_SEG_SIZE; i++) {
+ seg[i].socket = -1;
+ }
+
+ xchg = NULL;
+ if (!EI_ATOMIC_CMPXCHG_ACQ_REL(&socket_info_data->segments[six], &xchg, seg)) {
+ free(seg);
+ seg = xchg;
+ }
+ }
+
+ si = &seg[fd & EI_SOCKET_INFO_SEG_MASK];
+
+ if (dist_version < 0) {
+ socket = -1;
+ si->cbs = NULL;
+ si->ctx = NULL;
+ }
+ else {
+ si->dist_version = dist_version;
+ si->cnode = *ec;
+ si->cbs = cbs;
+ si->ctx = ctx;
+ strcpy(si->cookie, cookie);
+ }
+
+ EI_ATOMIC_STORE_REL(&si->socket, socket);
+
+ return 0;
+}
+
+static ei_socket_info* get_ei_socket_info(int fd)
+{
+ int six, socket;
+ ei_socket_info *seg, *si;
+
+ if (fd < 0 || socket_info_data->max_fds <= fd)
+ return NULL;
+
+ six = fd >> EI_SOCKET_INFO_SEG_BITS;
+ seg = EI_ATOMIC_LOAD_ACQ(&socket_info_data->segments[six]);
+
+ if (!seg)
+ return NULL;
+
+ si = &seg[fd & EI_SOCKET_INFO_SEG_MASK];
+ socket = EI_ATOMIC_LOAD_ACQ(&si->socket);
+ if (socket != fd)
+ return NULL;
+ return si;
+}
+
+#else /* EI_DISABLE_SEQ_SOCKET_INFO */
+
int ei_n_sockets = 0, ei_sz_sockets = 0;
ei_socket_info *ei_sockets = NULL;
+
#ifdef _REENTRANT
ei_mutex_t* ei_sockets_lock = NULL;
#endif /* _REENTRANT */
+static int init_socket_info(int late)
+{
+#ifdef _REENTRANT
+ if (late)
+ return ENOTSUP; /* Refuse doing unsafe initialization... */
+ ei_sockets_lock = ei_mutex_create();
+ if (!ei_sockets_lock)
+ return ENOMEM;
+#endif /* _REENTRANT */
+ return 0;
+}
-/***************************************************************************
- *
- * XXX
- *
- ***************************************************************************/
-
-static int put_ei_socket_info(int fd, int dist_version, char* cookie, ei_cnode *ec)
+static int put_ei_socket_info(int fd, int dist_version, char* cookie, ei_cnode *ec,
+ ei_socket_callbacks *cbs, void *ctx)
{
int i;
@@ -177,11 +384,13 @@ static int put_ei_socket_info(int fd, int dist_version, char* cookie, ei_cnode *
for (i = 0; i < ei_n_sockets; ++i) {
if (ei_sockets[i].socket == fd) {
if (dist_version == -1) {
- memmove(&ei_sockets[i], &ei_sockets[i+1],
+ memmove(&ei_sockets[i], &ei_sockets[i+1],
sizeof(ei_sockets[0])*(ei_n_sockets-i-1));
} else {
ei_sockets[i].dist_version = dist_version;
/* Copy the content, see ei_socket_info */
+ ei_sockets[i].cbs = cbs;
+ ei_sockets[i].ctx = ctx;
ei_sockets[i].cnode = *ec;
strcpy(ei_sockets[i].cookie, cookie);
}
@@ -204,7 +413,9 @@ static int put_ei_socket_info(int fd, int dist_version, char* cookie, ei_cnode *
}
ei_sockets[ei_n_sockets].socket = fd;
ei_sockets[ei_n_sockets].dist_version = dist_version;
- ei_sockets[i].cnode = *ec;
+ ei_sockets[ei_n_sockets].cnode = *ec;
+ ei_sockets[ei_n_sockets].cbs = cbs;
+ ei_sockets[ei_n_sockets].ctx = ctx;
strcpy(ei_sockets[ei_n_sockets].cookie, cookie);
++ei_n_sockets;
}
@@ -214,14 +425,6 @@ static int put_ei_socket_info(int fd, int dist_version, char* cookie, ei_cnode *
return 0;
}
-#if 0
-/* FIXME not used ?! */
-static int remove_ei_socket_info(int fd, int dist_version, char* cookie)
-{
- return put_ei_socket_info(fd, -1, NULL);
-}
-#endif
-
static ei_socket_info* get_ei_socket_info(int fd)
{
int i;
@@ -243,6 +446,13 @@ static ei_socket_info* get_ei_socket_info(int fd)
return NULL;
}
+#endif /* EI_DISABLE_SEQ_SOCKET_INFO */
+
+static int remove_ei_socket_info(int fd)
+{
+ return put_ei_socket_info(fd, -1, NULL, NULL, NULL, NULL);
+}
+
ei_cnode *ei_fd_to_cnode(int fd)
{
ei_socket_info *sockinfo = get_ei_socket_info(fd);
@@ -250,6 +460,19 @@ ei_cnode *ei_fd_to_cnode(int fd)
return &sockinfo->cnode;
}
+int ei_get_cbs_ctx__(ei_socket_callbacks **cbs, void **ctx, int fd)
+{
+ ei_socket_info *sockinfo = get_ei_socket_info(fd);
+ if (sockinfo) {
+ *cbs = sockinfo->cbs;
+ *ctx = sockinfo->ctx;
+ return 0;
+ }
+
+ *cbs = NULL;
+ *ctx = NULL;
+ return EBADF;
+}
/***************************************************************************
* Get/Set tracelevel
@@ -328,21 +551,6 @@ const char *ei_getfdcookie(int fd)
return r;
}
-/* call with cookie to set value to use on descriptor fd,
-* or specify NULL to use default
-*/
-/* FIXME why defined but not used? */
-#if 0
-static int ei_setfdcookie(ei_cnode* ec, int fd, char *cookie)
-{
- int dist_version = ei_distversion(fd);
-
- if (cookie == NULL)
- cookie = ec->ei_connect_cookie;
- return put_ei_socket_info(fd, dist_version, cookie);
-}
-#endif
-
static int get_int32(unsigned char *s)
{
return ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | (s[3] ));
@@ -395,34 +603,62 @@ static int initWinSock(void)
}
#endif
+static int init_connect(int late)
+{
+ int error;
+
+ /*
+ * 'late' is non-zero when not called via ei_init(). Such a
+ * call is not supported, but we for now save the day if
+ * it easy to do so; otherwise, return ENOTSUP.
+ */
+
+#ifdef __WIN32__
+ if (!initWinSock()) {
+ EI_TRACE_ERR0("ei_init_connect","can't initiate winsock");
+ return EIO;
+ }
+#endif /* win32 */
+
+ error = init_socket_info(late);
+ if (error) {
+ EI_TRACE_ERR0("ei_init_connect","can't initiate socket info");
+ return error;
+ }
+
+ ei_connect_initialized = !0;
+ return 0;
+}
+
+int ei_init_connect(void)
+{
+ return init_connect(0);
+}
+
/*
* Perhaps run this routine instead of ei_connect_init/2 ?
* Initailize by setting:
* thishostname, thisalivename, thisnodename and thisipaddr
*/
-int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
- const char *thisalivename, const char *thisnodename,
- Erl_IpAddr thisipaddr, const char *cookie,
- const short creation)
+int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
+ const char *thisalivename, const char *thisnodename,
+ Erl_IpAddr thisipaddr, const char *cookie,
+ const short creation, ei_socket_callbacks *cbs,
+ int cbs_sz, void *setup_context)
{
char *dbglevel;
-
-/* FIXME this code was enabled for 'erl'_connect_xinit(), why not here? */
-#if 0
-#ifdef __WIN32__
- if (!initWinSock()) {
- EI_TRACE_ERR0("ei_connect_xinit","can't initiate winsock");
- return ERL_ERROR;
- }
-#endif
-#endif
-#ifdef _REENTRANT
- if (ei_sockets_lock == NULL) {
- ei_sockets_lock = ei_mutex_create();
- }
-#endif /* _REENTRANT */
+ if (!ei_connect_initialized)
+ init_connect(!0);
+ if (cbs != &ei_default_socket_callbacks)
+ EI_SET_HAVE_PLUGIN_SOCKET_IMPL__;
+
+ if (cbs_sz < EI_SOCKET_CALLBACKS_SZ_V1) {
+ EI_TRACE_ERR0("ei_connect_xinit","invalid size of ei_socket_callbacks struct");
+ return ERL_ERROR;
+ }
+
ec->creation = creation & 0x3; /* 2 bits */
if (cookie) {
@@ -464,6 +700,9 @@ int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
ec->self.serial = 0;
ec->self.creation = creation & 0x3; /* 2 bits */
+ ec->cbs = cbs;
+ ec->setup_context = setup_context;
+
if ((dbglevel = getenv("EI_TRACELEVEL")) != NULL ||
(dbglevel = getenv("ERL_DEBUG_DIST")) != NULL)
ei_tracelevel = atoi(dbglevel);
@@ -471,31 +710,39 @@ int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
return 0;
}
+int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
+ const char *thisalivename, const char *thisnodename,
+ Erl_IpAddr thisipaddr, const char *cookie,
+ const short creation)
+{
+ return ei_connect_xinit_ussi(ec, thishostname, thisalivename, thisnodename,
+ thisipaddr, cookie, creation,
+ &ei_default_socket_callbacks,
+ sizeof(ei_default_socket_callbacks),
+ NULL);
+}
/*
* Initialize by set: thishostname, thisalivename,
* thisnodename and thisipaddr. At success return 0,
* otherwise return -1.
*/
-int ei_connect_init(ei_cnode* ec, const char* this_node_name,
- const char *cookie, short creation)
+int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name,
+ const char *cookie, short creation,
+ ei_socket_callbacks *cbs, int cbs_sz,
+ void *setup_context)
{
- struct hostent *hp;
char thishostname[EI_MAXHOSTNAMELEN+1];
char thisnodename[MAXNODELEN+1];
char thisalivename[EI_MAXALIVELEN+1];
+ struct hostent host, *hp;
+ char buffer[1024];
+ char *buf = buffer;
+ int ei_h_errno;
+ int res;
-#ifdef __WIN32__
- if (!initWinSock()) {
- EI_TRACE_ERR0("ei_connect_xinit","can't initiate winsock");
- return ERL_ERROR;
- }
-#endif /* win32 */
-#ifdef _REENTRANT
- if (ei_sockets_lock == NULL) {
- ei_sockets_lock = ei_mutex_create();
- }
-#endif /* _REENTRANT */
+ if (!ei_connect_initialized)
+ init_connect(!0);
/* gethostname requires len to be max(hostname) + 1 */
if (gethostname(thishostname, EI_MAXHOSTNAMELEN+1) == -1) {
@@ -517,10 +764,13 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name,
strcpy(thisalivename, this_node_name);
}
- if ((hp = ei_gethostbyname(thishostname)) == 0) {
+ hp = dyn_gethostbyname_r(thishostname,&host,&buf,sizeof(buffer),&ei_h_errno);
+ if (hp == NULL) {
/* Looking up IP given hostname fails. We must be on a standalone
host so let's use loopback for communication instead. */
- if ((hp = ei_gethostbyname("localhost")) == 0) {
+ hp = dyn_gethostbyname_r("localhost", &host, &buf, sizeof(buffer),
+ &ei_h_errno);
+ if (hp == NULL) {
#ifdef __WIN32__
char reason[1024];
@@ -541,48 +791,33 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name,
if (strcmp(hp->h_name, "localhost") == 0) {
/* We use a short node name */
if ((ct = strchr(thishostname, '.')) != NULL) *ct = '\0';
- sprintf(thisnodename, "%s@%s", this_node_name, thishostname);
} else {
/* We use a short node name */
if ((ct = strchr(hp->h_name, '.')) != NULL) *ct = '\0';
strcpy(thishostname, hp->h_name);
- sprintf(thisnodename, "%s@%s", this_node_name, hp->h_name);
}
}
- return ei_connect_xinit(ec, thishostname, thisalivename, thisnodename,
- (struct in_addr *)*hp->h_addr_list, cookie, creation);
+ if (strlen(this_node_name) + 1 + strlen(thishostname) > MAXNODELEN) {
+ EI_TRACE_ERR0("ei_connect_init_ussi","this node name is too long");
+ return ERL_ERROR;
+ }
+ sprintf(thisnodename, "%s@%s", this_node_name, thishostname);
+ res = ei_connect_xinit_ussi(ec, thishostname, thisalivename, thisnodename,
+ (struct in_addr *)*hp->h_addr_list, cookie, creation,
+ cbs, cbs_sz, setup_context);
+ if (buf != buffer)
+ free(buf);
+ return res;
}
-
-/* connects to port at ip-address ip_addr
-* and returns fd to socket
-* port has to be in host byte order
-*/
-static int cnct(uint16 port, struct in_addr *ip_addr, int addr_len, unsigned ms)
+int ei_connect_init(ei_cnode* ec, const char* this_node_name,
+ const char *cookie, short creation)
{
- int s, res;
- struct sockaddr_in iserv_addr;
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- erl_errno = errno;
- return ERL_ERROR;
- }
-
- memset((char*)&iserv_addr, 0, sizeof(struct sockaddr_in));
- memcpy((char*)&iserv_addr.sin_addr, (char*)ip_addr, addr_len);
- iserv_addr.sin_family = AF_INET;
- iserv_addr.sin_port = htons(port);
-
- if ((res = ei_connect_t(s, (struct sockaddr*)&iserv_addr,
- sizeof(iserv_addr),ms)) < 0) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- closesocket(s);
- return ERL_ERROR;
- }
-
- return s;
-} /* cnct */
-
+ return ei_connect_init_ussi(ec, this_node_name, cookie, creation,
+ &ei_default_socket_callbacks,
+ sizeof(ei_default_socket_callbacks),
+ NULL);
+}
/*
* Same as ei_gethostbyname_r, but also handles ERANGE error
@@ -595,6 +830,13 @@ struct hostent *dyn_gethostbyname_r(const char *name,
int buflen,
int *h_errnop)
{
+#ifdef __WIN32__
+ /*
+ * Apparently ei_gethostbyname_r not implemented for Windows (?)
+ * Fall back on ei_gethostbyname like before.
+ */
+ return ei_gethostbyname(name);
+#else
char* buf = *buffer_p;
struct hostent *hp;
@@ -629,6 +871,7 @@ struct hostent *dyn_gethostbyname_r(const char *name,
}
}
return hp;
+#endif
}
/*
@@ -649,6 +892,11 @@ int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms)
int ei_h_errno;
#endif /* !win32 */
int res;
+
+ if (strlen(nodename) > MAXNODELEN) {
+ EI_TRACE_ERR0("ei_connect","Too long nodename");
+ return ERL_ERROR;
+ }
/* extract the host and alive parts from nodename */
if (!(hostname = strchr(nodename,'@'))) {
@@ -735,91 +983,218 @@ int ei_connect(ei_cnode* ec, char *nodename)
* the node through epmd at that host
*
*/
-int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned ms)
+int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename, unsigned ms)
{
- struct in_addr *ip_addr=(struct in_addr *) adr;
+ ei_socket_callbacks *cbs = ec->cbs;
+ void *ctx;
int rport = 0; /*uint16 rport = 0;*/
int sockd;
- int one = 1;
int dist = 0;
- ErlConnect her_name;
unsigned her_flags, her_version;
-
+ unsigned our_challenge, her_challenge;
+ unsigned char our_digest[16];
+ int err;
+ int pkt_sz;
+ struct sockaddr_in addr;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
+
erl_errno = EIO; /* Default error code */
EI_TRACE_CONN1("ei_xconnect","-> CONNECT attempt to connect to %s",
alivename);
- if ((rport = ei_epmd_port_tmo(ip_addr,alivename,&dist, ms)) < 0) {
+ if ((rport = ei_epmd_port_tmo(ip_addr,alivename,&dist, tmo)) < 0) {
EI_TRACE_ERR0("ei_xconnect","-> CONNECT can't get remote port");
/* ei_epmd_port_tmo() has set erl_errno */
return ERL_NO_PORT;
}
-
- /* we now have port number to enode, try to connect */
- if((sockd = cnct((uint16)rport, ip_addr, sizeof(struct in_addr),ms)) < 0) {
- EI_TRACE_ERR0("ei_xconnect","-> CONNECT socket connect failed");
- /* cnct() has set erl_errno */
- return ERL_CONNECT_FAIL;
- }
-
- EI_TRACE_CONN0("ei_xconnect","-> CONNECT connected to remote");
- /* FIXME why connect before checking 'dist' output from ei_epmd_port() ?! */
if (dist <= 4) {
EI_TRACE_ERR0("ei_xconnect","-> CONNECT remote version not compatible");
- goto error;
+ return ERL_ERROR;
}
- else {
- unsigned our_challenge, her_challenge;
- unsigned char our_digest[16];
-
- if (send_name(sockd, ec->thisnodename, (unsigned) dist, ms))
- goto error;
- if (recv_status(sockd, ms))
- goto error;
- if (recv_challenge(sockd, &her_challenge, &her_version,
- &her_flags, &her_name, ms))
- goto error;
- our_challenge = gen_challenge();
- gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
- if (send_challenge_reply(sockd, our_digest, our_challenge, ms))
- goto error;
- if (recv_challenge_ack(sockd, our_challenge,
- ec->ei_connect_cookie, ms))
- goto error;
- put_ei_socket_info(sockd, dist, null_cookie, ec); /* FIXME check == 0 */
+
+ err = ei_socket_ctx__(cbs, &ctx, ec->setup_context);
+ if (err) {
+ EI_TRACE_ERR2("ei_xconnect","-> SOCKET failed: %s (%d)",
+ estr(err), err);
+ erl_errno = err;
+ return ERL_CONNECT_FAIL;
+ }
+
+ memset((void *) &addr, 0, sizeof(struct sockaddr_in));
+ memcpy((void *) &addr.sin_addr, (void *) ip_addr, sizeof(addr.sin_addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(rport);
+
+ err = ei_connect_ctx_t__(cbs, ctx, (void *) &addr, sizeof(addr), tmo);
+ if (err) {
+ EI_TRACE_ERR2("ei_xconnect","-> CONNECT socket connect failed: %s (%d)",
+ estr(err), err);
+ abort_connection(cbs, ctx);
+ erl_errno = err;
+ return ERL_CONNECT_FAIL;
}
- setsockopt(sockd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));
- setsockopt(sockd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof(one));
+ EI_TRACE_CONN0("ei_xconnect","-> CONNECT connected to remote");
- EI_TRACE_CONN1("ei_xconnect","-> CONNECT (ok) remote = %s",alivename);
+ err = EI_GET_FD__(cbs, ctx, &sockd);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ goto error;
+ }
+
+ err = cbs->handshake_packet_header_size(ctx, &pkt_sz);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ goto error;
+ }
+
+ if (send_name(cbs, ctx, pkt_sz, ec->thisnodename, (unsigned) dist, tmo))
+ goto error;
+ if (recv_status(cbs, ctx, pkt_sz, tmo))
+ goto error;
+ if (recv_challenge(cbs, ctx, pkt_sz, &her_challenge,
+ &her_version, &her_flags, NULL, tmo))
+ goto error;
+ our_challenge = gen_challenge();
+ gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
+ if (send_challenge_reply(cbs, ctx, pkt_sz, our_digest, our_challenge, tmo))
+ goto error;
+ if (recv_challenge_ack(cbs, ctx, pkt_sz, our_challenge,
+ ec->ei_connect_cookie, tmo))
+ goto error;
+ if (put_ei_socket_info(sockd, dist, null_cookie, ec, cbs, ctx) != 0)
+ goto error;
+
+ if (cbs->connect_handshake_complete) {
+ err = cbs->connect_handshake_complete(ctx);
+ if (err) {
+ EI_TRACE_ERR2("ei_xconnect","-> CONNECT failed: %s (%d)",
+ estr(err), err);
+ close_connection(cbs, ctx, sockd);
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
+ }
+ EI_TRACE_CONN1("ei_xconnect","-> CONNECT (ok) remote = %s",alivename);
+
erl_errno = 0;
return sockd;
error:
EI_TRACE_ERR0("ei_xconnect","-> CONNECT failed");
- closesocket(sockd);
+ abort_connection(cbs, ctx);
return ERL_ERROR;
} /* ei_xconnect */
-int ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename)
+int ei_xconnect(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename)
{
- return ei_xconnect_tmo(ec, adr, alivename, 0);
+ return ei_xconnect_tmo(ec, ip_addr, alivename, 0);
}
+int ei_listen(ei_cnode *ec, int *port, int backlog)
+{
+ struct in_addr ip_addr;
+ ip_addr.s_addr = htonl(INADDR_ANY);
+ return ei_xlisten(ec, &ip_addr, port, backlog);
+}
+
+int ei_xlisten(ei_cnode *ec, struct in_addr *ip_addr, int *port, int backlog)
+{
+ ei_socket_callbacks *cbs = ec->cbs;
+ struct sockaddr_in sock_addr;
+ void *ctx;
+ int fd, err, len;
+
+ err = ei_socket_ctx__(cbs, &ctx, ec->setup_context);
+ if (err) {
+ EI_TRACE_ERR2("ei_xlisten","-> SOCKET failed: %s (%d)",
+ estr(err), err);
+ erl_errno = err;
+ return ERL_ERROR;
+ }
+
+ memset((void *) &sock_addr, 0, sizeof(struct sockaddr_in));
+ memcpy((void *) &sock_addr.sin_addr, (void *) ip_addr, sizeof(*ip_addr));
+ sock_addr.sin_family = AF_INET;
+ sock_addr.sin_port = htons((short) *port);
+
+ len = sizeof(sock_addr);
+ err = ei_listen_ctx__(cbs, ctx, (void *) &sock_addr, &len, backlog);
+ if (err) {
+ EI_TRACE_ERR2("ei_xlisten","-> listen failed: %s (%d)",
+ estr(err), err);
+ erl_errno = err;
+ goto error;
+ }
+
+ if (len != sizeof(sock_addr)) {
+ if (len < offsetof(struct sockaddr_in, sin_addr) + sizeof(sock_addr.sin_addr)
+ || len < offsetof(struct sockaddr_in, sin_port) + sizeof(sock_addr.sin_port)) {
+ erl_errno = EIO;
+ EI_TRACE_ERR0("ei_xlisten","-> get info failed");
+ goto error;
+ }
+ }
+
+ memcpy((void *) ip_addr, (void *) &sock_addr.sin_addr, sizeof(*ip_addr));
+ *port = (int) ntohs(sock_addr.sin_port);
+
+ err = EI_GET_FD__(cbs, ctx, &fd);
+ if (err) {
+ erl_errno = err;
+ goto error;
+ }
+
+ if (put_ei_socket_info(fd, 0, null_cookie, ec, cbs, ctx) != 0) {
+ EI_TRACE_ERR0("ei_xlisten","-> save socket info failed");
+ erl_errno = EIO;
+ goto error;
+ }
+
+ erl_errno = 0;
+
+ return fd;
+
+error:
+ abort_connection(cbs, ctx);
+ return ERL_ERROR;
+}
+
+static int close_connection(ei_socket_callbacks *cbs, void *ctx, int fd)
+{
+ int err;
+ remove_ei_socket_info(fd);
+ err = ei_close_ctx__(cbs, ctx);
+ if (err) {
+ erl_errno = err;
+ return ERL_ERROR;
+ }
+ return 0;
+}
- /*
- * For symmetry reasons
-*/
-#if 0
int ei_close_connection(int fd)
{
- return closesocket(fd);
+ ei_socket_callbacks *cbs;
+ void *ctx;
+ int err = EI_GET_CBS_CTX__(&cbs, &ctx, fd);
+ if (err)
+ erl_errno = err;
+ else {
+ if (close_connection(cbs, ctx, fd) == 0)
+ return 0;
+ }
+ EI_TRACE_ERR2("ei_close_connection","<- CLOSE socket close failed: %s (%d)",
+ estr(erl_errno), erl_errno);
+ return ERL_ERROR;
} /* ei_close_connection */
-#endif
+
+static void abort_connection(ei_socket_callbacks *cbs, void *ctx)
+{
+ (void) ei_close_ctx__(cbs, ctx);
+}
/*
* Accept and initiate a connection from another
@@ -834,25 +1209,71 @@ int ei_accept(ei_cnode* ec, int lfd, ErlConnect *conp)
int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms)
{
int fd;
- struct sockaddr_in cli_addr;
- int cli_addr_len=sizeof(struct sockaddr_in);
unsigned her_version, her_flags;
- ErlConnect her_name;
+ char tmp_nodename[MAXNODELEN+1];
+ char *her_name;
+ int pkt_sz, err;
+ struct sockaddr_in addr;
+ int addr_len = sizeof(struct sockaddr_in);
+ ei_socket_callbacks *cbs;
+ void *ctx;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
erl_errno = EIO; /* Default error code */
+
+ err = EI_GET_CBS_CTX__(&cbs, &ctx, lfd);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
+
EI_TRACE_CONN0("ei_accept","<- ACCEPT waiting for connection");
+
+ if (conp) {
+ her_name = &conp->nodename[0];
+ }
+ else {
+ her_name = &tmp_nodename[0];
+ }
- if ((fd = ei_accept_t(lfd, (struct sockaddr*) &cli_addr,
- &cli_addr_len, ms )) < 0) {
- EI_TRACE_ERR0("ei_accept","<- ACCEPT socket accept failed");
- erl_errno = (fd == -2) ? ETIMEDOUT : EIO;
- goto error;
+ /*
+ * ei_accept_ctx_t__() replaces the pointer to the listen context
+ * with a pointer to the accepted connection context on success.
+ */
+ err = ei_accept_ctx_t__(cbs, &ctx, (void *) &addr, &addr_len, tmo);
+ if (err) {
+ EI_TRACE_ERR2("ei_accept","<- ACCEPT socket accept failed: %s (%d)",
+ estr(err), err);
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
+
+ err = EI_GET_FD__(cbs, ctx, &fd);
+ if (err) {
+ EI_TRACE_ERR2("ei_accept","<- ACCEPT get fd failed: %s (%d)",
+ estr(err), err);
+ EI_CONN_SAVE_ERRNO__(err);
+ }
+
+ if (addr_len != sizeof(struct sockaddr_in)) {
+ if (addr_len < (offsetof(struct sockaddr_in, sin_addr)
+ + sizeof(addr.sin_addr))) {
+ EI_TRACE_ERR0("ei_accept","<- ACCEPT get addr failed");
+ goto error;
+ }
+ }
+
+ err = cbs->handshake_packet_header_size(ctx, &pkt_sz);
+ if (err) {
+ EI_TRACE_ERR2("ei_accept","<- ACCEPT get packet size failed: %s (%d)",
+ estr(err), err);
+ EI_CONN_SAVE_ERRNO__(err);
}
EI_TRACE_CONN0("ei_accept","<- ACCEPT connected to remote");
- if (recv_name(fd, &her_version, &her_flags, &her_name, ms)) {
+ if (recv_name(cbs, ctx, pkt_sz, &her_version, &her_flags, her_name, tmo)) {
EI_TRACE_ERR0("ei_accept","<- ACCEPT initial ident failed");
goto error;
}
@@ -865,34 +1286,45 @@ int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms)
unsigned our_challenge;
unsigned her_challenge;
unsigned char our_digest[16];
-
- if (send_status(fd,"ok", ms))
+
+ if (send_status(cbs, ctx, pkt_sz, "ok", tmo))
goto error;
our_challenge = gen_challenge();
- if (send_challenge(fd, ec->thisnodename,
- our_challenge, her_version, ms))
+ if (send_challenge(cbs, ctx, pkt_sz, ec->thisnodename,
+ our_challenge, her_version, tmo))
goto error;
- if (recv_challenge_reply(fd, our_challenge,
- ec->ei_connect_cookie,
- &her_challenge, ms))
+ if (recv_challenge_reply(cbs, ctx, pkt_sz, our_challenge,
+ ec->ei_connect_cookie, &her_challenge, tmo))
goto error;
gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
- if (send_challenge_ack(fd, our_digest, ms))
+ if (send_challenge_ack(cbs, ctx, pkt_sz, our_digest, tmo))
goto error;
- put_ei_socket_info(fd, her_version, null_cookie, ec);
+ if (put_ei_socket_info(fd, her_version, null_cookie, ec, cbs, ctx) != 0)
+ goto error;
+ }
+ if (conp) {
+ memcpy((void *) conp->ipadr, (void *) &addr.sin_addr, sizeof(conp->ipadr));
+ }
+
+ if (cbs->accept_handshake_complete) {
+ err = cbs->accept_handshake_complete(ctx);
+ if (err) {
+ EI_TRACE_ERR2("ei_xconnect","-> ACCEPT handshake failed: %s (%d)",
+ estr(err), err);
+ close_connection(cbs, ctx, fd);
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
}
- if (conp)
- *conp = her_name;
- EI_TRACE_CONN1("ei_accept","<- ACCEPT (ok) remote = %s",her_name.nodename);
+ EI_TRACE_CONN1("ei_accept","<- ACCEPT (ok) remote = %s",her_name);
erl_errno = 0; /* No error */
return fd;
error:
EI_TRACE_ERR0("ei_accept","<- ACCEPT failed");
- if (fd>=0)
- closesocket(fd);
+ abort_connection(cbs, ctx);
return ERL_ERROR;
} /* ei_accept */
@@ -904,36 +1336,57 @@ error:
*/
int ei_receive_tmo(int fd, unsigned char *bufp, int bufsize, unsigned ms)
{
- int len;
+ ssize_t len;
unsigned char fourbyte[4]={0,0,0,0};
- int res;
-
- if ((res = ei_read_fill_t(fd, (char *) bufp, 4, ms)) != 4) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ int err;
+ ei_socket_callbacks *cbs;
+ void *ctx;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
+
+ err = EI_GET_CBS_CTX__(&cbs, &ctx, fd);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
+
+ len = (ssize_t) 4;
+ err = ei_read_fill_ctx_t__(cbs, ctx, (char *) bufp, &len, tmo);
+ if (!err && len != (ssize_t) 4)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
return ERL_ERROR;
}
/* Tick handling */
- if ((len = get_int32(bufp)) == ERL_TICK)
- {
- ei_write_fill_t(fd, (char *) fourbyte, 4, ms);
+ len = get_int32(bufp);
+ if (len == ERL_TICK) {
+ len = 4;
+ ei_write_fill_ctx_t__(cbs, ctx, (char *) fourbyte, &len, tmo);
/* FIXME ok to ignore error or timeout? */
erl_errno = EAGAIN;
return ERL_TICK;
}
- else if (len > bufsize)
- {
+
+ if (len > bufsize) {
/* FIXME: We should drain the message. */
erl_errno = EMSGSIZE;
return ERL_ERROR;
}
- else if ((res = ei_read_fill_t(fd, (char *) bufp, len, ms)) != len)
- {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return ERL_ERROR;
+ else {
+ ssize_t need = len;
+ err = ei_read_fill_ctx_t__(cbs, ctx, (char *) bufp, &len, tmo);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
+ if (len != need) {
+ erl_errno = EIO;
+ return ERL_ERROR;
+ }
}
- return len;
+ return (int) len;
}
@@ -999,7 +1452,7 @@ int ei_do_receive_msg(int fd, int staticbuffer_p,
erl_errno = EMSGSIZE;
return ERL_ERROR;
}
- x->index = x->buffsz;
+ x->index = msglen;
switch (msg->msgtype) { /* FIXME does not handle trace tokens and monitors */
case ERL_SEND:
case ERL_REG_SEND:
@@ -1089,36 +1542,11 @@ int ei_rpc_to(ei_cnode *ec, int fd, char *mod, char *fun,
int ei_rpc_from(ei_cnode *ec, int fd, int timeout, erlang_msg *msg,
ei_x_buff *x)
{
- fd_set readmask;
- struct timeval tv;
- struct timeval *t = NULL;
-
- if (timeout >= 0) {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- t = &tv;
- }
-
- FD_ZERO(&readmask);
- FD_SET(fd,&readmask);
-
- switch (select(fd+1, &readmask, NULL, NULL, t)) {
- case -1:
- erl_errno = EIO;
- return ERL_ERROR;
-
- case 0:
- erl_errno = ETIMEDOUT;
- return ERL_TIMEOUT;
-
- default:
- if (FD_ISSET(fd, &readmask)) {
- return ei_xreceive_msg(fd, msg, x);
- } else {
- erl_errno = EIO;
- return ERL_ERROR;
- }
- }
+ unsigned tmo = timeout < 0 ? EI_SCLBK_INF_TMO : (unsigned) timeout;
+ int res = ei_xreceive_msg_tmo(fd, msg, x, tmo);
+ if (res < 0 && erl_errno == ETIMEDOUT)
+ return ERL_TIMEOUT;
+ return res;
} /* rpc_from */
/*
@@ -1272,19 +1700,34 @@ static char *hex(char digest[16], char buff[33])
return buff;
}
-static int read_2byte_package(int fd, char **buf, int *buflen,
- int *is_static, unsigned ms)
+static int read_hs_package(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, char **buf, int *buflen,
+ int *is_static, unsigned ms)
{
- unsigned char nbuf[2];
+ unsigned char nbuf[4];
unsigned char *x = nbuf;
- unsigned len;
- int res;
-
- if((res = ei_read_fill_t(fd, (char *)nbuf, 2, ms)) != 2) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ ssize_t len, need;
+ int err;
+
+ len = (ssize_t) pkt_sz;
+ err = ei_read_fill_ctx_t__(cbs, ctx, (char *)nbuf, &len, ms);
+ if (!err && len != (ssize_t) pkt_sz)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
- len = get16be(x);
+
+ switch (pkt_sz) {
+ case 2:
+ len = get16be(x);
+ break;
+ case 4:
+ len = get32be(x);
+ break;
+ default:
+ return -1;
+ }
if (len > *buflen) {
if (*is_static) {
@@ -1306,20 +1749,26 @@ static int read_2byte_package(int fd, char **buf, int *buflen,
*buflen = len;
}
}
- if ((res = ei_read_fill_t(fd, *buf, len, ms)) != len) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ need = len;
+ err = ei_read_fill_ctx_t__(cbs, ctx, *buf, &len, ms);
+ if (!err && len != need)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
return len;
}
-static int send_status(int fd, char *status, unsigned ms)
+static int send_status(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, char *status, unsigned ms)
{
char *buf, *s;
char dbuf[DEFBUF_SIZ];
- int siz = strlen(status) + 1 + 2;
- int res;
+ int siz = strlen(status) + 1 + pkt_sz;
+ int err;
+ ssize_t len;
buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf;
if (!buf) {
@@ -1327,14 +1776,28 @@ static int send_status(int fd, char *status, unsigned ms)
return -1;
}
s = buf;
- put16be(s,siz - 2);
+ switch (pkt_sz) {
+ case 2:
+ put16be(s,siz - 2);
+ break;
+ case 4:
+ put32be(s,siz - 4);
+ break;
+ default:
+ return -1;
+ }
put8(s, 's');
memcpy(s, status, strlen(status));
- if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) {
- EI_TRACE_ERR0("send_status","-> SEND_STATUS socket write failed");
+ len = (ssize_t) siz;
+ err = ei_write_fill_ctx_t__(cbs, ctx, buf, &len, ms);
+ if (!err && len != (ssize_t) siz)
+ err = EIO;
+ if (err) {
+ EI_TRACE_ERR2("send_status","-> SEND_STATUS socket write failed: %s (%d)",
+ estr(err), err);
if (buf != dbuf)
- free(buf);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ free(buf);
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
EI_TRACE_CONN1("send_status","-> SEND_STATUS (%s)",status);
@@ -1344,7 +1807,8 @@ static int send_status(int fd, char *status, unsigned ms)
return 0;
}
-static int recv_status(int fd, unsigned ms)
+static int recv_status(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned ms)
{
char dbuf[DEFBUF_SIZ];
char *buf = dbuf;
@@ -1352,16 +1816,20 @@ static int recv_status(int fd, unsigned ms)
int buflen = DEFBUF_SIZ;
int rlen;
- if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) <= 0) {
+ if ((rlen = read_hs_package(cbs, ctx, pkt_sz,
+ &buf, &buflen, &is_static, ms)) <= 0) {
EI_TRACE_ERR1("recv_status",
"<- RECV_STATUS socket read failed (%d)", rlen);
goto error;
}
- if (rlen == 3 && buf[0] == 's' && buf[1] == 'o' &&
- buf[2] == 'k') {
+
+ EI_TRACE_CONN2("recv_status",
+ "<- RECV_STATUS (%.*s)", (rlen>20 ? 20 : rlen), buf);
+
+ if (rlen >= 3 && buf[0] == 's' && buf[1] == 'o' && buf[2] == 'k') {
+ /* Expecting "sok" or "sok_simultaneous" */
if (!is_static)
free(buf);
- EI_TRACE_CONN0("recv_status","<- RECV_STATUS (ok)");
return 0;
}
error:
@@ -1370,7 +1838,10 @@ error:
return -1;
}
-static int send_name_or_challenge(int fd, char *nodename,
+static int send_name_or_challenge(ei_socket_callbacks *cbs,
+ void *ctx,
+ int pkt_sz,
+ char *nodename,
int f_chall,
unsigned challenge,
unsigned version,
@@ -1379,9 +1850,10 @@ static int send_name_or_challenge(int fd, char *nodename,
char *buf;
unsigned char *s;
char dbuf[DEFBUF_SIZ];
- int siz = 2 + 1 + 2 + 4 + strlen(nodename);
+ int siz = pkt_sz + 1 + 2 + 4 + strlen(nodename);
const char* function[] = {"SEND_NAME", "SEND_CHALLENGE"};
- int res;
+ int err;
+ ssize_t len;
if (f_chall)
siz += 4;
@@ -1391,7 +1863,16 @@ static int send_name_or_challenge(int fd, char *nodename,
return -1;
}
s = (unsigned char *)buf;
- put16be(s,siz - 2);
+ switch (pkt_sz) {
+ case 2:
+ put16be(s,siz - 2);
+ break;
+ case 4:
+ put32be(s,siz - 4);
+ break;
+ default:
+ return -1;
+ }
put8(s, 'n');
put16be(s, version);
put32be(s, (DFLAG_EXTENDED_REFERENCES
@@ -1407,13 +1888,16 @@ static int send_name_or_challenge(int fd, char *nodename,
if (f_chall)
put32be(s, challenge);
memcpy(s, nodename, strlen(nodename));
-
- if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) {
+ len = (ssize_t) siz;
+ err = ei_write_fill_ctx_t__(cbs, ctx, buf, &len, ms);
+ if (!err && len != (ssize_t) siz)
+ err = EIO;
+ if (err) {
EI_TRACE_ERR1("send_name_or_challenge",
"-> %s socket write failed", function[f_chall]);
if (buf != dbuf)
free(buf);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
@@ -1422,9 +1906,9 @@ static int send_name_or_challenge(int fd, char *nodename,
return 0;
}
-static int recv_challenge(int fd, unsigned *challenge,
- unsigned *version,
- unsigned *flags, ErlConnect *namebuf, unsigned ms)
+static int recv_challenge(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned *challenge, unsigned *version,
+ unsigned *flags, char *namebuf, unsigned ms)
{
char dbuf[DEFBUF_SIZ];
char *buf = dbuf;
@@ -1432,13 +1916,13 @@ static int recv_challenge(int fd, unsigned *challenge,
int buflen = DEFBUF_SIZ;
int rlen;
char *s;
- struct sockaddr_in sin;
- socklen_t sin_len = sizeof(sin);
char tag;
-
+ char tmp_nodename[MAXNODELEN+1];
+
erl_errno = EIO; /* Default */
- if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) <= 0) {
+ if ((rlen = read_hs_package(cbs, ctx, pkt_sz, &buf, &buflen,
+ &is_static, ms)) <= 0) {
EI_TRACE_ERR1("recv_challenge",
"<- RECV_CHALLENGE socket read failed (%d)",rlen);
goto error;
@@ -1479,22 +1963,19 @@ static int recv_challenge(int fd, unsigned *challenge,
goto error;
}
- if (getpeername(fd, (struct sockaddr *) &sin, &sin_len) < 0) {
- EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE can't get peername");
- erl_errno = errno;
- goto error;
- }
- memcpy(namebuf->ipadr, &(sin.sin_addr.s_addr),
- sizeof(sin.sin_addr.s_addr));
- memcpy(namebuf->nodename, s, rlen - 11);
- namebuf->nodename[rlen - 11] = '\0';
+ if (!namebuf)
+ namebuf = &tmp_nodename[0];
+
+ memcpy(namebuf, s, rlen - 11);
+ namebuf[rlen - 11] = '\0';
+
if (!is_static)
free(buf);
EI_TRACE_CONN4("recv_challenge","<- RECV_CHALLENGE (ok) node = %s, "
"version = %u, "
"flags = %u, "
"challenge = %d",
- namebuf->nodename,
+ namebuf,
*version,
*flags,
*challenge
@@ -1507,24 +1988,40 @@ error:
return -1;
}
-static int send_challenge_reply(int fd, unsigned char digest[16],
+static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned char digest[16],
unsigned challenge, unsigned ms)
{
char *s;
char buf[DEFBUF_SIZ];
- int siz = 2 + 1 + 4 + 16;
- int res;
+ int siz = pkt_sz + 1 + 4 + 16;
+ int err;
+ ssize_t len;
s = buf;
- put16be(s,siz - 2);
+ switch (pkt_sz) {
+ case 2:
+ put16be(s,siz - 2);
+ break;
+ case 4:
+ put32be(s,siz - 4);
+ break;
+ default:
+ return -1;
+ }
put8(s, 'r');
put32be(s, challenge);
memcpy(s, digest, 16);
-
- if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) {
- EI_TRACE_ERR0("send_challenge_reply",
- "-> SEND_CHALLENGE_REPLY socket write failed");
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+
+ len = (ssize_t) siz;
+ err = ei_write_fill_ctx_t__(cbs, ctx, buf, &len, ms);
+ if (!err && len != (ssize_t) siz)
+ err = EIO;
+ if (err) {
+ EI_TRACE_ERR2("send_challenge_reply",
+ "-> SEND_CHALLENGE_REPLY socket write failed: %s (%d)",
+ estr(err), err);
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
@@ -1537,11 +2034,13 @@ static int send_challenge_reply(int fd, unsigned char digest[16],
return 0;
}
-static int recv_challenge_reply (int fd,
- unsigned our_challenge,
- char cookie[],
- unsigned *her_challenge,
- unsigned ms)
+static int recv_challenge_reply(ei_socket_callbacks *cbs,
+ void *ctx,
+ int pkt_sz,
+ unsigned our_challenge,
+ char cookie[],
+ unsigned *her_challenge,
+ unsigned ms)
{
char dbuf[DEFBUF_SIZ];
char *buf = dbuf;
@@ -1554,7 +2053,7 @@ static int recv_challenge_reply (int fd,
erl_errno = EIO; /* Default */
- if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) != 21) {
+ if ((rlen = read_hs_package(cbs, ctx, pkt_sz, &buf, &buflen, &is_static, ms)) != 21) {
EI_TRACE_ERR1("recv_challenge_reply",
"<- RECV_CHALLENGE_REPLY socket read failed (%d)",rlen);
goto error;
@@ -1594,23 +2093,38 @@ error:
return -1;
}
-static int send_challenge_ack(int fd, unsigned char digest[16], unsigned ms)
+static int send_challenge_ack(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
+ unsigned char digest[16], unsigned ms)
{
char *s;
char buf[DEFBUF_SIZ];
- int siz = 2 + 1 + 16;
- int res;
+ int siz = pkt_sz + 1 + 16;
+ int err;
+ ssize_t len;
s = buf;
-
- put16be(s,siz - 2);
+ switch (pkt_sz) {
+ case 2:
+ put16be(s,siz - 2);
+ break;
+ case 4:
+ put32be(s,siz - 4);
+ break;
+ default:
+ return -1;
+ }
put8(s, 'a');
memcpy(s, digest, 16);
- if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) {
- EI_TRACE_ERR0("recv_challenge_reply",
- "-> SEND_CHALLENGE_ACK socket write failed");
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ len = (ssize_t) siz;
+ err = ei_write_fill_ctx_t__(cbs, ctx, buf, &len, ms);
+ if (!err && len != (ssize_t) siz)
+ err = EIO;
+ if (err) {
+ EI_TRACE_ERR2("recv_challenge_reply",
+ "-> SEND_CHALLENGE_ACK socket write failed: %s (%d)",
+ estr(err), err);
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
@@ -1623,8 +2137,8 @@ static int send_challenge_ack(int fd, unsigned char digest[16], unsigned ms)
return 0;
}
-static int recv_challenge_ack(int fd,
- unsigned our_challenge,
+static int recv_challenge_ack(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned our_challenge,
char cookie[], unsigned ms)
{
char dbuf[DEFBUF_SIZ];
@@ -1638,7 +2152,7 @@ static int recv_challenge_ack(int fd,
erl_errno = EIO; /* Default */
- if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) != 17) {
+ if ((rlen = read_hs_package(cbs, ctx, pkt_sz, &buf, &buflen, &is_static, ms)) != 17) {
EI_TRACE_ERR1("recv_challenge_ack",
"<- RECV_CHALLENGE_ACK socket read failed (%d)",rlen);
goto error;
@@ -1675,20 +2189,24 @@ error:
return -1;
}
-static int send_name(int fd, char *nodename, unsigned version, unsigned ms)
+static int send_name(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
+ char *nodename, unsigned version, unsigned ms)
{
- return send_name_or_challenge(fd, nodename, 0, 0, version, ms);
+ return send_name_or_challenge(cbs, ctx, pkt_sz, nodename, 0,
+ 0, version, ms);
}
-static int send_challenge(int fd, char *nodename,
- unsigned challenge, unsigned version, unsigned ms)
+static int send_challenge(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
+ char *nodename, unsigned challenge, unsigned version,
+ unsigned ms)
{
- return send_name_or_challenge(fd, nodename, 1, challenge, version, ms);
+ return send_name_or_challenge(cbs, ctx, pkt_sz, nodename, 1,
+ challenge, version, ms);
}
-static int recv_name(int fd,
- unsigned *version,
- unsigned *flags, ErlConnect *namebuf, unsigned ms)
+static int recv_name(ei_socket_callbacks *cbs, void *ctx,
+ int pkt_sz, unsigned *version,
+ unsigned *flags, char *namebuf, unsigned ms)
{
char dbuf[DEFBUF_SIZ];
char *buf = dbuf;
@@ -1696,13 +2214,13 @@ static int recv_name(int fd,
int buflen = DEFBUF_SIZ;
int rlen;
char *s;
- struct sockaddr_in sin;
- socklen_t sin_len = sizeof(sin);
+ char tmp_nodename[MAXNODELEN+1];
char tag;
erl_errno = EIO; /* Default */
- if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) <= 0) {
+ if ((rlen = read_hs_package(cbs, ctx, pkt_sz, &buf, &buflen,
+ &is_static, ms)) <= 0) {
EI_TRACE_ERR1("recv_name","<- RECV_NAME socket read failed (%d)",rlen);
goto error;
}
@@ -1733,21 +2251,18 @@ static int recv_name(int fd,
erl_errno = EIO;
goto error;
}
-
- if (getpeername(fd, (struct sockaddr *) &sin, &sin_len) < 0) {
- EI_TRACE_ERR0("recv_name","<- RECV_NAME can't get peername");
- erl_errno = errno;
- goto error;
- }
- memcpy(namebuf->ipadr, &(sin.sin_addr.s_addr),
- sizeof(sin.sin_addr.s_addr));
- memcpy(namebuf->nodename, s, rlen - 7);
- namebuf->nodename[rlen - 7] = '\0';
+
+ if (!namebuf)
+ namebuf = &tmp_nodename[0];
+
+ memcpy(namebuf, s, rlen - 7);
+ namebuf[rlen - 7] = '\0';
+
if (!is_static)
free(buf);
EI_TRACE_CONN3("recv_name",
"<- RECV_NAME (ok) node = %s, version = %u, flags = %u",
- namebuf->nodename,*version,*flags);
+ namebuf,*version,*flags);
erl_errno = 0;
return 0;
@@ -1841,3 +2356,4 @@ static int get_cookie(char *buf, int bufsize)
return 1; /* Success! */
}
+
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index 022a43d255..225fddc784 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -57,9 +57,9 @@
#ifdef HAVE_GETHOSTBYNAME_R
-void ei_init_resolve(void)
+int ei_init_resolve(void)
{
- return; /* Do nothing */
+ return 0; /* Do nothing */
}
#else /* !HAVE_GETHOSTBYNAME_R */
@@ -103,7 +103,7 @@ static int verify_dns_configuration(void);
* our own, which are just wrappers around hostGetByName() and
* hostGetByAddr(). Here we look up the functions.
*/
-void ei_init_resolve(void)
+int ei_init_resolve(void)
{
#ifdef VXWORKS
@@ -134,9 +134,12 @@ void ei_init_resolve(void)
#ifdef _REENTRANT
ei_gethost_sem = ei_mutex_create();
+ if (!ei_gethost_sem)
+ return ENOMEM;
#endif /* _REENTRANT */
ei_resolve_initialized = 1;
+ return 0;
}
#ifdef VXWORKS
@@ -312,9 +315,11 @@ static struct hostent *my_gethostbyname_r(const char *name,
struct hostent *src;
struct hostent *rval = NULL;
- /* FIXME this should have been done in 'erl'_init()? */
- if (!ei_resolve_initialized) ei_init_resolve();
-
+ if (!ei_resolve_initialized) {
+ *h_errnop = NO_RECOVERY;
+ return NULL;
+ }
+
#ifdef _REENTRANT
/* === BEGIN critical section === */
if (ei_mutex_lock(ei_gethost_sem,0) != 0) {
@@ -377,7 +382,10 @@ static struct hostent *my_gethostbyaddr_r(const char *addr,
struct hostent *rval = NULL;
/* FIXME this should have been done in 'erl'_init()? */
- if (!ei_resolve_initialized) ei_init_resolve();
+ if (!ei_resolve_initialized) {
+ *h_errnop = NO_RECOVERY;
+ return NULL;
+ }
#ifdef _REENTRANT
/* === BEGIN critical section === */
diff --git a/lib/erl_interface/src/connect/ei_resolve.h b/lib/erl_interface/src/connect/ei_resolve.h
index 10a49ffbc6..5711d7da76 100644
--- a/lib/erl_interface/src/connect/ei_resolve.h
+++ b/lib/erl_interface/src/connect/ei_resolve.h
@@ -20,6 +20,6 @@
#ifndef _EI_RESOLVE_H
#define _EI_RESOLVE_H
-void ei_init_resolve(void);
+int ei_init_resolve(void);
#endif /* _EI_RESOLVE_H */
diff --git a/lib/erl_interface/src/connect/eirecv.c b/lib/erl_interface/src/connect/eirecv.c
index 7b9dbfc387..47eea06ced 100644
--- a/lib/erl_interface/src/connect/eirecv.c
+++ b/lib/erl_interface/src/connect/eirecv.c
@@ -60,22 +60,36 @@ ei_recv_internal (int fd,
int arity;
int version;
int index = 0;
- int i = 0;
- int res;
+ int err;
int show_this_msg = 0;
+ ei_socket_callbacks *cbs;
+ void *ctx;
+ ssize_t rlen;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
+
+ err = EI_GET_CBS_CTX__(&cbs, &ctx, fd);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
+ }
/* get length field */
- if ((res = ei_read_fill_t(fd, header, 4, ms)) != 4)
- {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
+ rlen = 4;
+ err = ei_read_fill_ctx_t__(cbs, ctx, header, &rlen, tmo);
+ if (!err && rlen != 4)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
+
len = get32be(s);
/* got tick - respond and return */
if (!len) {
char tock[] = {0,0,0,0};
- ei_write_fill_t(fd, tock, sizeof(tock), ms); /* Failure no problem */
+ ssize_t wlen = sizeof(tock);
+ ei_write_fill_ctx_t__(cbs, ctx, tock, &wlen, tmo); /* Failure no problem */
*msglenp = 0;
return 0; /* maybe flag ERL_EAGAIN [sverkerw] */
}
@@ -86,9 +100,12 @@ ei_recv_internal (int fd,
ei_trace(-1,NULL);
/* read enough to get at least entire header */
- bytesread = (len > EIRECVBUF ? EIRECVBUF : len);
- if ((i = ei_read_fill_t(fd,header,bytesread,ms)) != bytesread) {
- erl_errno = (i == -2) ? ETIMEDOUT : EIO;
+ rlen = bytesread = (len > EIRECVBUF ? EIRECVBUF : len);
+ err = ei_read_fill_ctx_t__(cbs, ctx, header, &rlen, tmo);
+ if (!err && rlen != bytesread)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
@@ -212,12 +229,17 @@ ei_recv_internal (int fd,
*/
if (msglen > *bufsz) {
if (staticbufp) {
- int sz = EIRECVBUF;
/* flush in rest of packet */
while (remain > 0) {
- if (remain < sz) sz = remain;
- if ((i=ei_read_fill_t(fd,header,sz,ms)) <= 0) break;
- remain -= i;
+ rlen = remain > EIRECVBUF ? EIRECVBUF : remain;
+ err = ei_read_fill_ctx_t__(cbs, ctx, header, &rlen, tmo);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
+ }
+ if (rlen == 0)
+ break;
+ remain -= rlen;
}
erl_errno = EMSGSIZE;
return -1;
@@ -247,11 +269,15 @@ ei_recv_internal (int fd,
/* read the rest of the message into callers buffer */
if (remain > 0) {
- if ((i = ei_read_fill_t(fd,mbuf+bytesread-index,remain,ms)) != remain) {
- *msglenp = bytesread-index+1; /* actual bytes in users buffer */
- erl_errno = (i == -2) ? ETIMEDOUT : EIO;
- return -1;
- }
+ rlen = remain;
+ err = ei_read_fill_ctx_t__(cbs, ctx, mbuf+bytesread-index, &rlen, tmo);
+ if (!err && rlen != remain)
+ err = EIO;
+ if (err) {
+ *msglenp = bytesread-index+1; /* actual bytes in users buffer */
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
+ }
}
if (show_this_msg)
diff --git a/lib/erl_interface/src/connect/send.c b/lib/erl_interface/src/connect/send.c
index 37d7db6d68..d97532d123 100644
--- a/lib/erl_interface/src/connect/send.c
+++ b/lib/erl_interface/src/connect/send.c
@@ -58,10 +58,17 @@ int ei_send_encoded_tmo(int fd, const erlang_pid *to,
char *s, header[1200]; /* see size calculation below */
erlang_trace *token = NULL;
int index = 5; /* reserve 5 bytes for control message */
- int res;
-#ifdef HAVE_WRITEV
- struct iovec v[2];
-#endif
+ int err;
+ ei_socket_callbacks *cbs;
+ void *ctx;
+ ssize_t len, tot_len;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
+
+ err = EI_GET_CBS_CTX__(&cbs, &ctx, fd);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
/* are we tracing? */
/* check that he can receive trace tokens first */
@@ -91,30 +98,47 @@ int ei_send_encoded_tmo(int fd, const erlang_pid *to,
if (ei_tracelevel >= 4)
ei_show_sendmsg(stderr,header,msg);
-#ifdef HAVE_WRITEV
-
- v[0].iov_base = (char *)header;
- v[0].iov_len = index;
- v[1].iov_base = (char *)msg;
- v[1].iov_len = msglen;
-
- if ((res = ei_writev_fill_t(fd,v,2,ms)) != index+msglen) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
- }
-
-#else /* !HAVE_WRITEV */
-
- if ((res = ei_write_fill_t(fd,header,index,ms)) != index) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+
+#ifdef EI_HAVE_STRUCT_IOVEC__
+ if (ei_socket_callbacks_have_writev__(cbs)) {
+ struct iovec v[2];
+
+ v[0].iov_base = (char *)header;
+ v[0].iov_len = index;
+ v[1].iov_base = (char *)msg;
+ v[1].iov_len = msglen;
+
+ len = tot_len = (ssize_t) index+msglen;
+ err = ei_writev_fill_ctx_t__(cbs, ctx, v, 2, &len, tmo);
+ if (!err && len != tot_len)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
+ }
+
+ return 0;
}
- if ((res = ei_write_fill_t(fd,msg,msglen,ms)) != msglen) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+#endif /* EI_HAVE_STRUCT_IOVEC__ */
+
+ /* no writev() */
+ len = tot_len = (ssize_t) index;
+ err = ei_write_fill_ctx_t__(cbs, ctx, header, &len, tmo);
+ if (!err && len != tot_len)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
}
-#endif /* !HAVE_WRITEV */
+ len = tot_len = (ssize_t) msglen;
+ err = ei_write_fill_ctx_t__(cbs, ctx, msg, &len, tmo);
+ if (!err && len != tot_len)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
+ }
return 0;
}
diff --git a/lib/erl_interface/src/connect/send_exit.c b/lib/erl_interface/src/connect/send_exit.c
index 2e298e3221..b4f7e14c7f 100644
--- a/lib/erl_interface/src/connect/send_exit.c
+++ b/lib/erl_interface/src/connect/send_exit.c
@@ -55,6 +55,17 @@ int ei_send_exit_tmo(int fd, const erlang_pid *from, const erlang_pid *to,
char *s;
int index = 0;
int len = strlen(reason) + 1080; /* see below */
+ ei_socket_callbacks *cbs;
+ void *ctx;
+ int err;
+ ssize_t wlen;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
+
+ err = EI_GET_CBS_CTX__(&cbs, &ctx, fd);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
if (len > EISMALLBUF)
if (!(dbuf = malloc(len)))
@@ -92,10 +103,16 @@ int ei_send_exit_tmo(int fd, const erlang_pid *from, const erlang_pid *to,
if (ei_tracelevel >= 4)
ei_show_sendmsg(stderr,msgbuf,NULL);
- ei_write_fill_t(fd,msgbuf,index,ms);
- /* FIXME ignore timeout etc? erl_errno?! */
-
- if (dbuf) free(dbuf);
+ wlen = (ssize_t) index;
+ err = ei_write_fill_ctx_t__(cbs, ctx, msgbuf, &wlen, tmo);
+ if (!err && wlen != (ssize_t) index)
+ err = EIO;
+ if (dbuf)
+ free(dbuf);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
return 0;
}
diff --git a/lib/erl_interface/src/connect/send_reg.c b/lib/erl_interface/src/connect/send_reg.c
index 62478f042d..80d61e57b5 100644
--- a/lib/erl_interface/src/connect/send_reg.c
+++ b/lib/erl_interface/src/connect/send_reg.c
@@ -51,11 +51,17 @@ int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from,
char *s, header[1400]; /* see size calculation below */
erlang_trace *token = NULL;
int index = 5; /* reserve 5 bytes for control message */
- int res;
+ int err;
+ ei_socket_callbacks *cbs;
+ void *ctx;
+ ssize_t len, tot_len;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
-#ifdef HAVE_WRITEV
- struct iovec v[2];
-#endif
+ err = EI_GET_CBS_CTX__(&cbs, &ctx, fd);
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return ERL_ERROR;
+ }
/* are we tracing? */
/* check that he can receive trace tokens first */
@@ -86,29 +92,45 @@ int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from,
if (ei_tracelevel >= 4)
ei_show_sendmsg(stderr,header,msg);
-#ifdef HAVE_WRITEV
+#ifdef EI_HAVE_STRUCT_IOVEC__
+ if (ei_socket_callbacks_have_writev__(cbs)) {
+ struct iovec v[2];
- v[0].iov_base = (char *)header;
- v[0].iov_len = index;
- v[1].iov_base = (char *)msg;
- v[1].iov_len = msglen;
+ v[0].iov_base = (char *)header;
+ v[0].iov_len = index;
+ v[1].iov_base = (char *)msg;
+ v[1].iov_len = msglen;
- if ((res = ei_writev_fill_t(fd,v,2,ms)) != index+msglen) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+ len = tot_len = (ssize_t) index+msglen;
+ err = ei_writev_fill_ctx_t__(cbs, ctx, v, 2, &len, tmo);
+ if (!err && len != tot_len)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
+ }
+ return 0;
}
-#else
-
+#endif /* EI_HAVE_STRUCT_IOVEC__ */
+
/* no writev() */
- if ((res = ei_write_fill_t(fd,header,index,ms)) != index) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+ len = tot_len = (ssize_t) index;
+ err = ei_write_fill_ctx_t__(cbs, ctx, header, &len, tmo);
+ if (!err && len != tot_len)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
}
- if ((res = ei_write_fill_t(fd,msg,msglen,ms)) != msglen) {
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+
+ len = tot_len = (ssize_t) msglen;
+ err = ei_write_fill_ctx_t__(cbs, ctx, msg, &len, tmo);
+ if (!err && len != tot_len)
+ err = EIO;
+ if (err) {
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
}
-#endif
return 0;
}
diff --git a/lib/erl_interface/src/depend.mk b/lib/erl_interface/src/depend.mk
deleted file mode 100644
index af753046e5..0000000000
--- a/lib/erl_interface/src/depend.mk
+++ /dev/null
@@ -1,1133 +0,0 @@
-# Generated dependency rules
-$(ST_OBJDIR)/ei_connect.o: connect/ei_connect.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h misc/eiext.h misc/ei_portio.h \
- misc/ei_internal.h connect/ei_connect_int.h misc/ei_locking.h \
- connect/eisend.h connect/eirecv.h misc/eimd5.h misc/putget.h \
- connect/ei_resolve.h epmd/ei_epmd.h
-$(ST_OBJDIR)/ei_resolve.o: connect/ei_resolve.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h connect/ei_resolve.h misc/ei_locking.h
-$(ST_OBJDIR)/eirecv.o: connect/eirecv.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eirecv.h misc/ei_portio.h \
- misc/ei_internal.h misc/putget.h misc/ei_trace.h misc/show_msg.h
-$(ST_OBJDIR)/send.o: connect/send.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(ST_OBJDIR)/send_exit.o: connect/send_exit.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/ei_connect_int.h misc/ei_trace.h \
- misc/ei_internal.h misc/putget.h misc/show_msg.h
-$(ST_OBJDIR)/send_reg.o: connect/send_reg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(ST_OBJDIR)/decode_atom.o: decode/decode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_big.o: decode/decode_big.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_bignum.o: decode/decode_bignum.c $(TARGET)/config.h
-$(ST_OBJDIR)/decode_binary.o: decode/decode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_boolean.o: decode/decode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_char.o: decode/decode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_double.o: decode/decode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_fun.o: decode/decode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_malloc.h decode/decode_skip.h misc/putget.h
-$(ST_OBJDIR)/decode_intlist.o: decode/decode_intlist.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_list_header.o: decode/decode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_long.o: decode/decode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_pid.o: decode/decode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_port.o: decode/decode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_ref.o: decode/decode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_skip.o: decode/decode_skip.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- decode/decode_skip.h
-$(ST_OBJDIR)/decode_string.o: decode/decode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_trace.o: decode/decode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(ST_OBJDIR)/decode_tuple_header.o: decode/decode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_ulong.o: decode/decode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_version.o: decode/decode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_longlong.o: decode/decode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/decode_ulonglong.o: decode/decode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_atom.o: encode/encode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_bignum.o: encode/encode_bignum.c $(TARGET)/config.h
-$(ST_OBJDIR)/encode_binary.o: encode/encode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_boolean.o: encode/encode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_char.o: encode/encode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_double.o: encode/encode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_fun.o: encode/encode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_list_header.o: encode/encode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_long.o: encode/encode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_pid.o: encode/encode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_port.o: encode/encode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_ref.o: encode/encode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_string.o: encode/encode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_trace.o: encode/encode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(ST_OBJDIR)/encode_tuple_header.o: encode/encode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_ulong.o: encode/encode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_version.o: encode/encode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(ST_OBJDIR)/encode_longlong.o: encode/encode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(ST_OBJDIR)/encode_ulonglong.o: encode/encode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(ST_OBJDIR)/epmd_port.o: epmd/epmd_port.c misc/ei_internal.h epmd/ei_epmd.h \
- misc/putget.h
-$(ST_OBJDIR)/epmd_publish.o: epmd/epmd_publish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(ST_OBJDIR)/epmd_unpublish.o: epmd/epmd_unpublish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(ST_OBJDIR)/ei_decode_term.o: misc/ei_decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_decode_term.h misc/putget.h
-$(ST_OBJDIR)/ei_format.o: misc/ei_format.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_malloc.h misc/ei_format.h
-$(ST_OBJDIR)/ei_locking.o: misc/ei_locking.c $(TARGET)/config.h \
- misc/ei_malloc.h misc/ei_locking.h
-$(ST_OBJDIR)/ei_malloc.o: misc/ei_malloc.c misc/ei_malloc.h
-$(ST_OBJDIR)/ei_portio.o: misc/ei_portio.c misc/ei_portio.h misc/ei_internal.h
-$(ST_OBJDIR)/ei_printterm.o: misc/ei_printterm.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_printterm.h misc/ei_malloc.h
-$(ST_OBJDIR)/ei_pthreads.o: misc/ei_pthreads.c $(TARGET)/config.h \
- ../include/ei.h misc/ei_locking.h
-$(ST_OBJDIR)/ei_trace.o: misc/ei_trace.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_trace.h
-$(ST_OBJDIR)/ei_x_encode.o: misc/ei_x_encode.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_x_encode.h \
- misc/ei_malloc.h
-$(ST_OBJDIR)/eimd5.o: misc/eimd5.c misc/eimd5.h
-$(ST_OBJDIR)/get_type.o: misc/get_type.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h
-$(ST_OBJDIR)/show_msg.o: misc/show_msg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h misc/ei_printterm.h \
- misc/ei_internal.h misc/show_msg.h
-$(ST_OBJDIR)/ei_compat.o: misc/ei_compat.c ../include/ei.h misc/ei_internal.h
-$(ST_OBJDIR)/hash_dohash.o: registry/hash_dohash.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_foreach.o: registry/hash_foreach.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_freetab.o: registry/hash_freetab.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_insert.o: registry/hash_insert.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_isprime.o: registry/hash_isprime.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_lookup.o: registry/hash_lookup.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_newtab.o: registry/hash_newtab.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_remove.o: registry/hash_remove.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_resize.o: registry/hash_resize.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/hash_rlookup.o: registry/hash_rlookup.c registry/hash.h ../include/ei.h
-$(ST_OBJDIR)/reg_close.o: registry/reg_close.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_delete.o: registry/reg_delete.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_dirty.o: registry/reg_dirty.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_dump.o: registry/reg_dump.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(ST_OBJDIR)/reg_free.o: registry/reg_free.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_get.o: registry/reg_get.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_getf.o: registry/reg_getf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_geti.o: registry/reg_geti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_getp.o: registry/reg_getp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_gets.o: registry/reg_gets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_make.o: registry/reg_make.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_open.o: registry/reg_open.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_purge.o: registry/reg_purge.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_resize.o: registry/reg_resize.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_restore.o: registry/reg_restore.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(ST_OBJDIR)/reg_set.o: registry/reg_set.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_setf.o: registry/reg_setf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_seti.o: registry/reg_seti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_setp.o: registry/reg_setp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_sets.o: registry/reg_sets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_stat.o: registry/reg_stat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/reg_tabstat.o: registry/reg_tabstat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(ST_OBJDIR)/decode_term.o: legacy/decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h ../include/erl_interface.h
-$(ST_OBJDIR)/encode_term.o: legacy/encode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h ../include/erl_interface.h \
- legacy/erl_marshal.h legacy/erl_eterm.h legacy/portability.h
-$(ST_OBJDIR)/erl_connect.o: legacy/erl_connect.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_config.h \
- legacy/erl_connect.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h misc/putget.h connect/ei_connect_int.h \
- misc/ei_locking.h epmd/ei_epmd.h misc/ei_internal.h
-$(ST_OBJDIR)/erl_error.o: legacy/erl_error.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_error.h
-$(ST_OBJDIR)/erl_eterm.o: legacy/erl_eterm.c misc/ei_locking.h \
- $(TARGET)/config.h connect/ei_resolve.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_eterm.h \
- legacy/portability.h legacy/erl_malloc.h legacy/erl_marshal.h \
- legacy/erl_error.h legacy/erl_internal.h misc/ei_internal.h
-$(ST_OBJDIR)/erl_fix_alloc.o: legacy/erl_fix_alloc.c $(TARGET)/config.h \
- misc/ei_locking.h ../include/erl_interface.h ../include/ei.h \
- legacy/erl_error.h legacy/erl_malloc.h legacy/erl_fix_alloc.h \
- legacy/erl_eterm.h legacy/portability.h
-$(ST_OBJDIR)/erl_format.o: legacy/erl_format.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h legacy/erl_error.h legacy/erl_internal.h
-$(ST_OBJDIR)/erl_malloc.o: legacy/erl_malloc.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_fix_alloc.h legacy/erl_malloc.h \
- legacy/erl_internal.h legacy/erl_eterm.h legacy/portability.h \
- misc/ei_malloc.h
-$(ST_OBJDIR)/erl_marshal.o: legacy/erl_marshal.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_marshal.h \
- legacy/erl_eterm.h legacy/portability.h legacy/erl_malloc.h \
- legacy/erl_error.h legacy/erl_internal.h misc/eiext.h misc/putget.h
-$(ST_OBJDIR)/erl_timeout.o: legacy/erl_timeout.c $(TARGET)/config.h \
- legacy/erl_timeout.h
-$(ST_OBJDIR)/global_names.o: legacy/global_names.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(ST_OBJDIR)/global_register.o: legacy/global_register.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h ../include/erl_interface.h
-$(ST_OBJDIR)/global_unregister.o: legacy/global_unregister.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(ST_OBJDIR)/global_whereis.o: legacy/global_whereis.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-
-$(MT_OBJDIR)/ei_connect.o: connect/ei_connect.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h misc/eiext.h misc/ei_portio.h \
- misc/ei_internal.h connect/ei_connect_int.h misc/ei_locking.h \
- connect/eisend.h connect/eirecv.h misc/eimd5.h misc/putget.h \
- connect/ei_resolve.h epmd/ei_epmd.h
-$(MT_OBJDIR)/ei_resolve.o: connect/ei_resolve.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h connect/ei_resolve.h misc/ei_locking.h
-$(MT_OBJDIR)/eirecv.o: connect/eirecv.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eirecv.h misc/ei_portio.h \
- misc/ei_internal.h misc/putget.h misc/ei_trace.h misc/show_msg.h
-$(MT_OBJDIR)/send.o: connect/send.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(MT_OBJDIR)/send_exit.o: connect/send_exit.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/ei_connect_int.h misc/ei_trace.h \
- misc/ei_internal.h misc/putget.h misc/show_msg.h
-$(MT_OBJDIR)/send_reg.o: connect/send_reg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(MT_OBJDIR)/decode_atom.o: decode/decode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_big.o: decode/decode_big.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_bignum.o: decode/decode_bignum.c $(TARGET)/config.h
-$(MT_OBJDIR)/decode_binary.o: decode/decode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_boolean.o: decode/decode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_char.o: decode/decode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_double.o: decode/decode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_fun.o: decode/decode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_malloc.h decode/decode_skip.h misc/putget.h
-$(MT_OBJDIR)/decode_intlist.o: decode/decode_intlist.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_list_header.o: decode/decode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_long.o: decode/decode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_pid.o: decode/decode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_port.o: decode/decode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_ref.o: decode/decode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_skip.o: decode/decode_skip.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- decode/decode_skip.h
-$(MT_OBJDIR)/decode_string.o: decode/decode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_trace.o: decode/decode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(MT_OBJDIR)/decode_tuple_header.o: decode/decode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_ulong.o: decode/decode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_version.o: decode/decode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_longlong.o: decode/decode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/decode_ulonglong.o: decode/decode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_atom.o: encode/encode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_bignum.o: encode/encode_bignum.c $(TARGET)/config.h
-$(MT_OBJDIR)/encode_binary.o: encode/encode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_boolean.o: encode/encode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_char.o: encode/encode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_double.o: encode/encode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_fun.o: encode/encode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_list_header.o: encode/encode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_long.o: encode/encode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_pid.o: encode/encode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_port.o: encode/encode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_ref.o: encode/encode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_string.o: encode/encode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_trace.o: encode/encode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(MT_OBJDIR)/encode_tuple_header.o: encode/encode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_ulong.o: encode/encode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_version.o: encode/encode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MT_OBJDIR)/encode_longlong.o: encode/encode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(MT_OBJDIR)/encode_ulonglong.o: encode/encode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(MT_OBJDIR)/epmd_port.o: epmd/epmd_port.c misc/ei_internal.h epmd/ei_epmd.h \
- misc/putget.h
-$(MT_OBJDIR)/epmd_publish.o: epmd/epmd_publish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(MT_OBJDIR)/epmd_unpublish.o: epmd/epmd_unpublish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(MT_OBJDIR)/ei_decode_term.o: misc/ei_decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_decode_term.h misc/putget.h
-$(MT_OBJDIR)/ei_format.o: misc/ei_format.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_malloc.h misc/ei_format.h
-$(MT_OBJDIR)/ei_locking.o: misc/ei_locking.c $(TARGET)/config.h \
- misc/ei_malloc.h misc/ei_locking.h
-$(MT_OBJDIR)/ei_malloc.o: misc/ei_malloc.c misc/ei_malloc.h
-$(MT_OBJDIR)/ei_portio.o: misc/ei_portio.c misc/ei_portio.h misc/ei_internal.h
-$(MT_OBJDIR)/ei_printterm.o: misc/ei_printterm.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_printterm.h misc/ei_malloc.h
-$(MT_OBJDIR)/ei_pthreads.o: misc/ei_pthreads.c $(TARGET)/config.h \
- ../include/ei.h misc/ei_locking.h
-$(MT_OBJDIR)/ei_trace.o: misc/ei_trace.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_trace.h
-$(MT_OBJDIR)/ei_x_encode.o: misc/ei_x_encode.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_x_encode.h \
- misc/ei_malloc.h
-$(MT_OBJDIR)/eimd5.o: misc/eimd5.c misc/eimd5.h
-$(MT_OBJDIR)/get_type.o: misc/get_type.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h
-$(MT_OBJDIR)/show_msg.o: misc/show_msg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h misc/ei_printterm.h \
- misc/ei_internal.h misc/show_msg.h
-$(MT_OBJDIR)/ei_compat.o: misc/ei_compat.c ../include/ei.h misc/ei_internal.h
-$(MT_OBJDIR)/hash_dohash.o: registry/hash_dohash.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_foreach.o: registry/hash_foreach.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_freetab.o: registry/hash_freetab.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_insert.o: registry/hash_insert.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_isprime.o: registry/hash_isprime.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_lookup.o: registry/hash_lookup.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_newtab.o: registry/hash_newtab.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_remove.o: registry/hash_remove.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_resize.o: registry/hash_resize.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/hash_rlookup.o: registry/hash_rlookup.c registry/hash.h ../include/ei.h
-$(MT_OBJDIR)/reg_close.o: registry/reg_close.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_delete.o: registry/reg_delete.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_dirty.o: registry/reg_dirty.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_dump.o: registry/reg_dump.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(MT_OBJDIR)/reg_free.o: registry/reg_free.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_get.o: registry/reg_get.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_getf.o: registry/reg_getf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_geti.o: registry/reg_geti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_getp.o: registry/reg_getp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_gets.o: registry/reg_gets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_make.o: registry/reg_make.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_open.o: registry/reg_open.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_purge.o: registry/reg_purge.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_resize.o: registry/reg_resize.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_restore.o: registry/reg_restore.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(MT_OBJDIR)/reg_set.o: registry/reg_set.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_setf.o: registry/reg_setf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_seti.o: registry/reg_seti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_setp.o: registry/reg_setp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_sets.o: registry/reg_sets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_stat.o: registry/reg_stat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/reg_tabstat.o: registry/reg_tabstat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MT_OBJDIR)/decode_term.o: legacy/decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h ../include/erl_interface.h
-$(MT_OBJDIR)/encode_term.o: legacy/encode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h ../include/erl_interface.h \
- legacy/erl_marshal.h legacy/erl_eterm.h legacy/portability.h
-$(MT_OBJDIR)/erl_connect.o: legacy/erl_connect.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_config.h \
- legacy/erl_connect.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h misc/putget.h connect/ei_connect_int.h \
- misc/ei_locking.h epmd/ei_epmd.h misc/ei_internal.h
-$(MT_OBJDIR)/erl_error.o: legacy/erl_error.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_error.h
-$(MT_OBJDIR)/erl_eterm.o: legacy/erl_eterm.c misc/ei_locking.h \
- $(TARGET)/config.h connect/ei_resolve.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_eterm.h \
- legacy/portability.h legacy/erl_malloc.h legacy/erl_marshal.h \
- legacy/erl_error.h legacy/erl_internal.h misc/ei_internal.h
-$(MT_OBJDIR)/erl_fix_alloc.o: legacy/erl_fix_alloc.c $(TARGET)/config.h \
- misc/ei_locking.h ../include/erl_interface.h ../include/ei.h \
- legacy/erl_error.h legacy/erl_malloc.h legacy/erl_fix_alloc.h \
- legacy/erl_eterm.h legacy/portability.h
-$(MT_OBJDIR)/erl_format.o: legacy/erl_format.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h legacy/erl_error.h legacy/erl_internal.h
-$(MT_OBJDIR)/erl_malloc.o: legacy/erl_malloc.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_fix_alloc.h legacy/erl_malloc.h \
- legacy/erl_internal.h legacy/erl_eterm.h legacy/portability.h \
- misc/ei_malloc.h
-$(MT_OBJDIR)/erl_marshal.o: legacy/erl_marshal.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_marshal.h \
- legacy/erl_eterm.h legacy/portability.h legacy/erl_malloc.h \
- legacy/erl_error.h legacy/erl_internal.h misc/eiext.h misc/putget.h
-$(MT_OBJDIR)/erl_timeout.o: legacy/erl_timeout.c $(TARGET)/config.h \
- legacy/erl_timeout.h
-$(MT_OBJDIR)/global_names.o: legacy/global_names.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(MT_OBJDIR)/global_register.o: legacy/global_register.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h ../include/erl_interface.h
-$(MT_OBJDIR)/global_unregister.o: legacy/global_unregister.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(MT_OBJDIR)/global_whereis.o: legacy/global_whereis.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-
-$(MD_OBJDIR)/ei_connect.o: connect/ei_connect.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h misc/eiext.h misc/ei_portio.h \
- misc/ei_internal.h connect/ei_connect_int.h misc/ei_locking.h \
- connect/eisend.h connect/eirecv.h misc/eimd5.h misc/putget.h \
- connect/ei_resolve.h epmd/ei_epmd.h
-$(MD_OBJDIR)/ei_resolve.o: connect/ei_resolve.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h connect/ei_resolve.h misc/ei_locking.h
-$(MD_OBJDIR)/eirecv.o: connect/eirecv.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eirecv.h misc/ei_portio.h \
- misc/ei_internal.h misc/putget.h misc/ei_trace.h misc/show_msg.h
-$(MD_OBJDIR)/send.o: connect/send.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(MD_OBJDIR)/send_exit.o: connect/send_exit.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/ei_connect_int.h misc/ei_trace.h \
- misc/ei_internal.h misc/putget.h misc/show_msg.h
-$(MD_OBJDIR)/send_reg.o: connect/send_reg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(MD_OBJDIR)/decode_atom.o: decode/decode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_big.o: decode/decode_big.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_bignum.o: decode/decode_bignum.c $(TARGET)/config.h
-$(MD_OBJDIR)/decode_binary.o: decode/decode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_boolean.o: decode/decode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_char.o: decode/decode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_double.o: decode/decode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_fun.o: decode/decode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_malloc.h decode/decode_skip.h misc/putget.h
-$(MD_OBJDIR)/decode_intlist.o: decode/decode_intlist.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_list_header.o: decode/decode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_long.o: decode/decode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_pid.o: decode/decode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_port.o: decode/decode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_ref.o: decode/decode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_skip.o: decode/decode_skip.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- decode/decode_skip.h
-$(MD_OBJDIR)/decode_string.o: decode/decode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_trace.o: decode/decode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(MD_OBJDIR)/decode_tuple_header.o: decode/decode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_ulong.o: decode/decode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_version.o: decode/decode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_longlong.o: decode/decode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/decode_ulonglong.o: decode/decode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_atom.o: encode/encode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_bignum.o: encode/encode_bignum.c $(TARGET)/config.h
-$(MD_OBJDIR)/encode_binary.o: encode/encode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_boolean.o: encode/encode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_char.o: encode/encode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_double.o: encode/encode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_fun.o: encode/encode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_list_header.o: encode/encode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_long.o: encode/encode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_pid.o: encode/encode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_port.o: encode/encode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_ref.o: encode/encode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_string.o: encode/encode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_trace.o: encode/encode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(MD_OBJDIR)/encode_tuple_header.o: encode/encode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_ulong.o: encode/encode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_version.o: encode/encode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MD_OBJDIR)/encode_longlong.o: encode/encode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(MD_OBJDIR)/encode_ulonglong.o: encode/encode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(MD_OBJDIR)/epmd_port.o: epmd/epmd_port.c misc/ei_internal.h epmd/ei_epmd.h \
- misc/putget.h
-$(MD_OBJDIR)/epmd_publish.o: epmd/epmd_publish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(MD_OBJDIR)/epmd_unpublish.o: epmd/epmd_unpublish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(MD_OBJDIR)/ei_decode_term.o: misc/ei_decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_decode_term.h misc/putget.h
-$(MD_OBJDIR)/ei_format.o: misc/ei_format.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_malloc.h misc/ei_format.h
-$(MD_OBJDIR)/ei_locking.o: misc/ei_locking.c $(TARGET)/config.h \
- misc/ei_malloc.h misc/ei_locking.h
-$(MD_OBJDIR)/ei_malloc.o: misc/ei_malloc.c misc/ei_malloc.h
-$(MD_OBJDIR)/ei_portio.o: misc/ei_portio.c misc/ei_portio.h misc/ei_internal.h
-$(MD_OBJDIR)/ei_printterm.o: misc/ei_printterm.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_printterm.h misc/ei_malloc.h
-$(MD_OBJDIR)/ei_pthreads.o: misc/ei_pthreads.c $(TARGET)/config.h \
- ../include/ei.h misc/ei_locking.h
-$(MD_OBJDIR)/ei_trace.o: misc/ei_trace.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_trace.h
-$(MD_OBJDIR)/ei_x_encode.o: misc/ei_x_encode.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_x_encode.h \
- misc/ei_malloc.h
-$(MD_OBJDIR)/eimd5.o: misc/eimd5.c misc/eimd5.h
-$(MD_OBJDIR)/get_type.o: misc/get_type.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h
-$(MD_OBJDIR)/show_msg.o: misc/show_msg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h misc/ei_printterm.h \
- misc/ei_internal.h misc/show_msg.h
-$(MD_OBJDIR)/ei_compat.o: misc/ei_compat.c ../include/ei.h misc/ei_internal.h
-$(MD_OBJDIR)/hash_dohash.o: registry/hash_dohash.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_foreach.o: registry/hash_foreach.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_freetab.o: registry/hash_freetab.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_insert.o: registry/hash_insert.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_isprime.o: registry/hash_isprime.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_lookup.o: registry/hash_lookup.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_newtab.o: registry/hash_newtab.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_remove.o: registry/hash_remove.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_resize.o: registry/hash_resize.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/hash_rlookup.o: registry/hash_rlookup.c registry/hash.h ../include/ei.h
-$(MD_OBJDIR)/reg_close.o: registry/reg_close.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_delete.o: registry/reg_delete.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_dirty.o: registry/reg_dirty.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_dump.o: registry/reg_dump.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(MD_OBJDIR)/reg_free.o: registry/reg_free.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_get.o: registry/reg_get.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_getf.o: registry/reg_getf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_geti.o: registry/reg_geti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_getp.o: registry/reg_getp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_gets.o: registry/reg_gets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_make.o: registry/reg_make.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_open.o: registry/reg_open.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_purge.o: registry/reg_purge.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_resize.o: registry/reg_resize.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_restore.o: registry/reg_restore.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(MD_OBJDIR)/reg_set.o: registry/reg_set.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_setf.o: registry/reg_setf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_seti.o: registry/reg_seti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_setp.o: registry/reg_setp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_sets.o: registry/reg_sets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_stat.o: registry/reg_stat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/reg_tabstat.o: registry/reg_tabstat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MD_OBJDIR)/decode_term.o: legacy/decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h ../include/erl_interface.h
-$(MD_OBJDIR)/encode_term.o: legacy/encode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h ../include/erl_interface.h \
- legacy/erl_marshal.h legacy/erl_eterm.h legacy/portability.h
-$(MD_OBJDIR)/erl_connect.o: legacy/erl_connect.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_config.h \
- legacy/erl_connect.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h misc/putget.h connect/ei_connect_int.h \
- misc/ei_locking.h epmd/ei_epmd.h misc/ei_internal.h
-$(MD_OBJDIR)/erl_error.o: legacy/erl_error.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_error.h
-$(MD_OBJDIR)/erl_eterm.o: legacy/erl_eterm.c misc/ei_locking.h \
- $(TARGET)/config.h connect/ei_resolve.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_eterm.h \
- legacy/portability.h legacy/erl_malloc.h legacy/erl_marshal.h \
- legacy/erl_error.h legacy/erl_internal.h misc/ei_internal.h
-$(MD_OBJDIR)/erl_fix_alloc.o: legacy/erl_fix_alloc.c $(TARGET)/config.h \
- misc/ei_locking.h ../include/erl_interface.h ../include/ei.h \
- legacy/erl_error.h legacy/erl_malloc.h legacy/erl_fix_alloc.h \
- legacy/erl_eterm.h legacy/portability.h
-$(MD_OBJDIR)/erl_format.o: legacy/erl_format.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h legacy/erl_error.h legacy/erl_internal.h
-$(MD_OBJDIR)/erl_malloc.o: legacy/erl_malloc.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_fix_alloc.h legacy/erl_malloc.h \
- legacy/erl_internal.h legacy/erl_eterm.h legacy/portability.h \
- misc/ei_malloc.h
-$(MD_OBJDIR)/erl_marshal.o: legacy/erl_marshal.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_marshal.h \
- legacy/erl_eterm.h legacy/portability.h legacy/erl_malloc.h \
- legacy/erl_error.h legacy/erl_internal.h misc/eiext.h misc/putget.h
-$(MD_OBJDIR)/erl_timeout.o: legacy/erl_timeout.c $(TARGET)/config.h \
- legacy/erl_timeout.h
-$(MD_OBJDIR)/global_names.o: legacy/global_names.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(MD_OBJDIR)/global_register.o: legacy/global_register.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h ../include/erl_interface.h
-$(MD_OBJDIR)/global_unregister.o: legacy/global_unregister.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(MD_OBJDIR)/global_whereis.o: legacy/global_whereis.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-
-$(MDD_OBJDIR)/ei_connect.o: connect/ei_connect.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h misc/eiext.h misc/ei_portio.h \
- misc/ei_internal.h connect/ei_connect_int.h misc/ei_locking.h \
- connect/eisend.h connect/eirecv.h misc/eimd5.h misc/putget.h \
- connect/ei_resolve.h epmd/ei_epmd.h
-$(MDD_OBJDIR)/ei_resolve.o: connect/ei_resolve.c $(TARGET)/config.h \
- misc/eidef.h ../include/ei.h connect/ei_resolve.h misc/ei_locking.h
-$(MDD_OBJDIR)/eirecv.o: connect/eirecv.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eirecv.h misc/ei_portio.h \
- misc/ei_internal.h misc/putget.h misc/ei_trace.h misc/show_msg.h
-$(MDD_OBJDIR)/send.o: connect/send.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(MDD_OBJDIR)/send_exit.o: connect/send_exit.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/ei_connect_int.h misc/ei_trace.h \
- misc/ei_internal.h misc/putget.h misc/show_msg.h
-$(MDD_OBJDIR)/send_reg.o: connect/send_reg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h connect/eisend.h misc/putget.h \
- connect/ei_connect_int.h misc/ei_internal.h misc/ei_trace.h \
- misc/show_msg.h
-$(MDD_OBJDIR)/decode_atom.o: decode/decode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_big.o: decode/decode_big.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_bignum.o: decode/decode_bignum.c $(TARGET)/config.h
-$(MDD_OBJDIR)/decode_binary.o: decode/decode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_boolean.o: decode/decode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_char.o: decode/decode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_double.o: decode/decode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_fun.o: decode/decode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_malloc.h decode/decode_skip.h misc/putget.h
-$(MDD_OBJDIR)/decode_intlist.o: decode/decode_intlist.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_list_header.o: decode/decode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_long.o: decode/decode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_pid.o: decode/decode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_port.o: decode/decode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_ref.o: decode/decode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_skip.o: decode/decode_skip.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- decode/decode_skip.h
-$(MDD_OBJDIR)/decode_string.o: decode/decode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_trace.o: decode/decode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(MDD_OBJDIR)/decode_tuple_header.o: decode/decode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_ulong.o: decode/decode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_version.o: decode/decode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_longlong.o: decode/decode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/decode_ulonglong.o: decode/decode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_atom.o: encode/encode_atom.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_bignum.o: encode/encode_bignum.c $(TARGET)/config.h
-$(MDD_OBJDIR)/encode_binary.o: encode/encode_binary.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_boolean.o: encode/encode_boolean.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_char.o: encode/encode_char.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_double.o: encode/encode_double.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_fun.o: encode/encode_fun.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_list_header.o: encode/encode_list_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_long.o: encode/encode_long.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_pid.o: encode/encode_pid.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_port.o: encode/encode_port.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_ref.o: encode/encode_ref.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_string.o: encode/encode_string.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_trace.o: encode/encode_trace.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/putget.h
-$(MDD_OBJDIR)/encode_tuple_header.o: encode/encode_tuple_header.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_ulong.o: encode/encode_ulong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_version.o: encode/encode_version.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h
-$(MDD_OBJDIR)/encode_longlong.o: encode/encode_longlong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(MDD_OBJDIR)/encode_ulonglong.o: encode/encode_ulonglong.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h
-$(MDD_OBJDIR)/epmd_port.o: epmd/epmd_port.c misc/ei_internal.h epmd/ei_epmd.h \
- misc/putget.h
-$(MDD_OBJDIR)/epmd_publish.o: epmd/epmd_publish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(MDD_OBJDIR)/epmd_unpublish.o: epmd/epmd_unpublish.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_internal.h \
- misc/putget.h ../include/erl_interface.h epmd/ei_epmd.h
-$(MDD_OBJDIR)/ei_decode_term.o: misc/ei_decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_decode_term.h misc/putget.h
-$(MDD_OBJDIR)/ei_format.o: misc/ei_format.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_malloc.h misc/ei_format.h
-$(MDD_OBJDIR)/ei_locking.o: misc/ei_locking.c $(TARGET)/config.h \
- misc/ei_malloc.h misc/ei_locking.h
-$(MDD_OBJDIR)/ei_malloc.o: misc/ei_malloc.c misc/ei_malloc.h
-$(MDD_OBJDIR)/ei_portio.o: misc/ei_portio.c misc/ei_portio.h misc/ei_internal.h
-$(MDD_OBJDIR)/ei_printterm.o: misc/ei_printterm.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/ei_printterm.h misc/ei_malloc.h
-$(MDD_OBJDIR)/ei_pthreads.o: misc/ei_pthreads.c $(TARGET)/config.h \
- ../include/ei.h misc/ei_locking.h
-$(MDD_OBJDIR)/ei_trace.o: misc/ei_trace.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/ei_trace.h
-$(MDD_OBJDIR)/ei_x_encode.o: misc/ei_x_encode.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/ei_x_encode.h \
- misc/ei_malloc.h
-$(MDD_OBJDIR)/eimd5.o: misc/eimd5.c misc/eimd5.h
-$(MDD_OBJDIR)/get_type.o: misc/get_type.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h
-$(MDD_OBJDIR)/show_msg.o: misc/show_msg.c misc/eidef.h $(TARGET)/config.h \
- ../include/ei.h misc/eiext.h misc/putget.h misc/ei_printterm.h \
- misc/ei_internal.h misc/show_msg.h
-$(MDD_OBJDIR)/ei_compat.o: misc/ei_compat.c ../include/ei.h misc/ei_internal.h
-$(MDD_OBJDIR)/hash_dohash.o: registry/hash_dohash.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_foreach.o: registry/hash_foreach.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_freetab.o: registry/hash_freetab.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_insert.o: registry/hash_insert.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_isprime.o: registry/hash_isprime.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_lookup.o: registry/hash_lookup.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_newtab.o: registry/hash_newtab.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_remove.o: registry/hash_remove.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_resize.o: registry/hash_resize.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/hash_rlookup.o: registry/hash_rlookup.c registry/hash.h ../include/ei.h
-$(MDD_OBJDIR)/reg_close.o: registry/reg_close.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_delete.o: registry/reg_delete.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_dirty.o: registry/reg_dirty.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_dump.o: registry/reg_dump.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(MDD_OBJDIR)/reg_free.o: registry/reg_free.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_get.o: registry/reg_get.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_getf.o: registry/reg_getf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_geti.o: registry/reg_geti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_getp.o: registry/reg_getp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_gets.o: registry/reg_gets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_make.o: registry/reg_make.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_open.o: registry/reg_open.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_purge.o: registry/reg_purge.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_resize.o: registry/reg_resize.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_restore.o: registry/reg_restore.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- registry/reg.h registry/hash.h connect/eisend.h connect/eirecv.h \
- connect/ei_connect_int.h
-$(MDD_OBJDIR)/reg_set.o: registry/reg_set.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_setf.o: registry/reg_setf.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_seti.o: registry/reg_seti.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_setp.o: registry/reg_setp.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_sets.o: registry/reg_sets.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_stat.o: registry/reg_stat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/reg_tabstat.o: registry/reg_tabstat.c registry/reg.h ../include/ei.h \
- registry/hash.h
-$(MDD_OBJDIR)/decode_term.o: legacy/decode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h ../include/erl_interface.h
-$(MDD_OBJDIR)/encode_term.o: legacy/encode_term.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- misc/putget.h misc/ei_x_encode.h ../include/erl_interface.h \
- legacy/erl_marshal.h legacy/erl_eterm.h legacy/portability.h
-$(MDD_OBJDIR)/erl_connect.o: legacy/erl_connect.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_config.h \
- legacy/erl_connect.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h misc/putget.h connect/ei_connect_int.h \
- misc/ei_locking.h epmd/ei_epmd.h misc/ei_internal.h
-$(MDD_OBJDIR)/erl_error.o: legacy/erl_error.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_error.h
-$(MDD_OBJDIR)/erl_eterm.o: legacy/erl_eterm.c misc/ei_locking.h \
- $(TARGET)/config.h connect/ei_resolve.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_eterm.h \
- legacy/portability.h legacy/erl_malloc.h legacy/erl_marshal.h \
- legacy/erl_error.h legacy/erl_internal.h misc/ei_internal.h
-$(MDD_OBJDIR)/erl_fix_alloc.o: legacy/erl_fix_alloc.c $(TARGET)/config.h \
- misc/ei_locking.h ../include/erl_interface.h ../include/ei.h \
- legacy/erl_error.h legacy/erl_malloc.h legacy/erl_fix_alloc.h \
- legacy/erl_eterm.h legacy/portability.h
-$(MDD_OBJDIR)/erl_format.o: legacy/erl_format.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_eterm.h legacy/portability.h \
- legacy/erl_malloc.h legacy/erl_error.h legacy/erl_internal.h
-$(MDD_OBJDIR)/erl_malloc.o: legacy/erl_malloc.c ../include/erl_interface.h \
- ../include/ei.h legacy/erl_fix_alloc.h legacy/erl_malloc.h \
- legacy/erl_internal.h legacy/erl_eterm.h legacy/portability.h \
- misc/ei_malloc.h
-$(MDD_OBJDIR)/erl_marshal.o: legacy/erl_marshal.c $(TARGET)/config.h \
- ../include/erl_interface.h ../include/ei.h legacy/erl_marshal.h \
- legacy/erl_eterm.h legacy/portability.h legacy/erl_malloc.h \
- legacy/erl_error.h legacy/erl_internal.h misc/eiext.h misc/putget.h
-$(MDD_OBJDIR)/erl_timeout.o: legacy/erl_timeout.c $(TARGET)/config.h \
- legacy/erl_timeout.h
-$(MDD_OBJDIR)/global_names.o: legacy/global_names.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(MDD_OBJDIR)/global_register.o: legacy/global_register.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h ../include/erl_interface.h
-$(MDD_OBJDIR)/global_unregister.o: legacy/global_unregister.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-$(MDD_OBJDIR)/global_whereis.o: legacy/global_whereis.c misc/eidef.h \
- $(TARGET)/config.h ../include/ei.h misc/eiext.h \
- connect/eisend.h connect/eirecv.h connect/ei_connect_int.h \
- ../include/erl_interface.h legacy/erl_connect.h
-
diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c
index 2ec418b24a..492c3fb3aa 100644
--- a/lib/erl_interface/src/epmd/epmd_port.c
+++ b/lib/erl_interface/src/epmd/epmd_port.c
@@ -62,31 +62,38 @@
int ei_epmd_connect_tmo(struct in_addr *inaddr, unsigned ms)
{
static unsigned int epmd_port = 0;
- struct sockaddr_in saddr;
- int sd;
- int res;
+ int port, sd, err;
+ struct in_addr ip_addr;
+ struct sockaddr_in addr;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
+
+ err = ei_socket__(&sd);
+ if (err) {
+ erl_errno = err;
+ return -1;
+ }
if (epmd_port == 0) {
char* port_str = getenv("ERL_EPMD_PORT");
epmd_port = (port_str != NULL) ? atoi(port_str) : EPMD_PORT;
}
- memset(&saddr, 0, sizeof(saddr));
- saddr.sin_port = htons(epmd_port);
- saddr.sin_family = AF_INET;
- if (!inaddr) saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- else memmove(&saddr.sin_addr,inaddr,sizeof(saddr.sin_addr));
+ port = (int) epmd_port;
- if (((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0))
- {
- erl_errno = errno;
- return -1;
+ if (!inaddr) {
+ ip_addr.s_addr = htonl(INADDR_LOOPBACK);
+ inaddr = &ip_addr;
}
+
+ memset((void *) &addr, 0, sizeof(struct sockaddr_in));
+ memcpy((void *) &addr.sin_addr, (void *) inaddr, sizeof(addr.sin_addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
- if ((res = ei_connect_t(sd,(struct sockaddr *)&saddr,sizeof(saddr),ms)) < 0)
- {
- erl_errno = (res == -2) ? ETIMEDOUT : errno;
- closesocket(sd);
+ err = ei_connect_t__(sd, (void *) &addr, sizeof(addr), tmo);
+ if (err) {
+ erl_errno = err;
+ ei_close__(sd);
return -1;
}
@@ -104,6 +111,9 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
int port;
int dist_high, dist_low, proto;
int res;
+ int err;
+ ssize_t dlen;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
#if defined(VXWORKS)
char ntoabuf[32];
#endif
@@ -124,10 +134,14 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
return -1;
}
- if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+ dlen = len + 2;
+ err = ei_write_fill_t__(fd, buf, &dlen, tmo);
+ if (!err && dlen != (ssize_t) len + 2)
+ erl_errno = EIO;
+ if (err) {
+ ei_close__(fd);
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
}
#ifdef VXWORKS
@@ -142,12 +156,15 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
"-> PORT2_REQ alive=%s ip=%s",alive,inet_ntoa(*addr));
#endif
- /* read first two bytes (response type, response) */
- if ((res = ei_read_fill_t(fd, buf, 2, ms)) != 2) {
- EI_TRACE_ERR0("ei_epmd_r4_port","<- CLOSE");
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- closesocket(fd);
- return -2; /* version mismatch */
+ dlen = (ssize_t) 2;
+ err = ei_read_fill_t__(fd, buf, &dlen, tmo);
+ if (!err && dlen != (ssize_t) 2)
+ erl_errno = EIO;
+ if (err) {
+ EI_TRACE_ERR0("ei_epmd_r4_port","<- CLOSE");
+ ei_close__(fd);
+ EI_CONN_SAVE_ERRNO__(err);
+ return -2;
}
s = buf;
@@ -156,7 +173,7 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
if (res != EI_EPMD_PORT2_RESP) { /* response type */
EI_TRACE_ERR1("ei_epmd_r4_port","<- unknown (%d)",res);
EI_TRACE_ERR0("ei_epmd_r4_port","-> CLOSE");
- closesocket(fd);
+ ei_close__(fd);
erl_errno = EIO;
return -1;
}
@@ -167,7 +184,7 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
if ((res = get8(s))) {
/* got negative response */
EI_TRACE_ERR1("ei_epmd_r4_port","<- PORT2_RESP result=%d (failure)",res);
- closesocket(fd);
+ ei_close__(fd);
erl_errno = EIO;
return -1;
}
@@ -175,14 +192,18 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive,
EI_TRACE_CONN1("ei_epmd_r4_port","<- PORT2_RESP result=%d (ok)",res);
/* expecting remaining 8 bytes */
- if ((res = ei_read_fill_t(fd,buf,8,ms)) != 8) {
+ dlen = (ssize_t) 8;
+ err = ei_read_fill_t__(fd, buf, &dlen, tmo);
+ if (!err && dlen != (ssize_t) 8)
+ err = EIO;
+ if (err) {
EI_TRACE_ERR0("ei_epmd_r4_port","<- CLOSE");
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- closesocket(fd);
+ ei_close__(fd);
+ EI_CONN_SAVE_ERRNO__(err);
return -1;
}
- closesocket(fd);
+ ei_close__(fd);
s = buf;
port = get16be(s);
diff --git a/lib/erl_interface/src/epmd/epmd_publish.c b/lib/erl_interface/src/epmd/epmd_publish.c
index 47d68a6db0..20b8e867e8 100644
--- a/lib/erl_interface/src/epmd/epmd_publish.c
+++ b/lib/erl_interface/src/epmd/epmd_publish.c
@@ -68,8 +68,10 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
int nlen = strlen(alive);
int len = elen + nlen + 13; /* hard coded: be careful! */
int n;
- int res, creation;
-
+ int err, res, creation;
+ ssize_t dlen;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
+
if (len > sizeof(buf)-2)
{
erl_errno = ERANGE;
@@ -93,29 +95,39 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd;
- if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) {
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+ dlen = (ssize_t) len+2;
+ err = ei_write_fill_t__(fd, buf, &dlen, tmo);
+ if (!err && dlen != (ssize_t) len + 2)
+ erl_errno = EIO;
+ if (err) {
+ ei_close__(fd);
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
}
EI_TRACE_CONN6("ei_epmd_r4_publish",
"-> ALIVE2_REQ alive=%s port=%d ntype=%d "
"proto=%d dist-high=%d dist-low=%d",
alive,port,'H',EI_MYPROTO,EI_DIST_HIGH,EI_DIST_LOW);
-
- if ((n = ei_read_fill_t(fd, buf, 4, ms)) != 4) {
+
+ dlen = (ssize_t) 4;
+ err = ei_read_fill_t__(fd, buf, &dlen, tmo);
+ n = (int) dlen;
+ if (!err && n != 4)
+ err = EIO;
+ if (err) {
EI_TRACE_ERR0("ei_epmd_r4_publish","<- CLOSE");
- closesocket(fd);
- erl_errno = (n == -2) ? ETIMEDOUT : EIO;
+ ei_close__(fd);
+ EI_CONN_SAVE_ERRNO__(err);
return -2; /* version mismatch */
}
+
/* Don't close fd here! It keeps us registered with epmd */
s = buf;
if (((res=get8(s)) != EI_EPMD_ALIVE2_RESP)) { /* response */
EI_TRACE_ERR1("ei_epmd_r4_publish","<- unknown (%d)",res);
EI_TRACE_ERR0("ei_epmd_r4_publish","-> CLOSE");
- closesocket(fd);
+ ei_close__(fd);
erl_errno = EIO;
return -1;
}
@@ -124,7 +136,7 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
if (((res=get8(s)) != 0)) { /* 0 == success */
EI_TRACE_ERR1("ei_epmd_r4_publish"," result=%d (fail)",res);
- closesocket(fd);
+ ei_close__(fd);
erl_errno = EIO;
return -1;
}
diff --git a/lib/erl_interface/src/epmd/epmd_unpublish.c b/lib/erl_interface/src/epmd/epmd_unpublish.c
index 255d0ffb59..c112f74147 100644
--- a/lib/erl_interface/src/epmd/epmd_unpublish.c
+++ b/lib/erl_interface/src/epmd/epmd_unpublish.c
@@ -58,7 +58,9 @@ int ei_unpublish_tmo(const char *alive, unsigned ms)
char buf[EPMDBUF];
char *s = (char*)buf;
int len = 1 + strlen(alive);
- int fd, res;
+ int fd, err;
+ ssize_t dlen;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
if (len > sizeof(buf)-3) {
erl_errno = ERANGE;
@@ -72,20 +74,29 @@ int ei_unpublish_tmo(const char *alive, unsigned ms)
/* FIXME can't connect, return success?! At least commen whats up */
if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd;
- if ((res = ei_write_fill_t(fd, buf, len+2,ms)) != len+2) {
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+ dlen = (ssize_t) len+2;
+ err = ei_write_fill_t__(fd, buf, &dlen, tmo);
+ if (!err && dlen != (ssize_t) len + 2)
+ erl_errno = EIO;
+ if (err) {
+ ei_close__(fd);
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
}
EI_TRACE_CONN1("ei_unpublish_tmo","-> STOP %s",alive);
-
- if ((res = ei_read_fill_t(fd, buf, 7, ms)) != 7) {
- closesocket(fd);
- erl_errno = (res == -2) ? ETIMEDOUT : EIO;
- return -1;
+
+ dlen = (ssize_t) 7;
+ err = ei_read_fill_t__(fd, buf, &dlen, tmo);
+ if (!err && dlen != (ssize_t) 7)
+ erl_errno = EIO;
+ if (err) {
+ ei_close__(fd);
+ EI_CONN_SAVE_ERRNO__(err);
+ return -1;
}
- closesocket(fd);
+
+ ei_close__(fd);
buf[7]=(char)0; /* terminate the string */
if (!strcmp("STOPPED",(char *)buf)) {
diff --git a/lib/erl_interface/src/legacy/erl_connect.c b/lib/erl_interface/src/legacy/erl_connect.c
index 7ffd545d3e..e2fd4611c0 100644
--- a/lib/erl_interface/src/legacy/erl_connect.c
+++ b/lib/erl_interface/src/legacy/erl_connect.c
@@ -179,15 +179,13 @@ int erl_xconnect(Erl_IpAddr addr, char *alivename)
*
* API: erl_close_connection()
*
- * Close a connection. FIXME call ei_close_connection() later.
- *
* Returns 0 on success and -1 on failure.
*
***************************************************************************/
int erl_close_connection(int fd)
{
- return closesocket(fd);
+ return ei_close_connection(fd);
}
/*
@@ -220,7 +218,10 @@ int erl_reg_send(int fd, char *server_name, ETERM *msg)
ei_x_buff x;
int r;
- ei_x_new_with_version(&x);
+ if (ei_x_new_with_version(&x) < 0) {
+ erl_errno = ENOMEM;
+ return 0;
+ }
if (ei_x_encode_term(&x, msg) < 0) {
erl_errno = EINVAL;
r = 0;
diff --git a/lib/erl_interface/src/legacy/erl_eterm.c b/lib/erl_interface/src/legacy/erl_eterm.c
index 9ad92121f4..7ed2bdbc93 100644
--- a/lib/erl_interface/src/legacy/erl_eterm.c
+++ b/lib/erl_interface/src/legacy/erl_eterm.c
@@ -65,7 +65,7 @@ void erl_init(void *hp,long heap_size)
{
erl_init_malloc(hp, heap_size);
erl_init_marshal();
- ei_init_resolve();
+ (void) ei_init();
}
void erl_set_compat_rel(unsigned rel)
diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c
index c18067b9bc..932bba43bf 100644
--- a/lib/erl_interface/src/legacy/erl_marshal.c
+++ b/lib/erl_interface/src/legacy/erl_marshal.c
@@ -1803,7 +1803,7 @@ static int cmp_exe2(unsigned char **e1, unsigned char **e2)
k = 0;
while (1) {
if (k++ == min){
- if (i == j) return 0;
+ if (i == j) return compare_top_ext(e1 , e2);
if (i < j) return -1;
return 1;
}
diff --git a/lib/erl_interface/src/misc/ei_init.c b/lib/erl_interface/src/misc/ei_init.c
new file mode 100644
index 0000000000..5357968657
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_init.c
@@ -0,0 +1,32 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2019. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "ei.h"
+#include "ei_resolve.h"
+#include "ei_internal.h"
+
+int
+ei_init(void)
+{
+ int error = ei_init_connect();
+ if (error)
+ return error;
+ return ei_init_resolve();
+}
diff --git a/lib/erl_interface/src/misc/ei_internal.h b/lib/erl_interface/src/misc/ei_internal.h
index aa6aacd703..f28dd6d668 100644
--- a/lib/erl_interface/src/misc/ei_internal.h
+++ b/lib/erl_interface/src/misc/ei_internal.h
@@ -22,19 +22,20 @@
#ifndef _EI_INTERNAL_H
#define _EI_INTERNAL_H
+#ifdef EI_HIDE_REAL_ERRNO
+# define EI_CONN_SAVE_ERRNO__(E) \
+ ((E) == ETIMEDOUT ? (erl_errno = ETIMEDOUT) : (erl_errno = EIO))
+#else
+# define EI_CONN_SAVE_ERRNO__(E) \
+ (erl_errno = (E))
+#endif
+
/*
* Some useful stuff not to be exported to users.
*/
#ifdef __WIN32__
#define MAXPATHLEN 256
-#define writesocket(sock,buf,nbyte) send(sock,buf,nbyte,0)
-#define readsocket(sock,buf,nbyte) recv(sock,buf,nbyte,0)
-#else /* not __WIN32__ */
-#define writesocket write
-#define readsocket read
-#define closesocket close
-#define ioctlsocket ioctl
#endif
/*
@@ -152,7 +153,12 @@
extern int ei_tracelevel;
+int ei_init_connect(void);
+
void ei_trace_printf(const char *name, int level, const char *format, ...);
int ei_internal_use_r9_pids_ports(void);
+
+int ei_get_cbs_ctx__(ei_socket_callbacks **cbs, void **ctx, int fd);
+
#endif /* _EI_INTERNAL_H */
diff --git a/lib/erl_interface/src/misc/ei_portio.c b/lib/erl_interface/src/misc/ei_portio.c
index 8cd35bf2e5..bccc86c1b1 100644
--- a/lib/erl_interface/src/misc/ei_portio.c
+++ b/lib/erl_interface/src/misc/ei_portio.c
@@ -19,9 +19,13 @@
*
*/
+
+#include "eidef.h"
+
#ifdef __WIN32__
#include <winsock2.h>
#include <windows.h>
+#include <winbase.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
@@ -35,10 +39,6 @@ static unsigned long param_one = 1;
#define SET_BLOCKING(Sock) ioctlsocket((Sock),FIONBIO,&param_zero)
#define SET_NONBLOCKING(Sock) ioctlsocket((Sock),FIONBIO,&param_one)
-#define ERROR_WOULDBLOCK WSAEWOULDBLOCK
-#define ERROR_TIMEDOUT WSAETIMEDOUT
-#define ERROR_INPROGRESS WSAEINPROGRESS
-#define GET_SOCKET_ERROR() WSAGetLastError()
#define MEANS_SOCKET_ERROR(Ret) ((Ret == SOCKET_ERROR))
#define IS_INVALID_SOCKET(Sock) ((Sock) == INVALID_SOCKET)
@@ -50,125 +50,414 @@ static unsigned long param_one = 1;
#include <taskLib.h>
#include <inetLib.h>
#include <selectLib.h>
-#include <sys/types.h>
#include <ioLib.h>
#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <timers.h>
static unsigned long param_zero = 0;
static unsigned long param_one = 1;
#define SET_BLOCKING(Sock) ioctl((Sock),FIONBIO,(int)&param_zero)
#define SET_NONBLOCKING(Sock) ioctl((Sock),FIONBIO,(int)&param_one)
-#define ERROR_WOULDBLOCK EWOULDBLOCK
-#define ERROR_TIMEDOUT ETIMEDOUT
-#define ERROR_INPROGRESS EINPROGRESS
-#define GET_SOCKET_ERROR() (errno)
#define MEANS_SOCKET_ERROR(Ret) ((Ret) == ERROR)
#define IS_INVALID_SOCKET(Sock) ((Sock) < 0)
#else /* other unix */
#include <stdlib.h>
-#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
-#ifndef EWOULDBLOCK
-#define ERROR_WOULDBLOCK EAGAIN
-#else
-#define ERROR_WOULDBLOCK EWOULDBLOCK
-#endif
#define SET_BLOCKING(fd) fcntl((fd), F_SETFL, \
fcntl((fd), F_GETFL, 0) & ~O_NONBLOCK)
#define SET_NONBLOCKING(fd) fcntl((fd), F_SETFL, \
fcntl((fd), F_GETFL, 0) | O_NONBLOCK)
-#define ERROR_TIMEDOUT ETIMEDOUT
-#define ERROR_INPROGRESS EINPROGRESS
-#define GET_SOCKET_ERROR() (errno)
#define MEANS_SOCKET_ERROR(Ret) ((Ret) < 0)
#define IS_INVALID_SOCKET(Sock) ((Sock) < 0)
#endif
/* common includes */
-#include "eidef.h"
+#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "ei_portio.h"
-#include "ei_internal.h"
-
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include "ei_portio.h"
+#include "ei_internal.h"
+
+#ifdef __WIN32__
-#ifdef HAVE_WRITEV
-static int ei_writev_t(int fd, struct iovec *iov, int iovcnt, unsigned ms)
+#define writesocket(sock,buf,nbyte) send(sock,buf,nbyte,0)
+#define readsocket(sock,buf,nbyte) recv(sock,buf,nbyte,0)
+
+static int get_error(void)
{
- int res;
- if (ms != 0) {
- fd_set writemask;
- struct timeval tv;
- tv.tv_sec = (time_t) (ms / 1000U);
- ms %= 1000U;
- tv.tv_usec = (time_t) (ms * 1000U);
- FD_ZERO(&writemask);
- FD_SET(fd,&writemask);
- switch (select(fd+1, NULL, &writemask, NULL, &tv)) {
- case -1 :
- return -1; /* i/o error */
- case 0:
- return -2; /* timeout */
- default:
- if (!FD_ISSET(fd, &writemask)) {
- return -1; /* Other error */
- }
- }
+ switch (WSAGetLastError()) {
+ case WSAEWOULDBLOCK: return EWOULDBLOCK;
+ case WSAETIMEDOUT: return ETIMEDOUT;
+ case WSAEINPROGRESS: return EINPROGRESS;
+ case WSA_NOT_ENOUGH_MEMORY: return ENOMEM;
+ case WSA_INVALID_PARAMETER: return EINVAL;
+ case WSAEBADF: return EBADF;
+ case WSAEINVAL: return EINVAL;
+ case WSAEADDRINUSE: return EADDRINUSE;
+ case WSAENETUNREACH: return ENETUNREACH;
+ case WSAECONNABORTED: return ECONNABORTED;
+ case WSAECONNRESET: return ECONNRESET;
+ case WSAECONNREFUSED: return ECONNREFUSED;
+ case WSAEHOSTUNREACH: return EHOSTUNREACH;
+ case WSAEMFILE: return EMFILE;
+ case WSAEALREADY: return EALREADY;
+ default: return EIO;
}
+}
+
+#else /* not __WIN32__ */
+
+#define writesocket write
+#define readsocket read
+#define closesocket close
+#define ioctlsocket ioctl
+
+static int get_error(void)
+{
+ int err = errno;
+ if (err == 0)
+ return EIO; /* Make sure never to return 0 as error code... */
+ return err;
+}
+
+#endif
+
+int ei_plugin_socket_impl__ = 0;
+
+/*
+ * Callbacks for communication over TCP/IPv4
+ */
+
+static int tcp_get_fd(void *ctx, int *fd)
+{
+ return EI_DFLT_CTX_TO_FD__(ctx, fd);
+}
+
+static int tcp_hs_packet_header_size(void *ctx, int *sz)
+{
+ int fd;
+ *sz = 2;
+ return EI_DFLT_CTX_TO_FD__(ctx, &fd);
+}
+
+static int tcp_handshake_complete(void *ctx)
+{
+ int res, fd, one = 1;
+
+ res = EI_DFLT_CTX_TO_FD__(ctx, &fd);
+ if (res)
+ return res;
+
+ res = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ res = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof(one));
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ return 0;
+}
+
+static int tcp_socket(void **ctx, void *setup_ctx)
+{
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (MEANS_SOCKET_ERROR(fd))
+ return get_error();
+
+ *ctx = EI_FD_AS_CTX__(fd);
+ return 0;
+}
+
+static int tcp_close(void *ctx)
+{
+ int fd, res;
+
+ res = EI_DFLT_CTX_TO_FD__(ctx, &fd);
+ if (res)
+ return res;
+
+ res = closesocket(fd);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ return 0;
+}
+
+static int tcp_listen(void *ctx, void *addr, int *len, int backlog)
+{
+ int res, fd;
+ socklen_t sz = (socklen_t) *len;
+ int on = 1;
+
+ res = EI_DFLT_CTX_TO_FD__(ctx, &fd);
+ if (res)
+ return res;
+
+ res = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ res = bind(fd, (struct sockaddr *) addr, sz);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ res = getsockname(fd, (struct sockaddr *) addr, (socklen_t *) &sz);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+ *len = (int) sz;
+
+ res = listen(fd, backlog);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ return 0;
+}
+
+static int tcp_accept(void **ctx, void *addr, int *len, unsigned unused)
+{
+ int fd, res;
+ socklen_t addr_len = (socklen_t) *len;
+
+ if (!ctx)
+ return EINVAL;
+
+ res = EI_DFLT_CTX_TO_FD__(*ctx, &fd);
+ if (res)
+ return res;
+
+ res = accept(fd, (struct sockaddr*) addr, &addr_len);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ *len = (int) addr_len;
+
+ *ctx = EI_FD_AS_CTX__(res);
+ return 0;
+}
+
+static int tcp_connect(void *ctx, void *addr, int len, unsigned unused)
+{
+ int res, fd;
+
+ res = EI_DFLT_CTX_TO_FD__(ctx, &fd);
+ if (res)
+ return res;
+
+ res = connect(fd, (struct sockaddr *) addr, len);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+
+ return 0;
+}
+
+#if defined(EI_HAVE_STRUCT_IOVEC__) && defined(HAVE_WRITEV)
+
+static int tcp_writev(void *ctx, const void *viov, int iovcnt, ssize_t *len, unsigned unused)
+{
+ const struct iovec *iov = (const struct iovec *) viov;
+ int fd, error;
+ ssize_t res;
+
+ error = EI_DFLT_CTX_TO_FD__(ctx, &fd);
+ if (error)
+ return error;
+
res = writev(fd, iov, iovcnt);
- return (res < 0) ? -1 : res;
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+ *len = res;
+ return 0;
+}
+
+#endif
+
+static int tcp_write(void *ctx, const char* buf, ssize_t *len, unsigned unused)
+{
+ int error, fd;
+ ssize_t res;
+
+ error = EI_DFLT_CTX_TO_FD__(ctx, &fd);
+ if (error)
+ return error;
+
+ res = writesocket(fd, buf, *len);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+ *len = res;
+ return 0;
+}
+
+static int tcp_read(void *ctx, char* buf, ssize_t *len, unsigned unused)
+{
+ int error, fd;
+ ssize_t res;
+
+ error = EI_DFLT_CTX_TO_FD__(ctx, &fd);
+ if (error)
+ return error;
+
+ res = readsocket(fd, buf, *len);
+ if (MEANS_SOCKET_ERROR(res))
+ return get_error();
+ *len = res;
+ return 0;
+}
+
+ei_socket_callbacks ei_default_socket_callbacks = {
+ 0, /* flags */
+ tcp_socket,
+ tcp_close,
+ tcp_listen,
+ tcp_accept,
+ tcp_connect,
+#if defined(EI_HAVE_STRUCT_IOVEC__) && defined(HAVE_WRITEV)
+ tcp_writev,
+#else
+ NULL,
+#endif
+ tcp_write,
+ tcp_read,
+
+ tcp_hs_packet_header_size,
+ tcp_handshake_complete,
+ tcp_handshake_complete,
+ tcp_get_fd
+
+};
+
+
+/*
+ *
+ */
+
+#if defined(EI_HAVE_STRUCT_IOVEC__)
+
+int ei_socket_callbacks_have_writev__(ei_socket_callbacks *cbs)
+{
+ return !!cbs->writev;
}
-int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, unsigned ms)
+static int writev_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
+ const struct iovec *iov, int iovcnt,
+ ssize_t *len,
+ unsigned ms)
{
- int i;
- int done;
+ int error;
+
+ if (!(cbs->flags & EI_SCLBK_FLG_FULL_IMPL) && ms != EI_SCLBK_INF_TMO) {
+ int fd;
+
+ error = EI_GET_FD__(cbs, ctx, &fd);
+ if (error)
+ return error;
+
+ do {
+ fd_set writemask;
+ struct timeval tv;
+
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&writemask);
+ FD_SET(fd,&writemask);
+ switch (select(fd+1, NULL, &writemask, NULL, &tv)) {
+ case -1 :
+ error = get_error();
+ if (error != EINTR)
+ return error;
+ break;
+ case 0:
+ return ETIMEDOUT; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &writemask)) {
+ return EIO; /* Other error */
+ }
+ error = 0;
+ break;
+ }
+ } while (error == EINTR);
+ }
+ do {
+ error = cbs->writev(ctx, (const void *) iov, iovcnt, len, ms);
+ } while (error == EINTR);
+ return error;
+}
+
+int ei_writev_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
+ const struct iovec *iov, int iovcnt,
+ ssize_t *len,
+ unsigned ms)
+{
+ ssize_t i, done, sum;
struct iovec *iov_base = NULL;
struct iovec *current_iov;
int current_iovcnt;
- int sum;
+ int fd, error;
+ int basic;
+
+ if (!cbs->writev)
+ return ENOTSUP;
+
+ error = EI_GET_FD__(cbs, ctx, &fd);
+ if (error)
+ return error;
+ basic = !(cbs->flags & EI_SCLBK_FLG_FULL_IMPL);
+
for (sum = 0, i = 0; i < iovcnt; ++i) {
sum += iov[i].iov_len;
}
- if (ms != 0U) {
+ if (basic && ms != 0U) {
SET_NONBLOCKING(fd);
}
current_iovcnt = iovcnt;
current_iov = (struct iovec *) iov;
done = 0;
for (;;) {
- i = ei_writev_t(fd, current_iov, current_iovcnt, ms);
- if (i <= 0) { /* ei_writev_t should always return at least 1 */
+
+ error = writev_ctx_t__(cbs, ctx, current_iov, current_iovcnt, &i, ms);
+ if (error) {
+ *len = done;
if (ms != 0U) {
SET_BLOCKING(fd);
}
if (iov_base != NULL) {
free(iov_base);
}
- return (i);
- }
+ return error;
+ }
done += i;
if (done < sum) {
if (iov_base == NULL) {
iov_base = malloc(sizeof(struct iovec) * iovcnt);
if (iov_base == NULL) {
- return -1;
+ *len = done;
+ return ENOMEM;
}
memcpy(iov_base, iov, sizeof(struct iovec) * iovcnt);
current_iov = iov_base;
@@ -189,195 +478,383 @@ int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, unsigned
break;
}
}
- if (ms != 0U) {
+ if (basic && ms != 0U) {
SET_BLOCKING(fd);
}
if (iov_base != NULL) {
free(iov_base);
}
- return (sum);
+ *len = done;
+ return 0;
}
+#endif /* defined(EI_HAVE_STRUCT_IOVEC__) */
-#endif
-
-int ei_connect_t(int fd, void *sinp, int sin_siz, unsigned ms)
+int ei_socket_ctx__(ei_socket_callbacks *cbs, void **ctx, void *setup_ctx)
{
int res;
- int error;
- int s_res;
- struct timeval tv;
- fd_set writefds;
- fd_set exceptfds;
-
- if (ms == 0) {
- res = connect(fd, sinp, sin_siz);
- return (res < 0) ? -1 : res;
- } else {
- SET_NONBLOCKING(fd);
- res = connect(fd, sinp, sin_siz);
- error = GET_SOCKET_ERROR();
- SET_BLOCKING(fd);
- if (!MEANS_SOCKET_ERROR(res)) {
- return (res < 0) ? -1 : res;
- } else {
- if (error != ERROR_WOULDBLOCK &&
- error != ERROR_INPROGRESS) {
- return -1;
- } else {
- tv.tv_sec = (long) (ms/1000U);
- ms %= 1000U;
- tv.tv_usec = (long) (ms * 1000U);
- FD_ZERO(&writefds);
- FD_SET(fd,&writefds);
- FD_ZERO(&exceptfds);
- FD_SET(fd,&exceptfds);
- s_res = select(fd + 1, NULL, &writefds, &exceptfds, &tv);
- switch (s_res) {
- case 0:
- return -2;
- case 1:
- if (FD_ISSET(fd, &exceptfds)) {
- return -1;
- } else {
- return 0; /* Connect completed */
- }
- default:
- return -1;
- }
- }
- }
- }
+
+ do {
+ res = cbs->socket(ctx, setup_ctx);
+ } while (res == EINTR);
+
+ return res;
}
-int ei_accept_t(int fd, void *addr, void *addrlen, unsigned ms)
+int ei_close_ctx__(ei_socket_callbacks *cbs, void *ctx)
{
- int res;
- if (ms != 0) {
- fd_set readmask;
- struct timeval tv;
- tv.tv_sec = (time_t) (ms / 1000U);
- ms %= 1000U;
- tv.tv_usec = (time_t) (ms * 1000U);
- FD_ZERO(&readmask);
- FD_SET(fd,&readmask);
- switch (select(fd+1, &readmask, NULL, NULL, &tv)) {
- case -1 :
- return -1; /* i/o error */
- case 0:
- return -2; /* timeout */
- default:
- if (!FD_ISSET(fd, &readmask)) {
- return -1; /* Other error */
- }
- }
- }
- res = (int) accept(fd,addr,addrlen);
- return (res < 0) ? -1 : res;
+ return cbs->close(ctx);
}
+
+int ei_connect_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
+ void *addr, int len, unsigned ms)
+{
+ int res, fd;
+
+ if ((cbs->flags & EI_SCLBK_FLG_FULL_IMPL) || ms == EI_SCLBK_INF_TMO) {
+ do {
+ res = cbs->connect(ctx, addr, len, ms);
+ } while (res == EINTR);
+ return res;
+ }
+
+ res = EI_GET_FD__(cbs, ctx, &fd);
+ if (res)
+ return res;
+ SET_NONBLOCKING(fd);
+ do {
+ res = cbs->connect(ctx, addr, len, 0);
+ } while (res == EINTR);
+ SET_BLOCKING(fd);
+ switch (res) {
+ case EINPROGRESS:
+ case EAGAIN:
+#ifdef EWOULDBLOCK
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+#endif
+ break;
+ default:
+ return res;
+ }
-static int ei_read_t(int fd, char* buf, int len, unsigned ms)
+ while (1) {
+ struct timeval tv;
+ fd_set writefds;
+ fd_set exceptfds;
+
+ tv.tv_sec = (long) (ms/1000U);
+ ms %= 1000U;
+ tv.tv_usec = (long) (ms * 1000U);
+ FD_ZERO(&writefds);
+ FD_SET(fd,&writefds);
+ FD_ZERO(&exceptfds);
+ FD_SET(fd,&exceptfds);
+ res = select(fd + 1, NULL, &writefds, &exceptfds, &tv);
+ switch (res) {
+ case -1:
+ res = get_error();
+ if (res != EINTR)
+ return res;
+ break;
+ case 0:
+ return ETIMEDOUT;
+ case 1:
+ if (!FD_ISSET(fd, &exceptfds))
+ return 0; /* Connect completed */
+ /* fall through... */
+ default:
+ return EIO;
+ }
+ }
+}
+
+int ei_listen_ctx__(ei_socket_callbacks *cbs, void *ctx,
+ void *adr, int *len, int backlog)
{
int res;
- if (ms != 0) {
- fd_set readmask;
- struct timeval tv;
- tv.tv_sec = (time_t) (ms / 1000U);
- ms %= 1000U;
- tv.tv_usec = (time_t) (ms * 1000U);
- FD_ZERO(&readmask);
- FD_SET(fd,&readmask);
- switch (select(fd+1, &readmask, NULL, NULL, &tv)) {
- case -1 :
- return -1; /* i/o error */
- case 0:
- return -2; /* timeout */
- default:
- if (!FD_ISSET(fd, &readmask)) {
- return -1; /* Other error */
- }
- }
+
+ do {
+ res = cbs->listen(ctx, adr, len, backlog);
+ } while (res == EINTR);
+ return res;
+}
+
+int ei_accept_ctx_t__(ei_socket_callbacks *cbs, void **ctx,
+ void *addr, int *len, unsigned ms)
+{
+ int error;
+
+ if (!(cbs->flags & EI_SCLBK_FLG_FULL_IMPL) && ms != EI_SCLBK_INF_TMO) {
+ int fd;
+
+ error = EI_GET_FD__(cbs, *ctx, &fd);
+ if (error)
+ return error;
+
+ do {
+ fd_set readmask;
+ struct timeval tv;
+
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&readmask);
+ FD_SET(fd,&readmask);
+ switch (select(fd+1, &readmask, NULL, NULL, &tv)) {
+ case -1 :
+ error = get_error();
+ if (error != EINTR)
+ return error;
+ break;
+ case 0:
+ return ETIMEDOUT; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &readmask)) {
+ return EIO; /* Other error */
+ }
+ error = 0;
+ break;
+ }
+ } while (error == EINTR);
}
- res = readsocket(fd, buf, len);
- return (res < 0) ? -1 : res;
+ do {
+ error = cbs->accept(ctx, addr, len, ms);
+ } while (error == EINTR);
+ return error;
}
-static int ei_write_t(int fd, const char* buf, int len, unsigned ms)
+static int read_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
+ char* buf, ssize_t *len, unsigned ms)
{
- int res;
- if (ms != 0) {
- fd_set writemask;
- struct timeval tv;
- tv.tv_sec = (time_t) (ms / 1000U);
- ms %= 1000U;
- tv.tv_usec = (time_t) (ms * 1000U);
- FD_ZERO(&writemask);
- FD_SET(fd,&writemask);
- switch (select(fd+1, NULL, &writemask, NULL, &tv)) {
- case -1 :
- return -1; /* i/o error */
- case 0:
- return -2; /* timeout */
- default:
- if (!FD_ISSET(fd, &writemask)) {
- return -1; /* Other error */
- }
- }
+ int error;
+
+ if (!(cbs->flags & EI_SCLBK_FLG_FULL_IMPL) && ms != EI_SCLBK_INF_TMO) {
+ int fd;
+
+ error = EI_GET_FD__(cbs, ctx, &fd);
+ if (error)
+ return error;
+
+ do {
+ fd_set readmask;
+ struct timeval tv;
+
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&readmask);
+ FD_SET(fd,&readmask);
+ switch (select(fd+1, &readmask, NULL, NULL, &tv)) {
+ case -1 :
+ error = get_error();
+ if (error != EINTR)
+ return error;
+ break;
+ case 0:
+ return ETIMEDOUT; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &readmask)) {
+ return EIO; /* Other error */
+ }
+ error = 0;
+ break;
+ }
+ } while (error == EINTR);
+ }
+ do {
+ error = cbs->read(ctx, buf, len, ms);
+ } while (error == EINTR);
+ return error;
+}
+
+static int write_ctx_t__(ei_socket_callbacks *cbs, void *ctx, const char* buf, ssize_t *len, unsigned ms)
+{
+ int error;
+
+ if (!(cbs->flags & EI_SCLBK_FLG_FULL_IMPL) && ms != EI_SCLBK_INF_TMO) {
+ int fd;
+
+ error = EI_GET_FD__(cbs, ctx, &fd);
+ if (error)
+ return error;
+
+ do {
+ fd_set writemask;
+ struct timeval tv;
+
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&writemask);
+ FD_SET(fd,&writemask);
+ switch (select(fd+1, NULL, &writemask, NULL, &tv)) {
+ case -1 :
+ error = get_error();
+ if (error != EINTR)
+ return error;
+ break;
+ case 0:
+ return ETIMEDOUT; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &writemask)) {
+ return EIO; /* Other error */
+ }
+ error = 0;
+ break;
+ }
+ } while (error == EINTR);
}
- res = writesocket(fd, buf, len);
- return (res < 0) ? -1 : res;
+ do {
+ error = cbs->write(ctx, buf, len, ms);
+ } while (error == EINTR);
+ return error;
}
/*
* Fill buffer, return buffer length, 0 for EOF, < 0 (and sets errno)
* for error. */
-int ei_read_fill_t(int fd, char* buf, int len, unsigned ms)
+int ei_read_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx, char* buf, ssize_t *len, unsigned ms)
{
- int i,got=0;
+ ssize_t got = 0;
+ ssize_t want = *len;
do {
- i = ei_read_t(fd, buf+got, len-got, ms);
- if (i <= 0)
- return (i);
- got += i;
- } while (got < len);
- return (len);
-
+ ssize_t read_len = want-got;
+ int error;
+
+ do {
+ error = read_ctx_t__(cbs, ctx, buf+got, &read_len, ms);
+ } while (error == EINTR);
+ if (error)
+ return error;
+ if (read_len == 0) {
+ *len = got;
+ return 0;
+ }
+ got += read_len;
+ } while (got < want);
+
+ *len = got;
+ return 0;
} /* read_fill */
-int ei_read_fill(int fd, char* buf, int len)
+int ei_read_fill_ctx__(ei_socket_callbacks *cbs, void *ctx, char* buf, ssize_t *len)
{
- return ei_read_fill_t(fd, buf, len, 0);
+ return ei_read_fill_ctx_t__(cbs, ctx, buf, len, 0);
}
/* write entire buffer on fd or fail (setting errno)
*/
-int ei_write_fill_t(int fd, const char *buf, int len, unsigned ms)
+int ei_write_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx, const char *buf, ssize_t *len, unsigned ms)
{
- int i,done=0;
- if (ms != 0U) {
+ ssize_t tot = *len, done = 0;
+ int error, fd = -1, basic = !(cbs->flags & EI_SCLBK_FLG_FULL_IMPL);
+
+ if (basic && ms != 0U) {
+ error = EI_GET_FD__(cbs, ctx, &fd);
+ if (error)
+ return error;
SET_NONBLOCKING(fd);
}
do {
- i = ei_write_t(fd, buf+done, len-done, ms);
- if (i <= 0) {
- if (ms != 0U) {
+ ssize_t write_len = tot-done;
+ error = write_ctx_t__(cbs, ctx, buf+done, &write_len, ms);
+ if (error) {
+ *len = done;
+ if (basic && ms != 0U) {
SET_BLOCKING(fd);
}
- return (i);
+ return error;
}
- done += i;
- } while (done < len);
- if (ms != 0U) {
+ done += write_len;
+ } while (done < tot);
+ if (basic && ms != 0U) {
SET_BLOCKING(fd);
}
- return (len);
+ *len = done;
+ return 0;
+}
+
+int ei_write_fill_ctx__(ei_socket_callbacks *cbs, void *ctx, const char *buf, ssize_t *len)
+{
+ return ei_write_fill_ctx_t__(cbs, ctx, buf, len, 0);
+}
+
+/*
+ * Internal API for TCP/IPv4
+ */
+
+int ei_connect_t__(int fd, void *addr, int len, unsigned ms)
+{
+ return ei_connect_ctx_t__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd),
+ addr, len, ms);
}
-int ei_write_fill(int fd, const char *buf, int len)
+int ei_socket__(int *fd)
{
- return ei_write_fill_t(fd, buf, len, 0);
+ void *ctx;
+ int error = ei_socket_ctx__(&ei_default_socket_callbacks, &ctx, NULL);
+ if (error)
+ return error;
+ return EI_GET_FD__(&ei_default_socket_callbacks, ctx, fd);
}
+int ei_close__(int fd)
+{
+ return ei_close_ctx__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd));
+}
+
+int ei_listen__(int fd, void *adr, int *len, int backlog)
+{
+ return ei_listen_ctx__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd),
+ adr, len, backlog);
+}
+
+int ei_accept_t__(int *fd, void *addr, int *len, unsigned ms)
+{
+ void *ctx = EI_FD_AS_CTX__(*fd);
+ int error = ei_accept_ctx_t__(&ei_default_socket_callbacks, &ctx,
+ addr, len, ms);
+ if (error)
+ return error;
+ return EI_GET_FD__(&ei_default_socket_callbacks, ctx, fd);
+}
+
+int ei_read_fill_t__(int fd, char* buf, ssize_t *len, unsigned ms)
+{
+ return ei_read_fill_ctx_t__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd),
+ buf, len, ms);
+}
+
+int ei_read_fill__(int fd, char* buf, ssize_t *len)
+{
+ return ei_read_fill_ctx_t__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd),
+ buf, len, 0);
+}
+
+int ei_write_fill_t__(int fd, const char *buf, ssize_t *len, unsigned ms)
+{
+ return ei_write_fill_ctx_t__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd),
+ buf, len, ms);
+}
+
+int ei_write_fill__(int fd, const char *buf, ssize_t *len)
+{
+ return ei_write_fill_ctx_t__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd),
+ buf, len, 0);
+}
+
+#if defined(EI_HAVE_STRUCT_IOVEC__) && defined(HAVE_WRITEV)
+
+int ei_writev_fill_t__(int fd, const struct iovec *iov, int iovcnt, ssize_t *len, unsigned ms)
+{
+ return ei_writev_fill_ctx_t__(&ei_default_socket_callbacks, EI_FD_AS_CTX__(fd),
+ iov, iovcnt, len, ms);
+}
+
+#endif
+
diff --git a/lib/erl_interface/src/misc/ei_portio.h b/lib/erl_interface/src/misc/ei_portio.h
index bded811a35..a84b5ca09c 100644
--- a/lib/erl_interface/src/misc/ei_portio.h
+++ b/lib/erl_interface/src/misc/ei_portio.h
@@ -21,21 +21,94 @@
*/
#ifndef _EI_PORTIO_H
#define _EI_PORTIO_H
-#if !defined(__WIN32__) && !defined(VXWORKS)
-#ifdef HAVE_WRITEV
+
+#undef EI_HAVE_STRUCT_IOVEC__
+#if !defined(__WIN32__) && !defined(VXWORKS) && defined(HAVE_SYS_UIO_H)
/* Declaration of struct iovec *iov should be visible in this scope. */
-#include <sys/uio.h>
+# include <sys/uio.h>
+# define EI_HAVE_STRUCT_IOVEC__
#endif
+
+/*
+ * Internal API. Should not be used outside of the erl_interface application...
+ */
+
+int ei_socket_ctx__(ei_socket_callbacks *cbs, void **ctx, void *setup);
+int ei_close_ctx__(ei_socket_callbacks *cbs, void *ctx);
+int ei_listen_ctx__(ei_socket_callbacks *cbs, void *ctx, void *adr, int *len, int backlog);
+int ei_accept_ctx_t__(ei_socket_callbacks *cbs, void **ctx, void *addr, int *len, unsigned ms);
+int ei_connect_ctx_t__(ei_socket_callbacks *cbs, void *ctx, void *addr, int len, unsigned ms);
+int ei_read_fill_ctx__(ei_socket_callbacks *cbs, void *ctx, char* buf, ssize_t *len);
+int ei_write_fill_ctx__(ei_socket_callbacks *cbs, void *ctx, const char *buf, ssize_t *len);
+int ei_read_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx, char* buf, ssize_t *len, unsigned ms);
+int ei_write_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx, const char *buf, ssize_t *len, unsigned ms);
+#if defined(EI_HAVE_STRUCT_IOVEC__)
+int ei_writev_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx, const struct iovec *iov, int iovcnt, ssize_t *len, unsigned ms);
+int ei_socket_callbacks_have_writev__(ei_socket_callbacks *cbs);
#endif
-int ei_accept_t(int fd, void *addr, void *addrlen, unsigned ms);
-int ei_connect_t(int fd, void *sinp, int sin_siz, unsigned ms);
-int ei_read_fill(int fd, char* buf, int len);
-int ei_write_fill(int fd, const char *buf, int len);
-int ei_read_fill_t(int fd, char* buf, int len, unsigned ms);
-int ei_write_fill_t(int fd, const char *buf, int len, unsigned ms);
-#ifdef HAVE_WRITEV
-int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, unsigned ms);
+ei_socket_callbacks ei_default_socket_callbacks;
+
+#define EI_FD_AS_CTX__(FD) \
+ ((void *) (long) (FD))
+
+#define EI_DFLT_CTX_TO_FD__(CTX, FD) \
+ ((int) (long) (CTX) < 0 \
+ ? EBADF \
+ : (*(FD) = (int) (long) (CTX), 0))
+
+#define EI_GET_FD__(CBS, CTX, FD) \
+ ((CBS) == &ei_default_socket_callbacks \
+ ? EI_DFLT_CTX_TO_FD__((CTX), FD) \
+ : (CBS)->get_fd((CTX), (FD)))
+
+extern int ei_plugin_socket_impl__;
+
+#if !defined(_REENTRANT)
+
+#define EI_HAVE_PLUGIN_SOCKET_IMPL__ \
+ ei_plugin_socket_impl__
+#define EI_SET_HAVE_PLUGIN_SOCKET_IMPL__ \
+ ei_plugin_socket_impl__ = 1
+
+#elif ((ETHR_HAVE___atomic_load_n & SIZEOF_INT) \
+ && (ETHR_HAVE___atomic_store_n & SIZEOF_INT))
+
+#define EI_HAVE_PLUGIN_SOCKET_IMPL__ \
+ __atomic_load_n(&ei_plugin_socket_impl__, __ATOMIC_ACQUIRE)
+#define EI_SET_HAVE_PLUGIN_SOCKET_IMPL__ \
+ __atomic_store_n(&ei_plugin_socket_impl__, 1, __ATOMIC_RELEASE)
+
+#else
+
+/* No gcc atomics; always lookup using ei_get_cbs_ctx()... */
+#define EI_HAVE_PLUGIN_SOCKET_IMPL__ 0
+#define EI_SET_HAVE_PLUGIN_SOCKET_IMPL__ (void) 0
+
+#endif
+
+#define EI_GET_CBS_CTX__(CBS, CTX, FD) \
+ (EI_HAVE_PLUGIN_SOCKET_IMPL__ \
+ ? ei_get_cbs_ctx__((CBS), (CTX), (FD)) \
+ : ((FD) < 0 \
+ ? EBADF \
+ : (*(CBS) = &ei_default_socket_callbacks, \
+ *(CTX) = EI_FD_AS_CTX__((FD)), \
+ 0)))
+/*
+ * The following uses our own TCP/IPv4 socket implementation...
+ */
+int ei_socket__(int *fd);
+int ei_close__(int fd);
+int ei_listen__(int fd, void *adr, int *len, int backlog);
+int ei_accept_t__(int *fd, void *addr, int *len, unsigned ms);
+int ei_connect_t__(int fd, void *addr, int len, unsigned ms);
+int ei_read_fill__(int fd, char* buf, ssize_t *len);
+int ei_write_fill__(int fd, const char *buf, ssize_t *len);
+int ei_read_fill_t__(int fd, char* buf, ssize_t *len, unsigned ms);
+int ei_write_fill_t__(int fd, const char *buf, ssize_t *len, unsigned ms);
+#if defined(EI_HAVE_STRUCT_IOVEC__) && defined(HAVE_WRITEV)
+int ei_writev_fill_t__(int fd, const struct iovec *iov, int iovcnt, ssize_t *len, unsigned ms);
#endif
#endif /* _EI_PORTIO_H */
diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c
index 25608edeec..ec1c8d956f 100644
--- a/lib/erl_interface/src/misc/ei_pthreads.c
+++ b/lib/erl_interface/src/misc/ei_pthreads.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -206,6 +206,7 @@ volatile int *__erl_errno_place(void)
use_fallback = 1;
return &fallback_errno;
}
+ *erl_errno_p = 0;
if (pthread_setspecific(erl_errno_key, erl_errno_p) != 0 ||
(erl_errno_p = pthread_getspecific(erl_errno_key)) == NULL) {
diff --git a/lib/erl_interface/src/not_used/send_link.c b/lib/erl_interface/src/not_used/send_link.c
index 7be476fd93..38fae27df4 100644
--- a/lib/erl_interface/src/not_used/send_link.c
+++ b/lib/erl_interface/src/not_used/send_link.c
@@ -50,6 +50,7 @@ static int link_unlink(int fd, const erlang_pid *from, const erlang_pid *to,
char *s;
int index = 0;
int n;
+ unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
index = 5; /* max sizes: */
ei_encode_version(msgbuf,&index); /* 1 */
@@ -69,7 +70,7 @@ static int link_unlink(int fd, const erlang_pid *from, const erlang_pid *to,
if (ei_trace_distribution > 1) ei_show_sendmsg(stderr,msgbuf,NULL);
#endif
- n = ei_write_fill_t(fd,msgbuf,index,ms);
+ n = ei_write_fill_t__(fd,msgbuf,index,tmo);
return (n==index ? 0 : -1);
}
diff --git a/lib/erl_interface/src/prog/ei_fake_prog.c b/lib/erl_interface/src/prog/ei_fake_prog.c
index c7a16dc7c4..158464b385 100644
--- a/lib/erl_interface/src/prog/ei_fake_prog.c
+++ b/lib/erl_interface/src/prog/ei_fake_prog.c
@@ -98,11 +98,18 @@ int main(void)
EI_ULONGLONG ulonglongx = 0;
#endif
erlang_char_encoding enc;
+ ei_socket_callbacks cbs;
intx = erl_errno;
+ ei_init();
+
+ ei_close_connection(intx);
+
ei_connect_init(&xec, charp, charp, creation);
+ ei_connect_init_ussi(&xec, charp, charp, creation, &cbs, sizeof(cbs), NULL);
ei_connect_xinit (&xec, charp, charp, charp, thisipaddr, charp, creation);
+ ei_connect_xinit_ussi(&xec, charp, charp, charp, thisipaddr, charp, creation, &cbs, sizeof(cbs), NULL);
ei_connect(&xec, charp);
ei_xconnect (&xec, thisipaddr, charp);
@@ -121,6 +128,8 @@ int main(void)
ei_publish(&xec, intx);
ei_accept(&xec, intx, &conp);
ei_unpublish(&xec);
+ ei_listen(&xec, intp, intx);
+ ei_xlisten(&xec, thisipaddr, intp, intx);
ei_thisnodename(&xec);
ei_thishostname(&xec);
@@ -187,7 +196,7 @@ int main(void)
ei_decode_char(charp, intp, charp);
ei_decode_string(charp, intp, charp);
ei_decode_atom(charp, intp, charp);
- ei_decode_atom_as(charp, intp, charp, MAXATOMLEN_UTF8, ERLANG_WHATEVER, &enc, &enc);
+ ei_decode_atom_as(charp, intp, charp, MAXATOMLEN_UTF8, ERLANG_UTF8, &enc, &enc);
ei_decode_binary(charp, intp, (void *)0, longp);
ei_decode_fun(charp, intp, &efun);
free_fun(&efun);
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index 52ad6885e8..ab91157035 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -88,10 +88,6 @@
#include "ei_resolve.h"
#include "erl_start.h" /* FIXME remove dependency */
-#ifdef __WIN32__
-static void initWinSock(void);
-#endif
-
/*
* Some nice global variables
* (I don't think "nice" is the right word actually... -gordon)
@@ -157,6 +153,8 @@ int erl_call(int argc, char **argv)
char* progname = argv[0];
ei_cnode ec;
+ ei_init();
+
/* Get the command line options */
while (i < argc) {
if (argv[i][0] != '-') {
@@ -317,14 +315,6 @@ int erl_call(int argc, char **argv)
struct in_addr h_ipadr;
char* ct;
-#ifdef __WIN32__
- /*
- * FIXME Extremly ugly, but needed to get ei_gethostbyname() below
- * to work.
- */
- initWinSock();
-#endif
-
/* gethostname requires len to be max(hostname) + 1 */
if (gethostname(h_hostname, EI_MAXHOSTNAMELEN+1) < 0) {
fprintf(stderr,"erl_call: failed to get host name: %d\n", errno);
@@ -857,46 +847,6 @@ static void usage(const char *progname) {
exit(0);
}
-
-/***************************************************************************
- *
- * OS specific functions
- *
- ***************************************************************************/
-
-#ifdef __WIN32__
-/*
- * FIXME This should not be here. This is a quick fix to make erl_call
- * work at all on Windows NT.
- */
-static void initWinSock(void)
-{
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
- static int initialized;
-
- wVersionRequested = MAKEWORD(1, 1);
- if (!initialized) {
- initialized = 1;
- err = WSAStartup(wVersionRequested, &wsaData);
-
- if (err != 0) {
- fprintf(stderr,"erl_call: "
- "Can't initialize windows sockets: %d\n", err);
- }
-
- if ( LOBYTE( wsaData.wVersion ) != 1 ||
- HIBYTE( wsaData.wVersion ) != 1 ) {
- fprintf(stderr,"erl_call: This version of "
- "windows sockets not supported\n");
- WSACleanup();
- }
- }
-}
-#endif
-
-
/***************************************************************************
*
* Utility functions
diff --git a/lib/erl_interface/src/prog/erl_start.c b/lib/erl_interface/src/prog/erl_start.c
index 670a5900c9..c766f4780e 100644
--- a/lib/erl_interface/src/prog/erl_start.c
+++ b/lib/erl_interface/src/prog/erl_start.c
@@ -657,7 +657,7 @@ static int wait_for_erlang(int sockd, int magic, struct timeval *timeout)
gettimeofday(&now,NULL);
to.tv_sec = stop_time.tv_sec - now.tv_sec;
to.tv_usec = stop_time.tv_usec - now.tv_usec;
- while ((to.tv_usec <= 0) && (to.tv_sec >= 0)) {
+ while ((to.tv_usec < 0) && (to.tv_sec > 0)) {
to.tv_usec += 1000000;
to.tv_sec--;
}
diff --git a/lib/erl_interface/test/Makefile b/lib/erl_interface/test/Makefile
index 94f4b422d6..f8f2ef0156 100644
--- a/lib/erl_interface/test/Makefile
+++ b/lib/erl_interface/test/Makefile
@@ -33,6 +33,7 @@ MODULES= \
ei_format_SUITE \
ei_print_SUITE \
ei_tmo_SUITE \
+ erl_call_SUITE \
erl_connect_SUITE \
erl_global_SUITE \
erl_eterm_SUITE \
diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl
index 85c567acd3..9c9c3f86b6 100644
--- a/lib/erl_interface/test/ei_accept_SUITE.erl
+++ b/lib/erl_interface/test/ei_accept_SUITE.erl
@@ -25,6 +25,7 @@
-include("ei_accept_SUITE_data/ei_accept_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
ei_accept/1, ei_threaded_accept/1,
monitor_ei_process/1]).
@@ -38,8 +39,11 @@ all() ->
[ei_accept, ei_threaded_accept,
monitor_ei_process].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
ei_accept(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
@@ -77,12 +81,10 @@ ei_accept(Config) when is_list(Config) ->
ei_threaded_accept(Config) when is_list(Config) ->
Einode = filename:join(proplists:get_value(data_dir, Config), "eiaccnode"),
- N = 1, % 3,
+ N = 3,
Host = atom_to_list(node()),
- Port = 6767,
- start_einode(Einode, N, Host, Port),
+ start_einode(Einode, N, Host),
io:format("started eiaccnode"),
- %%spawn_link(fun() -> start_einode(Einode, N, Host, Port) end),
TestServerPid = self(),
[spawn_link(fun() -> send_rec_einode(I, TestServerPid) end) || I <- lists:seq(0, N-1)],
[receive I -> ok end || I <- lists:seq(0, N-1) ],
@@ -91,7 +93,7 @@ ei_threaded_accept(Config) when is_list(Config) ->
%% Test erlang:monitor toward erl_interface "processes"
monitor_ei_process(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
@@ -99,7 +101,6 @@ monitor_ei_process(Config) when is_list(Config) ->
EINode = list_to_atom("c42@"++Myname),
io:format("EINode ~p ~n", [EINode]),
- Self = self(),
Port = 6543,
{ok, ListenFd} = ei_publish(P, Port),
MRef1 = erlang:monitor(process, {any, EINode}),
@@ -156,10 +157,9 @@ send_rec_einode(N, TestServerPid) ->
ct:fail(EINode)
end.
-start_einode(Einode, N, Host, Port) ->
+start_einode(Einode, N, Host) ->
Einodecmd = Einode ++ " " ++ atom_to_list(erlang:get_cookie())
- ++ " " ++ integer_to_list(N) ++ " " ++ Host ++ " "
- ++ integer_to_list(Port) ++ " nothreads",
+ ++ " " ++ integer_to_list(N) ++ " " ++ Host,
io:format("Einodecmd ~p ~n", [Einodecmd]),
open_port({spawn, Einodecmd}, []),
ok.
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
index 04bba90732..c209f506b1 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
@@ -74,12 +74,10 @@ TESTCASE(interpret)
int i;
ei_term term;
+ ei_init();
+
ei_x_new(&x);
- for (;;) {
- if (get_bin_term(&x, &term)) {
- report(1);
- return;
- } else {
+ while (get_bin_term(&x, &term) == 0) {
char* buf = x.buff, func[MAXATOMLEN];
int index = x.index, arity;
if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2)
@@ -100,8 +98,9 @@ TESTCASE(interpret)
message("\"%d\" \n", func);
fail("bad command");
}
- }
- }
+ }
+ report(1);
+ ei_x_free(&x);
}
static void cmd_ei_connect_init(char* buf, int len)
@@ -128,45 +127,26 @@ static void cmd_ei_connect_init(char* buf, int len)
ei_x_free(&res);
}
-static int my_listen(int port)
-{
- int listen_fd;
- struct sockaddr_in addr;
- const char *on = "1";
-
- if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- return -1;
-
- setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on));
-
- memset((void*) &addr, 0, (size_t) sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
- return -1;
-
- listen(listen_fd, 5);
- return listen_fd;
-}
-
static void cmd_ei_publish(char* buf, int len)
{
int index = 0;
- int listen, r;
- long port;
+ int iport, lfd, r;
+ long lport;
ei_x_buff x;
int i;
/* get port */
- if (ei_decode_long(buf, &index, &port) < 0)
+ if (ei_decode_long(buf, &index, &lport) < 0)
fail("expected int (port)");
/* Make a listen socket */
- if ((listen = my_listen(port)) <= 0)
+
+ iport = (int) lport;
+ lfd = ei_listen(&ec, &iport, 5);
+ if (lfd < 0)
fail("listen");
+ lport = (long) iport;
- if ((i = ei_publish(&ec, port)) == -1)
+ if ((i = ei_publish(&ec, lport)) == -1)
fail("ei_publish");
#ifdef VXWORKS
save_fd(i);
@@ -174,7 +154,7 @@ static void cmd_ei_publish(char* buf, int len)
/* send listen-fd, result and errno */
ei_x_new_with_version(&x);
ei_x_encode_tuple_header(&x, 3);
- ei_x_encode_long(&x, listen);
+ ei_x_encode_long(&x, (long) lfd);
ei_x_encode_long(&x, i);
ei_x_encode_long(&x, erl_errno);
send_bin_term(&x);
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c
index 308f843530..90c7a2259f 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c
@@ -47,8 +47,6 @@
#define MAIN main
#endif
-static int my_listen(int port);
-
/*
A small einode.
To be called from the test case ei_accept_SUITE:multi_thread
@@ -64,7 +62,6 @@ static int my_listen(int port);
*/
static const char* cookie, * desthost;
-static int port; /* actually base port */
#ifndef SD_SEND
#ifdef SHUTWR
@@ -74,10 +71,6 @@ static int port; /* actually base port */
#endif
#endif
-#ifndef __WIN32__
-#define closesocket(fd) close(fd)
-#endif
-
#ifdef __WIN32__
static DWORD WINAPI
#else
@@ -86,26 +79,32 @@ static void*
einode_thread(void* num)
{
int n = (int)num;
+ int port;
ei_cnode ec;
- char myname[100], destname[100];
+ char myname[100], destname[100], filename[100];
int r, fd, listen;
ErlConnect conn;
erlang_msg msg;
-/* FILE* f;*/
+ FILE* file;
- sprintf(myname, "eiacc%d", n);
- printf("thread %d (%s) listening\n", n, myname, destname);
+ sprintf(filename, "eiacc%d_trace.txt", n);
+ file = fopen(filename, "w");
+
+ sprintf(myname, "eiacc%d", n); fflush(file);
r = ei_connect_init(&ec, myname, cookie, 0);
- if ((listen = my_listen(port+n)) <= 0) {
- printf("listen err\n");
+ port = 0;
+ listen = ei_listen(&ec, &port, 5);
+ if (listen <= 0) {
+ fprintf(file, "listen err\n"); fflush(file);
exit(7);
}
- if (ei_publish(&ec, port + n) == -1) {
- printf("ei_publish port %d\n", port+n);
+ fprintf(file, "thread %d (%s:%s) listening on port %d\n", n, myname, destname, port);
+ if (ei_publish(&ec, port) == -1) {
+ fprintf(file, "ei_publish port %d\n", port+n); fflush(file);
exit(8);
}
fd = ei_accept(&ec, listen, &conn);
- printf("ei_accept %d\n", fd);
+ fprintf(file, "ei_accept %d\n", fd); fflush(file);
if (fd >= 0) {
ei_x_buff x, xs;
int index, version;
@@ -117,37 +116,38 @@ static void*
if (got == ERL_TICK)
continue;
if (got == ERL_ERROR) {
- printf("receive error %d\n", n);
+ fprintf(file, "receive error %d\n", n); fflush(file);
return 0;
}
- printf("received %d\n", got);
+ fprintf(file, "received %d\n", got); fflush(file);
break;
}
index = 0;
if (ei_decode_version(x.buff, &index, &version) != 0) {
- printf("ei_decode_version %d\n", n);
+ fprintf(file, "ei_decode_version %d\n", n); fflush(file);
return 0;
}
if (ei_decode_pid(x.buff, &index, &pid) != 0) {
- printf("ei_decode_pid %d\n", n);
+ fprintf(file, "ei_decode_pid %d\n", n); fflush(file);
return 0;
}
-/* fprintf(f, "got pid from %s \n", pid.node);*/
+ fprintf(file, "got pid from %s \n", pid.node); fflush(file);
ei_x_new_with_version(&xs);
ei_x_encode_tuple_header(&xs, 2);
ei_x_encode_long(&xs, n);
ei_x_encode_pid(&xs, &pid);
r = ei_send(fd, &pid, xs.buff, xs.index);
-/* fprintf(f, "sent %d bytes %d\n", xs.index, r);*/
+ fprintf(file, "sent %d bytes %d\n", xs.index, r); fflush(file);
shutdown(fd, SD_SEND);
- closesocket(fd);
+ ei_close_connection(fd);
ei_x_free(&x);
ei_x_free(&xs);
} else {
- printf("coudn't connect fd %d r %d\n", fd, r);
+ fprintf(file, "coudn't connect fd %d r %d\n", fd, r); fflush(file);
}
- printf("done thread %d\n", n);
-/* fclose(f);*/
+ ei_close_connection(listen);
+ fprintf(file, "done thread %d\n", n);
+ fclose(file);
return 0;
}
@@ -170,12 +170,16 @@ MAIN(int argc, char *argv[])
if (n > 100)
exit(2);
desthost = argv[3];
- port = atoi(argv[4]);
-#ifndef VXWORKS
- no_threads = argv[5] != NULL && strcmp(argv[5], "nothreads") == 0;
-#else
+ if (argc == 3)
+ no_threads = 0;
+ else
+ no_threads = argv[4] != NULL && strcmp(argv[4], "nothreads") == 0;
+#ifdef VXWORKS
no_threads = 1;
#endif
+
+ ei_init();
+
for (i = 0; i < n; ++i) {
if (!no_threads) {
#ifndef VXWORKS
@@ -209,27 +213,3 @@ MAIN(int argc, char *argv[])
printf("ok\n");
return 0;
}
-
-static int my_listen(int port)
-{
- int listen_fd;
- struct sockaddr_in addr;
- const char *on = "1";
-
- if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- return -1;
-
- setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on));
-
- memset((void*) &addr, 0, (size_t) sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
- return -1;
-
- listen(listen_fd, 5);
- return listen_fd;
-}
-
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 66498deadc..75b6bf18da 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_connect_SUITE_data/ei_connect_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
ei_send/1,
ei_reg_send/1,
ei_format_pid/1,
@@ -44,8 +45,11 @@ all() ->
[ei_send, ei_reg_send, ei_rpc, ei_format_pid, ei_send_funs,
ei_threaded_send, ei_set_get_tracelevel].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
ei_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -58,7 +62,7 @@ ei_send(Config) when is_list(Config) ->
ei_format_pid(Config) when is_list(Config) ->
S = self(),
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -70,7 +74,7 @@ ei_format_pid(Config) when is_list(Config) ->
ok.
ei_send_funs(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -88,7 +92,7 @@ ei_send_funs(Config) when is_list(Config) ->
ok.
ei_reg_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -137,7 +141,7 @@ start_einode(Einode, N, Host) ->
ok.
ei_rpc(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -150,7 +154,7 @@ ei_rpc(Config) when is_list(Config) ->
ok.
ei_set_get_tracelevel(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
5 = ei_set_get_tracelevel(P, 5),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index 6a3796dd24..58c0c7f8d8 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,12 +73,10 @@ TESTCASE(interpret)
int i;
ei_term term;
+ ei_init();
+
ei_x_new(&x);
- for (;;) {
- if (get_bin_term(&x, &term)) {
- report(1);
- return;
- } else {
+ while (get_bin_term(&x, &term) == 0) {
char* buf = x.buff, func[MAXATOMLEN];
int index = x.index, arity;
if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2)
@@ -99,8 +97,10 @@ TESTCASE(interpret)
message("\"%d\" \n", func);
fail("bad command");
}
- }
- }
+ }
+ report(1);
+ ei_x_free(&x);
+ return;
}
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index 74fb9b8916..75560ea7c9 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_decode_SUITE_data/ei_decode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_decode_long/1,
test_ei_decode_ulong/1,
test_ei_decode_longlong/1,
@@ -42,6 +43,9 @@ all() ->
test_ei_decode_char, test_ei_decode_nonoptimal,
test_ei_decode_misc, test_ei_decode_utf8_atom].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
% NOTE: for historical reasons we don't pach as tight as we can,
@@ -51,7 +55,7 @@ all() ->
%% ######################################################################## %%
test_ei_decode_long(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_long),
+ P = runner:start(Config, ?test_ei_decode_long),
send_integers(P),
runner:recv_eot(P),
ok.
@@ -60,7 +64,7 @@ test_ei_decode_long(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_ulong(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_ulong),
+ P = runner:start(Config, ?test_ei_decode_ulong),
send_integers(P),
runner:recv_eot(P),
ok.
@@ -77,7 +81,7 @@ test_ei_decode_longlong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_decode_longlong),
+ P = runner:start(Config, ?test_ei_decode_longlong),
send_integers2(P),
runner:recv_eot(P),
ok
@@ -91,7 +95,7 @@ test_ei_decode_ulonglong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_decode_ulonglong),
+ P = runner:start(Config, ?test_ei_decode_ulonglong),
send_integers2(P),
runner:recv_eot(P),
ok
@@ -104,7 +108,7 @@ test_ei_decode_ulonglong(Config) when is_list(Config) ->
%% FIXME maybe the API should change to use "unsigned char" to be clear?!
test_ei_decode_char(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_char),
+ P = runner:start(Config, ?test_ei_decode_char),
send_term_as_binary(P,0),
send_term_as_binary(P,16#7f),
@@ -119,7 +123,7 @@ test_ei_decode_char(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_nonoptimal(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_nonoptimal),
+ P = runner:start(Config, ?test_ei_decode_nonoptimal),
send_non_optimal_pos(P), % decode_char
send_non_optimal(P), % decode_long
@@ -168,7 +172,7 @@ send_non_optimal_neg(P) ->
%% ######################################################################## %%
test_ei_decode_misc(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_misc),
+ P = runner:start(Config, ?test_ei_decode_misc),
send_term_as_binary(P,0.0),
send_term_as_binary(P,-1.0),
@@ -199,7 +203,7 @@ test_ei_decode_misc(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_utf8_atom(Config) ->
- P = runner:start(?test_ei_decode_utf8_atom),
+ P = runner:start(Config, ?test_ei_decode_utf8_atom),
send_latin1_atom_as_binary(P,"å"),
send_latin1_atom_as_binary(P,"ä"),
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
index b7a2c4bb8b..e516f310b6 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -105,6 +105,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail1("size of encoded data (%d) is incorrect", size1); \
return; \
} \
+ free_packet(buf); \
} \
#define EI_DECODE_2_FAIL(FUNC,SIZE,TYPE,VAL) \
@@ -148,6 +149,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data should be 0"); \
return; \
} \
+ free_packet(buf); \
} \
#define dump(arr, num) { \
@@ -205,6 +207,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data is incorrect"); \
return; \
} \
+ free_packet(buf); \
} \
#define EI_DECODE_STRING(FUNC,SIZE,VAL) \
@@ -248,6 +251,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data should be 0"); \
return; \
} \
+ free_packet(buf); \
} \
//#define EI_DECODE_UTF8_STRING(FUNC,SIZE,VAL)
@@ -310,12 +314,15 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data is incorrect"); \
return; \
} \
+ free_packet(buf); \
} \
/* ******************************************************************** */
TESTCASE(test_ei_decode_long)
{
+ ei_init();
+
EI_DECODE_2 (decode_long, 2, long, 0);
EI_DECODE_2 (decode_long, 2, long, 255);
EI_DECODE_2 (decode_long, 5, long, 256);
@@ -358,6 +365,8 @@ TESTCASE(test_ei_decode_long)
TESTCASE(test_ei_decode_ulong)
{
+ ei_init();
+
EI_DECODE_2 (decode_ulong, 2, unsigned long, 0);
EI_DECODE_2 (decode_ulong, 2, unsigned long, 255);
EI_DECODE_2 (decode_ulong, 5, unsigned long, 256);
@@ -404,6 +413,8 @@ TESTCASE(test_ei_decode_ulong)
TESTCASE(test_ei_decode_longlong)
{
+ ei_init();
+
#ifndef VXWORKS
EI_DECODE_2 (decode_longlong, 2, EI_LONGLONG, 0);
EI_DECODE_2 (decode_longlong, 2, EI_LONGLONG, 255);
@@ -438,6 +449,8 @@ TESTCASE(test_ei_decode_longlong)
TESTCASE(test_ei_decode_ulonglong)
{
+ ei_init();
+
#ifndef VXWORKS
EI_DECODE_2 (decode_ulonglong, 2, EI_ULONGLONG, 0);
EI_DECODE_2 (decode_ulonglong, 2, EI_ULONGLONG, 255);
@@ -473,6 +486,8 @@ TESTCASE(test_ei_decode_ulonglong)
TESTCASE(test_ei_decode_char)
{
+ ei_init();
+
EI_DECODE_2(decode_char, 2, char, 0);
EI_DECODE_2(decode_char, 2, char, 0x7f);
EI_DECODE_2(decode_char, 2, char, 0xff);
@@ -486,6 +501,8 @@ TESTCASE(test_ei_decode_char)
TESTCASE(test_ei_decode_nonoptimal)
{
+ ei_init();
+
EI_DECODE_2(decode_char, 2, char, 42);
EI_DECODE_2(decode_char, 5, char, 42);
EI_DECODE_2(decode_char, 4, char, 42);
@@ -607,6 +624,8 @@ TESTCASE(test_ei_decode_nonoptimal)
TESTCASE(test_ei_decode_misc)
{
+ ei_init();
+
/*
EI_DECODE_0(decode_version);
*/
@@ -642,6 +661,7 @@ TESTCASE(test_ei_decode_misc)
TESTCASE(test_ei_decode_utf8_atom)
{
+ ei_init();
EI_DECODE_STRING_4(decode_my_atom_as, 4, P99({229,0}), /* LATIN1 "�" */
P99({ERLANG_ANY,ERLANG_LATIN1,ERLANG_LATIN1}));
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index 160720b413..0f23cdfbb9 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_decode_encode_SUITE_data/ei_decode_encode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_decode_encode/1]).
suite() ->
@@ -33,6 +34,9 @@ suite() ->
all() ->
[test_ei_decode_encode].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
% NOTE: these types have no meaning on the C side so we pass them
@@ -42,7 +46,7 @@ all() ->
%% ######################################################################## %%
test_ei_decode_encode(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_encode),
+ P = runner:start(Config, ?test_ei_decode_encode),
Fun = fun (X) -> {X,true} end,
Pid = self(),
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index 467f789fdb..55d9ed1b1a 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -466,6 +466,7 @@ void decode_encode_big(struct Type* t)
send_buffer(arg.buff, arg.index);
ei_x_free(&arg);
ei_free_big(p);
+ free_packet(buf);
}
@@ -476,6 +477,8 @@ TESTCASE(test_ei_decode_encode)
{
int i;
+ ei_init();
+
decode_encode_one(&fun_type);
decode_encode_one(&pid_type);
decode_encode_one(&port_type);
diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl
index 8857b092f3..0267a5126f 100644
--- a/lib/erl_interface/test/ei_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_encode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_encode_SUITE_data/ei_encode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_encode_long/1,
test_ei_encode_ulong/1,
test_ei_encode_longlong/1,
@@ -45,6 +46,9 @@ all() ->
test_ei_encode_fails, test_ei_encode_utf8_atom,
test_ei_encode_utf8_atom_len].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
@@ -55,7 +59,7 @@ all() ->
%% ######################################################################## %%
test_ei_encode_long(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_long),
+ P = runner:start(Config, ?test_ei_encode_long),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -77,7 +81,7 @@ test_ei_encode_long(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_ulong(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_ulong),
+ P = runner:start(Config, ?test_ei_encode_ulong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -101,7 +105,7 @@ test_ei_encode_longlong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_encode_longlong),
+ P = runner:start(Config, ?test_ei_encode_longlong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -132,7 +136,7 @@ test_ei_encode_ulonglong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_encode_ulonglong),
+ P = runner:start(Config, ?test_ei_encode_ulonglong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -158,7 +162,7 @@ test_ei_encode_ulonglong(Config) when is_list(Config) ->
%% FIXME maybe the API should change to use "unsigned char" to be clear?!
test_ei_encode_char(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_char),
+ P = runner:start(Config, ?test_ei_encode_char),
{<<97, 0>>,0} = get_buf_and_term(P),
{<<97,127>>,16#7f} = get_buf_and_term(P),
@@ -171,7 +175,7 @@ test_ei_encode_char(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_misc(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_misc),
+ P = runner:start(Config, ?test_ei_encode_misc),
<<131>> = get_binaries(P),
@@ -217,7 +221,7 @@ test_ei_encode_misc(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_fails(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_fails),
+ P = runner:start(Config, ?test_ei_encode_fails),
XAtom = list_to_atom(lists:duplicate(255, $x)),
YAtom = list_to_atom(lists:duplicate(255, $y)),
@@ -236,7 +240,7 @@ test_ei_encode_fails(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_utf8_atom(Config) ->
- P = runner:start(?test_ei_encode_utf8_atom),
+ P = runner:start(Config, ?test_ei_encode_utf8_atom),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
@@ -251,7 +255,7 @@ test_ei_encode_utf8_atom(Config) ->
%% ######################################################################## %%
test_ei_encode_utf8_atom_len(Config) ->
- P = runner:start(?test_ei_encode_utf8_atom_len),
+ P = runner:start(Config, ?test_ei_encode_utf8_atom_len),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
{<<119,4,195,133,195,132>>,'ÅÄ'} = get_buf_and_term(P),
diff --git a/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c
index 32811fdf22..6f63cc5d7e 100644
--- a/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c
+++ b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c
@@ -403,6 +403,8 @@
TESTCASE(test_ei_encode_long)
{
+ ei_init();
+
EI_ENCODE_1(encode_long, 0);
EI_ENCODE_1(encode_long, 255);
@@ -430,6 +432,8 @@ TESTCASE(test_ei_encode_long)
TESTCASE(test_ei_encode_ulong)
{
+ ei_init();
+
EI_ENCODE_1(encode_ulong, 0);
EI_ENCODE_1(encode_ulong, 255);
@@ -454,6 +458,7 @@ TESTCASE(test_ei_encode_ulong)
TESTCASE(test_ei_encode_longlong)
{
+ ei_init();
#ifndef VXWORKS
@@ -494,6 +499,7 @@ TESTCASE(test_ei_encode_longlong)
TESTCASE(test_ei_encode_ulonglong)
{
+ ei_init();
#ifndef VXWORKS
@@ -527,6 +533,8 @@ TESTCASE(test_ei_encode_ulonglong)
TESTCASE(test_ei_encode_char)
{
+ ei_init();
+
EI_ENCODE_1(encode_char, 0);
EI_ENCODE_1(encode_char, 0x7f);
@@ -540,6 +548,8 @@ TESTCASE(test_ei_encode_char)
TESTCASE(test_ei_encode_misc)
{
+ ei_init();
+
EI_ENCODE_0(encode_version);
EI_ENCODE_1(encode_double, 0.0);
@@ -594,6 +604,8 @@ TESTCASE(test_ei_encode_fails)
char buf[1024];
int index;
+ ei_init();
+
/* FIXME the ei_x versions are not tested */
index = 0;
@@ -660,6 +672,7 @@ TESTCASE(test_ei_encode_fails)
TESTCASE(test_ei_encode_utf8_atom)
{
+ ei_init();
EI_ENCODE_3(encode_atom_as, "�", ERLANG_LATIN1, ERLANG_UTF8);
EI_ENCODE_3(encode_atom_as, "�", ERLANG_LATIN1, ERLANG_LATIN1);
@@ -686,6 +699,7 @@ TESTCASE(test_ei_encode_utf8_atom)
TESTCASE(test_ei_encode_utf8_atom_len)
{
+ ei_init();
EI_ENCODE_4(encode_atom_len_as, "���", 1, ERLANG_LATIN1, ERLANG_UTF8);
EI_ENCODE_4(encode_atom_len_as, "���", 2, ERLANG_LATIN1, ERLANG_LATIN1);
diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl
index 07ee479b1f..e074c184c1 100644
--- a/lib/erl_interface/test/ei_format_SUITE.erl
+++ b/lib/erl_interface/test/ei_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
-export([format_wo_ver/1,
all/0, suite/0,
+ init_per_testcase/2,
atoms/1,
tuples/1,
lists/1]).
@@ -41,10 +42,13 @@ suite() ->
all() ->
[format_wo_ver, atoms, tuples, lists].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, ''} = get_term(P),
{term, 'a'} = get_term(P),
@@ -84,7 +88,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, {}} = get_term(P),
{term, {a}} = get_term(P),
@@ -105,7 +109,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, []} = get_term(P),
{term, [a]} = get_term(P),
@@ -146,7 +150,7 @@ lists(Config) when is_list(Config) ->
format_wo_ver(Config) when is_list(Config) ->
- P = runner:start(?format_wo_ver),
+ P = runner:start(Config, ?format_wo_ver),
{term, [-1, 2, $c, {a, "b"}, {c, 10}]} = get_term(P),
diff --git a/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c
index 8450332b28..1c0443c0f4 100644
--- a/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c
+++ b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c
@@ -48,6 +48,8 @@ send_format(char* format)
TESTCASE(atoms)
{
+ ei_init();
+
send_format("''");
send_format("'a'");
send_format("'A'");
@@ -82,6 +84,8 @@ TESTCASE(atoms)
TESTCASE(tuples)
{
+ ei_init();
+
send_format("{}");
send_format("{a}");
send_format("{a, b}");
@@ -108,6 +112,8 @@ TESTCASE(lists)
ei_x_buff x;
static char str[65537];
+ ei_init();
+
send_format("[]");
send_format("[a]");
send_format("[a, b]");
@@ -177,6 +183,8 @@ TESTCASE(format_wo_ver) {
*/
ei_x_buff x;
+ ei_init();
+
ei_x_new (&x);
ei_x_format(&x, "[-1, +2, ~c, {~a,~s},{~a,~i}]", 'c', "a", "b", "c", 10);
send_bin_term(&x);
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index 6d5c341eae..c75ce55a7d 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_print_SUITE_data/ei_print_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, tuples/1, lists/1, strings/1]).
-import(runner, [get_term/1]).
@@ -38,10 +39,13 @@ suite() ->
all() ->
[atoms, tuples, lists, strings].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, "''"} = get_term(P),
{term, "a"} = get_term(P),
@@ -79,7 +83,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, "{}"} = get_term(P),
{term, "{a}"} = get_term(P),
@@ -100,7 +104,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, "[]"} = get_term(P),
{term, "[a]"} = get_term(P),
@@ -125,7 +129,7 @@ lists(Config) when is_list(Config) ->
ok.
strings(Config) when is_list(Config) ->
- P = runner:start(?strings),
+ P = runner:start(Config, ?strings),
{term, "\"\\n\""} = get_term(P),
{term, "\"\\r\\n\""} = get_term(P),
diff --git a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c
index 15cfbcae34..80be3016e6 100644
--- a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c
+++ b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c
@@ -84,6 +84,8 @@ static void send_printed3f(char* format, float f1, float f2)
TESTCASE(atoms)
{
+ ei_init();
+
send_printed("''");
send_printed("'a'");
send_printed("'A'");
@@ -118,6 +120,8 @@ TESTCASE(atoms)
TESTCASE(tuples)
{
+ ei_init();
+
send_printed("{}");
send_printed("{a}");
send_printed("{a, b}");
@@ -138,6 +142,8 @@ TESTCASE(lists)
{
ei_x_buff x;
+ ei_init();
+
send_printed("[]");
send_printed("[a]");
send_printed("[a, b]");
@@ -164,6 +170,8 @@ TESTCASE(strings)
{
ei_x_buff x;
+ ei_init();
+
send_printed("\"\n\"");
send_printed("\"\r\n\"");
send_printed("\"a\"");
diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl
index 003fe20594..5b9de80128 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE.erl
+++ b/lib/erl_interface/test/ei_tmo_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,14 +39,16 @@ all() ->
[framework_check, ei_accept_tmo, ei_connect_tmo,
ei_send_tmo, ei_recv_tmo].
-init_per_testcase(_Case, Config) ->
+init_per_testcase(Case, Config) ->
+ Config1 = runner:init_per_testcase(?MODULE, Case, Config),
+
% test if platform is vxworks_simso
{_,Host} = split(node()),
Bool = case atom_to_list(Host) of
[$v,$x,$s,$i,$m | _] -> true;
_ -> false
end,
- [{vxsim,Bool}|Config].
+ [{vxsim,Bool} | Config1].
end_per_testcase(_Case, _Config) ->
ok.
@@ -55,7 +57,7 @@ end_per_testcase(_Case, _Config) ->
framework_check(Config) when is_list(Config) ->
%%dbg:tracer(),
%%dbg:p(self()),
- P = runner:start(?framework_check),
+ P = runner:start(Config, ?framework_check),
runner:send_term(P,{hello,world}),
{term, {hello,world}} = runner:get_term(P),
runner:recv_eot(P),
@@ -71,7 +73,7 @@ ei_recv_tmo(Config) when is_list(Config) ->
do_one_recv(Config,CNode) ->
{_,Host} = split(node()),
- P1 = runner:start(?recv_tmo),
+ P1 = runner:start(Config, ?recv_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -84,7 +86,7 @@ do_one_recv(Config,CNode) ->
runner:recv_eot(P1).
do_one_recv_failure(Config,CNode) ->
- P1 = runner:start(?recv_tmo),
+ P1 = runner:start(Config, ?recv_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -110,7 +112,7 @@ ei_send_tmo(Config) when is_list(Config) ->
do_one_send(Config,From,CNode) ->
{_,Host} = split(node()),
- P1 = runner:start(?send_tmo),
+ P1 = runner:start(Config, ?send_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -139,7 +141,7 @@ do_one_send_failure(Config,From,FakeName,CName,VxSim) ->
exit(Else)
end,
EpmdSocket = register(OurName, LSocket, 1, 5),
- P3 = runner:start(?send_tmo),
+ P3 = runner:start(Config, ?send_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{CName,
Cookie,
@@ -202,7 +204,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
%dbg:p(self()),
VxSim = proplists:get_value(vxsim, Config),
DummyNode = make_and_check_dummy(),
- P = runner:start(?connect_tmo),
+ P = runner:start(Config, ?connect_tmo),
runner:send_term(P,{c_nod_connect_tmo_1,
kaksmula_som_ingen_bryr_sig_om,
DummyNode}),
@@ -219,7 +221,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
end
end,
runner:recv_eot(P),
- P2 = runner:start(?connect_tmo),
+ P2 = runner:start(Config, ?connect_tmo),
runner:send_term(P2,{c_nod_connect_tmo_2,
erlang:get_cookie(),
node()}),
@@ -237,7 +239,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
exit(Else)
end,
EpmdSocket = register(OurName, LSocket, 1, 5),
- P3 = runner:start(?connect_tmo),
+ P3 = runner:start(Config, ?connect_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{c_nod_connect_tmo_3,
Cookie,
@@ -266,12 +268,12 @@ ei_connect_tmo(Config) when is_list(Config) ->
ei_accept_tmo(Config) when is_list(Config) ->
%%dbg:tracer(),
%%dbg:p(self()),
- P = runner:start(?accept_tmo),
+ P = runner:start(Config, ?accept_tmo),
runner:send_term(P,{c_nod_som_ingen_kontaktar_1,
kaksmula_som_ingen_bryr_sig_om}),
{term,{-1,ETimedout,ETimedout}} = runner:get_term(P, 10000),
runner:recv_eot(P),
- P2 = runner:start(?accept_tmo),
+ P2 = runner:start(Config, ?accept_tmo),
runner:send_term(P2,{c_nod_som_vi_kontaktar_1,
erlang:get_cookie()}),
receive after 1000 -> ok end,
@@ -280,7 +282,7 @@ ei_accept_tmo(Config) when is_list(Config) ->
{term, X} = runner:get_term(P2, 10000),
runner:recv_eot(P2),
true = is_integer(X),
- P3 = runner:start(?accept_tmo),
+ P3 = runner:start(Config, ?accept_tmo),
runner:send_term(P3,{c_nod_som_vi_kontaktar_2,
erlang:get_cookie()}),
receive after 1000 -> ok end,
diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c
index 39846e4a58..693e405f75 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c
+++ b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c
@@ -96,6 +96,8 @@ TESTCASE(framework_check)
int i;
#endif
+ ei_init();
+
OPEN_DEBUGFILE(1);
DEBUGF(("B�rjar... \n"));
@@ -340,6 +342,7 @@ TESTCASE(recv_tmo)
int com_sock = -1;
ei_cnode nodeinfo;
+ ei_init();
OPEN_DEBUGFILE(5);
@@ -450,6 +453,7 @@ TESTCASE(send_tmo)
int com_sock = -1;
ei_cnode nodeinfo;
+ ei_init();
OPEN_DEBUGFILE(4);
@@ -591,7 +595,7 @@ TESTCASE(connect_tmo)
int com_sock = -1;
ei_cnode nodeinfo;
-
+ ei_init();
OPEN_DEBUGFILE(3);
@@ -680,7 +684,7 @@ TESTCASE(accept_tmo)
ErlConnect peer;
ei_cnode nodeinfo;
-
+ ei_init();
OPEN_DEBUGFILE(2);
diff --git a/lib/erl_interface/test/erl_call_SUITE.erl b/lib/erl_interface/test/erl_call_SUITE.erl
new file mode 100644
index 0000000000..9e2b2e4251
--- /dev/null
+++ b/lib/erl_interface/test/erl_call_SUITE.erl
@@ -0,0 +1,96 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(erl_call_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0, smoke/1]).
+
+all() ->
+ [smoke].
+
+smoke(Config) when is_list(Config) ->
+ ErlCall = find_erl_call(),
+ NameSwitch = case net_kernel:longnames() of
+ true ->
+ "-name";
+ false ->
+ "-sname"
+ end,
+ Name = atom_to_list(?MODULE)
+ ++ "-"
+ ++ integer_to_list(erlang:system_time(microsecond)),
+
+ ArgsList = ["-s", "-a", "erlang node", NameSwitch, Name],
+ io:format("erl_call: \"~ts\"\n~nargs list: ~p~n", [ErlCall, ArgsList]),
+ CmdRes = get_smoke_port_res(open_port({spawn_executable, ErlCall},
+ [{args, ArgsList}, eof]), []),
+ io:format("CmdRes: ~p~n", [CmdRes]),
+
+ [_, Hostname] = string:lexemes(atom_to_list(node()), "@"),
+ NodeName = list_to_atom(Name ++ "@" ++ Hostname),
+ io:format("NodeName: ~p~n~n", [NodeName]),
+
+ pong = net_adm:ping(NodeName),
+ rpc:cast(NodeName, erlang, halt, []),
+ NodeName = list_to_atom(string:trim(CmdRes, both, "'")),
+ ok.
+
+%
+% Utility functions...
+%
+
+find_erl_call() ->
+ ErlCallName = case os:type() of
+ {win32, _} -> "erl_call.exe";
+ _ -> "erl_call"
+ end,
+ LibDir = code:lib_dir(erl_interface),
+ InstalledErlCall = filename:join([LibDir, "bin", ErlCallName]),
+ TargetDir = erlang:system_info(system_architecture),
+ TargetErlCall = filename:join([LibDir, "bin", TargetDir, ErlCallName]),
+
+ try
+ lists:foreach(fun (F) ->
+ io:format("Checking: \"~ts\"~n", [F]),
+ case file:read_file_info(F) of
+ {ok, _} ->
+ throw(F);
+ _ ->
+ ok
+ end
+ end,
+ [InstalledErlCall, TargetErlCall]),
+ exit({missing, erl_call})
+ catch
+ throw:ErlCall ->
+ ErlCall
+ end.
+
+get_smoke_port_res(Port, Acc) when is_port(Port) ->
+ receive
+ {Port, {data, Data}} ->
+ get_smoke_port_res(Port, [Acc|Data]);
+ {Port, eof} ->
+ lists:flatten(Acc)
+ end.
+
diff --git a/lib/erl_interface/test/erl_connect_SUITE.erl b/lib/erl_interface/test/erl_connect_SUITE.erl
index cd73f07b8f..782691b8fb 100644
--- a/lib/erl_interface/test/erl_connect_SUITE.erl
+++ b/lib/erl_interface/test/erl_connect_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_connect_SUITE_data/erl_connect_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
erl_send/1, erl_reg_send/1,
erl_send_cookie_file/1]).
@@ -38,8 +39,11 @@ all() ->
[erl_send, erl_reg_send, erl_send_cookie_file].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
erl_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = erl_connect(P, node()),
@@ -56,7 +60,7 @@ erl_send_cookie_file(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, '', 0),
{ok,Fd} = erl_connect(P, node()),
@@ -70,7 +74,7 @@ erl_send_cookie_file(Config) when is_list(Config) ->
end.
erl_reg_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = erl_connect(P, node()),
diff --git a/lib/erl_interface/test/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl
index 3d1e33081b..77910a9fc7 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE.erl
+++ b/lib/erl_interface/test/erl_eterm_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([all/0, suite/0,
+ init_per_testcase/2,
build_terms/1, round_trip_conversion/1,
decode_terms/1, decode_float/1,
t_erl_mk_int/1, t_erl_mk_list/1,
@@ -94,6 +95,9 @@ all() ->
high_chaparal, broken_data, cnode_1].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% 1. B a s i c t e s t s
@@ -104,7 +108,7 @@ all() ->
%% a list and verifies that the result is as expected.
build_terms(Config) when is_list(Config) ->
- P = runner:start(?build_terms),
+ P = runner:start(Config, ?build_terms),
{term, Term} = get_term(P),
io:format("Received: ~p", [Term]),
[ARefLN, ARef, APortLN, APort, APidLN, APid,
@@ -136,7 +140,7 @@ build_terms(Config) when is_list(Config) ->
%% This test is run entirely in C code.
round_trip_conversion(Config) when is_list(Config) ->
- runner:test(?round_trip_conversion),
+ runner:test(Config, ?round_trip_conversion),
ok.
%% This test sends a list of all data types to the C code function,
@@ -156,7 +160,7 @@ decode_terms(Config) when is_list(Config) ->
{element1, 42, 767}, "A string",
1, -1, 0, 3.0, ABinary, 'I am an atom'],
- P = runner:start(?decode_terms),
+ P = runner:start(Config, ?decode_terms),
runner:send_term(P, Terms),
runner:recv_eot(P),
@@ -165,7 +169,7 @@ decode_terms(Config) when is_list(Config) ->
%% Decodes the floating point number 3.1415.
decode_float(Config) when is_list(Config) ->
- P = runner:start(?decode_float),
+ P = runner:start(Config, ?decode_float),
runner:send_term(P, 3.1415),
runner:recv_eot(P),
ok.
@@ -173,7 +177,7 @@ decode_float(Config) when is_list(Config) ->
%% Tests the erl_free_compound() function.
t_erl_free_compound(Config) when is_list(Config) ->
- runner:test(?t_erl_free_compound),
+ runner:test(Config, ?t_erl_free_compound),
ok.
@@ -186,7 +190,7 @@ t_erl_free_compound(Config) when is_list(Config) ->
%% This tests the erl_mk_list() function.
t_erl_mk_list(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_list),
+ P = runner:start(Config, ?t_erl_mk_list),
{term, []} = get_term(P),
{term, [abc]} = get_term(P),
@@ -200,7 +204,7 @@ t_erl_mk_list(Config) when is_list(Config) ->
%% This tests the erl_mk_int() function.
t_erl_mk_int(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_int),
+ P = runner:start(Config, ?t_erl_mk_int),
{term, 0} = get_term(P),
{term, 127} = get_term(P),
@@ -255,14 +259,14 @@ t_erl_mk_int(Config) when is_list(Config) ->
%% Basic test of erl_copy_term().
basic_copy(Config) when is_list(Config) ->
- runner:test(?basic_copy),
+ runner:test(Config, ?basic_copy),
ok.
%% This tests the erl_mk_tuple() function.
t_erl_mk_tuple(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_tuple),
+ P = runner:start(Config, ?t_erl_mk_tuple),
{term, {madonna, 21, 'mad donna', 12}} = get_term(P),
{term, {'Madonna',21,{children,{"Isabella",2}},
@@ -275,7 +279,7 @@ t_erl_mk_tuple(Config) when is_list(Config) ->
%% This tests the erl_mk_atom() function.
t_erl_mk_atom(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_atom),
+ P = runner:start(Config, ?t_erl_mk_atom),
{term, madonna} = (get_term(P)),
{term, 'Madonna'} = (get_term(P)),
@@ -295,7 +299,7 @@ t_erl_mk_atom(Config) when is_list(Config) ->
%% This tests the erl_mk_binary() function.
t_erl_mk_binary(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_binary),
+ P = runner:start(Config, ?t_erl_mk_binary),
{term, Bin} = (get_term(P)),
"{madonna,21,'mad donna',1234.567.890, !#$%&/()=?+-@, \" \\}" = binary_to_list(Bin),
@@ -307,7 +311,7 @@ t_erl_mk_binary(Config) when is_list(Config) ->
%% This tests the erl_mk_empty_list() function.
t_erl_mk_empty_list(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_empty_list),
+ P = runner:start(Config, ?t_erl_mk_empty_list),
{term, []} = get_term(P),
@@ -322,7 +326,7 @@ t_erl_mk_float(Config) when is_list(Config) ->
vxworks ->
{skipped, "Floating point numbers never compare equal on PPC"};
_ ->
- P = runner:start(?t_erl_mk_float),
+ P = runner:start(Config, ?t_erl_mk_float),
{term, {3.1415, 1.999999, 2.000000, 2.000001,
2.000002, 12345.67890}} = get_term(P),
runner:recv_eot(P),
@@ -333,7 +337,7 @@ t_erl_mk_float(Config) when is_list(Config) ->
%% This tests the erl_mk_pid() function.
t_erl_mk_pid(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_pid),
+ P = runner:start(Config, ?t_erl_mk_pid),
{term, A_pid} = (get_term(P)),
{pid, kalle@localhost, 3, 2} = nc2vinfo(A_pid),
@@ -342,7 +346,7 @@ t_erl_mk_pid(Config) when is_list(Config) ->
ok.
t_erl_mk_xpid(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_xpid),
+ P = runner:start(Config, ?t_erl_mk_xpid),
{term, A_pid} = (get_term(P)),
{pid, kalle@localhost, 32767, 8191} = nc2vinfo(A_pid),
@@ -354,7 +358,7 @@ t_erl_mk_xpid(Config) when is_list(Config) ->
%% This tests the erl_mk_port() function.
t_erl_mk_port(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_port),
+ P = runner:start(Config, ?t_erl_mk_port),
{term, A_port} = (get_term(P)),
{port, kalle@localhost, 4} = nc2vinfo(A_port),
@@ -363,7 +367,7 @@ t_erl_mk_port(Config) when is_list(Config) ->
ok.
t_erl_mk_xport(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_xport),
+ P = runner:start(Config, ?t_erl_mk_xport),
{term, A_port} = (get_term(P)),
{port, kalle@localhost, 268435455} = nc2vinfo(A_port),
@@ -375,7 +379,7 @@ t_erl_mk_xport(Config) when is_list(Config) ->
%% This tests the erl_mk_ref() function.
t_erl_mk_ref(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_ref),
+ P = runner:start(Config, ?t_erl_mk_ref),
{term, A_ref} = (get_term(P)),
{ref, kalle@localhost, _Length, [6]} = nc2vinfo(A_ref),
@@ -384,7 +388,7 @@ t_erl_mk_ref(Config) when is_list(Config) ->
ok.
t_erl_mk_long_ref(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_long_ref),
+ P = runner:start(Config, ?t_erl_mk_long_ref),
{term, A_ref} = (get_term(P)),
{ref, kalle@localhost, _Length, [4294967295,4294967295,262143]}
@@ -397,7 +401,7 @@ t_erl_mk_long_ref(Config) when is_list(Config) ->
%% This tests the erl_mk_string() function.
t_erl_mk_string(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_string),
+ P = runner:start(Config, ?t_erl_mk_string),
{term, "madonna"} = (get_term(P)),
{term, "Madonna"} = (get_term(P)),
@@ -417,7 +421,7 @@ t_erl_mk_string(Config) when is_list(Config) ->
%% This tests the erl_mk_estring() function.
t_erl_mk_estring(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_estring),
+ P = runner:start(Config, ?t_erl_mk_estring),
{term, "madonna"} = (get_term(P)),
{term, "Madonna"} = (get_term(P)),
@@ -437,7 +441,7 @@ t_erl_mk_estring(Config) when is_list(Config) ->
%% This tests the erl_mk_uint() function.
t_erl_mk_uint(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_uint),
+ P = runner:start(Config, ?t_erl_mk_uint),
{term, 54321} = (get_term(P)),
{term, 2147483647} = (get_term(P)),
@@ -453,7 +457,7 @@ t_erl_mk_uint(Config) when is_list(Config) ->
%% This tests the erl_mk_var() function.
t_erl_mk_var(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_var),
+ P = runner:start(Config, ?t_erl_mk_var),
{term, 1} = (get_term(P)),
{term, 0} = (get_term(P)),
@@ -470,7 +474,7 @@ t_erl_mk_var(Config) when is_list(Config) ->
%% This tests the erl_cons() function.
t_erl_cons(Config) when is_list(Config) ->
- P = runner:start(?t_erl_cons),
+ P = runner:start(Config, ?t_erl_cons),
{term, [madonna, 21]} = get_term(P),
@@ -490,7 +494,7 @@ t_erl_cons(Config) when is_list(Config) ->
%% Tests the erl_length() function.
t_erl_length(Config) when is_list(Config) ->
- P = runner:start(?t_erl_length),
+ P = runner:start(Config, ?t_erl_length),
0 = erl_length(P, []),
1 = erl_length(P, [a]),
@@ -513,7 +517,7 @@ erl_length(Port, List) ->
%% Tests the erl_hd() function.
t_erl_hd(Config) when is_list(Config) ->
- P = runner:start(?t_erl_hd),
+ P = runner:start(Config, ?t_erl_hd),
'NULL' = erl_hd(P, 42),
'NULL' = erl_hd(P, abc),
@@ -537,7 +541,7 @@ erl_hd(Port, List) ->
%% Tests the erl_tail() function.
t_erl_tl(Config) when is_list(Config) ->
- P = runner:start(?t_erl_tl),
+ P = runner:start(Config, ?t_erl_tl),
'NULL' = erl_tl(P, 42),
'NULL' = erl_tl(P, abc),
@@ -561,20 +565,20 @@ erl_tl(Port, List) ->
%% Tests the type checking macros (done in the C program).
type_checks(Config) when is_list(Config) ->
- runner:test(?type_checks),
+ runner:test(Config, ?type_checks),
ok.
%% Tests the extractor macros (done in the C program).
extractor_macros(Config) when is_list(Config) ->
- runner:test(?extractor_macros),
+ runner:test(Config, ?extractor_macros),
ok.
%% This tests the erl_size() function.
t_erl_size(Config) when is_list(Config) ->
- P = runner:start(?t_erl_size),
+ P = runner:start(Config, ?t_erl_size),
{term, 0} = (get_term(P)),
{term, 4} = (get_term(P)),
@@ -589,7 +593,7 @@ t_erl_size(Config) when is_list(Config) ->
%% This tests the erl_var_content() function.
t_erl_var_content(Config) when is_list(Config) ->
- P = runner:start(?t_erl_var_content),
+ P = runner:start(Config, ?t_erl_var_content),
{term, 17} = (get_term(P)),
{term, "http://www.madonna.com"} = (get_term(P)),
@@ -604,7 +608,7 @@ t_erl_var_content(Config) when is_list(Config) ->
%% This tests the erl_element() function.
t_erl_element(Config) when is_list(Config) ->
- P = runner:start(?t_erl_element),
+ P = runner:start(Config, ?t_erl_element),
{term, madonna} = get_term(P),
{term, 21} = get_term(P),
@@ -630,7 +634,7 @@ t_erl_element(Config) when is_list(Config) ->
%% Tests the erl_iolist_length() function.
t_erl_iolist_length(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_length),
+ P = runner:start(Config, ?t_erl_iolist_length),
%% Flat lists.
@@ -697,7 +701,7 @@ erl_iolist_length(Port, List) ->
%% Tests the erl_iolist_to_binary() function.
t_erl_iolist_to_binary(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_to_binary),
+ P = runner:start(Config, ?t_erl_iolist_to_binary),
%% Flat lists.
@@ -768,7 +772,7 @@ iolist_to_list(Port, Term) ->
%% Tests the erl_iolist_to_string() function.
t_erl_iolist_to_string(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_to_string),
+ P = runner:start(Config, ?t_erl_iolist_to_string),
%% Flat lists.
@@ -947,14 +951,14 @@ collect_line1([C|Rest], Result) ->
%% Test case submitted by Per Lundgren, ERV.
high_chaparal(Config) when is_list(Config) ->
- P = runner:start(?high_chaparal),
+ P = runner:start(Config, ?high_chaparal),
{term, [hello, world]} = get_term(P),
runner:recv_eot(P),
ok.
%% OTP-7448
broken_data(Config) when is_list(Config) ->
- P = runner:start(?broken_data),
+ P = runner:start(Config, ?broken_data),
runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c b/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c
index bead0f8413..b87feb9dfc 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c
+++ b/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c
@@ -20,7 +20,7 @@
#include <stdlib.h>
#include <stdio.h>
-
+#include <string.h>
#include "ei.h"
#include "erl_interface.h"
@@ -68,6 +68,7 @@ MAIN(int argc, char **argv)
char host[80];
int number;
ETERM *ref, *ref1, *ref2;
+ FILE *dfile = fopen("cnode_debug_printout", "w");
erl_init(NULL, 0);
@@ -80,28 +81,30 @@ MAIN(int argc, char **argv)
gethostname(host, sizeof(host));
sprintf(node, "c%d@%s", number, host);
- printf("s = %d\n", s);
+ fprintf(dfile, "s = %d\n", s); fflush(dfile);
sprintf(server, "test_server@%s", host);
fd = erl_connect(server);
- printf("fd = %d\n", fd);
+ fprintf(dfile, "fd = %d\n", fd);
-/* printf("dist = %d\n", erl_distversion(fd)); */
+/* fprintf(dfile, "dist = %d\n", erl_distversion(fd)); */
#if 1
ref = erl_mk_long_ref(node, 4711, 113, 98, 0);
#else
ref = erl_mk_ref(node, 4711, 0);
#endif
- printf("ref = %d\n", ref);
+ fprintf(dfile, "ref = %p\n", ref); fflush(dfile);
s = erl_reg_send(fd, "mip", ref);
- printf("s = %d\n", s);
+ fprintf(dfile, "s = %d\n", s); fflush(dfile);
{
ETERM* emsg;
emsg = SELF(fd);
- erl_reg_send(fd,"mip",emsg);
+ fprintf(dfile, "pid = %p\n", emsg); fflush(dfile);
+ s = erl_reg_send(fd,"mip",emsg);
+ fprintf(dfile, "s2 = %d\n", s); fflush(dfile);
erl_free_term(emsg);
}
@@ -116,28 +119,29 @@ MAIN(int argc, char **argv)
#endif
switch (s) {
case ERL_TICK:
- printf("tick\n");
+ fprintf(dfile, "tick\n");
break;
case ERL_ERROR:
- printf("error\n");
+ fprintf(dfile, "error: %s (%d)\n", strerror(erl_errno), erl_errno);
break;
case ERL_MSG:
- printf("msg %d\n", msgsize);
+ fprintf(dfile, "msg %d\n", msgsize);
break;
default:
- printf("unknown result %d\n", s);
+ fprintf(dfile, "unknown result %d\n", s);
break;
}
+ fflush(dfile);
} while (s == ERL_TICK);
s = erl_reg_send(fd, "mip", msg.msg);
- printf("s = %d\n", s);
+ fprintf(dfile, "s = %d\n", s); fflush(dfile);
s = erl_reg_send(fd, "mip", msg.to);
- printf("s = %d\n", s);
+ fprintf(dfile, "s = %d\n", s); fflush(dfile);
#if 0
/* from = NULL! */
s = erl_reg_send(fd, "mip", msg.from);
- printf("s = %d\n", s);
+ fprintf(dfile, "s = %d\n", s); fflush(dfile);
#endif
#if 0
@@ -150,17 +154,19 @@ MAIN(int argc, char **argv)
ref1 = erl_mk_long_ref(node, 4711, 113, 98, 0);
ref2 = erl_mk_ref(node, 4711, 0);
s = erl_encode(ref1, buf1);
- printf("enc1 s = %d\n", s);
+ fprintf(dfile, "enc1 s = %d\n", s); fflush(dfile);
s = erl_encode(ref2, buf2);
- printf("enc2 s = %d\n", s);
+ fprintf(dfile, "enc2 s = %d\n", s); fflush(dfile);
s = erl_compare_ext(buf1, buf2);
- printf("comp s = %d\n", s);
+ fprintf(dfile, "comp s = %d\n", s); fflush(dfile);
/* Compare, in another way */
s = erl_match(ref1, ref2);
- printf("match s = %d\n", s);
+ fprintf(dfile, "match s = %d\n", s); fflush(dfile);
#endif
+ fclose(dfile);
+
erl_close_connection(fd);
return 0;
diff --git a/lib/erl_interface/test/erl_ext_SUITE.erl b/lib/erl_interface/test/erl_ext_SUITE.erl
index afaba1fd93..ff3b495f7b 100644
--- a/lib/erl_interface/test/erl_ext_SUITE.erl
+++ b/lib/erl_interface/test/erl_ext_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_ext_SUITE_data/ext_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
compare_tuple/1,
compare_list/1,
compare_string/1,
@@ -40,28 +41,30 @@ all() ->
[compare_tuple, compare_list, compare_string,
compare_list_string, compare_nc_ext].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
compare_tuple(Config) when is_list(Config) ->
- P = runner:start(?compare_tuple),
+ P = runner:start(Config, ?compare_tuple),
runner:recv_eot(P),
ok.
compare_list(Config) when is_list(Config) ->
- P = runner:start(?compare_list),
+ P = runner:start(Config, ?compare_list),
runner:recv_eot(P),
ok.
compare_string(Config) when is_list(Config) ->
- P = runner:start(?compare_string),
+ P = runner:start(Config, ?compare_string),
runner:recv_eot(P),
ok.
compare_list_string(Config) when is_list(Config) ->
- P = runner:start(?compare_list_string),
+ P = runner:start(Config, ?compare_list_string),
runner:recv_eot(P),
ok.
compare_nc_ext(Config) when is_list(Config) ->
- P = runner:start(?compare_nc_ext),
+ P = runner:start(Config, ?compare_nc_ext),
runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
index 1e986feacf..6b47c3e510 100644
--- a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
+++ b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,6 +88,11 @@ TESTCASE(compare_list) {
// erlang:term_to_binary([0, 1000])
unsigned char term4[] = {131,108,0,0,0,2,97,0,98,0,0,3,232,106};
+ // erlang:term_to_binary([a|b])
+ unsigned char term5a[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,98};
+ // erlang:term_to_binary([a|c])
+ unsigned char term5b[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,99};
+
erl_init(NULL, 0);
start_a = term1;
start_b = term2;
@@ -103,6 +108,13 @@ TESTCASE(compare_list) {
test_compare_ext("lists1", start_a, end_a, start_b, end_b, -1);
+ start_a = term5a;
+ start_b = term5b;
+ end_a = term5a + sizeof(term5a);
+ end_b = term5b + sizeof(term5b);
+
+ test_compare_ext("lists5", start_a, end_a, start_b, end_b, -1);
+
report(1);
}
diff --git a/lib/erl_interface/test/erl_format_SUITE.erl b/lib/erl_interface/test/erl_format_SUITE.erl
index c1a7d8377e..69dfdcc4c8 100644
--- a/lib/erl_interface/test/erl_format_SUITE.erl
+++ b/lib/erl_interface/test/erl_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_format_SUITE_data/format_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, tuples/1, lists/1]).
-import(runner, [get_term/1]).
@@ -38,10 +39,13 @@ suite() ->
all() ->
[atoms, tuples, lists].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, ''} = get_term(P),
{term, 'a'} = get_term(P),
@@ -79,7 +83,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, {}} = get_term(P),
{term, {a}} = get_term(P),
@@ -100,7 +104,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, []} = get_term(P),
{term, [a]} = get_term(P),
diff --git a/lib/erl_interface/test/erl_global_SUITE.erl b/lib/erl_interface/test/erl_global_SUITE.erl
index ecc6753c7f..6d3a75c8d7 100644
--- a/lib/erl_interface/test/erl_global_SUITE.erl
+++ b/lib/erl_interface/test/erl_global_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_global_SUITE_data/erl_global_test_cases.hrl").
-export([all/0,suite/0,
+ init_per_testcase/2,
erl_global_registration/1,
erl_global_whereis/1, erl_global_names/1]).
@@ -39,9 +40,11 @@ suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {seconds, 30}}].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
erl_global_registration(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
ok = erl_global_register(P, Fd, ?GLOBAL_NAME),
@@ -53,7 +56,7 @@ erl_global_registration(Config) when is_list(Config) ->
ok.
erl_global_whereis(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
Self = self(),
@@ -66,7 +69,7 @@ erl_global_whereis(Config) when is_list(Config) ->
ok.
erl_global_names(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
Self = self(),
diff --git a/lib/erl_interface/test/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl
index 5566714092..bb62d6288d 100644
--- a/lib/erl_interface/test/erl_match_SUITE.erl
+++ b/lib/erl_interface/test/erl_match_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_match_SUITE_data/match_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, lists/1, tuples/1, references/1, pids/1, ports/1,
bind/1, integers/1, floats/1, binaries/1, strings/1]).
@@ -40,6 +41,8 @@ all() ->
[atoms, lists, tuples, references, pids, ports, bind,
integers, floats, binaries, strings].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
atoms(Config) when is_list(Config) ->
P = start_matcher(Config),
@@ -239,7 +242,7 @@ bind(Config) when is_list(Config) ->
ok.
start_bind(Config) ->
- runner:start(?erl_match_bind).
+ runner:start(Config, ?erl_match_bind).
bind_ok(Port, Bind, Term) ->
true = erl_bind(Port, Bind, Term).
@@ -258,7 +261,7 @@ erl_bind(Port, Pattern, Term) ->
start_matcher(Config) ->
- runner:start(?erl_match_server).
+ runner:start(Config, ?erl_match_server).
eq(Port, Pattern, Term) ->
true = erl_match(Port, Pattern, Term).
diff --git a/lib/erl_interface/test/port_call_SUITE.erl b/lib/erl_interface/test/port_call_SUITE.erl
index fb10bd895f..5c4f5f3cee 100644
--- a/lib/erl_interface/test/port_call_SUITE.erl
+++ b/lib/erl_interface/test/port_call_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,9 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export([all/0, suite/0, basic/1]).
+-export([all/0, suite/0,
+ init_per_testcase/2,
+ basic/1]).
% Private exports
-include_lib("common_test/include/ct.hrl").
@@ -44,6 +46,8 @@ suite() ->
all() ->
[basic].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
basic(Config) when is_list(Config) ->
case os:type() of
diff --git a/lib/erl_interface/test/runner.erl b/lib/erl_interface/test/runner.erl
index 947e56c4e0..484890006e 100644
--- a/lib/erl_interface/test/runner.erl
+++ b/lib/erl_interface/test/runner.erl
@@ -21,8 +21,9 @@
%%
-module(runner).
--export([test/1, test/2,
- start/1, send_term/2, finish/1, send_eot/1, recv_eot/1,
+-export([test/2, test/3,
+ init_per_testcase/3,
+ start/2, send_term/2, finish/1, send_eot/1, recv_eot/1,
get_term/1, get_term/2]).
-define(default_timeout, 5000).
@@ -32,11 +33,11 @@
%% This function is useful for test cases written in C which requires
%% no further input, and only returns a result by calling report().
-test(Tc) ->
- test(Tc, ?default_timeout).
+test(Config, Tc) ->
+ test(Config, Tc, ?default_timeout).
-test(Tc, Timeout) ->
- Port = start(Tc),
+test(Config, Tc, Timeout) ->
+ Port = start(Config, Tc),
case get_term(Port, Timeout) of
eot ->
@@ -54,12 +55,51 @@ test(Tc, Timeout) ->
%%
%% Returns: {ok, Port}
-start({Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
- Port = open_port({spawn, Prog}, [{packet, 4}, exit_status]),
+start(Config, {Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
+ Port = open_port({spawn, prog_cmd(Config, Prog)},
+ [{packet, 4}, exit_status]),
Command = [Tc div 256, Tc rem 256],
Port ! {self(), {command, Command}},
Port.
+prog_cmd(Config, Prog) ->
+ case proplists:get_value(valgrind_cmd_fun, Config) of
+ undefined ->
+ Prog;
+ Fun when is_function(Fun) ->
+ Fun(Prog)
+ end.
+
+init_per_testcase(Suite, Case, Config) ->
+ case os:getenv("VALGRIND_LOG_DIR") of
+ false ->
+ Config;
+ LogDir ->
+ Valgrind = case os:find_executable("valgrind") of
+ false ->
+ ct:fail("VALGRIND_LOG_DIR set, "
+ "but no valgrind executable found");
+ VG -> VG
+ end,
+
+ LogFileOpt = case os:getenv("VALGRIND_LOG_XML") of
+ false ->
+ " --log-file=";
+ "yes" ->
+ " --xml=yes --xml-file="
+ end,
+ Fun = fun(Prog) ->
+ LogFile = io_lib:format("erl_interface-~w.~w-~s.log.%p",
+ [Suite, Case, filename:basename(Prog)]),
+ Valgrind
+ ++ LogFileOpt ++ filename:join(LogDir,LogFile)
+ ++ " " ++ os:getenv("VALGRIND_MISC_FLAGS","")
+ ++ " " ++ Prog
+ end,
+ [{valgrind_cmd_fun, Fun} | Config]
+ end.
+
+
%% Finishes a test case by send an 'eot' message to the C program
%% and waiting for an 'eot'.
%%
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 586b23c5b3..4e31b3835d 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 3.10.3
+EI_VSN = 3.11.3
ERL_INTERFACE_VSN = $(EI_VSN)
diff --git a/lib/et/doc/src/Makefile b/lib/et/doc/src/Makefile
index 4758559220..93e2f8eeee 100644
--- a/lib/et/doc/src/Makefile
+++ b/lib/et/doc/src/Makefile
@@ -85,6 +85,7 @@ clean clean_docs:
fi \
done
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/et/doc/src/et.xml b/lib/et/doc/src/et.xml
index 3009b559e1..a362d00b3e 100644
--- a/lib/et/doc/src/et.xml
+++ b/lib/et/doc/src/et.xml
@@ -32,14 +32,14 @@
<rev>%VSN%</rev>
<file>et</file>
</header>
- <module>et</module>
+ <module since="">et</module>
<modulesummary>Main API of the Event Trace (ET) application</modulesummary>
<description>
<p>Interface module for the Event Trace (ET) application</p>
</description>
<funcs>
<func>
- <name>trace_me(DetailLevel, From, To, Label, Contents) -> hopefully_traced</name>
+ <name since="OTP R13B04">trace_me(DetailLevel, From, To, Label, Contents) -> hopefully_traced</name>
<fsummary>A function that is intended to be traced.</fsummary>
<type>
<v>DetailLevel = integer(X) when X =&lt; 0, X >= 100</v>
@@ -70,7 +70,7 @@
</func>
<func>
- <name>trace_me(DetailLevel, FromTo, Label, Contents) -> hopefully_traced</name>
+ <name since="OTP R13B04">trace_me(DetailLevel, FromTo, Label, Contents) -> hopefully_traced</name>
<fsummary>A function that is intended to be traced.</fsummary>
<desc>
<p>Invokes <c>et:trace_me/5</c> with both <c>From</c> and <c>To</c>
@@ -79,8 +79,8 @@
</func>
<func>
- <name>phone_home(DetailLevel, FromTo, Label, Contents) -> hopefully_traced</name>
- <name>phone_home(DetailLevel, From, To, Label, Contents) -> hopefully_traced</name>
+ <name since="">phone_home(DetailLevel, FromTo, Label, Contents) -> hopefully_traced</name>
+ <name since="">phone_home(DetailLevel, From, To, Label, Contents) -> hopefully_traced</name>
<fsummary>Send a signal to the outer space</fsummary>
<desc>
<p>These functions sends a signal to the outer space and the
@@ -90,8 +90,8 @@
</desc>
</func>
<func>
- <name>report_event(DetailLevel, FromTo, Label, Contents) -> hopefully_traced</name>
- <name>report_event(DetailLevel, From, To, Label, Contents) -> hopefully_traced</name>
+ <name since="">report_event(DetailLevel, FromTo, Label, Contents) -> hopefully_traced</name>
+ <name since="">report_event(DetailLevel, From, To, Label, Contents) -> hopefully_traced</name>
<fsummary>Deprecated functions</fsummary>
<desc>
<p>Deprecated functions which for the time being are kept for
diff --git a/lib/et/doc/src/et_collector.xml b/lib/et/doc/src/et_collector.xml
index 6a85b81ec2..f908612797 100644
--- a/lib/et/doc/src/et_collector.xml
+++ b/lib/et/doc/src/et_collector.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,21 +32,22 @@
<rev>%VSN%</rev>
<file>et_collector.xml</file>
</header>
- <module>et_collector</module>
+ <module since="">et_collector</module>
<modulesummary>Collect trace events and provide a backing storage appropriate for iteration </modulesummary>
<description>
<p>Interface module for the Event Trace (ET) application</p>
</description>
<funcs>
<func>
- <name>start_link(Options) -> {ok, CollectorPid} | {error, Reason}</name>
+ <name since="">start_link(Options) -> {ok, CollectorPid} | {error, Reason}</name>
<fsummary>Start a collector process</fsummary>
<type>
<v>Options = [option()]</v>
<v>option() = {parent_pid, pid()} | {event_order, event_order()} | {dict_insert, {filter, collector}, collector_fun()} | {dict_insert, {filter, event_filter_name()}, event_filter_fun()} | {dict_insert, {subscriber, pid()}, dict_val()} | {dict_insert, dict_key(), dict_val()} | {dict_delete, dict_key()} | {trace_client, trace_client()} | {trace_global, boolean()} | {trace_pattern, trace_pattern()} | {trace_port, integer()} | {trace_max_queue, integer()}</v>
<v>event_order() = trace_ts | event_ts</v>
<v>trace_pattern() = {report_module(), extended_dbg_match_spec()} | undefined</v>
- <v>report_module() = atom() | undefined &lt;v>extended_dbg_match_spec()() = detail_level() | dbg_match_spec()</v>
+ <v>report_module() = atom() | undefined</v>
+ <v>extended_dbg_match_spec() = detail_level() | dbg_match_spec()</v>
<v>detail_level() = min | max | integer(X) when X =&lt; 0, X >= 100</v>
<v>trace_client() = {event_file, file_name()} | {dbg_trace_type(), dbg_trace_parameters()}</v>
<v>file_name() = string()</v>
@@ -104,7 +105,7 @@
</desc>
</func>
<func>
- <name>stop(CollectorPid) -> ok</name>
+ <name since="">stop(CollectorPid) -> ok</name>
<fsummary>Stop a collector process</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -114,7 +115,7 @@
</desc>
</func>
<func>
- <name>save_event_file(CollectorPid, FileName, Options) -> ok | {error, Reason}</name>
+ <name since="">save_event_file(CollectorPid, FileName, Options) -> ok | {error, Reason}</name>
<fsummary>Save the events to a file</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -138,7 +139,7 @@
</desc>
</func>
<func>
- <name>load_event_file(CollectorPid, FileName) -> {ok, BadBytes} | exit(Reason)</name>
+ <name since="">load_event_file(CollectorPid, FileName) -> {ok, BadBytes} | exit(Reason)</name>
<fsummary>Load the event table from a file</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -151,9 +152,9 @@
</desc>
</func>
<func>
- <name>report(Handle, TraceOrEvent) -> {ok, Continuation} | exit(Reason)</name>
- <name>report_event(Handle, DetailLevel, FromTo, Label, Contents) -> {ok, Continuation} | exit(Reason)</name>
- <name>report_event(Handle, DetailLevel, From, To, Label, Contents) -> {ok, Continuation} | exit(Reason)</name>
+ <name since="">report(Handle, TraceOrEvent) -> {ok, Continuation} | exit(Reason)</name>
+ <name since="">report_event(Handle, DetailLevel, FromTo, Label, Contents) -> {ok, Continuation} | exit(Reason)</name>
+ <name since="">report_event(Handle, DetailLevel, From, To, Label, Contents) -> {ok, Continuation} | exit(Reason)</name>
<fsummary>Report an event to the collector</fsummary>
<type>
<v>Handle = Initial | Continuation</v>
@@ -180,7 +181,7 @@
</desc>
</func>
<func>
- <name>make_key(Type, Stuff) -> Key</name>
+ <name since="">make_key(Type, Stuff) -> Key</name>
<fsummary>Make a key out of an event record or an old key</fsummary>
<type>
<v>Type = record(table_handle) | trace_ts | event_ts</v>
@@ -192,7 +193,7 @@
</desc>
</func>
<func>
- <name>get_table_handle(CollectorPid) -> Handle</name>
+ <name since="">get_table_handle(CollectorPid) -> Handle</name>
<fsummary>Return a table handle</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -203,7 +204,7 @@
</desc>
</func>
<func>
- <name>get_global_pid() -> CollectorPid | exit(Reason)</name>
+ <name since="">get_global_pid() -> CollectorPid | exit(Reason)</name>
<fsummary>Return a the identity of the globally registered collector if there is any</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -215,13 +216,13 @@
</desc>
</func>
<func>
- <name>change_pattern(CollectorPid, RawPattern) -> {old_pattern, TracePattern}</name>
+ <name since="">change_pattern(CollectorPid, RawPattern) -> {old_pattern, TracePattern}</name>
<fsummary>Change active trace pattern globally on all trace nodes</fsummary>
<type>
<v>CollectorPid = pid()</v>
<v>RawPattern = {report_module(), extended_dbg_match_spec()}</v>
<v>report_module() = atom() | undefined</v>
- <v>extended_dbg_match_spec()() = detail_level() | dbg_match_spec()</v>
+ <v>extended_dbg_match_spec() = detail_level() | dbg_match_spec()</v>
<v>RawPattern = detail_level()</v>
<v>detail_level() = min | max | integer(X) when X =&lt; 0, X >= 100</v>
<v>TracePattern = {report_module(), dbg_match_spec_match_spec()}</v>
@@ -231,9 +232,9 @@
</desc>
</func>
<func>
- <name>dict_insert(CollectorPid, {filter, collector}, FilterFun) -> ok</name>
- <name>dict_insert(CollectorPid, {subscriber, SubscriberPid}, Void) -> ok</name>
- <name>dict_insert(CollectorPid, Key, Val) -> ok</name>
+ <name since="">dict_insert(CollectorPid, {filter, collector}, FilterFun) -> ok</name>
+ <name since="">dict_insert(CollectorPid, {subscriber, SubscriberPid}, Void) -> ok</name>
+ <name since="">dict_insert(CollectorPid, Key, Val) -> ok</name>
<fsummary>Insert a dictionary entry and send a {et, {dict_insert, Key, Val}} tuple to all registered subscribers.</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -258,7 +259,7 @@
</desc>
</func>
<func>
- <name>dict_lookup(CollectorPid, Key) -> [Val]</name>
+ <name since="">dict_lookup(CollectorPid, Key) -> [Val]</name>
<fsummary>Lookup a dictionary entry and return zero or one value</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -272,7 +273,7 @@
</desc>
</func>
<func>
- <name>dict_delete(CollectorPid, Key) -> ok</name>
+ <name since="">dict_delete(CollectorPid, Key) -> ok</name>
<fsummary>Delete a dictionary entry and send a {et, {dict_delete, Key}} tuple to all registered subscribers.</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -289,7 +290,7 @@
</desc>
</func>
<func>
- <name>dict_match(CollectorPid, Pattern) -> [Match]</name>
+ <name since="">dict_match(CollectorPid, Pattern) -> [Match]</name>
<fsummary>Match some dictionary entries</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -305,7 +306,7 @@
</desc>
</func>
<func>
- <name>multicast(_CollectorPid, Msg) -> ok</name>
+ <name since="">multicast(_CollectorPid, Msg) -> ok</name>
<fsummary>Sends a message to all registered subscribers</fsummary>
<type>
<v>CollectorPid = pid()</v>
@@ -317,7 +318,7 @@
</desc>
</func>
<func>
- <name>start_trace_client(CollectorPid, Type, Parameters) -> file_loaded | {trace_client_pid, pid()} | exit(Reason)</name>
+ <name since="">start_trace_client(CollectorPid, Type, Parameters) -> file_loaded | {trace_client_pid, pid()} | exit(Reason)</name>
<fsummary>Load raw Erlang trace from a file, port or process.</fsummary>
<type>
<v>Type = dbg_trace_client_type()</v>
@@ -329,14 +330,14 @@
</desc>
</func>
<func>
- <name>iterate(Handle, Prev, Limit) -> NewAcc</name>
+ <name since="">iterate(Handle, Prev, Limit) -> NewAcc</name>
<fsummary>Iterates over the currently stored events</fsummary>
<desc>
<p>Short for iterate(Handle, Prev, Limit, undefined, Prev) -&gt; NewAcc</p>
</desc>
</func>
<func>
- <name>iterate(Handle, Prev, Limit, Fun, Acc) -> NewAcc</name>
+ <name since="">iterate(Handle, Prev, Limit, Fun, Acc) -> NewAcc</name>
<fsummary>Iterate over the currently stored events</fsummary>
<type>
<v>Handle = collector_pid() | table_handle()</v>
@@ -348,7 +349,8 @@
<v>done() = 0</v>
<v>forward() = infinity | integer(X) where X > 0</v>
<v>backward() = '-infinity' | integer(X) where X &lt; 0</v>
- <v>Fun = fun(Event, Acc) -> NewAcc &lt;v>Acc = NewAcc = term()</v>
+ <v>Fun = fun(Event, Acc) -> NewAcc</v>
+ <v>Acc = NewAcc = term()</v>
</type>
<desc>
<p>Iterate over the currently stored events.</p>
@@ -359,7 +361,7 @@
</desc>
</func>
<func>
- <name>clear_table(Handle) -> ok</name>
+ <name since="">clear_table(Handle) -> ok</name>
<fsummary>Clear the event table</fsummary>
<type>
<v>Handle = collector_pid() | table_handle()</v>
diff --git a/lib/et/doc/src/et_selector.xml b/lib/et/doc/src/et_selector.xml
index 441a4dd278..3c766cafb7 100644
--- a/lib/et/doc/src/et_selector.xml
+++ b/lib/et/doc/src/et_selector.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>et_selector.xml</file>
</header>
- <module>et_selector</module>
+ <module since="">et_selector</module>
<modulesummary>Define event transforms and trace patterns</modulesummary>
<description>
<p></p>
@@ -40,7 +40,7 @@
<funcs>
<func>
- <name>make_pattern(RawPattern) -> TracePattern</name>
+ <name since="">make_pattern(RawPattern) -> TracePattern</name>
<fsummary>Makes a trace pattern suitable to feed change_pattern/1</fsummary>
<type>
@@ -61,7 +61,7 @@
</func>
<func>
- <name>change_pattern(Pattern) -> ok</name>
+ <name since="">change_pattern(Pattern) -> ok</name>
<fsummary>Activates/deactivates tracing by changing the current trace pattern</fsummary>
@@ -85,12 +85,14 @@
</desc>
</func>
<func>
- <name>parse_event(Mod, ValidTraceData) -> false | true | {true, Event}</name>
+ <name since="">parse_event(Mod, ValidTraceData) -> false | true | {true, Event}</name>
<fsummary>Transforms trace data and makes an event record out of it</fsummary>
<type>
- <v>Mod = module_name() | undefined &lt;v>module_name() = atom() &lt;v>ValidTraceData = erlang_trace_data() | record(event)</v>
+ <v>Mod = module_name() | undefined</v>
+ <v>module_name() = atom()</v>
+ <v>ValidTraceData = erlang_trace_data() | record(event)</v>
<v>erlang_trace_data() = {trace, Pid, Label, Info} | {trace, Pid, Label, Info, Extra} | {trace_ts, Pid, Label, Info, ReportedTS} | {trace_ts, Pid, Label, Info, Extra, ReportedTS} | {seq_trace, Label, Info} | {seq_trace, Label, Info, ReportedTS} | {drop, NumberOfDroppedItems}</v>
</type>
diff --git a/lib/et/doc/src/et_viewer.xml b/lib/et/doc/src/et_viewer.xml
index e0b39636e9..9d59eef668 100644
--- a/lib/et/doc/src/et_viewer.xml
+++ b/lib/et/doc/src/et_viewer.xml
@@ -32,14 +32,14 @@
<rev>%VSN%</rev>
<file>et_viewer.xml</file>
</header>
- <module>et_viewer</module>
+ <module since="">et_viewer</module>
<modulesummary>Displays a sequence chart for trace events (messages/actions)</modulesummary>
<description>
<p></p>
</description>
<funcs>
<func>
- <name>file(FileName) -> {ok, ViewerPid} | {error, Reason}</name>
+ <name since="">file(FileName) -> {ok, ViewerPid} | {error, Reason}</name>
<fsummary>Start a new event viewer and a corresponding collector and load them with trace events from a trace file.</fsummary>
<type>
<v>FileName() = string()</v>
@@ -52,7 +52,7 @@
</desc>
</func>
<func>
- <name>start() -> ok</name>
+ <name since="">start() -> ok</name>
<fsummary>Simplified start of a sequence chart viewer with global tracing activated.</fsummary>
<desc>
<p>Simplified start of a sequence chart viewer with
@@ -62,7 +62,7 @@
</desc>
</func>
<func>
- <name>start(Options) -> ok</name>
+ <name since="">start(Options) -> ok</name>
<fsummary>Start of a sequence chart viewer without linking to the parent process.</fsummary>
<desc>
<p>Start of a sequence chart viewer without linking
@@ -70,7 +70,7 @@
</desc>
</func>
<func>
- <name>start_link(Options) -> {ok, ViewerPid} | {error, Reason}</name>
+ <name since="">start_link(Options) -> {ok, ViewerPid} | {error, Reason}</name>
<fsummary>Start a sequence chart viewer for trace events (messages/actions)</fsummary>
<type>
<v>Options = [option() | collector_option()]</v>
@@ -125,7 +125,7 @@
</desc>
</func>
<func>
- <name>get_collector_pid(ViewerPid) -> CollectorPid</name>
+ <name since="">get_collector_pid(ViewerPid) -> CollectorPid</name>
<fsummary>Returns the identifier of the collector process</fsummary>
<type>
<v>ViewerPid = pid()</v>
@@ -136,7 +136,7 @@
</desc>
</func>
<func>
- <name>stop(ViewerPid) -> ok</name>
+ <name since="">stop(ViewerPid) -> ok</name>
<fsummary>Stops a viewer</fsummary>
<type>
<v>ViewerPid = pid()</v>
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index e7cec937b3..e144defb69 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -37,6 +37,38 @@
one section in this document. The title of each section is the
version number of <c>Event Tracer (ET)</c>.</p>
+<section><title>ET 1.6.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The scroll bar of the et_viewer window could not be
+ dragged all the way to the top of the window. It would
+ always stop at the second event. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15463 Aux Id: ERL-780 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ET 1.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.6.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index ffe244324c..3609238509 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -509,7 +509,7 @@ get_global_pid() ->
%% CollectorPid = pid()
%% RawPattern = {report_module(), extended_dbg_match_spec()}
%% report_module() = atom() | undefined
-%% extended_dbg_match_spec()() = detail_level() | dbg_match_spec()
+%% extended_dbg_match_spec() = detail_level() | dbg_match_spec()
%% RawPattern = detail_level()
%% detail_level() = min | max | integer(X) when X =< 0, X >= 100
%% TracePattern = {report_module(), dbg_match_spec_match_spec()}
diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl
index 4dd44e7a4c..041527fec4 100644
--- a/lib/et/src/et_wx_viewer.erl
+++ b/lib/et/src/et_wx_viewer.erl
@@ -793,8 +793,8 @@ handle_info(#wx{event = #wxScroll{type = scroll_changed}} = Wx, S) ->
N = round(S#state.n_events * Pos / Range),
Diff =
case N - event_pos(S) of
- D when D < 0 -> D - 1;
- D -> D + 1
+ D when D < 0 -> D;
+ D -> D
end,
S2 = scroll_changed(S, Diff),
noreply(S2);
@@ -1002,7 +1002,7 @@ scroll_changed(S, Expected) ->
scroll_first(S);
last ->
scroll_last(S)
- end;
+ end;
true ->
%% Down
OldPos = event_pos(S),
@@ -1018,19 +1018,24 @@ scroll_changed(S, Expected) ->
end.
jump_up(S, OldKey, OldPos, NewPos) ->
- Try = NewPos - OldPos,
+ Try = NewPos - OldPos -1,
Order = S#state.event_order,
- Fun = fun(Event, #e{pos = P}) when P >= NewPos ->
- Key = et_collector:make_key(Order, Event),
- #e{event = Event, key = Key, pos = P - 1};
- (_, Acc) ->
- Acc
- end,
- PrevE = et_collector:iterate(S#state.collector_pid,
- OldKey,
- Try,
- Fun,
- #e{key = OldKey, pos = OldPos}),
+ PrevE =
+ if NewPos =:= 0 ->
+ first;
+ true ->
+ Fun = fun(Event, #e{pos = P}) when P >= NewPos ->
+ Key = et_collector:make_key(Order, Event),
+ #e{event = Event, key = Key, pos = P - 1};
+ (_E, Acc) ->
+ Acc
+ end,
+ et_collector:iterate(S#state.collector_pid,
+ OldKey,
+ Try,
+ Fun,
+ #e{key = OldKey, pos = OldPos})
+ end,
case collect_more_events(S, PrevE, S#state.events_per_page) of
{_, []} ->
S;
@@ -2013,7 +2018,7 @@ update_scroll_bar(#state{scroll_bar = ScrollBar,
PixelsPerEvent = Range / EventsPerPage,
Share = EventsPerPage / N,
wxScrollBar:setScrollbar(ScrollBar,
- trunc(EventPos * Share * PixelsPerEvent),
+ trunc(EventPos * Share * PixelsPerEvent),
round(Share * Range),
Range,
round(Share * Range),
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index 08ded8b6f1..d5416f1ea9 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.6.2
+ET_VSN = 1.6.4
diff --git a/lib/eunit/doc/src/Makefile b/lib/eunit/doc/src/Makefile
index e91d947592..117542cb37 100644
--- a/lib/eunit/doc/src/Makefile
+++ b/lib/eunit/doc/src/Makefile
@@ -146,6 +146,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index 0d2d61d553..67a9ae5fcb 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -33,6 +33,21 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.3.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.3.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index 054e21f6ad..46ef5eea3c 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.3.6
+EUNIT_VSN = 2.3.7
diff --git a/lib/ftp/doc/src/Makefile b/lib/ftp/doc/src/Makefile
index e96a9c032f..20fbbc73a9 100644
--- a/lib/ftp/doc/src/Makefile
+++ b/lib/ftp/doc/src/Makefile
@@ -103,6 +103,7 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
man: $(MAN3_FILES)
diff --git a/lib/ftp/doc/src/ftp.xml b/lib/ftp/doc/src/ftp.xml
index 3dbd3ed403..9645b03364 100644
--- a/lib/ftp/doc/src/ftp.xml
+++ b/lib/ftp/doc/src/ftp.xml
@@ -29,7 +29,7 @@
<rev>B</rev>
<file>ftp.xml</file>
</header>
- <module>ftp</module>
+ <module since="">ftp</module>
<modulesummary>A File Transfer Protocol client.</modulesummary>
<description>
@@ -272,7 +272,7 @@
<funcs>
<func>
- <name>account(Pid, Account) -> ok | {error, Reason}</name>
+ <name since="">account(Pid, Account) -> ok | {error, Reason}</name>
<fsummary>Specifies which account to use.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -289,8 +289,8 @@
</func>
<func>
- <name>append(Pid, LocalFile) -> </name>
- <name>append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
+ <name since="">append(Pid, LocalFile) -> </name>
+ <name since="">append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
<fsummary>Transfers a file to remote server, and appends it to
<c>Remotefile</c>.</fsummary>
<type>
@@ -310,11 +310,11 @@
</func>
<func>
- <name>append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
+ <name since="">append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
<fsummary>Transfers a binary into a remote file.</fsummary>
<type>
<v>Pid = pid()</v>
- <v>Bin = binary()()</v>
+ <v>Bin = binary()</v>
<v>RemoteFile = string()</v>
<v>Reason = restriction_reason()| shortage_reason() | common_reason()</v>
</type>
@@ -328,7 +328,7 @@
</func>
<func>
- <name>append_chunk(Pid, Bin) -> ok | {error, Reason}</name>
+ <name since="">append_chunk(Pid, Bin) -> ok | {error, Reason}</name>
<fsummary>Appends a chunk to the remote file.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -348,7 +348,7 @@
</func>
<func>
- <name>append_chunk_start(Pid, File) -> ok | {error, Reason}</name>
+ <name since="">append_chunk_start(Pid, File) -> ok | {error, Reason}</name>
<fsummary>Starts transfer of file chunks for appending to <c>File</c>.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -365,7 +365,7 @@
</func>
<func>
- <name>append_chunk_end(Pid) -> ok | {error, Reason}</name>
+ <name since="">append_chunk_end(Pid) -> ok | {error, Reason}</name>
<fsummary>Stops transfer of chunks for appending.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -381,7 +381,7 @@
</func>
<func>
- <name>cd(Pid, Dir) -> ok | {error, Reason}</name>
+ <name since="">cd(Pid, Dir) -> ok | {error, Reason}</name>
<fsummary>Changes remote working directory.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -397,7 +397,7 @@
</func>
<func>
- <name>close(Pid) -> ok</name>
+ <name since="">close(Pid) -> ok</name>
<fsummary>Ends the FTP session.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -411,7 +411,7 @@
</func>
<func>
- <name>delete(Pid, File) -> ok | {error, Reason}</name>
+ <name since="">delete(Pid, File) -> ok | {error, Reason}</name>
<fsummary>Deletes a file at the remote server.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -426,7 +426,7 @@
</func>
<func>
- <name>formaterror(Tag) -> string()</name>
+ <name since="">formaterror(Tag) -> string()</name>
<fsummary>Returns error diagnostics.</fsummary>
<type>
<v>Tag = {error, atom()} | atom()</v>
@@ -440,7 +440,7 @@
</func>
<func>
- <name>lcd(Pid, Dir) -> ok | {error, Reason}</name>
+ <name since="">lcd(Pid, Dir) -> ok | {error, Reason}</name>
<fsummary>Changes local working directory.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -455,7 +455,7 @@
</func>
<func>
- <name>lpwd(Pid) -> {ok, Dir}</name>
+ <name since="">lpwd(Pid) -> {ok, Dir}</name>
<fsummary>Gets local current working directory.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -470,8 +470,8 @@
</func>
<func>
- <name>ls(Pid) -> </name>
- <name>ls(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
+ <name since="">ls(Pid) -> </name>
+ <name since="">ls(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
<fsummary>List of files.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -493,7 +493,7 @@
</func>
<func>
- <name>mkdir(Pid, Dir) -> ok | {error, Reason}</name>
+ <name since="">mkdir(Pid, Dir) -> ok | {error, Reason}</name>
<fsummary>Creates a remote directory.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -510,8 +510,8 @@
</func>
<func>
- <name>nlist(Pid) -> </name>
- <name>nlist(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
+ <name since="">nlist(Pid) -> </name>
+ <name since="">nlist(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
<fsummary>List of files.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -535,8 +535,8 @@
</func>
<func>
- <name>open(Host) -> {ok, Pid} | {error, Reason}</name>
- <name>open(Host, Opts) -> {ok, Pid} | {error, Reason}</name>
+ <name since="">open(Host) -> {ok, Pid} | {error, Reason}</name>
+ <name since="">open(Host, Opts) -> {ok, Pid} | {error, Reason}</name>
<fsummary>Starts a standalone FTP client.</fsummary>
<type>
<v>Host = string() | ip_address()</v>
@@ -546,11 +546,12 @@
<v>start_option() = {verbose, verbose()} | {debug, debug()}</v>
<v>verbose() = boolean() (default is false)</v>
<v>debug() = disable | debug | trace (default is disable)</v>
- <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()}</v>
+ <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress() | {sock_ctrl, sock_opts()} | {sock_data_act, sock_opts()} | {sock_data_pass, sock_opts()} }</v>
<v>ipfamily() = inet | inet6 | inet6fb4 (default is inet)</v>
<v>port() = integer() > 0 (default is 21)</v>
<v>mode() = active | passive (default is passive)</v>
- <v>tls_options() = [<seealso marker="ssl:ssl#type-ssloption">ssl:ssloption()</seealso>]</v>
+ <v>tls_options() = [<seealso marker="ssl:ssl#type-tls_option">ssl:tls_option()</seealso>]</v>
+ <v>sock_opts() = [<seealso marker="kernel:gen_tcp#type-option">gen_tcp:option()</seealso> except for ipv6_v6only, active, packet, mode, packet_size and header</v>
<v>timeout() = integer() > 0 (default is 60000 milliseconds)</v>
<v>dtimeout() = integer() > 0 | infinity (default is infinity)</v>
<v>pogress() = ignore | {module(), function(), initial_data()} (default is ignore)</v>
@@ -573,6 +574,11 @@
is used for securing both the control connection and the data sessions.
</p>
+ <p>The options <c>sock_ctrl</c>, <c>sock_data_act</c> and <c>sock_data_pass</c> passes options down to
+ the underlying transport layer (tcp). The default value for <c>sock_ctrl</c> is <c>[]</c>. Both
+ <c>sock_data_act</c> and <c>sock_data_pass</c> uses the value of <c>sock_ctrl</c> as default value.
+ </p>
+
<p>A session opened in this way is closed using function
<seealso marker="#close">close</seealso>.</p>
@@ -581,7 +587,7 @@
</func>
<func>
- <name>pwd(Pid) -> {ok, Dir} | {error, Reason}</name>
+ <name since="">pwd(Pid) -> {ok, Dir} | {error, Reason}</name>
<fsummary>Gets the remote current working directory.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -597,8 +603,8 @@
</func>
<func>
- <name>recv(Pid, RemoteFile) -> </name>
- <name>recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason}</name>
+ <name since="">recv(Pid, RemoteFile) -> </name>
+ <name since="">recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason}</name>
<fsummary>Transfers a file from remote server.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -621,7 +627,7 @@
</func>
<func>
- <name>recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason}</name>
+ <name since="">recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason}</name>
<fsummary>Transfers a file from remote server as a binary.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -638,7 +644,7 @@
</func>
<func>
- <name>recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason}</name>
+ <name since="">recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason}</name>
<fsummary>Starts chunk-reading of the remote file.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -654,7 +660,7 @@
</func>
<func>
- <name>recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason}</name>
+ <name since="">recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason}</name>
<fsummary>Receives a chunk of the remote file.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -676,7 +682,7 @@
</func>
<func>
- <name>rename(Pid, Old, New) -> ok | {error, Reason}</name>
+ <name since="">rename(Pid, Old, New) -> ok | {error, Reason}</name>
<fsummary>Renames a file at the remote server.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -691,7 +697,7 @@
</func>
<func>
- <name>rmdir(Pid, Dir) -> ok | {error, Reason}</name>
+ <name since="">rmdir(Pid, Dir) -> ok | {error, Reason}</name>
<fsummary>Removes a remote directory.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -708,8 +714,8 @@
</func>
<func>
- <name>send(Pid, LocalFile) -></name>
- <name>send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
+ <name since="">send(Pid, LocalFile) -></name>
+ <name since="">send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
<fsummary>Transfers a file to the remote server.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -726,11 +732,11 @@
</func>
<func>
- <name>send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
+ <name since="">send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
<fsummary>Transfers a binary into a remote file.</fsummary>
<type>
<v>Pid = pid()</v>
- <v>Bin = binary()()</v>
+ <v>Bin = binary()</v>
<v>RemoteFile = string()</v>
<v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
</type>
@@ -743,7 +749,7 @@
</func>
<func>
- <name>send_chunk(Pid, Bin) -> ok | {error, Reason}</name>
+ <name since="">send_chunk(Pid, Bin) -> ok | {error, Reason}</name>
<fsummary>Writes a chunk to the remote file.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -763,7 +769,7 @@
</func>
<func>
- <name>send_chunk_start(Pid, File) -> ok | {error, Reason}</name>
+ <name since="">send_chunk_start(Pid, File) -> ok | {error, Reason}</name>
<fsummary>Starts transfer of file chunks.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -779,7 +785,7 @@
</func>
<func>
- <name>send_chunk_end(Pid) -> ok | {error, Reason}</name>
+ <name since="">send_chunk_end(Pid) -> ok | {error, Reason}</name>
<fsummary>Stops transfer of chunks.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -795,7 +801,7 @@
</func>
<func>
- <name>start_service(ServiceConfig) -> {ok, Pid} | {error, Reason}</name>
+ <name since="OTP 21.0">start_service(ServiceConfig) -> {ok, Pid} | {error, Reason}</name>
<fsummary>Dynamically starts an <c>FTP</c>
session after the <c>ftp</c> application has been started.</fsummary>
<type>
@@ -814,7 +820,7 @@
</func>
<func>
- <name>stop_service(Reference) -> ok | {error, Reason} </name>
+ <name since="OTP 21.0">stop_service(Reference) -> ok | {error, Reason} </name>
<fsummary>Stops an FTP session.</fsummary>
<type>
<v>Reference = pid() | term() - service-specified reference</v>
@@ -826,7 +832,7 @@
</func>
<func>
- <name>type(Pid, Type) -> ok | {error, Reason}</name>
+ <name since="">type(Pid, Type) -> ok | {error, Reason}</name>
<fsummary>Sets transfer type to <c>ascii</c>or <c>binary</c>.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -843,7 +849,7 @@
</func>
<func>
- <name>user(Pid, User, Password) -> ok | {error, Reason}</name>
+ <name since="">user(Pid, User, Password) -> ok | {error, Reason}</name>
<fsummary>User login.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -858,7 +864,7 @@
</func>
<func>
- <name>user(Pid, User, Password, Account) -> ok | {error, Reason}</name>
+ <name since="">user(Pid, User, Password, Account) -> ok | {error, Reason}</name>
<fsummary>User login.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -874,7 +880,7 @@
</func>
<func>
- <name>quote(Pid, Command) -> [FTPLine]</name>
+ <name since="">quote(Pid, Command) -> [FTPLine]</name>
<fsummary>Sends an arbitrary FTP command.</fsummary>
<type>
<v>Pid = pid()</v>
diff --git a/lib/ftp/doc/src/notes.xml b/lib/ftp/doc/src/notes.xml
index 50f38941e5..61da079900 100644
--- a/lib/ftp/doc/src/notes.xml
+++ b/lib/ftp/doc/src/notes.xml
@@ -33,7 +33,38 @@
<file>notes.xml</file>
</header>
- <section><title>FTP 1.0</title>
+ <section><title>Ftp 1.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed timing related bug that could make ftp functions
+ behave badly.</p>
+ <p>
+ Own Id: OTP-15659 Aux Id: ERIERL-316 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ftp 1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>FTP 1.0</title>
<section><title>First released version</title>
<list>
diff --git a/lib/ftp/src/ftp.app.src b/lib/ftp/src/ftp.app.src
index 237174358f..66ccace390 100644
--- a/lib/ftp/src/ftp.app.src
+++ b/lib/ftp/src/ftp.app.src
@@ -1,6 +1,6 @@
{application, ftp,
[{description, "FTP client"},
- {vsn, "1.0"},
+ {vsn, "%VSN%"},
{registered, []},
{mod, { ftp_app, []}},
{applications,
diff --git a/lib/ftp/src/ftp.erl b/lib/ftp/src/ftp.erl
index 8790bfec13..18cd8c7524 100644
--- a/lib/ftp/src/ftp.erl
+++ b/lib/ftp/src/ftp.erl
@@ -101,6 +101,9 @@
%% data needed further on.
caller = undefined, % term()
ipfamily, % inet | inet6 | inet6fb4
+ sockopts_ctrl = [],
+ sockopts_data_passive = [],
+ sockopts_data_active = [],
progress = ignore, % ignore | pid()
dtimeout = ?DATA_ACCEPT_TIMEOUT, % non_neg_integer() | infinity
tls_upgrading_data_connection = false,
@@ -135,9 +138,10 @@ start_standalone(Options) ->
try
{ok, StartOptions} = start_options(Options),
{ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
case start_link(StartOptions, []) of
{ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
Error1 ->
Error1
end
@@ -149,10 +153,11 @@ start_standalone(Options) ->
start_service(Options) ->
try
{ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
{ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
Error1 ->
Error1
end
@@ -200,9 +205,10 @@ open({option_list, Options}) when is_list(Options) ->
try
{ok, StartOptions} = start_options(Options),
{ok, OpenOptions} = open_options(Options),
+ {ok, SockOpts} = socket_options(Options),
case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
{ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
+ call(Pid, {open, ip_comm, OpenOptions, SockOpts}, plain);
Error1 ->
Error1
end
@@ -227,9 +233,10 @@ open(Host, Opts) when is_list(Opts) ->
try
{ok, StartOptions} = start_options(Opts),
{ok, OpenOptions} = open_options([{host, Host}|Opts]),
+ {ok, SocketOptions} = socket_options(Opts),
case start_link(StartOptions, []) of
{ok, Pid} ->
- do_open(Pid, OpenOptions, tls_options(Opts));
+ do_open(Pid, OpenOptions, SocketOptions, tls_options(Opts));
Error1 ->
Error1
end
@@ -238,8 +245,8 @@ open(Host, Opts) when is_list(Opts) ->
Error2
end.
-do_open(Pid, OpenOptions, TLSOpts) ->
- case call(Pid, {open, ip_comm, OpenOptions}, plain) of
+do_open(Pid, OpenOptions, SocketOptions, TLSOpts) ->
+ case call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain) of
{ok, Pid} ->
maybe_tls_upgrade(Pid, TLSOpts);
Error ->
@@ -1026,7 +1033,7 @@ handle_call({_,latest_ctrl_response}, _, #state{latest_ctrl_response=Resp} = Sta
handle_call({Pid, _}, _, #state{owner = Owner} = State) when Owner =/= Pid ->
{reply, {error, not_connection_owner}, State};
-handle_call({_, {open, ip_comm, Opts}}, From, State) ->
+handle_call({_, {open, ip_comm, Opts, {CtrlOpts, DataPassOpts, DataActOpts}}}, From, State) ->
case key_search(host, Opts, undefined) of
undefined ->
{stop, normal, {error, ehost}, State};
@@ -1043,6 +1050,9 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
mode = Mode,
progress = progress(Progress),
ipfamily = IpFamily,
+ sockopts_ctrl = CtrlOpts,
+ sockopts_data_passive = DataPassOpts,
+ sockopts_data_active = DataActOpts,
dtimeout = DTimeout,
ftp_extension = FtpExt},
@@ -1055,31 +1065,9 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
end
end;
-handle_call({_, {open, ip_comm, Host, Opts}}, From, State) ->
- Mode = key_search(mode, Opts, ?DEFAULT_MODE),
- Port = key_search(port, Opts, ?FTP_PORT),
- Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
- DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
- Progress = key_search(progress, Opts, ignore),
- FtpExt = key_search(ftp_extension, Opts, ?FTP_EXT_DEFAULT),
-
- State2 = State#state{client = From,
- mode = Mode,
- progress = progress(Progress),
- dtimeout = DTimeout,
- ftp_extension = FtpExt},
-
- case setup_ctrl_connection(Host, Port, Timeout, State2) of
- {ok, State3, WaitTimeout} ->
- {noreply, State3, WaitTimeout};
- {error, _Reason} ->
- gen_server:reply(From, {error, ehost}),
- {stop, normal, State2#state{client = undefined}}
- end;
-
-handle_call({_, {open, tls_upgrade, TLSOptions}}, From, State) ->
- _ = send_ctrl_message(State, mk_cmd("AUTH TLS", [])),
- activate_ctrl_connection(State),
+handle_call({_, {open, tls_upgrade, TLSOptions}}, From, State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("AUTH TLS", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = open, tls_options = TLSOptions}};
handle_call({_, {user, User, Password}}, From,
@@ -1093,17 +1081,17 @@ handle_call({_, {user, User, Password, Acc}}, From,
handle_call({_, {account, Acc}}, From, State)->
handle_user_account(Acc, State#state{client = From});
-handle_call({_, pwd}, From, #state{chunk = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd("PWD", [])),
- activate_ctrl_connection(State),
+handle_call({_, pwd}, From, #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("PWD", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = pwd}};
handle_call({_, lpwd}, From, #state{ldir = LDir} = State) ->
{reply, {ok, LDir}, State#state{client = From}};
-handle_call({_, {cd, Dir}}, From, #state{chunk = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd("CWD ~s", [Dir])),
- activate_ctrl_connection(State),
+handle_call({_, {cd, Dir}}, From, #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("CWD ~s", [Dir])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = cd}};
handle_call({_,{lcd, Dir}}, _From, #state{ldir = LDir0} = State) ->
@@ -1120,41 +1108,41 @@ handle_call({_, {dir, Len, Dir}}, {_Pid, _} = From,
setup_data_connection(State#state{caller = {dir, Dir, Len},
client = From});
handle_call({_, {rename, CurrFile, NewFile}}, From,
- #state{chunk = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd("RNFR ~s", [CurrFile])),
- activate_ctrl_connection(State),
+ #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("RNFR ~s", [CurrFile])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {rename, NewFile}, client = From}};
handle_call({_, {delete, File}}, {_Pid, _} = From,
- #state{chunk = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd("DELE ~s", [File])),
- activate_ctrl_connection(State),
+ #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("DELE ~s", [File])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From}};
-handle_call({_, {mkdir, Dir}}, From, #state{chunk = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd("MKD ~s", [Dir])),
- activate_ctrl_connection(State),
+handle_call({_, {mkdir, Dir}}, From, #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("MKD ~s", [Dir])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From}};
-handle_call({_,{rmdir, Dir}}, From, #state{chunk = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd("RMD ~s", [Dir])),
- activate_ctrl_connection(State),
+handle_call({_,{rmdir, Dir}}, From, #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("RMD ~s", [Dir])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From}};
-handle_call({_,{type, Type}}, From, #state{chunk = false} = State) ->
+handle_call({_,{type, Type}}, From, #state{chunk = false} = State0) ->
case Type of
ascii ->
- _ = send_ctrl_message(State, mk_cmd("TYPE A", [])),
- activate_ctrl_connection(State),
+ _ = send_ctrl_message(State0, mk_cmd("TYPE A", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = type, type = ascii,
client = From}};
binary ->
- _ = send_ctrl_message(State, mk_cmd("TYPE I", [])),
- activate_ctrl_connection(State),
+ _ = send_ctrl_message(State0, mk_cmd("TYPE I", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = type, type = binary,
client = From}};
_ ->
- {reply, {error, etype}, State}
+ {reply, {error, etype}, State0}
end;
handle_call({_,{recv, RemoteFile, LocalFile}}, From,
@@ -1193,8 +1181,8 @@ handle_call({_, recv_chunk}, _From, #state{chunk = true,
} = State0) ->
%% The ftp:recv_chunk call was the last event we waited for, finnish and clean up
?DBG("recv_chunk_closing ftp:recv_chunk, last event",[]),
- activate_ctrl_connection(State0),
- {reply, ok, State0#state{caller = undefined,
+ State = activate_ctrl_connection(State0),
+ {reply, ok, State#state{caller = undefined,
chunk = false,
client = undefined}};
@@ -1250,18 +1238,18 @@ handle_call({_, {transfer_chunk, Bin}}, _, #state{chunk = true} = State) ->
handle_call({_, {transfer_chunk, _}}, _, #state{chunk = false} = State) ->
{reply, {error, echunk}, State};
-handle_call({_, chunk_end}, From, #state{chunk = true} = State) ->
- close_data_connection(State),
- activate_ctrl_connection(State),
+handle_call({_, chunk_end}, From, #state{chunk = true} = State0) ->
+ close_data_connection(State0),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, dsock = undefined,
caller = end_chunk_transfer, chunk = false}};
handle_call({_, chunk_end}, _, #state{chunk = false} = State) ->
{reply, {error, echunk}, State};
-handle_call({_, {quote, Cmd}}, From, #state{chunk = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd(Cmd, [])),
- activate_ctrl_connection(State),
+handle_call({_, {quote, Cmd}}, From, #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd(Cmd, [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = quote}};
handle_call({_, _Req}, _From, #state{csock = CSock} = State)
@@ -1337,38 +1325,38 @@ handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}} = State0) when T
Data/binary>>}};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
- caller = {recv_file, Fd}} = State)
+ caller = {recv_file, Fd}} = State0)
when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
file_close(Fd),
- progress_report({transfer_size, 0}, State),
- activate_ctrl_connection(State),
+ progress_report({transfer_size, 0}, State0),
+ State = activate_ctrl_connection(State0),
?DBG("Data channel close",[]),
{noreply, State#state{dsock = undefined, data = <<>>}};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
client = Client,
- caller = recv_chunk} = State)
+ caller = recv_chunk} = State0)
when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
?DBG("Data channel close recv_chunk",[]),
- activate_ctrl_connection(State),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{dsock = undefined,
caller = #recv_chunk_closing{dconn_closed = true,
client_called_us = Client =/= undefined}
}};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, caller = recv_bin,
- data = Data} = State)
+ data = Data} = State0)
when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
?DBG("Data channel close",[]),
- activate_ctrl_connection(State),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{dsock = undefined, data = <<>>,
caller = {recv_bin, Data}}};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, data = Data,
- caller = {handle_dir_result, Dir}}
- = State) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ caller = {handle_dir_result, Dir}}
+ = State0) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
?DBG("Data channel close",[]),
- activate_ctrl_connection(State),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{dsock = undefined,
caller = {handle_dir_result, Dir, Data},
% data = <<?CR,?LF>>}};
@@ -1389,7 +1377,7 @@ handle_info({Transport, Socket, Data}, #state{csock = {Transport, Socket},
client = From,
ctrl_data = {CtrlData, AccLines,
LineStatus}}
- = State) ->
+ = State0) ->
?DBG('--ctrl ~p ----> ~s~p~n',[Socket,<<CtrlData/binary, Data/binary>>,State]),
case ftp_response:parse_lines(<<CtrlData/binary, Data/binary>>,
AccLines, LineStatus) of
@@ -1399,21 +1387,21 @@ handle_info({Transport, Socket, Data}, #state{csock = {Transport, Socket},
case Caller of
quote ->
gen_server:reply(From, string:tokens(Lines, [?CR, ?LF])),
- {noreply, State#state{client = undefined,
- caller = undefined,
- latest_ctrl_response = Lines,
- ctrl_data = {NextMsgData, [],
- start}}};
+ {noreply, State0#state{client = undefined,
+ caller = undefined,
+ latest_ctrl_response = Lines,
+ ctrl_data = {NextMsgData, [],
+ start}}};
_ ->
?DBG(' ...handle_ctrl_result(~p,...) ctrl_data=~p~n',[CtrlResult,{NextMsgData, [], start}]),
handle_ctrl_result(CtrlResult,
- State#state{latest_ctrl_response = Lines,
- ctrl_data =
- {NextMsgData, [], start}})
+ State0#state{latest_ctrl_response = Lines,
+ ctrl_data =
+ {NextMsgData, [], start}})
end;
{continue, NewCtrlData} ->
?DBG(' ...Continue... ctrl_data=~p~n',[NewCtrlData]),
- activate_ctrl_connection(State),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{ctrl_data = NewCtrlData}}
end;
@@ -1579,19 +1567,19 @@ start_link(Opts, GenServerOptions) ->
%%% Help functions to handle_call and/or handle_ctrl_result
%%--------------------------------------------------------------------------
%% User handling
-handle_user(User, Password, Acc, State) ->
- _ = send_ctrl_message(State, mk_cmd("USER ~s", [User])),
- activate_ctrl_connection(State),
+handle_user(User, Password, Acc, State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("USER ~s", [User])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {handle_user, Password, Acc}}}.
-handle_user_passwd(Password, Acc, State) ->
- _ = send_ctrl_message(State, mk_cmd("PASS ~s", [Password])),
- activate_ctrl_connection(State),
+handle_user_passwd(Password, Acc, State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("PASS ~s", [Password])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {handle_user_passwd, Acc}}}.
-handle_user_account(Acc, State) ->
- _ = send_ctrl_message(State, mk_cmd("ACCT ~s", [Acc])),
- activate_ctrl_connection(State),
+handle_user_account(Acc, State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("ACCT ~s", [Acc])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = handle_user_account}}.
@@ -1606,9 +1594,9 @@ handle_ctrl_result({tls_upgrade, _}, #state{csock = {tcp, Socket},
?DBG('<--ctrl ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
case ssl:connect(Socket, TLSOptions, Timeout) of
{ok, TLSSocket} ->
- State = State0#state{csock = {ssl,TLSSocket}},
- _ = send_ctrl_message(State, mk_cmd("PBSZ 0", [])),
- activate_ctrl_connection(State),
+ State1 = State0#state{csock = {ssl,TLSSocket}},
+ _ = send_ctrl_message(State1, mk_cmd("PBSZ 0", [])),
+ State = activate_ctrl_connection(State1),
{noreply, State#state{tls_upgrading_data_connection = {true, pbsz}} };
{error, _} = Error ->
gen_server:reply(From, {Error, self()}),
@@ -1617,9 +1605,9 @@ handle_ctrl_result({tls_upgrade, _}, #state{csock = {tcp, Socket},
tls_upgrading_data_connection = false}}
end;
-handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, pbsz}} = State) ->
- _ = send_ctrl_message(State, mk_cmd("PROT P", [])),
- activate_ctrl_connection(State),
+handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, pbsz}} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("PROT P", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{tls_upgrading_data_connection = {true, prot}}};
handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, prot},
@@ -1659,11 +1647,12 @@ handle_ctrl_result({pos_compl, Lines},
client = From,
caller = {setup_data_connection, Caller},
csock = CSock,
+ sockopts_data_passive = SockOpts,
timeout = Timeout}
= State) ->
[_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
{ok, {IP, _}} = peername(CSock),
- case connect(IP, list_to_integer(PortStr), Timeout, State) of
+ case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
{ok, _, Socket} ->
handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
{error, _Reason} = Error ->
@@ -1676,7 +1665,8 @@ handle_ctrl_result({pos_compl, Lines},
ipfamily = inet,
client = From,
caller = {setup_data_connection, Caller},
- timeout = Timeout,
+ timeout = Timeout,
+ sockopts_data_passive = SockOpts,
ftp_extension = false} = State) ->
{_, [?LEFT_PAREN | Rest]} =
@@ -1690,7 +1680,7 @@ handle_ctrl_result({pos_compl, Lines},
Port = (P1 * 256) + P2,
?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,Port,Caller]),
- case connect(IP, Port, Timeout, State) of
+ case connect(IP, Port, SockOpts, Timeout, State) of
{ok, _, Socket} ->
handle_caller(State#state{caller = Caller, dsock = {tcp,Socket}});
{error, _Reason} = Error ->
@@ -1705,13 +1695,14 @@ handle_ctrl_result({pos_compl, Lines},
caller = {setup_data_connection, Caller},
csock = CSock,
timeout = Timeout,
+ sockopts_data_passive = SockOpts,
ftp_extension = true} = State) ->
[_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
{ok, {IP, _}} = peername(CSock),
?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,PortStr,Caller]),
- case connect(IP, list_to_integer(PortStr), Timeout, State) of
+ case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
{ok, _, Socket} ->
handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
{error, _Reason} = Error ->
@@ -1810,10 +1801,10 @@ handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir,
handle_ctrl_result({pos_compl, Lines},
#state{caller = {handle_dir_data, Dir, DirData}} =
- State) ->
+ State0) ->
OldDir = pwd_result(Lines),
- _ = send_ctrl_message(State, mk_cmd("CWD ~s", [Dir])),
- activate_ctrl_connection(State),
+ _ = send_ctrl_message(State0, mk_cmd("CWD ~s", [Dir])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {handle_dir_data_second_phase, OldDir,
DirData}}};
handle_ctrl_result({Status, _},
@@ -1827,9 +1818,9 @@ handle_ctrl_result(S={_Status, _},
handle_ctrl_result({pos_compl, _},
#state{caller = {handle_dir_data_second_phase, OldDir,
- DirData}} = State) ->
- _ = send_ctrl_message(State, mk_cmd("CWD ~s", [OldDir])),
- activate_ctrl_connection(State),
+ DirData}} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("CWD ~s", [OldDir])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {handle_dir_data_third_phase, DirData}}};
handle_ctrl_result({Status, _},
#state{caller = {handle_dir_data_second_phase, _, _}}
@@ -1849,9 +1840,9 @@ handle_ctrl_result(Status={epath, _}, #state{caller = {dir,_}} = State) ->
%%--------------------------------------------------------------------------
%% File renaming
handle_ctrl_result({pos_interm, _}, #state{caller = {rename, NewFile}}
- = State) ->
- _ = send_ctrl_message(State, mk_cmd("RNTO ~s", [NewFile])),
- activate_ctrl_connection(State),
+ = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("RNTO ~s", [NewFile])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = rename_second_phase}};
handle_ctrl_result({Status, _},
@@ -1925,10 +1916,10 @@ handle_ctrl_result({pos_compl, _}, #state{client = From,
%% The pos_compl was the last event we waited for, finnish and clean up
?DBG("recv_chunk_closing pos_compl, last event",[]),
gen_server:reply(From, ok),
- activate_ctrl_connection(State0),
- {noreply, State0#state{caller = undefined,
- chunk = false,
- client = undefined}};
+ State = activate_ctrl_connection(State0),
+ {noreply, State#state{caller = undefined,
+ chunk = false,
+ client = undefined}};
handle_ctrl_result({pos_compl, _}, #state{caller = #recv_chunk_closing{}=R}
= State0) ->
@@ -2022,71 +2013,71 @@ ctrl_result_response(_, #state{client = From} = State, ErrorMsg) ->
{noreply, State#state{client = undefined, caller = undefined}}.
%%--------------------------------------------------------------------------
-handle_caller(#state{caller = {dir, Dir, Len}} = State) ->
+handle_caller(#state{caller = {dir, Dir, Len}} = State0) ->
Cmd = case Len of
short -> "NLST";
long -> "LIST"
end,
_ = case Dir of
"" ->
- send_ctrl_message(State, mk_cmd(Cmd, ""));
+ send_ctrl_message(State0, mk_cmd(Cmd, ""));
_ ->
- send_ctrl_message(State, mk_cmd(Cmd ++ " ~s", [Dir]))
+ send_ctrl_message(State0, mk_cmd(Cmd ++ " ~s", [Dir]))
end,
- activate_ctrl_connection(State),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {dir, Dir}}};
-handle_caller(#state{caller = {recv_bin, RemoteFile}} = State) ->
- _ = send_ctrl_message(State, mk_cmd("RETR ~s", [RemoteFile])),
- activate_ctrl_connection(State),
+handle_caller(#state{caller = {recv_bin, RemoteFile}} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("RETR ~s", [RemoteFile])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = recv_bin}};
handle_caller(#state{caller = {start_chunk_transfer, Cmd, RemoteFile}} =
- State) ->
- _ = send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
- activate_ctrl_connection(State),
+ State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("~s ~s", [Cmd, RemoteFile])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = start_chunk_transfer}};
-handle_caller(#state{caller = {recv_file, RemoteFile, Fd}} = State) ->
- _ = send_ctrl_message(State, mk_cmd("RETR ~s", [RemoteFile])),
- activate_ctrl_connection(State),
+handle_caller(#state{caller = {recv_file, RemoteFile, Fd}} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("RETR ~s", [RemoteFile])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {recv_file, Fd}}};
handle_caller(#state{caller = {transfer_file, {Cmd, LocalFile, RemoteFile}},
- ldir = LocalDir, client = From} = State) ->
+ ldir = LocalDir, client = From} = State0) ->
case file_open(filename:absname(LocalFile, LocalDir), read) of
{ok, Fd} ->
- _ = send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
- activate_ctrl_connection(State),
+ _ = send_ctrl_message(State0, mk_cmd("~s ~s", [Cmd, RemoteFile])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {transfer_file, Fd}}};
{error, _} ->
gen_server:reply(From, {error, epath}),
- {noreply, State#state{client = undefined, caller = undefined,
- dsock = undefined}}
+ {noreply, State0#state{client = undefined, caller = undefined,
+ dsock = undefined}}
end;
handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
- State) ->
- _ = send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
- activate_ctrl_connection(State),
+ State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("~s ~s", [Cmd, RemoteFile])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {transfer_data, Bin}}}.
%% ----------- FTP SERVER COMMUNICATION -------------------------
%% Connect to FTP server at Host (default is TCP port 21)
%% in order to establish a control connection.
-setup_ctrl_connection(Host, Port, Timeout, State) ->
+setup_ctrl_connection(Host, Port, Timeout, #state{sockopts_ctrl = SockOpts} = State0) ->
MsTime = erlang:monotonic_time(),
- case connect(Host, Port, Timeout, State) of
+ case connect(Host, Port, SockOpts, Timeout, State0) of
{ok, IpFam, CSock} ->
- NewState = State#state{csock = {tcp, CSock}, ipfamily = IpFam},
- activate_ctrl_connection(NewState),
+ State1 = State0#state{csock = {tcp, CSock}, ipfamily = IpFam},
+ State = activate_ctrl_connection(State1),
case Timeout - millisec_passed(MsTime) of
Timeout2 when (Timeout2 >= 0) ->
- {ok, NewState#state{caller = open}, Timeout2};
+ {ok, State#state{caller = open}, Timeout2};
_ ->
%% Oups: Simulate timeout
- {ok, NewState#state{caller = open}, 0}
+ {ok, State#state{caller = open}, 0}
end;
Error ->
Error
@@ -2095,95 +2086,100 @@ setup_ctrl_connection(Host, Port, Timeout, State) ->
setup_data_connection(#state{mode = active,
caller = Caller,
csock = CSock,
- ftp_extension = FtpExt} = State) ->
+ sockopts_data_active = SockOpts,
+ ftp_extension = FtpExt} = State0) ->
case (catch sockname(CSock)) of
- {ok, {{_, _, _, _, _, _, _, _} = IP, _}} ->
+ {ok, {{_, _, _, _, _, _, _, _} = IP0, _}} ->
+ IP = proplists:get_value(ip, SockOpts, IP0),
{ok, LSock} =
gen_tcp:listen(0, [{ip, IP}, {active, false},
- inet6, binary, {packet, 0}]),
+ inet6, binary, {packet, 0} |
+ lists:keydelete(ip,1,SockOpts)]),
{ok, {_, Port}} = sockname({tcp,LSock}),
IpAddress = inet_parse:ntoa(IP),
Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
- _ = send_ctrl_message(State, Cmd),
- activate_ctrl_connection(State),
+ _ = send_ctrl_message(State0, Cmd),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection,
{LSock, Caller}}}};
- {ok, {{_,_,_,_} = IP, _}} ->
+ {ok, {{_,_,_,_} = IP0, _}} ->
+ IP = proplists:get_value(ip, SockOpts, IP0),
{ok, LSock} = gen_tcp:listen(0, [{ip, IP}, {active, false},
- binary, {packet, 0}]),
+ binary, {packet, 0} |
+ lists:keydelete(ip,1,SockOpts)]),
{ok, Port} = inet:port(LSock),
_ = case FtpExt of
false ->
{IP1, IP2, IP3, IP4} = IP,
{Port1, Port2} = {Port div 256, Port rem 256},
- send_ctrl_message(State,
+ send_ctrl_message(State0,
mk_cmd("PORT ~w,~w,~w,~w,~w,~w",
[IP1, IP2, IP3, IP4, Port1, Port2]));
true ->
IpAddress = inet_parse:ntoa(IP),
Cmd = mk_cmd("EPRT |1|~s|~p|", [IpAddress, Port]),
- send_ctrl_message(State, Cmd)
+ send_ctrl_message(State0, Cmd)
end,
- activate_ctrl_connection(State),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection,
{LSock, Caller}}}}
end;
setup_data_connection(#state{mode = passive, ipfamily = inet6,
- caller = Caller} = State) ->
- _ = send_ctrl_message(State, mk_cmd("EPSV", [])),
- activate_ctrl_connection(State),
+ caller = Caller} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("EPSV", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection, Caller}}};
setup_data_connection(#state{mode = passive, ipfamily = inet,
caller = Caller,
- ftp_extension = false} = State) ->
- _ = send_ctrl_message(State, mk_cmd("PASV", [])),
- activate_ctrl_connection(State),
+ ftp_extension = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("PASV", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection, Caller}}};
setup_data_connection(#state{mode = passive, ipfamily = inet,
caller = Caller,
- ftp_extension = true} = State) ->
- _ = send_ctrl_message(State, mk_cmd("EPSV", [])),
- activate_ctrl_connection(State),
+ ftp_extension = true} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("EPSV", [])),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection, Caller}}}.
-connect(Host, Port, Timeout, #state{ipfamily = inet = IpFam}) ->
- connect2(Host, Port, IpFam, Timeout);
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet = IpFam}) ->
+ connect2(Host, Port, IpFam, SockOpts, Timeout);
-connect(Host, Port, Timeout, #state{ipfamily = inet6 = IpFam}) ->
- connect2(Host, Port, IpFam, Timeout);
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6 = IpFam}) ->
+ connect2(Host, Port, IpFam, SockOpts, Timeout);
-connect(Host, Port, Timeout, #state{ipfamily = inet6fb4}) ->
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6fb4}) ->
case inet:getaddr(Host, inet6) of
{ok, {0, 0, 0, 0, 0, 16#ffff, _, _} = IPv6} ->
case inet:getaddr(Host, inet) of
{ok, IPv4} ->
IpFam = inet,
- connect2(IPv4, Port, IpFam, Timeout);
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
_ ->
IpFam = inet6,
- connect2(IPv6, Port, IpFam, Timeout)
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout)
end;
{ok, IPv6} ->
IpFam = inet6,
- connect2(IPv6, Port, IpFam, Timeout);
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout);
_ ->
case inet:getaddr(Host, inet) of
{ok, IPv4} ->
IpFam = inet,
- connect2(IPv4, Port, IpFam, Timeout);
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
Error ->
Error
end
end.
-connect2(Host, Port, IpFam, Timeout) ->
- Opts = [IpFam, binary, {packet, 0}, {active, false}],
+connect2(Host, Port, IpFam, SockOpts, Timeout) ->
+ Opts = [IpFam, binary, {packet, 0}, {active, false} | SockOpts],
case gen_tcp:connect(Host, Port, Opts, Timeout) of
{ok, Sock} ->
{ok, IpFam, Sock};
@@ -2252,14 +2248,15 @@ send_message({tcp, Socket}, Message) ->
send_message({ssl, Socket}, Message) ->
ssl:send(Socket, Message).
-activate_ctrl_connection(#state{csock = CSock, ctrl_data = {<<>>, _, _}}) ->
- activate_connection(CSock);
-activate_ctrl_connection(#state{csock = CSock}) ->
+activate_ctrl_connection(#state{csock = CSock, ctrl_data = {<<>>, _, _}} = State) ->
+ activate_connection(CSock),
+ State;
+activate_ctrl_connection(#state{csock = CSock} = State0) ->
activate_connection(CSock),
%% We have already received at least part of the next control message,
%% that has been saved in ctrl_data, process this first.
- self() ! {socket_type(CSock), unwrap_socket(CSock), <<>>},
- ok.
+ {noreply, State} = handle_info({socket_type(CSock), unwrap_socket(CSock), <<>>}, State0),
+ State.
activate_data_connection(#state{dsock = DSock} = State) ->
activate_connection(DSock),
@@ -2294,22 +2291,22 @@ close_connection({ssl, Socket}) -> ignore_return_value( ssl:close(Socket) ).
%% ------------ FILE HANDLING ----------------------------------------
send_file(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Fd) ->
{noreply, State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_file, Fd}}};
-send_file(State, Fd) ->
+send_file(State0, Fd) ->
case file_read(Fd) of
{ok, N, Bin} when N > 0 ->
- send_data_message(State, Bin),
- progress_report({binary, Bin}, State),
- send_file(State, Fd);
+ send_data_message(State0, Bin),
+ progress_report({binary, Bin}, State0),
+ send_file(State0, Fd);
{ok, _, _} ->
file_close(Fd),
- close_data_connection(State),
- progress_report({transfer_size, 0}, State),
- activate_ctrl_connection(State),
+ close_data_connection(State0),
+ progress_report({transfer_size, 0}, State0),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = transfer_file_second_phase,
dsock = undefined}};
{error, Reason} ->
- gen_server:reply(State#state.client, {error, Reason}),
- {stop, normal, State#state{client = undefined}}
+ gen_server:reply(State0#state.client, {error, Reason}),
+ {stop, normal, State0#state{client = undefined}}
end.
file_open(File, Option) ->
@@ -2351,10 +2348,10 @@ cast(GenServer, Msg) ->
send_bin(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Bin) ->
State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_bin, Bin}};
-send_bin(State, Bin) ->
- send_data_message(State, Bin),
- close_data_connection(State),
- activate_ctrl_connection(State),
+send_bin(State0, Bin) ->
+ send_data_message(State0, Bin),
+ close_data_connection(State0),
+ State = activate_ctrl_connection(State0),
{noreply, State#state{caller = transfer_data_second_phase,
dsock = undefined}}.
@@ -2553,6 +2550,32 @@ open_options(Options) ->
{ftp_extension, ValidateFtpExtension, false, ?FTP_EXT_DEFAULT}],
validate_options(Options, ValidOptions, []).
+socket_options(Options) ->
+ CtrlOpts = proplists:get_value(sock_ctrl, Options, []),
+ DataActOpts = proplists:get_value(sock_data_act, Options, CtrlOpts),
+ DataPassOpts = proplists:get_value(sock_data_pass, Options, CtrlOpts),
+ case [O || O <- lists:usort(CtrlOpts++DataPassOpts++DataActOpts),
+ not valid_socket_option(O)] of
+ [] ->
+ {ok, {CtrlOpts, DataPassOpts, DataActOpts}};
+ Invalid ->
+ throw({error,{sock_opts,Invalid}})
+ end.
+
+
+valid_socket_option(inet ) -> false;
+valid_socket_option(inet6 ) -> false;
+valid_socket_option({ipv6_v6only, _}) -> false;
+valid_socket_option({active,_} ) -> false;
+valid_socket_option({packet,_} ) -> false;
+valid_socket_option({mode,_} ) -> false;
+valid_socket_option(binary ) -> false;
+valid_socket_option(list ) -> false;
+valid_socket_option({header,_} ) -> false;
+valid_socket_option({packet_size,_} ) -> false;
+valid_socket_option(_) -> true.
+
+
tls_options(Options) ->
%% Options will be validated by ssl application
proplists:get_value(tls, Options, undefined).
diff --git a/lib/ftp/test/ftp_SUITE.erl b/lib/ftp/test/ftp_SUITE.erl
index 7c87d5cbdb..0b070ee8cb 100644
--- a/lib/ftp/test/ftp_SUITE.erl
+++ b/lib/ftp/test/ftp_SUITE.erl
@@ -96,6 +96,7 @@ ftp_tests()->
recv_chunk,
recv_chunk_twice,
recv_chunk_three_times,
+ recv_chunk_delay,
type,
quote,
error_elogin,
@@ -669,9 +670,9 @@ recv_chunk(Config0) ->
Contents = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
Config = set_state([reset, {mkfile,File,Contents}], Config0),
Pid = proplists:get_value(ftp, Config),
- {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+ {error, "ftp:recv_chunk_start/2 not called"} = do_recv_chunk(Pid),
ok = ftp:recv_chunk_start(Pid, id2ftp(File,Config)),
- {ok, ReceivedContents, _Ncunks} = recv_chunk(Pid, <<>>),
+ {ok, ReceivedContents} = do_recv_chunk(Pid),
find_diff(ReceivedContents, Contents).
recv_chunk_twice() ->
@@ -683,11 +684,11 @@ recv_chunk_twice(Config0) ->
Contents2 = crypto:strong_rand_bytes(1200),
Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}], Config0),
Pid = proplists:get_value(ftp, Config),
- {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+ {error, "ftp:recv_chunk_start/2 not called"} = do_recv_chunk(Pid),
ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
- {ok, ReceivedContents1, _Ncunks1} = recv_chunk(Pid, <<>>),
+ {ok, ReceivedContents1} = do_recv_chunk(Pid),
ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
- {ok, ReceivedContents2, _Ncunks2} = recv_chunk(Pid, <<>>),
+ {ok, ReceivedContents2} = do_recv_chunk(Pid),
find_diff(ReceivedContents1, Contents1),
find_diff(ReceivedContents2, Contents2).
@@ -704,46 +705,56 @@ recv_chunk_three_times(Config0) ->
Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}, {mkfile,File3,Contents3}], Config0),
Pid = proplists:get_value(ftp, Config),
- {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+ {error, "ftp:recv_chunk_start/2 not called"} = do_recv_chunk(Pid),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File3,Config)),
+ {ok, ReceivedContents3} = do_recv_chunk(Pid),
+
ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
- {ok, ReceivedContents1, Nchunks1} = recv_chunk(Pid, <<>>),
+ {ok, ReceivedContents1} = do_recv_chunk(Pid),
ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
- {ok, ReceivedContents2, _Nchunks2} = recv_chunk(Pid, <<>>),
-
- ok = ftp:recv_chunk_start(Pid, id2ftp(File3,Config)),
- {ok, ReceivedContents3, _Nchunks3} = recv_chunk(Pid, <<>>, 10000, 0, Nchunks1),
+ {ok, ReceivedContents2} = do_recv_chunk(Pid),
find_diff(ReceivedContents1, Contents1),
find_diff(ReceivedContents2, Contents2),
find_diff(ReceivedContents3, Contents3).
-
+do_recv_chunk(Pid) ->
+ recv_chunk(Pid, <<>>).
recv_chunk(Pid, Acc) ->
- recv_chunk(Pid, Acc, 0, 0, undefined).
-
-
-
-%% ExpectNchunks :: integer() | undefined
-recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) when N+1 < ExpectNchunks ->
- %% for all I in integer(), I < undefined
- recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks);
-
-recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
- %% N >= ExpectNchunks-1
- timer:sleep(DelayMilliSec),
- recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks).
+ case ftp:recv_chunk(Pid) of
+ ok ->
+ {ok, Acc};
+ {ok, Bin} ->
+ recv_chunk(Pid, <<Acc/binary, Bin/binary>>);
+ Error ->
+ Error
+ end.
+recv_chunk_delay(Config0) when is_list(Config0) ->
+ File1 = "big_file1.txt",
+ Contents = list_to_binary(lists:duplicate(1000, lists:seq(0,255))),
+ Config = set_state([reset, {mkfile,File1,Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
+ {ok, ReceivedContents} = delay_recv_chunk(Pid),
+ find_diff(ReceivedContents, Contents).
-recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
- ct:log("Call ftp:recv_chunk",[]),
+delay_recv_chunk(Pid) ->
+ delay_recv_chunk(Pid, <<>>).
+delay_recv_chunk(Pid, Acc) ->
+ ct:pal("Recived size ~p", [byte_size(Acc)]),
case ftp:recv_chunk(Pid) of
- ok -> {ok, Acc, N};
- {ok, Bin} -> recv_chunk(Pid, <<Acc/binary, Bin/binary>>, DelayMilliSec, N+1, ExpectNchunks);
- Error -> {Error, N}
- end.
+ ok ->
+ {ok, Acc};
+ {ok, Bin} ->
+ ct:sleep(100),
+ delay_recv_chunk(Pid, <<Acc/binary, Bin/binary>>);
+ Error ->
+ Error
+ end.
%%-------------------------------------------------------------------------
type() ->
diff --git a/lib/ftp/vsn.mk b/lib/ftp/vsn.mk
index 3099144a6e..9f14658099 100644
--- a/lib/ftp/vsn.mk
+++ b/lib/ftp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = ftp
-FTP_VSN = 1.0
+FTP_VSN = 1.0.2
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(FTP_VSN)$(PRE_VSN)"
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 48ce641ab9..8ae1cd4ab7 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -2225,10 +2225,7 @@ type_order() ->
t_map(), t_list(), t_bitstr()].
key_comparisons_fail(X0, KeyPos, TupleList, Opaques) ->
- X = case t_is_number(t_inf(X0, t_number(), Opaques), Opaques) of
- false -> X0;
- true -> t_number()
- end,
+ X = erl_types:t_widen_to_number(X0),
lists:all(fun(Tuple) ->
Key = type(erlang, element, 2, [KeyPos, Tuple]),
t_is_none(t_inf(Key, X, Opaques))
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 9abb4d31d9..d61cd8664c 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -66,7 +66,6 @@
t_find_opaque_mismatch/3,
t_find_unknown_opaque/3,
t_fixnum/0,
- t_map/2,
t_non_neg_fixnum/0,
t_pos_fixnum/0,
t_float/0,
@@ -205,6 +204,7 @@
t_unopaque/1, t_unopaque/2,
t_var/1,
t_var_name/1,
+ t_widen_to_number/1,
%% t_assign_variables_to_subtype/2,
type_is_defined/4,
record_field_diffs_to_string/2,
@@ -1594,6 +1594,50 @@ lift_list_to_pos_empty(?nil) -> ?nil;
lift_list_to_pos_empty(?list(Content, Termination, _)) ->
?list(Content, Termination, ?unknown_qual).
+-spec t_widen_to_number(erl_type()) -> erl_type().
+
+%% Widens integers and floats to t_number().
+%% Used by erl_bif_types:key_comparison_fail().
+
+t_widen_to_number(?any) -> ?any;
+t_widen_to_number(?none) -> ?none;
+t_widen_to_number(?unit) -> ?unit;
+t_widen_to_number(?atom(_Set) = T) -> T;
+t_widen_to_number(?bitstr(_Unit, _Base) = T) -> T;
+t_widen_to_number(?float) -> t_number();
+t_widen_to_number(?function(Domain, Range)) ->
+ ?function(t_widen_to_number(Domain), t_widen_to_number(Range));
+t_widen_to_number(?identifier(_Types) = T) -> T;
+t_widen_to_number(?int_range(_From, _To)) -> t_number();
+t_widen_to_number(?int_set(_Set)) -> t_number();
+t_widen_to_number(?integer(_Types)) -> t_number();
+t_widen_to_number(?list(Type, Tail, Size)) ->
+ ?list(t_widen_to_number(Type), t_widen_to_number(Tail), Size);
+t_widen_to_number(?map(Pairs, DefK, DefV)) ->
+ L = [{t_widen_to_number(K), MNess, t_widen_to_number(V)} ||
+ {K, MNess, V} <- Pairs],
+ t_map(L, t_widen_to_number(DefK), t_widen_to_number(DefV));
+t_widen_to_number(?matchstate(_P, _Slots) = T) -> T;
+t_widen_to_number(?nil) -> ?nil;
+t_widen_to_number(?number(_Set, _Tag)) -> t_number();
+t_widen_to_number(?opaque(Set)) ->
+ L = [Opaque#opaque{struct = t_widen_to_number(S)} ||
+ #opaque{struct = S} = Opaque <- set_to_list(Set)],
+ ?opaque(ordsets:from_list(L));
+t_widen_to_number(?product(Types)) ->
+ ?product(list_widen_to_number(Types));
+t_widen_to_number(?tuple(?any, _, _) = T) -> T;
+t_widen_to_number(?tuple(Types, Arity, Tag)) ->
+ ?tuple(list_widen_to_number(Types), Arity, Tag);
+t_widen_to_number(?tuple_set(_) = Tuples) ->
+ t_sup([t_widen_to_number(T) || T <- t_tuple_subtypes(Tuples)]);
+t_widen_to_number(?union(List)) ->
+ ?union(list_widen_to_number(List));
+t_widen_to_number(?var(_Id)= T) -> T.
+
+list_widen_to_number(List) ->
+ [t_widen_to_number(E) || E <- List].
+
%%-----------------------------------------------------------------------------
%% Maps
%%
@@ -3104,9 +3148,18 @@ is_compat_arg(?list(Contents1, Termination1, Size1),
is_compat_arg(?product(Types1), ?product(Types2)) ->
is_compat_list(Types1, Types2);
is_compat_arg(?map(Pairs1, DefK1, DefV1), ?map(Pairs2, DefK2, DefV2)) ->
- (is_compat_list(Pairs1, Pairs2) andalso
- is_compat_arg(DefK1, DefK2) andalso
- is_compat_arg(DefV1, DefV2));
+ {Ks1, _, Vs1} = lists:unzip3(Pairs1),
+ {Ks2, _, Vs2} = lists:unzip3(Pairs2),
+ Key1 = t_sup([DefK1 | Ks1]),
+ Key2 = t_sup([DefK2 | Ks2]),
+ case is_compat_arg(Key1, Key2) of
+ true ->
+ Value1 = t_sup([DefV1 | Vs1]),
+ Value2 = t_sup([DefV2 | Vs2]),
+ is_compat_arg(Value1, Value2);
+ false ->
+ false
+ end;
is_compat_arg(?tuple(?any, ?any, ?any), ?tuple(_, _, _)) -> false;
is_compat_arg(?tuple(_, _, _), ?tuple(?any, ?any, ?any)) -> false;
is_compat_arg(?tuple(Elements1, Arity, _),
@@ -4156,39 +4209,6 @@ t_abstract_records(?opaque(_)=Type, RecDict) ->
t_abstract_records(T, _RecDict) ->
T.
-%% Map over types. Depth first. Used by the contract checker. ?list is
-%% not fully implemented so take care when changing the type in Termination.
-
--spec t_map(fun((erl_type()) -> erl_type()), erl_type()) -> erl_type().
-
-t_map(Fun, ?list(Contents, Termination, Size)) ->
- Fun(?list(t_map(Fun, Contents), t_map(Fun, Termination), Size));
-t_map(Fun, ?function(Domain, Range)) ->
- Fun(?function(t_map(Fun, Domain), t_map(Fun, Range)));
-t_map(Fun, ?product(Types)) ->
- Fun(?product([t_map(Fun, T) || T <- Types]));
-t_map(Fun, ?union(Types)) ->
- Fun(t_sup([t_map(Fun, T) || T <- Types]));
-t_map(Fun, ?tuple(?any, ?any, ?any) = T) ->
- Fun(T);
-t_map(Fun, ?tuple(Elements, _Arity, _Tag)) ->
- Fun(t_tuple([t_map(Fun, E) || E <- Elements]));
-t_map(Fun, ?tuple_set(_) = Tuples) ->
- Fun(t_sup([t_map(Fun, T) || T <- t_tuple_subtypes(Tuples)]));
-t_map(Fun, ?opaque(Set)) ->
- L = [Opaque#opaque{struct = NewS} ||
- #opaque{struct = S} = Opaque <- set_to_list(Set),
- not t_is_none(NewS = t_map(Fun, S))],
- Fun(case L of
- [] -> ?none;
- _ -> ?opaque(ordsets:from_list(L))
- end);
-t_map(Fun, ?map(Pairs,DefK,DefV)) ->
- %% TODO:
- Fun(t_map(Pairs, Fun(DefK), Fun(DefV)));
-t_map(Fun, T) ->
- Fun(T).
-
%%=============================================================================
%%
%% Prettyprinter
diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile
index 1c774d3357..104c15f2bb 100644
--- a/lib/hipe/doc/src/Makefile
+++ b/lib/hipe/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2017. All Rights Reserved.
+# Copyright Ericsson AB 2006-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -94,6 +94,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index f47868296a..9a803cb9df 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -31,6 +31,52 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.18.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug in the handling of the <c>Key</c> argument
+ of <c>lists:{keysearch, keyfind, keymember}</c>. </p>
+ <p>
+ Own Id: OTP-15570</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.18.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The code was updated to avoid causing a dialyzer
+ warning because of a tightened spec for
+ <c>beam_lib:info/1</c>.</p>
+ <p>
+ Own Id: OTP-15482</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.18.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.18</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index ac2e6c1e3b..e2cb9c0f0b 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -542,7 +542,7 @@ file(File) ->
| {'error', term()}
when Mod :: mod().
file(File, Options) when is_atom(File) ->
- case beam_lib:info(File) of
+ case beam_lib:info(atom_to_list(File)) of
L when is_list(L) ->
{module, Mod} = lists:keyfind(module, 1, L),
case compile(Mod, File, Options) of
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index b081cb0c26..39565d721f 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.18
+HIPE_VSN = 3.18.3
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index 29b8678cda..cbc0e384d8 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -115,6 +115,7 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
man: $(MAN3_FILES)
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index 2dec5acbf9..6d3547f4fe 100644
--- a/lib/inets/doc/src/http_uri.xml
+++ b/lib/inets/doc/src/http_uri.xml
@@ -30,7 +30,7 @@
<rev></rev>
</header>
- <module>http_uri</module>
+ <module since="OTP R15B01">http_uri</module>
<modulesummary>URI utility module</modulesummary>
<description>
@@ -79,7 +79,7 @@
<funcs>
<func>
- <name>decode(HexEncodedURI) -> URI</name>
+ <name since="OTP R15B01">decode(HexEncodedURI) -> URI</name>
<fsummary>Decodes a hexadecimal encoded URI.</fsummary>
<type>
@@ -93,7 +93,7 @@
</desc>
</func>
<func>
- <name>encode(URI) -> HexEncodedURI</name>
+ <name since="OTP R15B01">encode(URI) -> HexEncodedURI</name>
<fsummary>Encodes a hexadecimal encoded URI.</fsummary>
<type>
@@ -109,8 +109,8 @@
</func>
<func>
- <name>parse(URI) -> {ok, Result} | {error, Reason}</name>
- <name>parse(URI, Options) -> {ok, Result} | {error, Reason}</name>
+ <name since="OTP R15B01">parse(URI) -> {ok, Result} | {error, Reason}</name>
+ <name since="OTP R15B01">parse(URI, Options) -> {ok, Result} | {error, Reason}</name>
<fsummary>Parses a URI.</fsummary>
<type>
<v>URI = uri()</v>
@@ -165,7 +165,7 @@ fun(SchemeStr :: string() | binary()) ->
</func>
<func>
- <name>scheme_defaults() -> SchemeDefaults</name>
+ <name since="OTP R15B01">scheme_defaults() -> SchemeDefaults</name>
<fsummary>A list of the scheme and their default ports.</fsummary>
<type>
<v>SchemeDefaults = [{scheme(), default_scheme_port_number()}] </v>
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index a2871f3b95..7451b314ec 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -30,7 +30,7 @@
<rev></rev>
</header>
- <module>httpc</module>
+ <module since="OTP R13B04">httpc</module>
<modulesummary>An HTTP/1.1 client</modulesummary>
<description>
@@ -151,8 +151,8 @@
<funcs>
<func>
- <name>cancel_request(RequestId) -></name>
- <name>cancel_request(RequestId, Profile) -> ok</name>
+ <name since="OTP R13B04">cancel_request(RequestId) -></name>
+ <name since="OTP R13B04">cancel_request(RequestId, Profile) -> ok</name>
<fsummary>Cancels an asynchronous HTTP request.</fsummary>
<type>
<v>RequestId = request_id() - A unique identifier as returned
@@ -169,9 +169,9 @@
</func>
<func>
- <name>cookie_header(Url) -> </name>
- <name>cookie_header(Url, Profile | Opts) -> header() | {error, Reason}</name>
- <name>cookie_header(Url, Opts, Profile) -> header() | {error, Reason}</name>
+ <name since="OTP R13B04">cookie_header(Url) -> </name>
+ <name since="OTP R13B04">cookie_header(Url, Profile | Opts) -> header() | {error, Reason}</name>
+ <name since="OTP R15B">cookie_header(Url, Opts, Profile) -> header() | {error, Reason}</name>
<fsummary>Returns the cookie header that would have been sent when
making a request to URL using the profile <c>Profile</c>.</fsummary>
<type>
@@ -193,8 +193,8 @@
</func>
<func>
- <name>get_options(OptionItems) -> {ok, Values} | {error, Reason}</name>
- <name>get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason}</name>
+ <name since="OTP R15B01">get_options(OptionItems) -> {ok, Values} | {error, Reason}</name>
+ <name since="OTP R15B01">get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason}</name>
<fsummary>Gets the currently used options.</fsummary>
<type>
<v>OptionItems = all | [option_item()]</v>
@@ -223,8 +223,8 @@
</func>
<func>
- <name>info() -> list()</name>
- <name>info(Profile) -> list()</name>
+ <name since="OTP R15B02">info() -> list()</name>
+ <name since="OTP R15B02">info(Profile) -> list()</name>
<fsummary>Produces a list of miscellaneous information.</fsummary>
<type>
<v>Profile = profile() | pid()</v>
@@ -239,8 +239,8 @@
<func>
- <name>reset_cookies() -> void()</name>
- <name>reset_cookies(Profile) -> void()</name>
+ <name since="OTP R13B04">reset_cookies() -> void()</name>
+ <name since="OTP R13B04">reset_cookies(Profile) -> void()</name>
<fsummary>Resets the cookie database.</fsummary>
<type>
<v>Profile = profile() | pid()</v>
@@ -254,8 +254,8 @@
</func>
<func>
- <name>request(Url) -> </name>
- <name>request(Url, Profile) -> {ok, Result} | {error, Reason}</name>
+ <name since="OTP R13B04">request(Url) -> </name>
+ <name since="OTP R13B04">request(Url, Profile) -> {ok, Result} | {error, Reason}</name>
<fsummary>Sends a get HTTP request.</fsummary>
<type>
<v>Url = url()</v>
@@ -272,8 +272,8 @@
</func>
<func>
- <name>request(Method, Request, HTTPOptions, Options) -></name>
- <name>request(Method, Request, HTTPOptions, Options, Profile) -> {ok, Result} | {ok, saved_to_file} | {error, Reason}</name>
+ <name since="OTP R13B04">request(Method, Request, HTTPOptions, Options) -></name>
+ <name since="OTP R13B04">request(Method, Request, HTTPOptions, Options, Profile) -> {ok, Result} | {ok, saved_to_file} | {error, Reason}</name>
<fsummary>Sends an HTTP request.</fsummary>
<type>
@@ -521,8 +521,8 @@
<func>
- <name>set_options(Options) -> </name>
- <name>set_options(Options, Profile) -> ok | {error, Reason}</name>
+ <name since="OTP R13B04">set_options(Options) -> </name>
+ <name since="OTP R13B04">set_options(Options, Profile) -> ok | {error, Reason}</name>
<fsummary>Sets options to be used for subsequent requests.</fsummary>
<type>
<v>Options = [Option]</v>
@@ -639,8 +639,8 @@
</func>
<func>
- <name>store_cookies(SetCookieHeaders, Url) -> </name>
- <name>store_cookies(SetCookieHeaders, Url, Profile) -> ok | {error, Reason}</name>
+ <name since="OTP R14B02">store_cookies(SetCookieHeaders, Url) -> </name>
+ <name since="OTP R14B02">store_cookies(SetCookieHeaders, Url, Profile) -> ok | {error, Reason}</name>
<fsummary>Saves the cookies defined in <c>SetCookieHeaders</c> in the
client profile cookie database.</fsummary>
<type>
@@ -658,7 +658,7 @@
</func>
<func>
- <name>stream_next(Pid) -> ok</name>
+ <name since="OTP R13B04">stream_next(Pid) -> ok</name>
<fsummary>Triggers the next message to be streamed, that is,
the same behavior as active one for sockets.
</fsummary>
@@ -676,8 +676,8 @@
</func>
<func>
- <name>which_cookies() -> cookies()</name>
- <name>which_cookies(Profile) -> cookies()</name>
+ <name since="OTP R13B04">which_cookies() -> cookies()</name>
+ <name since="OTP R13B04">which_cookies(Profile) -> cookies()</name>
<fsummary>Dumps the entire cookie database.</fsummary>
<type>
<v>Profile = profile() | pid()</v>
@@ -695,8 +695,8 @@
</func>
<func>
- <name>which_sessions() -> session_info()</name>
- <name>which_sessions(Profile) -> session_info()</name>
+ <name since="OTP R15B02">which_sessions() -> session_info()</name>
+ <name since="OTP R15B02">which_sessions(Profile) -> session_info()</name>
<fsummary>Produces a slightly processed dump of the sessions database.</fsummary>
<type>
<v>Profile = profile() | pid()</v>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 2c70c2b050..66369e8df9 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -29,7 +29,7 @@
<rev>2.2</rev>
<file>httpd.sgml</file>
</header>
- <module>httpd</module>
+ <module since="">httpd</module>
<modulesummary>
HTTP server API
</modulesummary>
@@ -874,8 +874,8 @@ text/plain asc txt</pre>
<funcs>
<func>
- <name>info(Pid) -></name>
- <name>info(Pid, Properties) -> [{Option, Value}]</name>
+ <name since="">info(Pid) -></name>
+ <name since="">info(Pid, Properties) -> [{Option, Value}]</name>
<fsummary>Fetches information about the HTTP server.</fsummary>
<type>
<v>Properties = [property()]</v>
@@ -899,10 +899,10 @@ text/plain asc txt</pre>
</func>
<func>
- <name>info(Address, Port) -> </name>
- <name>info(Address, Port, Profile) -> </name>
- <name>info(Address, Port, Profile, Properties) -> [{Option, Value}] </name>
- <name>info(Address, Port, Properties) -> [{Option, Value}] </name>
+ <name since="">info(Address, Port) -> </name>
+ <name since="">info(Address, Port, Profile) -> </name>
+ <name since="OTP 18.0">info(Address, Port, Profile, Properties) -> [{Option, Value}] </name>
+ <name since="">info(Address, Port, Properties) -> [{Option, Value}] </name>
<fsummary>Fetches information about the HTTP server.</fsummary>
<type>
<v>Address = ip_address()</v>
@@ -927,7 +927,7 @@ text/plain asc txt</pre>
</func>
<func>
- <name>reload_config(Config, Mode) -> ok | {error, Reason}</name>
+ <name since="">reload_config(Config, Mode) -> ok | {error, Reason}</name>
<fsummary>Reloads the HTTP server configuration without
restarting the server.</fsummary>
<type>
@@ -1051,7 +1051,7 @@ text/plain asc txt</pre>
</section>
<funcs>
<func>
- <name>Module:do(ModData)-> {proceed, OldData} | {proceed, NewData} | {break, NewData} | done</name>
+ <name since="">Module:do(ModData)-> {proceed, OldData} | {proceed, NewData} | {break, NewData} | done</name>
<fsummary>Called for each request to the web server.</fsummary>
<type>
<v>OldData = list()</v>
@@ -1105,7 +1105,7 @@ text/plain asc txt</pre>
</func>
<func>
- <name>Module:load(Line, AccIn)-> eof | ok | {ok, AccOut} | {ok, AccOut, {Option, Value}} | {ok, AccOut, [{Option, Value}]} | {error, Reason}</name>
+ <name since="">Module:load(Line, AccIn)-> eof | ok | {ok, AccOut} | {ok, AccOut, {Option, Value}} | {ok, AccOut, [{Option, Value}]} | {error, Reason}</name>
<fsummary>Converts a line in an Apache-like config
file to an <c>{Option, Value}</c> tuple.</fsummary>
<type>
@@ -1128,7 +1128,7 @@ text/plain asc txt</pre>
</func>
<func>
- <name>Module:remove(ConfigDB) -> ok | {error, Reason} </name>
+ <name since="">Module:remove(ConfigDB) -> ok | {error, Reason} </name>
<fsummary>Callback function that is called when the web server is closed.</fsummary>
<type>
<v>ConfigDB = ets_table()</v>
@@ -1143,7 +1143,7 @@ text/plain asc txt</pre>
</func>
<func>
- <name>Module:store({Option, Value}, Config)-> {ok, {Option, NewValue}} | {error, Reason}</name>
+ <name since="">Module:store({Option, Value}, Config)-> {ok, {Option, NewValue}} | {error, Reason}</name>
<fsummary>Checks the validity of the configuration options.</fsummary>
<type>
<v>Line = string()</v>
@@ -1171,7 +1171,7 @@ text/plain asc txt</pre>
</section>
<funcs>
<func>
- <name>parse_query(QueryString) -> [{Key,Value}]</name>
+ <name since="">parse_query(QueryString) -> [{Key,Value}]</name>
<fsummary>Parses incoming data to <c>erl</c> and <c>eval</c> scripts.</fsummary>
<type>
<v>QueryString = string()</v>
diff --git a/lib/inets/doc/src/httpd_custom_api.xml b/lib/inets/doc/src/httpd_custom_api.xml
index d2e5441895..2c0f92ff83 100644
--- a/lib/inets/doc/src/httpd_custom_api.xml
+++ b/lib/inets/doc/src/httpd_custom_api.xml
@@ -25,7 +25,7 @@
<title>httpd_custom_api</title>
<file>httpd_custom_api.xml</file>
</header>
- <module>httpd_custom_api</module>
+ <module since="OTP 17.5.6">httpd_custom_api</module>
<modulesummary>Behaviour with optional callbacks to customize the inets HTTP server.</modulesummary>
<description>
<p> The module implementing this behaviour shall be supplied to to the servers
@@ -34,7 +34,7 @@
</description>
<funcs>
<func>
- <name>response_default_headers() -> [Header] </name>
+ <name since="OTP 18.1.1">response_default_headers() -> [Header] </name>
<fsummary>Provide default headers for the HTTP servers responses.</fsummary>
<type>
<v>Header = {HeaderName :: string(), HeaderValue::string()}</v>
@@ -48,7 +48,7 @@
</func>
<func>
- <name>response_header({HeaderName, HeaderValue}) -> {true, Header} | false </name>
+ <name since="OTP 17.5.6">response_header({HeaderName, HeaderValue}) -> {true, Header} | false </name>
<fsummary>Filter and possible alter HTTP response headers.</fsummary>
<type>
<v>Header = {HeaderName :: string(), HeaderValue::string()}</v>
@@ -61,7 +61,7 @@
</func>
<func>
- <name>request_header({HeaderName, HeaderValue}) -> {true, Header} | false </name>
+ <name since="OTP 17.5.6">request_header({HeaderName, HeaderValue}) -> {true, Header} | false </name>
<fsummary>Filter and possible alter HTTP request headers.</fsummary>
<type>
<v>Header = {HeaderName :: string(), HeaderValue::string()}</v>
diff --git a/lib/inets/doc/src/httpd_socket.xml b/lib/inets/doc/src/httpd_socket.xml
index d3aa82a540..22ead06f38 100644
--- a/lib/inets/doc/src/httpd_socket.xml
+++ b/lib/inets/doc/src/httpd_socket.xml
@@ -29,7 +29,7 @@
<rev>2.2</rev>
<file>httpd_socket.sgml</file>
</header>
- <module>httpd_socket</module>
+ <module since="">httpd_socket</module>
<modulesummary>Communication utility functions to be used by the Erlang
web server API programmer.</modulesummary>
<description>
@@ -43,7 +43,7 @@
<funcs>
<func>
- <name>deliver(SocketType, Socket, Data) -> Result</name>
+ <name since="">deliver(SocketType, Socket, Data) -> Result</name>
<fsummary>Sends binary data over socket.</fsummary>
<type>
<v>SocketType = socket_type()</v>
@@ -63,7 +63,7 @@
</func>
<func>
- <name>peername(SocketType,Socket) -> {Port,IPAddress}</name>
+ <name since="">peername(SocketType,Socket) -> {Port,IPAddress}</name>
<fsummary>Returns the port and IP address of the remote socket.</fsummary>
<type>
<v>SocketType = socket_type()</v>
@@ -81,7 +81,7 @@
</func>
<func>
- <name>resolve() -> HostName</name>
+ <name since="">resolve() -> HostName</name>
<fsummary>Returns the official name of the current host.</fsummary>
<type>
<v>HostName = string()</v>
diff --git a/lib/inets/doc/src/httpd_util.xml b/lib/inets/doc/src/httpd_util.xml
index 220a2ede35..e0f947f860 100644
--- a/lib/inets/doc/src/httpd_util.xml
+++ b/lib/inets/doc/src/httpd_util.xml
@@ -29,7 +29,7 @@
<rev>2.2</rev>
<file>httpd_util.sgml</file>
</header>
- <module>httpd_util</module>
+ <module since="">httpd_util</module>
<modulesummary>Miscellaneous utility functions to be used when implementing
Erlang web server API modules.</modulesummary>
<description>
@@ -41,12 +41,11 @@
<funcs>
<func>
- <name>convert_request_date(DateString) -> ErlDate|bad_date</name>
+ <name since="">convert_request_date(DateString) -> ErlDate|bad_date</name>
<fsummary>Converts the date to the Erlang date format.</fsummary>
<type>
<v>DateString = string()</v>
- <v>ErlDate = {{Year,Month,Date},{Hour,Min,Sec}}</v>
- <v>Year = Month = Date = Hour = Min = Sec = integer()</v>
+ <v>ErlDate = calendar:datetime() </v>
</type>
<desc>
<p><c>convert_request_date/1</c> converts <c>DateString</c> to
@@ -57,7 +56,7 @@
</func>
<func>
- <name>create_etag(FileInfo) -> Etag</name>
+ <name since="">create_etag(FileInfo) -> Etag</name>
<fsummary>Calculates the Etag for a file.</fsummary>
<type>
<v>FileInfo = file_info()</v>
@@ -71,7 +70,7 @@
</func>
<func>
- <name>day(NthDayOfWeek) -> DayOfWeek</name>
+ <name since="">day(NthDayOfWeek) -> DayOfWeek</name>
<fsummary>Converts the day of the week
(integer [1-7]) to an abbreviated string.</fsummary>
<type>
@@ -87,7 +86,7 @@
</func>
<func>
- <name>decode_hex(HexValue) -> DecValue</name>
+ <name since="">decode_hex(HexValue) -> DecValue</name>
<fsummary>Converts a hexadecimal value into its decimal equivalent.</fsummary>
<type>
<v>HexValue = DecValue = string()</v>
@@ -99,7 +98,7 @@
</func>
<func>
- <name>flatlength(NestedList) -> Size</name>
+ <name since="">flatlength(NestedList) -> Size</name>
<fsummary>Computes the size of a possibly nested list.</fsummary>
<type>
<v>NestedList = list()</v>
@@ -112,7 +111,7 @@
</func>
<func>
- <name>hexlist_to_integer(HexString) -> Number</name>
+ <name since="">hexlist_to_integer(HexString) -> Number</name>
<fsummary>Converts a hexadecimal string to an integer.</fsummary>
<type>
<v>Number = integer()</v>
@@ -125,7 +124,7 @@
</func>
<func>
- <name>integer_to_hexlist(Number) -> HexString</name>
+ <name since="">integer_to_hexlist(Number) -> HexString</name>
<fsummary>Converts an integer to a hexadecimal string.</fsummary>
<type>
<v>Number = integer()</v>
@@ -138,8 +137,8 @@
</func>
<func>
- <name>lookup(ETSTable,Key) -> Result</name>
- <name>lookup(ETSTable,Key,Undefined) -> Result</name>
+ <name since="">lookup(ETSTable,Key) -> Result</name>
+ <name since="">lookup(ETSTable,Key,Undefined) -> Result</name>
<fsummary>Extracts the first value associated with a <c>Key</c>
in an ETS table.</fsummary>
<type>
@@ -160,8 +159,8 @@
</func>
<func>
- <name>lookup_mime(ConfigDB,Suffix)</name>
- <name>lookup_mime(ConfigDB,Suffix,Undefined) -> MimeType</name>
+ <name since="">lookup_mime(ConfigDB,Suffix)</name>
+ <name since="">lookup_mime(ConfigDB,Suffix,Undefined) -> MimeType</name>
<fsummary>Returns the MIME type associated with a specific file suffix.</fsummary>
<type>
<v>ConfigDB = ets_table()</v>
@@ -179,8 +178,8 @@
</func>
<func>
- <name>lookup_mime_default(ConfigDB,Suffix)</name>
- <name>lookup_mime_default(ConfigDB,Suffix,Undefined) -> MimeType</name>
+ <name since="">lookup_mime_default(ConfigDB,Suffix)</name>
+ <name since="">lookup_mime_default(ConfigDB,Suffix,Undefined) -> MimeType</name>
<fsummary>Returns the MIME type associated with a specific file suffix
or the value of the DefaultType.</fsummary>
<type>
@@ -201,7 +200,7 @@
</func>
<func>
- <name>message(StatusCode,PhraseArgs,ConfigDB) -> Message</name>
+ <name since="">message(StatusCode,PhraseArgs,ConfigDB) -> Message</name>
<fsummary>Returns an informative HTTP 1.1 status string in HTML.</fsummary>
<type>
<v>StatusCode = 301 | 400 | 403 | 404 | 500 | 501 | 504</v>
@@ -236,7 +235,7 @@
</func>
<func>
- <name>month(NthMonth) -> Month</name>
+ <name since="">month(NthMonth) -> Month</name>
<fsummary>Converts the month as an integer (1-12) to an abbreviated string.</fsummary>
<type>
<v>NthMonth = 1-12</v>
@@ -250,7 +249,7 @@
</func>
<func>
- <name>multi_lookup(ETSTable,Key) -> Result</name>
+ <name since="">multi_lookup(ETSTable,Key) -> Result</name>
<fsummary>Extracts the values associated with a key in an ETS table.</fsummary>
<type>
<v>ETSTable = ets_table()</v>
@@ -265,7 +264,7 @@
</func>
<func>
- <name>reason_phrase(StatusCode) -> Description</name>
+ <name since="">reason_phrase(StatusCode) -> Description</name>
<fsummary>Returns the description of an HTTP 1.1 status code.</fsummary>
<type>
<v>StatusCode = 100| 200 | 201 | 202 | 204 | 205 | 206 | 300 | 301 | 302 | 303 | 304 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 410 411 | 412 | 413 | 414 415 | 416 | 417 | 500 | 501 | 502 | 503 | 504 | 505</v>
@@ -280,11 +279,11 @@
</func>
<func>
- <name>rfc1123_date() -> RFC1123Date</name>
- <name>rfc1123_date({{YYYY,MM,DD},{Hour,Min,Sec}}) -> RFC1123Date</name>
+ <name since="">rfc1123_date() -> RFC1123Date</name>
+ <name since="">rfc1123_date(Date) -> RFC1123Date</name>
<fsummary>Returns the current date in RFC 1123 format.</fsummary>
<type>
- <v>YYYY = MM = DD = Hour = Min = Sec = integer()</v>
+ <v> Date = calendar:datetime()</v>
<v>RFC1123Date = string()</v>
</type>
<desc>
@@ -295,7 +294,7 @@
</func>
<func>
- <name>split(String,RegExp,N) -> SplitRes</name>
+ <name since="">split(String,RegExp,N) -> SplitRes</name>
<fsummary>Splits a string in N chunks using a regular expression.</fsummary>
<type>
<v>String = RegExp = string()</v>
@@ -313,7 +312,7 @@
</func>
<func>
- <name>split_script_path(RequestLine) -> Splitted</name>
+ <name since="">split_script_path(RequestLine) -> Splitted</name>
<fsummary>Splits a <c>RequestLine</c> in a file reference to an executable,
and a <c>QueryString</c> or a <c>PathInfo</c>string.</fsummary>
<type>
@@ -330,7 +329,7 @@
</func>
<func>
- <name>split_path(RequestLine) -> {Path,QueryStringOrPathInfo}</name>
+ <name since="">split_path(RequestLine) -> {Path,QueryStringOrPathInfo}</name>
<fsummary>Splits a <c>RequestLine</c> in a file reference, and a
<c>QueryString</c> or a <c>PathInfo</c> string.</fsummary>
<type>
@@ -356,7 +355,7 @@
</func>
<func>
- <name>strip(String) -> Stripped</name>
+ <name since="">strip(String) -> Stripped</name>
<fsummary>Returns <c>String</c> where the leading and trailing space
tabs are removed.</fsummary>
<type>
@@ -370,7 +369,7 @@
</func>
<func>
- <name>suffix(FileName) -> Suffix</name>
+ <name since="">suffix(FileName) -> Suffix</name>
<fsummary>Extracts the file suffix from a given filename.</fsummary>
<type>
<v>FileName = Suffix = string()</v>
diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml
index 9b0ffaad5e..176af3137a 100644
--- a/lib/inets/doc/src/inets.xml
+++ b/lib/inets/doc/src/inets.xml
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>inets</module>
+ <module since="">inets</module>
<modulesummary>The Inets services API.</modulesummary>
<description>
<p>This module provides the most basic API to the
@@ -51,7 +51,7 @@
<funcs>
<func>
- <name>services() -> [{Service, Pid}]</name>
+ <name since="">services() -> [{Service, Pid}]</name>
<fsummary>Returns a list of currently running services.</fsummary>
<type>
<v>Service = service()</v>
@@ -68,7 +68,7 @@
</func>
<func>
- <name>services_info() -> [{Service, Pid, Info}]</name>
+ <name since="">services_info() -> [{Service, Pid, Info}]</name>
<fsummary>Returns a list of currently running services where
each service is described by an <c>[{Option, Value}]</c>
list.</fsummary>
@@ -91,7 +91,7 @@
</func>
<func>
- <name>service_names() -> [Service] </name>
+ <name since="">service_names() -> [Service] </name>
<fsummary>Returns a list of available service names.</fsummary>
<type>
<v>Service = service()</v>
@@ -104,8 +104,8 @@
</func>
<func>
- <name>start() -> </name>
- <name>start(Type) -> ok | {error, Reason}</name>
+ <name since="">start() -> </name>
+ <name since="">start(Type) -> ok | {error, Reason}</name>
<fsummary>Starts the <c>Inets</c> application.</fsummary>
<type>
<v>Type = permanent | transient | temporary</v>
@@ -120,8 +120,8 @@
</func>
<func>
- <name>start(Service, ServiceConfig) -> {ok, Pid} | {error, Reason}</name>
- <name>start(Service, ServiceConfig, How) -> {ok, Pid} | {error, Reason}</name>
+ <name since="">start(Service, ServiceConfig) -> {ok, Pid} | {error, Reason}</name>
+ <name since="">start(Service, ServiceConfig, How) -> {ok, Pid} | {error, Reason}</name>
<fsummary>Dynamically starts an <c>Inets</c>
service after the <c>Inets</c> application has been started.</fsummary>
<type>
@@ -156,7 +156,7 @@
</func>
<func>
- <name>stop() -> ok </name>
+ <name since="">stop() -> ok </name>
<fsummary>Stops the <c>Inets</c> application.</fsummary>
<desc>
<p>Stops the <c>Inets</c> application. See also
@@ -167,7 +167,7 @@
</func>
<func>
- <name>stop(Service, Reference) -> ok | {error, Reason} </name>
+ <name since="">stop(Service, Reference) -> ok | {error, Reason} </name>
<fsummary>Stops a started service of the <c>Inets</c> application or takes
down a <c>stand_alone </c>service gracefully.</fsummary>
<type>
diff --git a/lib/inets/doc/src/mod_alias.xml b/lib/inets/doc/src/mod_alias.xml
index 6ae19700a5..ff57d49d08 100644
--- a/lib/inets/doc/src/mod_alias.xml
+++ b/lib/inets/doc/src/mod_alias.xml
@@ -29,7 +29,7 @@
<rev>2.2</rev>
<file>mod_alias.sgml</file>
</header>
- <module>mod_alias</module>
+ <module since="">mod_alias</module>
<modulesummary>URL aliasing.</modulesummary>
<description>
<p>Erlang web server internal API for handling of, for example,
@@ -40,7 +40,7 @@
<funcs>
<func>
- <name>default_index(ConfigDB, Path) -> NewPath</name>
+ <name since="">default_index(ConfigDB, Path) -> NewPath</name>
<fsummary>Returns a new path with the default resource or file appended.</fsummary>
<type>
<v>ConfigDB = config_db()</v>
@@ -64,7 +64,7 @@
</func>
<func>
- <name>path(PathData, ConfigDB, RequestURI) -> Path</name>
+ <name since="">path(PathData, ConfigDB, RequestURI) -> Path</name>
<fsummary>Returns the file path to a URL.</fsummary>
<type>
<v>PathData = interaction_data()</v>
@@ -89,7 +89,7 @@
</func>
<func>
- <name>real_name(ConfigDB, RequestURI, Aliases) -> Ret</name>
+ <name since="">real_name(ConfigDB, RequestURI, Aliases) -> Ret</name>
<fsummary>Expands a request URI using <c>Aliases</c> config directives.</fsummary>
<type>
<v>ConfigDB = config_db()</v>
@@ -120,7 +120,7 @@
</func>
<func>
- <name>real_script_name(ConfigDB, RequestURI, ScriptAliases) -> Ret</name>
+ <name since="">real_script_name(ConfigDB, RequestURI, ScriptAliases) -> Ret</name>
<fsummary>Expands a request URI using <c>ScriptAliases</c>
config directives.</fsummary>
<type>
diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml
index c4f844622b..ad864ca4d1 100644
--- a/lib/inets/doc/src/mod_auth.xml
+++ b/lib/inets/doc/src/mod_auth.xml
@@ -29,7 +29,7 @@
<rev>2.3</rev>
<file>mod_auth.sgml</file>
</header>
- <module>mod_auth</module>
+ <module since="">mod_auth</module>
<modulesummary>User authentication using text files, Dets, or Mnesia database.</modulesummary>
<description>
<p>This module provides for basic user authentication using
@@ -38,9 +38,9 @@
<funcs>
<func>
- <name>add_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name>
- <name>add_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name>
- <name>add_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">add_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name>
+ <name since="">add_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">add_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name>
<fsummary>Adds a user to a group.</fsummary>
<type>
<v>GroupName = string()</v>
@@ -65,9 +65,9 @@
</func>
<func>
- <name>add_user(UserName, Options) -> true| {error, Reason}</name>
- <name>add_user(UserName, Password, UserData, Port, Dir) -> true | {error, Reason}</name>
- <name>add_user(UserName, Password, UserData, Address, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">add_user(UserName, Options) -> true| {error, Reason}</name>
+ <name since="">add_user(UserName, Password, UserData, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">add_user(UserName, Password, UserData, Address, Port, Dir) -> true | {error, Reason}</name>
<fsummary>Adds a user to the user database.</fsummary>
<type>
<v>UserName = string()</v>
@@ -92,8 +92,8 @@
</func>
<func>
- <name>delete_group(GroupName, Options) -> true | {error,Reason} &lt;name>delete_group(GroupName, Port, Dir) -> true | {error, Reason}</name>
- <name>delete_group(GroupName, Address, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">delete_group(GroupName, Options) -> true | {error,Reason} &lt;name>delete_group(GroupName, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">delete_group(GroupName, Address, Port, Dir) -> true | {error, Reason}</name>
<fsummary>Deletes a group.</fsummary>
<type>
<v>Options = [Option]</v>
@@ -115,9 +115,9 @@
</func>
<func>
- <name>delete_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name>
- <name>delete_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name>
- <name>delete_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">delete_group_member(GroupName, UserName, Options) -> true | {error, Reason}</name>
+ <name since="">delete_group_member(GroupName, UserName, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">delete_group_member(GroupName, UserName, Address, Port, Dir) -> true | {error, Reason}</name>
<fsummary>Removes a user from a group.</fsummary>
<type>
<v>GroupName = string()</v>
@@ -141,9 +141,9 @@
</func>
<func>
- <name>delete_user(UserName,Options) -> true | {error, Reason}</name>
- <name>delete_user(UserName, Port, Dir) -> true | {error, Reason}</name>
- <name>delete_user(UserName, Address, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">delete_user(UserName,Options) -> true | {error, Reason}</name>
+ <name since="">delete_user(UserName, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">delete_user(UserName, Address, Port, Dir) -> true | {error, Reason}</name>
<fsummary>Deletes a user from the user database.</fsummary>
<type>
<v>UserName = string()</v>
@@ -166,9 +166,9 @@
</func>
<func>
- <name>get_user(UserName,Options) -> {ok, #httpd_user} |{error, Reason}</name>
- <name>get_user(UserName, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name>
- <name>get_user(UserName, Address, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name>
+ <name since="">get_user(UserName,Options) -> {ok, #httpd_user} |{error, Reason}</name>
+ <name since="">get_user(UserName, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name>
+ <name since="">get_user(UserName, Address, Port, Dir) -> {ok, #httpd_user} | {error, Reason}</name>
<fsummary>Returns a user from the user database.</fsummary>
<type>
<v>UserName = string()</v>
@@ -190,9 +190,9 @@
</func>
<func>
- <name>list_groups(Options) -> {ok, Groups} | {error, Reason}</name>
- <name>list_groups(Port, Dir) -> {ok, Groups} | {error, Reason}</name>
- <name>list_groups(Address, Port, Dir) -> {ok, Groups} | {error, Reason}</name>
+ <name since="">list_groups(Options) -> {ok, Groups} | {error, Reason}</name>
+ <name since="">list_groups(Port, Dir) -> {ok, Groups} | {error, Reason}</name>
+ <name since="">list_groups(Address, Port, Dir) -> {ok, Groups} | {error, Reason}</name>
<fsummary>Lists all the groups.</fsummary>
<type>
<v>Options = [Option]</v>
@@ -214,9 +214,9 @@
</func>
<func>
- <name>list_group_members(GroupName, Options) -> {ok, Users} | {error, Reason}</name>
- <name>list_group_members(GroupName, Port, Dir) -> {ok, Users} | {error, Reason}</name>
- <name>list_group_members(GroupName, Address, Port, Dir) -> {ok, Users} | {error, Reason}</name>
+ <name since="">list_group_members(GroupName, Options) -> {ok, Users} | {error, Reason}</name>
+ <name since="">list_group_members(GroupName, Port, Dir) -> {ok, Users} | {error, Reason}</name>
+ <name since="">list_group_members(GroupName, Address, Port, Dir) -> {ok, Users} | {error, Reason}</name>
<fsummary>Lists the members of a group.</fsummary>
<type>
<v>GroupName = string()</v>
@@ -240,9 +240,9 @@
</func>
<func>
- <name>list_users(Options) -> {ok, Users} | {error, Reason}</name>
- <name>list_users(Port, Dir) -> {ok, Users} | {error, Reason}</name>
- <name>list_users(Address, Port, Dir) -> {ok, Users} | {error, Reason}</name>
+ <name since="">list_users(Options) -> {ok, Users} | {error, Reason}</name>
+ <name since="OTP R14B01">list_users(Port, Dir) -> {ok, Users} | {error, Reason}</name>
+ <name since="">list_users(Address, Port, Dir) -> {ok, Users} | {error, Reason}</name>
<fsummary>Lists users in the user database.</fsummary>
<type>
<v>Options = [Option]</v>
@@ -264,8 +264,8 @@
</func>
<func>
- <name>update_password(Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name>
- <name>update_password(Address,Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name>
+ <name since="">update_password(Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name>
+ <name since="">update_password(Address,Port, Dir, OldPassword, NewPassword, NewPassword) -> ok | {error, Reason}</name>
<fsummary>Changes <c>AuthAcessPassword</c>.</fsummary>
<type>
<v>Port = integer()</v>
diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml
index ede7dc8f7d..bc5f98068f 100644
--- a/lib/inets/doc/src/mod_esi.xml
+++ b/lib/inets/doc/src/mod_esi.xml
@@ -25,7 +25,7 @@
<title>mod_esi</title>
<file>mod_esi.sgml</file>
</header>
- <module>mod_esi</module>
+ <module since="">mod_esi</module>
<modulesummary>Erlang Server Interface</modulesummary>
<description>
<p>This module defines the Erlang Server Interface (ESI) API.
@@ -88,7 +88,7 @@
<funcs>
<func>
- <name>deliver(SessionID, Data) -> ok | {error, Reason}</name>
+ <name since="">deliver(SessionID, Data) -> ok | {error, Reason}</name>
<fsummary>Sends <c>Data</c> back to client.</fsummary>
<type>
<v>SessionID = term()</v>
@@ -121,7 +121,7 @@
<funcs>
<func>
- <name>Module:Function(SessionID, Env, Input)-> {continue, State} | _ </name>
+ <name since="">Module:Function(SessionID, Env, Input)-> {continue, State} | _ </name>
<fsummary>Creates a dynamic web page and returns it chunk by chunk
to the server process by calling <c>mod_esi:deliver/2</c>.</fsummary>
<type>
@@ -179,7 +179,7 @@
</func>
<func>
- <name>Module:Function(Env, Input)-> Response </name>
+ <name since="">Module:Function(Env, Input)-> Response </name>
<fsummary>Creates a dynamic web page and returns it as a list.
This function is deprecated and is only kept for backwards compatibility.</fsummary>
<type>
diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml
index ec8d6ec42c..c26d7468c2 100644
--- a/lib/inets/doc/src/mod_security.xml
+++ b/lib/inets/doc/src/mod_security.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2016</year>
+ <year>1998</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -29,7 +29,7 @@
<rev>1.0</rev>
<file>mod_security.sgml</file>
</header>
- <module>mod_security</module>
+ <module since="">mod_security</module>
<modulesummary>Security Audit and Trailing Functionality</modulesummary>
<description>
<p>Security Audit and Trailing Functionality</p>
@@ -37,8 +37,8 @@
<funcs>
<func>
- <name>block_user(User, Port, Dir, Seconds) -> true | {error, Reason}</name>
- <name>block_user(User, Address, Port, Dir, Seconds) -> true | {error, Reason}</name>
+ <name since="">block_user(User, Port, Dir, Seconds) -> true | {error, Reason}</name>
+ <name since="">block_user(User, Address, Port, Dir, Seconds) -> true | {error, Reason}</name>
<fsummary>Blocks a user from access to a directory for a certain amount of time.</fsummary>
<type>
<v>User = string()</v>
@@ -56,10 +56,10 @@
</func>
<func>
- <name>list_auth_users(Port) -> Users | []</name>
- <name>list_auth_users(Address, Port) -> Users | []</name>
- <name>list_auth_users(Port, Dir) -> Users | []</name>
- <name>list_auth_users(Address, Port, Dir) -> Users | []</name>
+ <name since="">list_auth_users(Port) -> Users | []</name>
+ <name since="">list_auth_users(Address, Port) -> Users | []</name>
+ <name since="">list_auth_users(Port, Dir) -> Users | []</name>
+ <name since="">list_auth_users(Address, Port, Dir) -> Users | []</name>
<fsummary>Lists users that have authenticated within the <c>SecurityAuthTimeout</c>
time for a given address (if specified), port number, and directory
(if specified).</fsummary>
@@ -77,10 +77,10 @@
</desc>
</func>
<func>
- <name>list_blocked_users(Port) -> Users | []</name>
- <name>list_blocked_users(Address, Port) -> Users | []</name>
- <name>list_blocked_users(Port, Dir) -> Users | []</name>
- <name>list_blocked_users(Address, Port, Dir) -> Users | []</name>
+ <name since="">list_blocked_users(Port) -> Users | []</name>
+ <name since="">list_blocked_users(Address, Port) -> Users | []</name>
+ <name since="">list_blocked_users(Port, Dir) -> Users | []</name>
+ <name since="">list_blocked_users(Address, Port, Dir) -> Users | []</name>
<fsummary>Lists users that are currently blocked from access to a
specified port number, for a given address (if specified).</fsummary>
<type>
@@ -97,10 +97,10 @@
</func>
<func>
- <name>unblock_user(User, Port) -> true | {error, Reason}</name>
- <name>unblock_user(User, Address, Port) -> true | {error, Reason}</name>
- <name>unblock_user(User, Port, Dir) -> true | {error, Reason}</name>
- <name>unblock_user(User, Address, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">unblock_user(User, Port) -> true | {error, Reason}</name>
+ <name since="">unblock_user(User, Address, Port) -> true | {error, Reason}</name>
+ <name since="">unblock_user(User, Port, Dir) -> true | {error, Reason}</name>
+ <name since="">unblock_user(User, Address, Port, Dir) -> true | {error, Reason}</name>
<fsummary>Removes a blocked user from the block list.</fsummary>
<type>
<v>User = string()</v>
@@ -129,13 +129,14 @@
<funcs>
<func>
- <name>Module:event(What, Port, Dir, Data) -> ignored</name>
- <name>Module:event(What, Address, Port, Dir, Data) -> ignored</name>
+ <name since="OTP 18.1">Module:event(What, Port, Dir, Data) -> ignored</name>
+ <name since="OTP 18.1">Module:event(What, Address, Port, Dir, Data) -> ignored</name>
<fsummary>Called whenever an event occurs in <c>mod_security</c>.</fsummary>
<type>
<v>What = atom()</v>
<v>Port = integer()</v>
- <v>Address = {A,B,C,D} | string() &lt;v>Dir = string()</v>
+ <v>Address = {A,B,C,D} | string()</v>
+ <v>Dir = string()</v>
<v>Data = [Info]</v>
<v>Info = {Name, Value}</v>
</type>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index f4bf4b1e1f..a1b5dfc309 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,12 +33,185 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 7.0</title>
+ <section><title>Inets 7.0.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the internal handling of the option
+ erl_script_timeout in httpd. If explicit
+ erl_script_timeout value was supplied in seconds it was
+ not correctly converted to millisecond units for internal
+ usage.</p>
+ <p>
+ This change fixes the handling of erl_script_timeout in
+ all possible configuration scenarios.</p>
+ <p>
+ Own Id: OTP-15769 Aux Id: ERIERL-345 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the internal handling of the option
+ erl_script_timeout in httpd. When httpd was started with
+ explicit erl_script_timeout, the value of the option was
+ converted to milliseconds before storage. Subsequent
+ calls to httpd:info/1 returned the input value multiplied
+ by 1000.</p>
+ <p>
+ This change fixes the handing of erl_script_timeout by
+ storing the timeout in seconds and converting to
+ milliseconds before usage.</p>
+ <p>
+ Own Id: OTP-15669 Aux Id: ERIERL-321 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Enhance documentation</p>
+ <p>
+ Own Id: OTP-15508 Aux Id: ERL-816 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
<p>
+ Fixed bug that causes a crash in http client when using
+ hostnames (e.g. localhost) with the the option
+ ipv6_host_with_brackets set to true.</p>
+ <p>
+ This change also fixes a regression: httpc:request fails
+ with connection error (nxdomain) if option
+ ipv6_host_with_brackets set to true and host component of
+ the URI is an IPv6 address.</p>
+ <p>
+ Own Id: OTP-15554 Aux Id: ERIERL-289 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make sure ipv6 addresses with brackets in URIs are
+ converted correctly before passing to lower level
+ functions like gen_tcp and ssl functions. Could cause
+ connection to fail.</p>
+ <p>
+ Own Id: OTP-15544 Aux Id: ERIERL-289 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed http client to not send 'content-length' header in
+ chunked encoded requests.</p>
+ <p>
+ Own Id: OTP-15338 Aux Id: ERL-733 </p>
+ </item>
+ <item>
+ <p>
+ Fixed http client to not drop explicit 'Content-Type'
+ header in requests without a body such as requests with
+ the 'Content-Type' of application/x-www-form-urlencoded.</p>
+ <p>
+ Own Id: OTP-15339 Aux Id: ERL-736 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling, that is mod_get will return 403
+ if a path is a directory and not a file.</p>
+ <p>
+ Own Id: OTP-15192</p>
+ </item>
+ <item>
+ <p>
+ Do not use chunked-encoding with 1xx, 204 and 304
+ responses when using mod_esi. Old behavior was not
+ compliant with HTTP/1.1 RFC and could cause clients to
+ hang when they received 1xx, 204 or 304 responses that
+ included an empty chunked-encoded body.</p>
+ <p>
+ Own Id: OTP-15241</p>
+ </item>
+ <item>
+ <p>
+ Add robust handling of chunked-encoded HTTP responses
+ with an empty body (1xx, 204, 304). Old behavior could
+ cause the client to hang when connecting to a faulty
+ server implementation.</p>
+ <p>
+ Own Id: OTP-15242</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Inets 7.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
Fixed HTTP content injection bug in httpc (ERL-456).</p>
<p>
Own Id: OTP-14726</p>
@@ -79,7 +252,6 @@
</list>
</section>
-
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -91,8 +263,86 @@
</list>
</section>
+ </section>
+
+ <section><title>Inets 6.5.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not use chunked-encoding with 1xx, 204 and 304
+ responses when using mod_esi. Old behavior was not
+ compliant with HTTP/1.1 RFC and could cause clients to
+ hang when they received 1xx, 204 or 304 responses that
+ included an empty chunked-encoded body.</p>
+ <p>
+ Own Id: OTP-15241</p>
+ </item>
+ <item>
+ <p>
+ Add robust handling of chunked-encoded HTTP responses
+ with an empty body (1xx, 204, 304). Old behavior could
+ cause the client to hang when connecting to a faulty
+ server implementation.</p>
+ <p>
+ Own Id: OTP-15242</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Inets 6.5.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
+
</section>
+<section><title>Inets 6.5.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling, that is mod_get will return 403
+ if a path is a directory and not a file.</p>
+ <p>
+ Own Id: OTP-15192</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Inets 6.5.2.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Options added for setting low-level properties on the
+ underlying TCP connections. The options are:
+ <c>sock_ctrl</c>, <c>sock_data_act</c> and
+ <c>sock_data_pass</c>. See the manual for details.</p>
+ <p>
+ Own Id: OTP-15120 Aux Id: ERIERL-192 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
<section><title>Inets 6.5.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 5e05b8170a..8d443a1477 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -809,7 +809,7 @@ connect_and_send_first_request(Address, Request, #state{options = Options0} = St
SocketType = socket_type(Request),
ConnTimeout = (Request#request.settings)#http_options.connect_timeout,
Options = handle_unix_socket_options(Request, Options0),
- case connect(SocketType, Address, Options, ConnTimeout) of
+ case connect(SocketType, format_address(Address), Options, ConnTimeout) of
{ok, Socket} ->
ClientClose =
httpc_request:is_client_closing(
@@ -961,13 +961,23 @@ handle_http_body(_, #state{status = {ssl_tunnel, Request},
NewState = answer_request(Request, ClientErrMsg, State),
{stop, normal, NewState};
-handle_http_body(<<>>, #state{status_line = {_,304, _}} = State) ->
+%% All 1xx (informational), 204 (no content), and 304 (not modified)
+%% responses MUST NOT include a message-body, and thus are always
+%% terminated by the first empty line after the header fields.
+%% This implies that chunked encoding MUST NOT be used for these
+%% status codes.
+handle_http_body(<<>>, #state{headers = Headers,
+ status_line = {_,StatusCode, _}} = State)
+ when Headers#http_response_h.'transfer-encoding' =/= "chunked" andalso
+ (StatusCode =:= 204 orelse %% No Content
+ StatusCode =:= 304 orelse %% Not Modified
+ 100 =< StatusCode andalso StatusCode =< 199) -> %% Informational
handle_response(State#state{body = <<>>});
-handle_http_body(<<>>, #state{status_line = {_,204, _}} = State) ->
- handle_response(State#state{body = <<>>});
-handle_http_body(<<>>, #state{request = #request{method = head}} = State) ->
+handle_http_body(<<>>, #state{headers = Headers,
+ request = #request{method = head}} = State)
+ when Headers#http_response_h.'transfer-encoding' =/= "chunked" ->
handle_response(State#state{body = <<>>});
handle_http_body(Body, #state{headers = Headers,
@@ -1728,4 +1738,8 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
{stacktrace, Stacktrace}]}}
end.
-
+format_address({[$[|T], Port}) ->
+ {ok, Address} = inet:parse_address(string:strip(T, right, $])),
+ {Address, Port};
+format_address(HostPort) ->
+ HostPort.
diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl
index 9b81bd7a80..0f20d93bc1 100644
--- a/lib/inets/src/http_client/httpc_request.erl
+++ b/lib/inets/src/http_client/httpc_request.erl
@@ -213,15 +213,18 @@ update_body(Headers, Body) ->
update_headers(Headers, ContentType, Body, []) ->
case Body of
[] ->
- Headers#http_request_h{'content-length' = "0"};
+ Headers1 = Headers#http_request_h{'content-length' = "0"},
+ handle_content_type(Headers1, ContentType);
<<>> ->
- Headers#http_request_h{'content-length' = "0"};
+ Headers1 = Headers#http_request_h{'content-length' = "0"},
+ handle_content_type(Headers1, ContentType);
{Fun, _Acc} when is_function(Fun, 1) ->
%% A client MUST NOT generate a 100-continue expectation in a request
%% that does not include a message body. This implies that either the
%% Content-Length or the Transfer-Encoding header MUST be present.
%% DO NOT send content-type when Body is empty.
- Headers#http_request_h{'content-type' = ContentType};
+ Headers1 = Headers#http_request_h{'content-type' = ContentType},
+ handle_transfer_encoding(Headers1);
_ ->
Headers#http_request_h{
'content-length' = body_length(Body),
@@ -230,12 +233,26 @@ update_headers(Headers, ContentType, Body, []) ->
update_headers(_, _, _, HeadersAsIs) ->
HeadersAsIs.
+handle_transfer_encoding(Headers = #http_request_h{'transfer-encoding' = undefined}) ->
+ Headers;
+handle_transfer_encoding(Headers) ->
+ %% RFC7230 3.3.2
+ %% A sender MUST NOT send a 'Content-Length' header field in any message
+ %% that contains a 'Transfer-Encoding' header field.
+ Headers#http_request_h{'content-length' = undefined}.
+
body_length(Body) when is_binary(Body) ->
integer_to_list(size(Body));
body_length(Body) when is_list(Body) ->
integer_to_list(length(Body)).
+%% Set 'Content-Type' when it is explicitly set.
+handle_content_type(Headers, "") ->
+ Headers;
+handle_content_type(Headers, ContentType) ->
+ Headers#http_request_h{'content-type' = ContentType}.
+
method(Method) ->
http_util:to_upper(atom_to_list(Method)).
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index 0f3bd0a06d..78d6b4ed24 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -423,23 +423,24 @@ resolve_uri(Scheme, Host, Port, Path, Query, URI) ->
resolve_uri(Scheme, Host, Port, Path, Query, URI, #{}).
%%
resolve_uri(Scheme, Host, Port, Path, Query, URI, Map0) ->
- case maps:is_key(scheme, URI) of
- true ->
- Port = get_port(URI),
+ case maps:get(scheme, URI, undefined) of
+ undefined ->
+ Port0 = get_port(Scheme, URI),
+ Map = Map0#{scheme => Scheme,
+ port => Port0},
+ resolve_authority(Host, Port, Path, Query, URI, Map);
+ URIScheme ->
+ Port0 = get_port(URIScheme, URI),
maybe_add_query(
- Map0#{scheme => maps:get(scheme, URI),
- host => maps:get(host, URI),
- port => Port,
- path => maps:get(path, URI)},
- URI);
- false ->
- Map = Map0#{scheme => Scheme},
- resolve_authority(Host, Port, Path, Query, URI, Map)
+ Map0#{scheme => URIScheme,
+ host => maps:get(host, URI),
+ port => Port0,
+ path => maps:get(path, URI)},
+ URI)
end.
-get_port(URI) ->
- Scheme = maps:get(scheme, URI),
+get_port(Scheme, URI) ->
case maps:get(port, URI, undefined) of
undefined ->
get_default_port(Scheme);
@@ -457,15 +458,13 @@ get_default_port("https") ->
resolve_authority(Host, Port, Path, Query, RelURI, Map) ->
case maps:is_key(host, RelURI) of
true ->
- Port = get_port(RelURI),
maybe_add_query(
Map#{host => maps:get(host, RelURI),
- port => Port,
path => maps:get(path, RelURI)},
RelURI);
false ->
Map1 = Map#{host => Host,
- port => Port},
+ port => Port},
resolve_path(Path, Query, RelURI, Map1)
end.
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index 52f5fa03a9..aaa7e428c2 100644
--- a/lib/inets/src/http_server/httpd_example.erl
+++ b/lib/inets/src/http_server/httpd_example.erl
@@ -22,9 +22,9 @@
-export([print/1]).
-export([get/2, put/2, post/2, yahoo/2, test1/2, get_bin/2, peer/2,new_status_and_location/2]).
--export([newformat/3, post_chunked/3]).
+-export([newformat/3, post_chunked/3, post_204/3]).
%% These are used by the inets test-suite
--export([delay/1, chunk_timeout/3]).
+-export([delay/1, chunk_timeout/3, get_chunks/3]).
print(String) ->
@@ -151,6 +151,12 @@ post_chunked(SessionID, _Env, {last, _Body, undefined} = _Bodychunk) ->
post_chunked(_, _, _Body) ->
exit(body_not_chunked).
+post_204(SessionID, _Env, _Input) ->
+ mod_esi:deliver(SessionID,
+ ["Status: 204 No Content" ++ "\r\n\r\n"]),
+ mod_esi:deliver(SessionID, []).
+
+
newformat(SessionID,_,_) ->
mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
mod_esi:deliver(SessionID, top("new esi format test")),
@@ -190,3 +196,22 @@ chunk_timeout(SessionID, _, _StrInt) ->
mod_esi:deliver(SessionID, top("Test chunk encoding timeout")),
timer:sleep(20000),
mod_esi:deliver(SessionID, footer()).
+
+get_chunks(Sid, _Env, In) ->
+ Tokens = string:tokens(In, [$&]),
+ PropList = lists:map(fun(E) ->
+ list_to_tuple(string:tokens(E,[$=])) end,
+ Tokens),
+ HeaderDelay =
+ list_to_integer(proplists:get_value("header_delay", PropList, "0")),
+ ChunkDelay =
+ list_to_integer(proplists:get_value("chunk_delay", PropList, "0")),
+ BadChunkDelay =
+ list_to_integer(proplists:get_value("bad_chunk_delay", PropList, "0")),
+ timer:sleep(HeaderDelay),
+ mod_esi:deliver(Sid, ["Content-Type: text/plain\r\n\r\n"]),
+ mod_esi:deliver(Sid, "Chunk 0 ms\r\n"),
+ timer:sleep(ChunkDelay),
+ mod_esi:deliver(Sid, io_lib:format("Chunk ~p ms\r\n", [ChunkDelay])),
+ timer:sleep(ChunkDelay + BadChunkDelay),
+ mod_esi:deliver(Sid, "BAD Chunk\r\n").
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index 4d419172d0..bf7554bd08 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,9 @@ handle_error(enoent, Op, ModData, Path) ->
handle_error(enotdir, Op, ModData, Path) ->
handle_error(404, Op, ModData, Path,
": A component of the file name is not a directory");
+handle_error(eisdir, Op, ModData, Path) ->
+ handle_error(403, Op, ModData, Path,
+ ":Ilegal operation expected a file not a directory");
handle_error(emfile, Op, _ModData, Path) ->
handle_error(500, Op, none, Path, ": Too many open files");
handle_error({enfile,_}, Op, _ModData, Path) ->
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index 3ee8665a54..bb946664f9 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -61,8 +61,12 @@ generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
{StatusCode, Response} -> %% Old way
send_response_old(ModData, StatusCode, Response),
ok;
- undefined ->
- send_status(ModData, 500, none),
+ undefined ->
+ %% Happens when no mod_*
+ %% handles the request
+ send_status(ModData, 501, {ModData#mod.method,
+ ModData#mod.request_uri,
+ ModData#mod.http_version}),
ok
end
end
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index 21aafa7f7b..8cbd9798e6 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -33,7 +33,7 @@
-include("httpd_internal.hrl").
-define(VMODULE,"ESI").
--define(DEFAULT_ERL_TIMEOUT,15000).
+-define(DEFAULT_ERL_TIMEOUT,15).
%%%=========================================================================
@@ -119,7 +119,7 @@ load("EvalScriptAlias " ++ EvalScriptAlias, []) ->
load("ErlScriptTimeout " ++ Timeout, [])->
case catch list_to_integer(string:strip(Timeout)) of
TimeoutSec when is_integer(TimeoutSec) ->
- {ok, [], {erl_script_timeout, TimeoutSec * 1000}};
+ {ok, [], {erl_script_timeout, TimeoutSec}};
_ ->
{error, ?NICE(string:strip(Timeout) ++
" is an invalid ErlScriptTimeout")}
@@ -174,7 +174,7 @@ store({erl_script_alias, Value}, _) ->
{error, {wrong_type, {erl_script_alias, Value}}};
store({erl_script_timeout, TimeoutSec}, _)
when is_integer(TimeoutSec) andalso (TimeoutSec >= 0) ->
- {ok, {erl_script_timeout, TimeoutSec * 1000}};
+ {ok, {erl_script_timeout, TimeoutSec}};
store({erl_script_timeout, Value}, _) ->
{error, {wrong_type, {erl_script_timeout, Value}}};
store({erl_script_nocache, Value} = Conf, _)
@@ -394,7 +394,16 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
Continue;
{Headers, Body} ->
{ok, NewHeaders, StatusCode} = httpd_esi:handle_headers(Headers),
- IsDisableChunkedSend = httpd_response:is_disable_chunked_send(Db),
+ %% All 1xx (informational), 204 (no content), and 304 (not modified)
+ %% responses MUST NOT include a message-body, and thus are always
+ %% terminated by the first empty line after the header fields.
+ %% This implies that chunked encoding MUST NOT be used for these
+ %% status codes.
+ IsDisableChunkedSend =
+ httpd_response:is_disable_chunked_send(Db) orelse
+ StatusCode =:= 204 orelse %% No Content
+ StatusCode =:= 304 orelse %% Not Modified
+ (100 =< StatusCode andalso StatusCode =< 199), %% Informational
case (ModData#mod.http_version =/= "HTTP/1.1") or
(IsDisableChunkedSend) of
true ->
@@ -405,8 +414,8 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
send_headers(ModData, StatusCode,
[{"transfer-encoding",
"chunked"} | NewHeaders])
- end,
- handle_body(Pid, ModData, Body, Timeout, length(Body),
+ end,
+ handle_body(Pid, ModData, Body, Timeout, length(Body),
IsDisableChunkedSend);
timeout ->
send_headers(ModData, 504, [{"connection", "close"}]),
@@ -491,7 +500,7 @@ kill_esi_delivery_process(Pid) ->
erl_script_timeout(Db) ->
- httpd_util:lookup(Db, erl_script_timeout, ?DEFAULT_ERL_TIMEOUT).
+ httpd_util:lookup(Db, erl_script_timeout, ?DEFAULT_ERL_TIMEOUT) * 1000.
script_elements(FuncAndInput, Input) ->
case input_type(FuncAndInput) of
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 0dcf66265e..b197590bfd 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -18,10 +18,12 @@
%% %CopyrightEnd%
{"%VSN%",
[
+ {<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
],
[
+ {<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
]
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index d43e2cc179..8357e02014 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -59,7 +59,8 @@ all() ->
{group, http_unix_socket},
{group, https},
{group, sim_https},
- {group, misc}
+ {group, misc},
+ {group, sim_mixed} % HTTP and HTTPS sim servers
].
groups() ->
@@ -74,7 +75,8 @@ groups() ->
{http_unix_socket, [], simulated_unix_socket()},
{https, [], real_requests()},
{sim_https, [], only_simulated()},
- {misc, [], misc()}
+ {misc, [], misc()},
+ {sim_mixed, [], sim_mixed()}
].
real_requests()->
@@ -154,6 +156,7 @@ only_simulated() ->
multipart_chunks,
get_space,
delete_no_body,
+ post_with_content_type,
stream_fun_server_close
].
@@ -167,7 +170,15 @@ misc() ->
[
server_does_not_exist,
timeout_memory_leak,
- wait_for_whole_response
+ wait_for_whole_response,
+ post_204_chunked,
+ chunkify_fun
+ ].
+
+sim_mixed() ->
+ [
+ redirect_http_to_https,
+ redirect_relative_different_port
].
%%--------------------------------------------------------------------
@@ -195,7 +206,8 @@ init_per_group(misc = Group, Config) ->
Config;
-init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https->
+init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https;
+ Group =:= sim_mixed ->
catch crypto:stop(),
try crypto:start() of
ok ->
@@ -238,6 +250,13 @@ end_per_group(http_unix_socket,_Config) ->
end_per_group(_, _Config) ->
ok.
+do_init_per_group(Group=sim_mixed, Config0) ->
+ % The mixed group uses two server ports (http and https), so we use
+ % different config names here.
+ Config1 = init_ssl(Config0),
+ Config2 = proplists:delete(http_port, proplists:delete(https_port, Config1)),
+ {HttpPort, HttpsPort} = server_start(Group, server_config(sim_https, Config2)),
+ [{http_port, HttpPort} | [{https_port, HttpsPort} | Config2]];
do_init_per_group(Group, Config0) ->
Config1 =
case Group of
@@ -734,6 +753,48 @@ redirect_loop(Config) when is_list(Config) ->
= httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
+redirect_http_to_https() ->
+ [{doc, "Test that a 30X redirect from one scheme to another is handled "
+ "correctly."}].
+redirect_http_to_https(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+ TargetUrl = mixed_url(https, "/dummy.html", Config),
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
+redirect_relative_different_port() ->
+ [{doc, "Test that a 30X redirect with a relative target, but different "
+ "port, is handled correctly."}].
+redirect_relative_different_port(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+
+ % We need an extra server of the same protocol here, so spawn a new
+ % HTTP-protocol one
+ Port = server_start(sim_http, []),
+ {ok, Host} = inet:gethostname(),
+ % Prefix the URI with '/' instead of a scheme
+ TargetUrl = "//" ++ Host ++ ":" ++ integer_to_list(Port) ++ "/dummy.html",
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
cookie() ->
[{doc, "Test cookies."}].
cookie(Config) when is_list(Config) ->
@@ -1333,6 +1394,109 @@ wait_for_whole_response(Config) when is_list(Config) ->
ReqSeqNumServer ! shutdown.
%%--------------------------------------------------------------------
+post_204_chunked() ->
+ [{doc,"Test that chunked encoded 204 responses do not freeze the http client"}].
+post_204_chunked(_Config) ->
+ Msg = "HTTP/1.1 204 No Content\r\n" ++
+ "Date: Thu, 23 Aug 2018 13:36:29 GMT\r\n" ++
+ "Content-Type: text/html\r\n" ++
+ "Server: inets/6.5.2.3\r\n" ++
+ "Cache-Control: no-cache\r\n" ++
+ "Pragma: no-cache\r\n" ++
+ "Expires: Fri, 24 Aug 2018 07:49:35 GMT\r\n" ++
+ "Transfer-Encoding: chunked\r\n" ++
+ "\r\n",
+ Chunk = "0\r\n\r\n",
+
+ {ok, ListenSocket} = gen_tcp:listen(0, [{active,once}, binary]),
+ {ok,{_,Port}} = inet:sockname(ListenSocket),
+ spawn(fun () -> custom_server(Msg, Chunk, ListenSocket,
+ fun post_204_receive/0) end),
+
+ {ok,Host} = inet:gethostname(),
+ End = "/cgi-bin/erl/httpd_example:post_204",
+ URL = ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End,
+ {ok, _} = httpc:request(post, {URL, [], "text/html", []}, [], []),
+ timer:sleep(500),
+ %% Second request times out in the faulty case.
+ {ok, _} = httpc:request(post, {URL, [], "text/html", []}, [], []).
+
+post_204_receive() ->
+ receive
+ {tcp, _, Msg} ->
+ ct:log("Message received: ~p", [Msg])
+ after
+ 1000 ->
+ ct:fail("Timeout: did not recive packet")
+ end.
+
+%% Custom server is used to test special cases when using chunked encoding
+custom_server(Msg, Chunk, ListenSocket, ReceiveFun) ->
+ {ok, Accept} = gen_tcp:accept(ListenSocket),
+ ReceiveFun(),
+ send_response(Msg, Chunk, Accept),
+ custom_server_loop(Msg, Chunk, Accept, ReceiveFun).
+
+custom_server_loop(Msg, Chunk, Accept, ReceiveFun) ->
+ ReceiveFun(),
+ send_response(Msg, Chunk, Accept),
+ custom_server_loop(Msg, Chunk, Accept, ReceiveFun).
+
+send_response(Msg, Chunk, Socket) ->
+ inet:setopts(Socket, [{active, once}]),
+ gen_tcp:send(Socket, Msg),
+ timer:sleep(250),
+ gen_tcp:send(Socket, Chunk).
+
+%%--------------------------------------------------------------------
+chunkify_fun() ->
+ [{doc,"Test that a chunked encoded request does not include the 'Content-Length header'"}].
+chunkify_fun(_Config) ->
+ Msg = "HTTP/1.1 204 No Content\r\n" ++
+ "Date: Thu, 23 Aug 2018 13:36:29 GMT\r\n" ++
+ "Content-Type: text/html\r\n" ++
+ "Server: inets/6.5.2.3\r\n" ++
+ "Cache-Control: no-cache\r\n" ++
+ "Pragma: no-cache\r\n" ++
+ "Expires: Fri, 24 Aug 2018 07:49:35 GMT\r\n" ++
+ "Transfer-Encoding: chunked\r\n" ++
+ "\r\n",
+ Chunk = "0\r\n\r\n",
+
+ {ok, ListenSocket} = gen_tcp:listen(0, [{active,once}, binary]),
+ {ok,{_,Port}} = inet:sockname(ListenSocket),
+ spawn(fun () -> custom_server(Msg, Chunk, ListenSocket,
+ fun chunkify_receive/0) end),
+
+ {ok,Host} = inet:gethostname(),
+ End = "/cgi-bin/erl/httpd_example",
+ URL = ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End,
+ Fun = fun(_) -> {ok,<<1>>,eof_body} end,
+ Acc = start,
+
+ {ok, {{_,204,_}, _, _}} =
+ httpc:request(put, {URL, [], "text/html", {chunkify, Fun, Acc}}, [], []).
+
+chunkify_receive() ->
+ Error = "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length: 0\r\n\r\n",
+ receive
+ {tcp, Port, Msg} ->
+ case binary:match(Msg, <<"content-length">>) of
+ nomatch ->
+ ct:log("Message received: ~s", [binary_to_list(Msg)]);
+ {_, _} ->
+ ct:log("Message received (negative): ~s", [binary_to_list(Msg)]),
+ %% Signal a testcase failure when the received HTTP request
+ %% contains a 'Content-Length' header.
+ gen_tcp:send(Port, Error),
+ ct:fail("Content-Length present in received headers.")
+ end
+ after
+ 1000 ->
+ ct:fail("Timeout: did not recive packet")
+ end.
+%%--------------------------------------------------------------------
stream_fun_server_close() ->
[{doc, "Test that an error msg is received when using a receiver fun as stream target"}].
stream_fun_server_close(Config) when is_list(Config) ->
@@ -1438,6 +1602,15 @@ delete_no_body(Config) when is_list(Config) ->
httpc:request(delete, {URL, [], "text/plain", "TEST"}, [], []).
%%--------------------------------------------------------------------
+post_with_content_type(doc) ->
+ ["Test that a POST request with explicit 'Content-Type' does not drop the 'Content-Type' header - Solves ERL-736"];
+post_with_content_type(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/delete_no_body.html", Config),
+ %% Simulated server replies 500 if 'Content-Type' header is present
+ {ok, {{_,500,_}, _, _}} =
+ httpc:request(post, {URL, [], "application/x-www-form-urlencoded", ""}, [], []).
+
+%%--------------------------------------------------------------------
request_options() ->
[{doc, "Test http get request with socket options against local server (IPv6)"}].
request_options(Config) when is_list(Config) ->
@@ -1559,6 +1732,21 @@ url(sim_http, UserInfo, End, Config) ->
url(sim_https, UserInfo, End, Config) ->
url(https, UserInfo, End, Config).
+% Only for use in the `mixed` test group, where both http and https
+% URLs are possible.
+mixed_url(http, End, Config) ->
+ mixed_url(http_port, End, Config);
+mixed_url(https, End, Config) ->
+ mixed_url(https_port, End, Config);
+mixed_url(PortType, End, Config) ->
+ Port = proplists:get_value(PortType, Config),
+ {ok, Host} = inet:gethostname(),
+ Start = case PortType of
+ http_port -> ?URL_START;
+ https_port -> ?TLS_URL_START
+ end,
+ Start ++ Host ++ ":" ++ integer_to_list(Port) ++ End.
+
group_name(Config) ->
GroupProp = proplists:get_value(tc_group_properties, Config),
proplists:get_value(name, GroupProp).
@@ -1587,6 +1775,9 @@ server_start(http_ipv6, HttpdConfig) ->
Serv = inets:services_info(),
{value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
proplists:get_value(port, Info);
+server_start(sim_mixed, Config) ->
+ % For the mixed http/https case, we start two servers and return both ports.
+ {server_start(sim_http, []), server_start(sim_https, Config)};
server_start(_, HttpdConfig) ->
{ok, Pid} = inets:start(httpd, HttpdConfig),
Serv = inets:services_info(),
@@ -1645,6 +1836,8 @@ start_apps(https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(sim_https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
+start_apps(sim_mixed) ->
+ inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(_) ->
ok.
@@ -2089,6 +2282,20 @@ handle_uri(_,"/301_rel_uri.html",_,_,_,_) ->
"Content-Length:" ++ integer_to_list(length(Body))
++ "\r\n\r\n" ++ Body;
+handle_uri("HEAD","/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+
+handle_uri(_,"/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
handle_uri("HEAD","/302.html",Port,_,Socket,_) ->
NewUri = url_start(Socket) ++
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 97aca73d6b..fc5ca14dcd 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -76,7 +76,13 @@ all() ->
{group, http_logging},
{group, http_post},
{group, http_rel_path_script_alias},
- mime_types_format
+ {group, http_not_sup},
+ {group, https_not_sup},
+ mime_types_format,
+ erl_script_timeout_default,
+ erl_script_timeout_option,
+ erl_script_timeout_proplist,
+ erl_script_timeout_apache
].
groups() ->
@@ -103,6 +109,8 @@ groups() ->
{http_reload, [], [{group, reload}]},
{https_reload, [], [{group, reload}]},
{http_post, [], [{group, post}]},
+ {http_not_sup, [], [{group, not_sup}]},
+ {https_not_sup, [], [{group, not_sup}]},
{http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]},
{limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]},
{custom, [], [customize, add_default]},
@@ -116,7 +124,7 @@ groups() ->
disturbing_0_9,
reload_config_file
]},
- {post, [], [chunked_post, chunked_chunked_encoded_post]},
+ {post, [], [chunked_post, chunked_chunked_encoded_post, post_204]},
{basic_auth, [], [basic_auth_1_1, basic_auth_1_0, basic_auth_0_9]},
{auth_api, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9
]},
@@ -134,7 +142,8 @@ groups() ->
esi_put, esi_post] ++ http_head() ++ http_get() ++ load()},
{http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()},
{http_0_9, [], http_head() ++ http_get() ++ load()},
- {http_rel_path_script_alias, [], [cgi]}
+ {http_rel_path_script_alias, [], [cgi]},
+ {not_sup, [], [put_not_sup]}
].
basic_groups ()->
@@ -207,7 +216,8 @@ init_per_group(Group, Config0) when Group == https_basic;
Group == https_auth_api_dets;
Group == https_auth_api_mnesia;
Group == https_security;
- Group == https_reload
+ Group == https_reload;
+ Group == https_not_sup
->
catch crypto:stop(),
try crypto:start() of
@@ -226,6 +236,7 @@ init_per_group(Group, Config0) when Group == http_basic;
Group == http_auth_api_mnesia;
Group == http_security;
Group == http_reload;
+ Group == http_not_sup;
Group == http_post;
Group == http_mime_types
->
@@ -275,6 +286,8 @@ init_per_group(http_logging, Config) ->
init_per_group(http_rel_path_script_alias = Group, Config) ->
ok = start_apps(Group),
init_httpd(Group, [{type, ip_comm},{http_version, "HTTP/1.1"}| Config]);
+init_per_group(not_sup, Config) ->
+ [{http_version, "HTTP/1.1"} | Config];
init_per_group(_, Config) ->
Config.
@@ -374,6 +387,10 @@ init_per_testcase(disk_log_bad_file, Config0) ->
ct:timetrap({seconds, 20}),
dbg(disk_log_internal, Config1, init);
+init_per_testcase(erl_script_timeout_default, Config) ->
+ ct:timetrap({seconds, 60}),
+ dbg(erl_script_timeout_default, Config, init);
+
init_per_testcase(Case, Config) ->
ct:timetrap({seconds, 20}),
dbg(Case, Config, init).
@@ -448,8 +465,19 @@ get(Config) when is_list(Config) ->
{header, "Content-Type", "text/html"},
{header, "Date"},
{header, "Server"},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
+ transport_opts(Type, Config),
+ proplists:get_value(node, Config),
+ http_request("GET /open/ ", Version, Host),
+ [{statuscode, 403},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
{version, Version}]).
-
+
basic_auth_1_1(Config) when is_list(Config) ->
basic_auth([{http_version, "HTTP/1.1"} | Config]).
@@ -733,6 +761,42 @@ chunked_chunked_encoded_post(Config) when is_list(Config) ->
[{http_version, "HTTP/1.1"} | Config],
[{statuscode, 200}]).
+%%-------------------------------------------------------------------------
+post_204() ->
+ [{doc,"Test that 204 responses are not chunk encoded"}].
+post_204(Config) ->
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ SockType = proplists:get_value(type, Config),
+ TranspOpts = transport_opts(SockType, Config),
+ Request = "POST /cgi-bin/erl/httpd_example:post_204 ",
+
+ try inets_test_lib:connect_bin(SockType, Host, Port, TranspOpts) of
+ {ok, Socket} ->
+ RequestStr = http_request(Request, "HTTP/1.1", Host),
+ ok = inets_test_lib:send(SockType, Socket, RequestStr),
+ receive
+ {tcp, Socket, Data} ->
+ case binary:match(Data, <<"chunked">>,[]) of
+ nomatch ->
+ ok;
+ {_, _} ->
+ ct:fail("Chunked encoding detected.")
+ end
+ after 2000 ->
+ ct:fail(connection_timed_out)
+ end;
+ ConnectError ->
+ ct:fail({connect_error, ConnectError,
+ [SockType, Host, Port, TranspOpts]})
+ catch
+ T:E ->
+ ct:fail({connect_failure,
+ [{type, T},
+ {error, E},
+ {stacktrace, erlang:get_stacktrace()},
+ {args, [SockType, Host, Port, TranspOpts]}]})
+ end.
%%-------------------------------------------------------------------------
htaccess_1_1(Config) when is_list(Config) ->
@@ -898,6 +962,33 @@ max_clients_0_9() ->
max_clients_0_9(Config) when is_list(Config) ->
do_max_clients([{http_version, "HTTP/0.9"} | Config]).
+
+
+%%-------------------------------------------------------------------------
+put_not_sup() ->
+ [{doc, "Test unhandled request"}].
+
+put_not_sup(Config) when is_list(Config) ->
+ ok = http_status("PUT /index.html ",
+ {"Content-Length:100 \r\n",
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"},
+ Config, [{statuscode, 501}]).
%%-------------------------------------------------------------------------
esi() ->
[{doc, "Test mod_esi"}].
@@ -1693,6 +1784,130 @@ mime_types_format(Config) when is_list(Config) ->
{"cpt","application/mac-compactpro"},
{"hqx","application/mac-binhex40"}]} = httpd_conf:load_mime_types(MimeTypes).
+erl_script_timeout_default(Config) when is_list(Config) ->
+ inets:start(),
+ {ok, Pid} = inets:start(httpd,
+ [{port, 0},
+ {server_name,"localhost"},
+ {server_root,"./"},
+ {document_root,"./"},
+ {bind_address, any},
+ {mimetypes, [{"html", "text/html"}]},
+ {modules,[mod_esi]},
+ {erl_script_alias, {"/erl", [httpd_example]}}
+ ]),
+ Info = httpd:info(Pid),
+
+ Port = proplists:get_value(port, Info),
+
+ %% Default erl_script_timeout is 15.
+ %% Verify: 13 =< erl_script_timeout =< 17
+ Url = http_get_url(Port, 500, 13000, 4000),
+
+ {ok, {_, _, Body}} = httpc:request(get, {Url, []}, [{timeout, 45000}], []),
+ ct:log("Response: ~p~n", [Body]),
+ verify_body(Body, 13000),
+ inets:stop().
+
+erl_script_timeout_option(Config) when is_list(Config) ->
+ inets:start(),
+ {ok, Pid} = inets:start(httpd,
+ [{port, 0},
+ {server_name,"localhost"},
+ {server_root,"./"},
+ {document_root,"./"},
+ {bind_address, any},
+ {mimetypes, [{"html", "text/html"}]},
+ {modules,[mod_esi]},
+ {erl_script_timeout, 2},
+ {erl_script_alias, {"/erl", [httpd_example]}}
+ ]),
+ Info = httpd:info(Pid),
+ verify_timeout(Info, 2),
+
+ Port = proplists:get_value(port, Info),
+
+ %% Verify: 1 =< erl_script_timeout =< 3
+ Url = http_get_url(Port, 500, 1000, 2000),
+
+ {ok, {_, _, Body}} = httpc:request(Url),
+ ct:log("Response: ~p~n", [Body]),
+ verify_body(Body, 1000),
+ inets:stop().
+
+erl_script_timeout_proplist(Config) when is_list(Config) ->
+ HttpdConf = filename:join(get_tmp_dir(Config),
+ "httpd_erl_script_timeout_proplist.conf"),
+ ServerConfig =
+ "[{port, 0},\n" ++
+ " {server_name,\"localhost\"},\n" ++
+ " {server_root,\"./\"},\n" ++
+ " {document_root,\"./\"},\n" ++
+ " {bind_address, any},\n" ++
+ " {mimetypes, [{\"html\", \"text/html\"}]},\n" ++
+ " {modules,[mod_esi]},\n" ++
+ " {erl_script_timeout, 5},\n" ++
+ " {erl_script_alias, {\"/erl\", [httpd_example]}}\n" ++
+ "].",
+ ok = file:write_file(HttpdConf, ServerConfig),
+
+ inets:start(),
+ {ok, Pid} = inets:start(httpd,
+ [{proplist_file, HttpdConf}]),
+ Info = httpd:info(Pid),
+ verify_timeout(Info, 5),
+
+ Port = proplists:get_value(port, Info),
+
+ %% Verify: 3 =< erl_script_timeout =< 7
+ Url = http_get_url(Port, 500, 3000, 4000),
+
+ {ok, {_, _, Body}} = httpc:request(Url),
+ ct:log("Response: ~p~n", [Body]),
+ verify_body(Body, 3000),
+ inets:stop().
+
+erl_script_timeout_apache(Config) when is_list(Config) ->
+ HttpdConf = filename:join(get_tmp_dir(Config),
+ "httpd_erl_script_timeout.conf"),
+ MimeTypes = filename:join(get_tmp_dir(Config),
+ "erl_script_timeout_mime_types.conf"),
+
+ MimeTypesConf =
+ "html\n" ++
+ "text/html\n",
+
+ ok = file:write_file(MimeTypes, MimeTypesConf),
+
+ ServerConfig =
+ "Port 0\n" ++
+ "ServerName localhost\n" ++
+ "ServerRoot ./\n" ++
+ "DocumentRoot ./\n" ++
+ "BindAddress 0.0.0.0\n" ++
+ "MimeTypes " ++ MimeTypes ++ "\n" ++
+ "Modules mod_esi\n" ++
+ "ErlScriptTimeout 8\n" ++
+ "ErlScriptAlias /erl httpd_example\n",
+
+ ok = file:write_file(HttpdConf, ServerConfig),
+
+ inets:start(),
+ {ok, Pid} = inets:start(httpd,
+ [{file, HttpdConf}]),
+ Info = httpd:info(Pid),
+ verify_timeout(Info, 8),
+
+ Port = proplists:get_value(port, Info),
+
+ %% Verify: 6 =< erl_script_timeout =< 10
+ Url = http_get_url(Port, 500, 6000, 4000),
+
+ {ok, {_, _, Body}} = httpc:request(Url),
+ ct:log("Response: ~p~n", [Body]),
+ verify_body(Body, 6000),
+ inets:stop().
+
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------
@@ -1702,6 +1917,38 @@ url(http, End, Config) ->
{ok,Host} = inet:gethostname(),
?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End.
+http_get_url(Port0, HeaderDelay, ChunkDelay, BadChunkDelay) ->
+ {ok, Host} = inet:gethostname(),
+ Port = integer_to_list(Port0),
+ HD = integer_to_list(HeaderDelay),
+ CD = integer_to_list(ChunkDelay),
+ BD = integer_to_list(BadChunkDelay),
+ "http://" ++ Host ++ ":" ++ Port ++
+ "/erl/httpd_example/get_chunks?header_delay=" ++ HD ++
+ "&chunk_delay=" ++ CD ++
+ "&bad_chunk_delay=" ++ BD.
+
+verify_body(Body, Timeout0) ->
+ Timeout = integer_to_list(Timeout0),
+ Res = string:find(Body, Timeout),
+ ct:log("Result: ~p~n", [Res]),
+ %% Fail if BAD chunk is found.
+ case Res =:= Timeout ++ " ms\r\n" of
+ true ->
+ ok;
+ false ->
+ ct:fail("Unexpected chunk received!")
+ end.
+
+verify_timeout(Info, Expected) ->
+ Timeout = proplists:get_value(erl_script_timeout, Info),
+ case Timeout =:= Expected of
+ true ->
+ ok;
+ false ->
+ ct:fail("Bad Timeout - Expected: ~p Got: ~p", [Expected, Timeout])
+ end.
+
do_max_clients(Config) ->
Version = proplists:get_value(http_version, Config),
Host = proplists:get_value(host, Config),
@@ -1793,7 +2040,8 @@ start_apps(Group) when Group == https_basic;
Group == https_auth_api_mnesia;
Group == https_htaccess;
Group == https_security;
- Group == https_reload
+ Group == https_reload;
+ Group == https_not_sup
->
inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]);
start_apps(Group) when Group == http_basic;
@@ -1809,7 +2057,9 @@ start_apps(Group) when Group == http_basic;
Group == http_reload;
Group == http_post;
Group == http_mime_types;
- Group == http_rel_path_script_alias ->
+ Group == http_rel_path_script_alias;
+ Group == http_not_sup;
+ Group == http_mime_types->
inets_test_lib:start_apps([inets]).
server_start(_, HttpdConfig) ->
@@ -1844,6 +2094,10 @@ server_config(http_basic, Config) ->
basic_conf() ++ server_config(http, Config);
server_config(https_basic, Config) ->
basic_conf() ++ server_config(https, Config);
+server_config(http_not_sup, Config) ->
+ not_sup_conf() ++ server_config(http, Config);
+server_config(https_not_sup, Config) ->
+ not_sup_conf() ++ server_config(https, Config);
server_config(http_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(http, Config);
server_config(http_post, Config) ->
@@ -1992,7 +2246,10 @@ head_status(_) ->
basic_conf() ->
[{modules, [mod_alias, mod_range, mod_responsecontrol,
- mod_trace, mod_esi, mod_cgi, mod_dir, mod_get, mod_head]}].
+ mod_trace, mod_esi, mod_cgi, mod_get, mod_head]}].
+
+not_sup_conf() ->
+ [{modules, [mod_get]}].
auth_access_conf() ->
[{modules, [mod_alias, mod_htaccess, mod_dir, mod_get, mod_head]},
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index b76390ad66..fd248e793a 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 7.0
+INETS_VSN = 7.0.7
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/jinterface/doc/src/Makefile b/lib/jinterface/doc/src/Makefile
index 37de0a35c5..f5cba9d074 100644
--- a/lib/jinterface/doc/src/Makefile
+++ b/lib/jinterface/doc/src/Makefile
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2017. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -129,6 +129,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
@@ -136,6 +137,7 @@ clean clean_docs:
jdoc:$(JAVA_SRC_FILES)
(cd ../../java_src;$(JAVADOC) -sourcepath . -d $(JAVADOC_DEST) \
-windowtitle $(JAVADOC_TITLE) $(JAVADOC_PKGS))
+ touch jdoc
man:
@@ -151,15 +153,8 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
$(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
$(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html/java/$(JAVA_PKG_PATH)"
$(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- ($(CP) -rf ../html "$(RELSYSDIR)/doc")
-
-# $(INSTALL_DATA) $(GIF_FILES) $(EXTRA_FILES) $(HTML_FILES) \
-# "$(RELSYSDIR)/doc/html"
-# $(INSTALL_DATA) $(JAVA_EXTRA_FILES) "$(RELSYSDIR)/doc/html/java"
-# $(INSTALL_DATA) $(TOP_HTML_FILES) "$(RELSYSDIR)/doc"
+ $(INSTALL_DIR_DATA) $(HTMLDIR) "$(RELSYSDIR)/doc/html"
release_spec:
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index 9aaa8a0840..75a2364384 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Jinterface application.</p>
+<section><title>Jinterface 1.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.9</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk
index f527a83092..a8dc815145 100644
--- a/lib/jinterface/vsn.mk
+++ b/lib/jinterface/vsn.mk
@@ -1 +1 @@
-JINTERFACE_VSN = 1.9
+JINTERFACE_VSN = 1.9.1
diff --git a/lib/kernel/doc/src/.gitignore b/lib/kernel/doc/src/.gitignore
new file mode 100644
index 0000000000..c2813ac866
--- /dev/null
+++ b/lib/kernel/doc/src/.gitignore
@@ -0,0 +1 @@
+*.eps \ No newline at end of file
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index f34eee71ba..f8867ccf25 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -84,6 +84,7 @@ XML_CHAPTER_FILES = \
BOOK_FILES = book.xml
+# The .png file is generated from a .dia file with target 'update_png'
IMAGE_FILES = \
logger_arch.png
@@ -112,6 +113,17 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
+# FIGURES
+# ----------------------------------------------------
+# In order to update the figures you have to have both dia
+# and imagemagick installed.
+# The generated .png file must be committed.
+
+update_png:
+ dia --export=logger_arch.eps logger_arch.dia
+ convert logger_arch.eps -resize 65% logger_arch.png
+
+# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
@@ -142,12 +154,13 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
- rm -f errs core *~
+ rm -f errs core *~ *.eps
$(SPECDIR)/specs_erl_prim_loader_stub.xml:
$(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 38c7b5acf1..83a83ebad2 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>application</module>
+ <module since="">application</module>
<modulesummary>Generic OTP application functions</modulesummary>
<description>
<p>In OTP, <em>application</em> denotes a component implementing
@@ -67,8 +67,8 @@
</datatypes>
<funcs>
<func>
- <name name="ensure_all_started" arity="1"/>
- <name name="ensure_all_started" arity="2"/>
+ <name name="ensure_all_started" arity="1" since="OTP R16B02"/>
+ <name name="ensure_all_started" arity="2" since="OTP R16B02"/>
<fsummary>Load and start an application and its dependencies, recursively.</fsummary>
<desc>
<p>Equivalent to calling
@@ -85,8 +85,8 @@
</desc>
</func>
<func>
- <name name="ensure_started" arity="1"/>
- <name name="ensure_started" arity="2"/>
+ <name name="ensure_started" arity="1" since="OTP R16B01"/>
+ <name name="ensure_started" arity="2" since="OTP R16B01"/>
<fsummary>Load and start an application.</fsummary>
<desc>
<p>Equivalent to
@@ -95,8 +95,8 @@
</desc>
</func>
<func>
- <name name="get_all_env" arity="0"/>
- <name name="get_all_env" arity="1"/>
+ <name name="get_all_env" arity="0" since=""/>
+ <name name="get_all_env" arity="1" since=""/>
<fsummary>Get the configuration parameters for an application.</fsummary>
<desc>
<p>Returns the configuration parameters and their values for
@@ -108,8 +108,8 @@
</desc>
</func>
<func>
- <name name="get_all_key" arity="0"/>
- <name name="get_all_key" arity="1"/>
+ <name name="get_all_key" arity="0" since=""/>
+ <name name="get_all_key" arity="1" since=""/>
<fsummary>Get the application specification keys.</fsummary>
<desc>
<p>Returns the application specification keys and their values
@@ -122,8 +122,8 @@
</desc>
</func>
<func>
- <name name="get_application" arity="0"/>
- <name name="get_application" arity="1"/>
+ <name name="get_application" arity="0" since=""/>
+ <name name="get_application" arity="1" since=""/>
<fsummary>Get the name of an application containing a certain process or module.</fsummary>
<desc>
<p>Returns the name of the application to which the process
@@ -136,8 +136,8 @@
</desc>
</func>
<func>
- <name name="get_env" arity="1"/>
- <name name="get_env" arity="2"/>
+ <name name="get_env" arity="1" since=""/>
+ <name name="get_env" arity="2" since=""/>
<fsummary>Get the value of a configuration parameter.</fsummary>
<desc>
<p>Returns the value of configuration parameter <c><anno>Par</anno></c>
@@ -153,7 +153,7 @@
</desc>
</func>
<func>
- <name name="get_env" arity="3"/>
+ <name name="get_env" arity="3" since="OTP R16B"/>
<fsummary>Get the value of a configuration parameter using a default.</fsummary>
<desc>
<p>Works like <seealso marker="#get_env/2"><c>get_env/2</c></seealso> but returns
@@ -162,8 +162,8 @@
</desc>
</func>
<func>
- <name name="get_key" arity="1"/>
- <name name="get_key" arity="2"/>
+ <name name="get_key" arity="1" since=""/>
+ <name name="get_key" arity="2" since=""/>
<fsummary>Get the value of an application specification key.</fsummary>
<desc>
<p>Returns the value of the application specification key
@@ -180,8 +180,8 @@
</desc>
</func>
<func>
- <name name="load" arity="1"/>
- <name name="load" arity="2"/>
+ <name name="load" arity="1" since=""/>
+ <name name="load" arity="2" since=""/>
<fsummary>Load an application.</fsummary>
<type name="application_spec"/>
<type name="application_opt"/>
@@ -226,7 +226,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="loaded_applications" arity="0"/>
+ <name name="loaded_applications" arity="0" since=""/>
<fsummary>Get the currently loaded applications.</fsummary>
<desc>
<p>Returns a list with information about the applications, and included
@@ -238,7 +238,42 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="permit" arity="2"/>
+ <name name="set_env" arity="1" since="OTP 21.3"/>
+ <name name="set_env" arity="2" since="OTP 21.3"/>
+ <fsummary>Sets the configuration parameters of multiple applications.</fsummary>
+ <desc>
+ <p>Sets the configuration <c><anno>Config</anno></c> for multiple
+ applications. It is equivalent to calling <c>set_env/4</c> on
+ each application individially, except it is more efficient.
+ The given <c><anno>Config</anno></c> is validated before the
+ configuration is set.</p>
+ <p><c>set_env/2</c> uses the standard <c>gen_server</c> time-out
+ value (5000 ms). Option <c>timeout</c> can be specified
+ if another time-out value is useful, for example, in situations
+ where the application controller is heavily loaded.</p>
+ <p>Option <c>persistent</c> can be set to <c>true</c>
+ to guarantee that parameters set with <c>set_env/2</c>
+ are not overridden by those defined in the application resource
+ file on load. This means that persistent values will stick after the application
+ is loaded and also on application reload.</p>
+ <p>If an application is given more than once or if an application
+ has the same key given more than once, the behaviour is undefined
+ and a warning message will be logged. In future releases, an error
+ will be raised.</p>
+ <p><c>set_env/1</c> is equivalent to <c>set_env(Config, [])</c>.</p>
+ <warning>
+ <p>Use this function only if you know what you are doing,
+ that is, on your own applications. It is very
+ application-dependent and
+ configuration parameter-dependent when and how often
+ the value is read by the application. Careless use
+ of this function can put the application in a
+ weird, inconsistent, and malfunctioning state.</p>
+ </warning>
+ </desc>
+ </func>
+ <func>
+ <name name="permit" arity="2" since=""/>
<fsummary>Change the permission for an application to run at a node.</fsummary>
<desc>
<p>Changes the permission for <c><anno>Application</anno></c> to run at
@@ -271,8 +306,8 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="set_env" arity="3"/>
- <name name="set_env" arity="4"/>
+ <name name="set_env" arity="3" since=""/>
+ <name name="set_env" arity="4" since=""/>
<fsummary>Set the value of a configuration parameter.</fsummary>
<desc>
<p>Sets the value of configuration parameter <c><anno>Par</anno></c> for
@@ -302,8 +337,8 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="start" arity="1"/>
- <name name="start" arity="2"/>
+ <name name="start" arity="1" since=""/>
+ <name name="start" arity="2" since=""/>
<fsummary>Load and start an application.</fsummary>
<desc>
<p>Starts <c><anno>Application</anno></c>. If it is not loaded,
@@ -353,7 +388,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="start_type" arity="0"/>
+ <name name="start_type" arity="0" since=""/>
<fsummary>Get the start type of an ongoing application startup.</fsummary>
<desc>
<p>This function is intended to be called by a process belonging
@@ -370,7 +405,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="stop" arity="1"/>
+ <name name="stop" arity="1" since=""/>
<fsummary>Stop an application.</fsummary>
<desc>
<p>Stops <c><anno>Application</anno></c>. The application master calls
@@ -399,7 +434,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="takeover" arity="2"/>
+ <name name="takeover" arity="2" since=""/>
<fsummary>Take over a distributed application.</fsummary>
<desc>
<p>Takes over the distributed application
@@ -424,7 +459,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="unload" arity="1"/>
+ <name name="unload" arity="1" since=""/>
<fsummary>Unload an application.</fsummary>
<desc>
<p>Unloads the application specification for <c><anno>Application</anno></c>
@@ -435,8 +470,8 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="unset_env" arity="2"/>
- <name name="unset_env" arity="3"/>
+ <name name="unset_env" arity="2" since=""/>
+ <name name="unset_env" arity="3" since=""/>
<fsummary>Unset the value of a configuration parameter.</fsummary>
<desc>
<p>Removes the configuration parameter <c><anno>Par</anno></c> and its value
@@ -459,8 +494,8 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name name="which_applications" arity="0"/>
- <name name="which_applications" arity="1"/>
+ <name name="which_applications" arity="0" since=""/>
+ <name name="which_applications" arity="1" since=""/>
<fsummary>Get the currently running applications.</fsummary>
<desc>
<p>Returns a list with information about the applications that
@@ -484,7 +519,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</section>
<funcs>
<func>
- <name>Module:start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State} | {error, Reason}</name>
+ <name since="">Module:start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State} | {error, Reason}</name>
<fsummary>Start an application.</fsummary>
<type>
<v>StartType = <seealso marker="#type-start_type"><c>start_type()</c></seealso></v>
@@ -526,7 +561,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>Module:start_phase(Phase, StartType, PhaseArgs) -> ok | {error, Reason}</name>
+ <name since="">Module:start_phase(Phase, StartType, PhaseArgs) -> ok | {error, Reason}</name>
<fsummary>Extended start of an application.</fsummary>
<type>
<v>Phase = atom()</v>
@@ -551,7 +586,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>Module:prep_stop(State) -> NewState</name>
+ <name since="">Module:prep_stop(State) -> NewState</name>
<fsummary>Prepare an application for termination.</fsummary>
<type>
<v>State = NewState = term()</v>
@@ -569,7 +604,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>Module:stop(State)</name>
+ <name since="">Module:stop(State)</name>
<fsummary>Clean up after termination of an application.</fsummary>
<type>
<v>State = term()</v>
@@ -585,7 +620,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>Module:config_change(Changed, New, Removed) -> ok</name>
+ <name since="">Module:config_change(Changed, New, Removed) -> ok</name>
<fsummary>Update the configuration parameters for an application.</fsummary>
<type>
<v>Changed = [{Par,Val}]</v>
diff --git a/lib/kernel/doc/src/auth.xml b/lib/kernel/doc/src/auth.xml
index 5901446960..a57da18de9 100644
--- a/lib/kernel/doc/src/auth.xml
+++ b/lib/kernel/doc/src/auth.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>auth</module>
+ <module since="">auth</module>
<modulesummary>Erlang network authentication server.</modulesummary>
<description>
<p>This module is deprecated. For a description of the Magic
@@ -42,7 +42,7 @@
</datatypes>
<funcs>
<func>
- <name name="cookie" arity="0"/>
+ <name name="cookie" arity="0" since=""/>
<fsummary>Magic cookie for local node (deprecated).</fsummary>
<desc>
<p>Use
@@ -51,7 +51,7 @@
</desc>
</func>
<func>
- <name name="cookie" arity="1"/>
+ <name name="cookie" arity="1" since=""/>
<fsummary>Set the magic for the local node (deprecated).</fsummary>
<type_desc variable="TheCookie">
The cookie can also be specified as a list with a single atom element.
@@ -63,7 +63,7 @@
</desc>
</func>
<func>
- <name name="is_auth" arity="1"/>
+ <name name="is_auth" arity="1" since=""/>
<fsummary>Status of communication authorization (deprecated).</fsummary>
<desc>
<p>Returns <c>yes</c> if communication with <c><anno>Node</anno></c> is
@@ -76,7 +76,7 @@
</desc>
</func>
<func>
- <name>node_cookie([Node, Cookie]) -> yes | no</name>
+ <name since="">node_cookie([Node, Cookie]) -> yes | no</name>
<fsummary>Set the magic cookie for a node and verify authorization (deprecated).</fsummary>
<type>
<v>Node = node()</v>
@@ -88,7 +88,7 @@
</desc>
</func>
<func>
- <name name="node_cookie" arity="2"/>
+ <name name="node_cookie" arity="2" since=""/>
<fsummary>Set the magic cookie for a node and verify authorization (deprecated).</fsummary>
<desc>
<p>Sets the magic cookie of <c><anno>Node</anno></c> to
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index aff3e8133c..85178da930 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>code</module>
+ <module since="">code</module>
<modulesummary>Erlang code server.</modulesummary>
<description>
<p>This module contains the interface to the Erlang
@@ -322,7 +322,7 @@ zip:create("mnesia-4.4.7.ez",
<funcs>
<func>
- <name name="set_path" arity="1"/>
+ <name name="set_path" arity="1" since=""/>
<fsummary>Set the code server search path.</fsummary>
<desc>
<p>Sets the code path to the list of directories <c><anno>Path</anno></c>.</p>
@@ -336,15 +336,15 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="get_path" arity="0"/>
+ <name name="get_path" arity="0" since=""/>
<fsummary>Return the code server search path.</fsummary>
<desc>
<p>Returns the code path.</p>
</desc>
</func>
<func>
- <name name="add_path" arity="1"/>
- <name name="add_pathz" arity="1"/>
+ <name name="add_path" arity="1" since=""/>
+ <name name="add_pathz" arity="1" since=""/>
<fsummary>Add a directory to the end of the code path.</fsummary>
<type name="add_path_ret"/>
<desc>
@@ -357,7 +357,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="add_patha" arity="1"/>
+ <name name="add_patha" arity="1" since=""/>
<fsummary>Add a directory to the beginning of the code path.</fsummary>
<type name="add_path_ret"/>
<desc>
@@ -370,8 +370,8 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="add_paths" arity="1"/>
- <name name="add_pathsz" arity="1"/>
+ <name name="add_paths" arity="1" since=""/>
+ <name name="add_pathsz" arity="1" since=""/>
<fsummary>Add directories to the end of the code path.</fsummary>
<desc>
<p>Adds the directories in <c><anno>Dirs</anno></c> to the end of the code
@@ -381,7 +381,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="add_pathsa" arity="1"/>
+ <name name="add_pathsa" arity="1" since=""/>
<fsummary>Add directories to the beginning of the code path.</fsummary>
<desc>
<p>Traverses <c><anno>Dirs</anno></c> and adds
@@ -397,7 +397,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="del_path" arity="1"/>
+ <name name="del_path" arity="1" since=""/>
<fsummary>Delete a directory from the code path.</fsummary>
<desc>
<p>Deletes a directory from the code path. The argument can be
@@ -417,7 +417,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="replace_path" arity="2"/>
+ <name name="replace_path" arity="2" since=""/>
<fsummary>Replace a directory with another in the code path.</fsummary>
<desc>
<p>Replaces an old occurrence of a directory
@@ -441,7 +441,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="load_file" arity="1"/>
+ <name name="load_file" arity="1" since=""/>
<fsummary>Load a module.</fsummary>
<type name="load_ret"/>
<desc>
@@ -460,7 +460,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="load_abs" arity="1"/>
+ <name name="load_abs" arity="1" since=""/>
<fsummary>Load a module, residing in a specified file.</fsummary>
<type name="load_ret"/>
<type name="loaded_filename"/>
@@ -477,7 +477,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="ensure_loaded" arity="1"/>
+ <name name="ensure_loaded" arity="1" since=""/>
<fsummary>Ensure that a module is loaded.</fsummary>
<desc>
<p>Tries to load a module in the same way as
@@ -489,7 +489,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="load_binary" arity="3"/>
+ <name name="load_binary" arity="3" since=""/>
<fsummary>Load object code for a module.</fsummary>
<type name="loaded_filename"/>
<type name="loaded_ret_atoms"/>
@@ -507,7 +507,7 @@ zip:create("mnesia-4.4.7.ez",
</desc>
</func>
<func>
- <name name="atomic_load" arity="1"/>
+ <name name="atomic_load" arity="1" since="OTP 19.0"/>
<fsummary>Load a list of modules atomically</fsummary>
<desc>
<p>Tries to load all of the modules in the list
@@ -566,7 +566,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="prepare_loading" arity="1"/>
+ <name name="prepare_loading" arity="1" since="OTP 19.0"/>
<fsummary>Prepare a list of modules atomically</fsummary>
<desc>
<p>Prepares to load the modules in the list
@@ -598,7 +598,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="finish_loading" arity="1"/>
+ <name name="finish_loading" arity="1" since="OTP 19.0"/>
<fsummary>Finish loading a list of prepared modules atomically</fsummary>
<desc>
<p>Tries to load code for all modules that have been previously
@@ -627,7 +627,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="ensure_modules_loaded" arity="1"/>
+ <name name="ensure_modules_loaded" arity="1" since="OTP 19.0"/>
<fsummary>Ensure that a list of modules is loaded</fsummary>
<desc>
<p>Tries to load any modules not already loaded in the list
@@ -639,7 +639,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="delete" arity="1"/>
+ <name name="delete" arity="1" since=""/>
<fsummary>Remove current code for a module.</fsummary>
<desc>
<p>Removes the current code for <c><anno>Module</anno></c>, that is,
@@ -652,7 +652,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="purge" arity="1"/>
+ <name name="purge" arity="1" since=""/>
<fsummary>Remove old code for a module.</fsummary>
<desc>
<p>Purges the code for <c><anno>Module</anno></c>, that is, removes code
@@ -668,7 +668,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="soft_purge" arity="1"/>
+ <name name="soft_purge" arity="1" since=""/>
<fsummary>Remove old code for a module, unless no process uses it.</fsummary>
<desc>
<p>Purges the code for <c><anno>Module</anno></c>, that is, removes code
@@ -683,7 +683,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="is_loaded" arity="1"/>
+ <name name="is_loaded" arity="1" since=""/>
<fsummary>Check if a module is loaded.</fsummary>
<type name="loaded_filename"/>
<type name="loaded_ret_atoms"/>
@@ -702,7 +702,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="all_loaded" arity="0"/>
+ <name name="all_loaded" arity="0" since=""/>
<fsummary>Get all loaded modules.</fsummary>
<type name="loaded_filename"/>
<type name="loaded_ret_atoms"/>
@@ -716,7 +716,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="which" arity="1"/>
+ <name name="which" arity="1" since=""/>
<fsummary>The object code file of a module.</fsummary>
<type name="loaded_ret_atoms"/>
<desc>
@@ -731,7 +731,7 @@ ok = code:finish_loading(Prepared),
</desc>
</func>
<func>
- <name name="get_object_code" arity="1"/>
+ <name name="get_object_code" arity="1" since=""/>
<fsummary>Gets the object code for a module.</fsummary>
<desc>
<p>Searches the code path for the object code of module
@@ -750,7 +750,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="root_dir" arity="0"/>
+ <name name="root_dir" arity="0" since=""/>
<fsummary>Root directory of Erlang/OTP.</fsummary>
<desc>
<p>Returns the root directory of Erlang/OTP, which is
@@ -762,7 +762,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="lib_dir" arity="0"/>
+ <name name="lib_dir" arity="0" since=""/>
<fsummary>Library directory of Erlang/OTP.</fsummary>
<desc>
<p>Returns the library directory, <c>$OTPROOT/lib</c>, where
@@ -774,7 +774,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="lib_dir" arity="1"/>
+ <name name="lib_dir" arity="1" since=""/>
<fsummary>Library directory for an application.</fsummary>
<desc>
<p>Returns the path
@@ -807,7 +807,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="lib_dir" arity="2"/>
+ <name name="lib_dir" arity="2" since=""/>
<fsummary>Subdirectory for an application.</fsummary>
<desc>
<p>Returns the path to a subdirectory directly under the top
@@ -827,7 +827,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="compiler_dir" arity="0"/>
+ <name name="compiler_dir" arity="0" since=""/>
<fsummary>Library directory for the compiler.</fsummary>
<desc>
<p>Returns the compiler library directory. Equivalent to
@@ -835,7 +835,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="priv_dir" arity="1"/>
+ <name name="priv_dir" arity="1" since=""/>
<fsummary>Priv directory for an application.</fsummary>
<desc>
<p>Returns the path to the <c>priv</c> directory in an
@@ -846,7 +846,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="objfile_extension" arity="0"/>
+ <name name="objfile_extension" arity="0" since=""/>
<fsummary>Object code file extension.</fsummary>
<desc>
<p>Returns the object code file extension corresponding to
@@ -854,7 +854,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="stick_dir" arity="1"/>
+ <name name="stick_dir" arity="1" since=""/>
<fsummary>Mark a directory as sticky.</fsummary>
<desc>
<p>Marks <c><anno>Dir</anno></c> as sticky.</p>
@@ -862,7 +862,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="unstick_dir" arity="1"/>
+ <name name="unstick_dir" arity="1" since=""/>
<fsummary>Remove a sticky directory mark.</fsummary>
<desc>
<p>Unsticks a directory that is marked as
@@ -871,7 +871,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="is_sticky" arity="1"/>
+ <name name="is_sticky" arity="1" since=""/>
<fsummary>Test if a module is sticky.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Module</anno></c> is the
@@ -882,7 +882,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="where_is_file" arity="1"/>
+ <name name="where_is_file" arity="1" since=""/>
<fsummary>Full name of a file located in the code path.</fsummary>
<desc>
<p>Searches the code path for <c><anno>Filename</anno></c>, a file of
@@ -893,7 +893,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="clash" arity="0"/>
+ <name name="clash" arity="0" since=""/>
<fsummary>Search for modules with identical names.</fsummary>
<desc>
<p>Searches all directories in the code path for module names with
@@ -901,7 +901,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="module_status" arity="1"/>
+ <name name="module_status" arity="1" since="OTP 20.0"/>
<fsummary>Return the status of the module in relation to object file on disk.</fsummary>
<desc>
<p>Returns:</p>
@@ -934,7 +934,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="modified_modules" arity="0"/>
+ <name name="modified_modules" arity="0" since="OTP 20.0"/>
<fsummary>Return a list of all modules modified on disk.</fsummary>
<desc>
<p>Returns the list of all currently loaded modules for which
@@ -943,7 +943,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name name="is_module_native" arity="1"/>
+ <name name="is_module_native" arity="1" since=""/>
<fsummary>Test if a module has native code.</fsummary>
<desc>
<p>Returns:</p>
@@ -961,7 +961,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</func>
<func>
- <name name="get_mode" arity="0"/>
+ <name name="get_mode" arity="0" since="OTP R16B"/>
<fsummary>The mode of the code server.</fsummary>
<desc>
<p>Returns an atom describing the mode of the code server:
diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml
index 884cb32c0c..e308b06f3c 100644
--- a/lib/kernel/doc/src/disk_log.xml
+++ b/lib/kernel/doc/src/disk_log.xml
@@ -34,7 +34,7 @@
<rev>D</rev>
<file>disk_log.sgml</file>
</header>
- <module>disk_log</module>
+ <module since="">disk_log</module>
<modulesummary>A disk-based term logging facility.</modulesummary>
<description>
<p><c>disk_log</c> is a disk-based term logger that enables
@@ -238,7 +238,7 @@
</datatypes>
<funcs>
<func>
- <name name="accessible_logs" arity="0"/>
+ <name name="accessible_logs" arity="0" since=""/>
<fsummary>Return the accessible disk logs on the current node.</fsummary>
<desc>
<p>Returns the names of the disk logs accessible on the current node.
@@ -248,8 +248,8 @@
</desc>
</func>
<func>
- <name name="alog" arity="2"/>
- <name name="balog" arity="2"/>
+ <name name="alog" arity="2" since=""/>
+ <name name="balog" arity="2" since=""/>
<fsummary>Asynchronously log an item on to a disk log.</fsummary>
<type variable="Log"/>
<type variable="Term" name_i="1"/>
@@ -275,8 +275,8 @@
</desc>
</func>
<func>
- <name name="alog_terms" arity="2"/>
- <name name="balog_terms" arity="2"/>
+ <name name="alog_terms" arity="2" since=""/>
+ <name name="balog_terms" arity="2" since=""/>
<fsummary>Asynchronously log many items on to a disk log.</fsummary>
<type variable="Log"/>
<type variable="TermList" name_i="1"/>
@@ -303,8 +303,8 @@
</desc>
</func>
<func>
- <name name="block" arity="1"/>
- <name name="block" arity="2"/>
+ <name name="block" arity="1" since=""/>
+ <name name="block" arity="2" since=""/>
<fsummary>Block a disk log.</fsummary>
<type name="block_error_rsn"/>
<desc>
@@ -330,21 +330,21 @@
</desc>
</func>
<func>
- <name name="change_header" arity="2"/>
+ <name name="change_header" arity="2" since=""/>
<fsummary>Change option head or head_func for an owner of a disk log.</fsummary>
<desc>
<p>Changes the value of option <c>head</c> or <c>head_func</c> for an owner of a disk log.</p>
</desc>
</func>
<func>
- <name name="change_notify" arity="3"/>
+ <name name="change_notify" arity="3" since=""/>
<fsummary>Change option notify for an owner of a disk log.</fsummary>
<desc>
<p>Changes the value of option <c>notify</c> for an owner of a disk log. </p>
</desc>
</func>
<func>
- <name name="change_size" arity="2"/>
+ <name name="change_size" arity="2" since=""/>
<fsummary>Change the size of an open disk log.</fsummary>
<desc>
<p>Changes the size of an open log.
@@ -384,10 +384,10 @@
</desc>
</func>
<func>
- <name name="chunk" arity="2"/>
- <name name="chunk" arity="3"/>
- <name name="bchunk" arity="2"/>
- <name name="bchunk" arity="3"/>
+ <name name="chunk" arity="2" since=""/>
+ <name name="chunk" arity="3" since=""/>
+ <name name="bchunk" arity="2" since=""/>
+ <name name="bchunk" arity="3" since=""/>
<fsummary>Read a chunk of items written to a disk log.</fsummary>
<type variable="Log"/>
<type variable="Continuation"/>
@@ -447,7 +447,7 @@
</desc>
</func>
<func>
- <name name="chunk_info" arity="1"/>
+ <name name="chunk_info" arity="1" since=""/>
<fsummary>Return information about a chunk continuation of a disk log.</fsummary>
<desc>
<p>Returns the pair <c>{node, <anno>Node</anno>}</c>,
@@ -457,7 +457,7 @@
</desc>
</func>
<func>
- <name name="chunk_step" arity="3"/>
+ <name name="chunk_step" arity="3" since=""/>
<fsummary>Step forward or backward among the wrap log files of a disk log.</fsummary>
<desc>
<p>Can be used with <c>chunk/2,3</c> and <c>bchunk/2,3</c>
@@ -480,7 +480,7 @@
</desc>
</func>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close a disk log.</fsummary>
<type name="close_error_rsn"/>
<desc>
@@ -505,7 +505,7 @@
</desc>
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Return an English description of a disk log error reply.</fsummary>
<desc>
<p>Given the error returned by any function in this module,
@@ -517,7 +517,7 @@
</desc>
</func>
<func>
- <name name="inc_wrap_file" arity="1"/>
+ <name name="inc_wrap_file" arity="1" since=""/>
<fsummary>Change to the next wrap log file of a disk log.</fsummary>
<type name="inc_wrap_error_rsn"/>
<type name="invalid_header"/>
@@ -534,7 +534,7 @@
</desc>
</func>
<func>
- <name name="info" arity="1"/>
+ <name name="info" arity="1" since=""/>
<fsummary>Return information about a disk log.</fsummary>
<type name="dlog_info"/>
<desc>
@@ -685,8 +685,8 @@
</desc>
</func>
<func>
- <name name="lclose" arity="1"/>
- <name name="lclose" arity="2"/>
+ <name name="lclose" arity="1" since=""/>
+ <name name="lclose" arity="2" since=""/>
<fsummary>Close a disk log on one node.</fsummary>
<type name="lclose_error_rsn"/>
<desc>
@@ -704,8 +704,8 @@
</desc>
</func>
<func>
- <name name="log" arity="2"/>
- <name name="blog" arity="2"/>
+ <name name="log" arity="2" since=""/>
+ <name name="blog" arity="2" since=""/>
<fsummary>Log an item onto a disk log.</fsummary>
<type variable="Log"/>
<type variable="Term" name_i="1"/>
@@ -739,8 +739,8 @@
</desc>
</func>
<func>
- <name name="log_terms" arity="2"/>
- <name name="blog_terms" arity="2"/>
+ <name name="log_terms" arity="2" since=""/>
+ <name name="blog_terms" arity="2" since=""/>
<fsummary>Log many items onto a disk log.</fsummary>
<type variable="Log"/>
<type variable="TermList" name_i="1"/>
@@ -768,7 +768,7 @@
</desc>
</func>
<func>
- <name name="open" arity="1"/>
+ <name name="open" arity="1" since=""/>
<fsummary>Open a disk log file.</fsummary>
<type name="dlog_options"/>
<type name="dlog_option"/>
@@ -1041,7 +1041,7 @@
</desc>
</func>
<func>
- <name name="pid2name" arity="1"/>
+ <name name="pid2name" arity="1" since=""/>
<fsummary>Return the name of the disk log handled by a pid.</fsummary>
<desc>
<p>Returns the log name
@@ -1053,9 +1053,9 @@
</desc>
</func>
<func>
- <name name="reopen" arity="2"/>
- <name name="reopen" arity="3"/>
- <name name="breopen" arity="3"/>
+ <name name="reopen" arity="2" since=""/>
+ <name name="reopen" arity="3" since=""/>
+ <name name="breopen" arity="3" since=""/>
<fsummary>Reopen a disk log and save the old log.</fsummary>
<type variable="Log"/>
<type variable="File" name_i="1"/>
@@ -1087,7 +1087,7 @@
</desc>
</func>
<func>
- <name name="sync" arity="1"/>
+ <name name="sync" arity="1" since=""/>
<fsummary>Flush the contents of a disk log to the disk.</fsummary>
<type name="sync_error_rsn"/>
<desc>
@@ -1097,9 +1097,9 @@
</desc>
</func>
<func>
- <name name="truncate" arity="1"/>
- <name name="truncate" arity="2"/>
- <name name="btruncate" arity="2"/>
+ <name name="truncate" arity="1" since=""/>
+ <name name="truncate" arity="2" since=""/>
+ <name name="btruncate" arity="2" since=""/>
<fsummary>Truncate a disk log.</fsummary>
<type variable="Log"/>
<type variable="Head" name_i="2"/>
@@ -1129,7 +1129,7 @@
</desc>
</func>
<func>
- <name name="unblock" arity="1"/>
+ <name name="unblock" arity="1" since=""/>
<fsummary>Unblock a disk log.</fsummary>
<type name="unblock_error_rsn"/>
<desc>
diff --git a/lib/kernel/doc/src/erl_boot_server.xml b/lib/kernel/doc/src/erl_boot_server.xml
index 4109251387..89f9855c49 100644
--- a/lib/kernel/doc/src/erl_boot_server.xml
+++ b/lib/kernel/doc/src/erl_boot_server.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>erl_boot_server</module>
+ <module since="">erl_boot_server</module>
<modulesummary>Boot server for other Erlang machines.</modulesummary>
<description>
<p>This server is used to assist diskless Erlang nodes that fetch
@@ -52,14 +52,14 @@
</description>
<funcs>
<func>
- <name name="add_slave" arity="1"/>
+ <name name="add_slave" arity="1" since=""/>
<fsummary>Add a slave to the list of allowed slaves.</fsummary>
<desc>
<p>Adds a <c><anno>Slave</anno></c> node to the list of allowed slave hosts.</p>
</desc>
</func>
<func>
- <name name="delete_slave" arity="1"/>
+ <name name="delete_slave" arity="1" since=""/>
<fsummary>Delete a slave from the list of allowed slaves.</fsummary>
<desc>
<p>Deletes a <c><anno>Slave</anno></c> node from the list of allowed slave
@@ -67,7 +67,7 @@
</desc>
</func>
<func>
- <name name="start" arity="1"/>
+ <name name="start" arity="1" since=""/>
<fsummary>Start the boot server.</fsummary>
<desc>
<p>Starts the boot server. <c><anno>Slaves</anno></c> is a list of
@@ -76,7 +76,7 @@
</desc>
</func>
<func>
- <name name="start_link" arity="1"/>
+ <name name="start_link" arity="1" since=""/>
<fsummary>Start the boot server and link to the the caller.</fsummary>
<desc>
<p>Starts the boot server and links to the caller. This function
@@ -85,7 +85,7 @@
</desc>
</func>
<func>
- <name name="which_slaves" arity="0"/>
+ <name name="which_slaves" arity="0" since=""/>
<fsummary>Return the current list of allowed slave hosts.</fsummary>
<desc>
<p>Returns the current list of allowed slave hosts.</p>
diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml
index 75114e015c..f2d5e1b397 100644
--- a/lib/kernel/doc/src/erl_ddll.xml
+++ b/lib/kernel/doc/src/erl_ddll.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>erl_ddll</module>
+ <module since="">erl_ddll</module>
<modulesummary>Dynamic driver loader and linker.</modulesummary>
<description>
<p>This module provides an interface for loading
@@ -196,7 +196,7 @@
</datatypes>
<funcs>
<func>
- <name name="demonitor" arity="1"/>
+ <name name="demonitor" arity="1" since=""/>
<fsummary>Remove a monitor for a driver.</fsummary>
<desc>
<p>Removes a driver monitor in much the same way as
@@ -212,7 +212,7 @@
</desc>
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Format an error descriptor.</fsummary>
<desc>
<p>Takes an <c><anno>ErrorDesc</anno></c> returned by load, unload, or
@@ -229,7 +229,7 @@
</desc>
</func>
<func>
- <name name="info" arity="0"/>
+ <name name="info" arity="0" since=""/>
<fsummary>Retrieve information about all drivers.</fsummary>
<desc>
<p>Returns a list of tuples <c>{<anno>DriverName</anno>, <anno>InfoList</anno>}</c>,
@@ -240,7 +240,7 @@
</desc>
</func>
<func>
- <name name="info" arity="1"/>
+ <name name="info" arity="1" since=""/>
<fsummary>Retrieve information about one driver.</fsummary>
<desc>
<p>Returns a list of tuples <c>{<anno>Tag</anno>, <anno>Value</anno>}</c>,
@@ -266,7 +266,7 @@
</desc>
</func>
<func>
- <name name="info" arity="2"/>
+ <name name="info" arity="2" since=""/>
<fsummary>Retrieve specific information about one driver.</fsummary>
<desc>
<p>Returns specific information about one aspect of a driver.
@@ -328,7 +328,7 @@
</desc>
</func>
<func>
- <name name="load" arity="2"/>
+ <name name="load" arity="2" since=""/>
<fsummary>Load a driver.</fsummary>
<desc>
<p>Loads and links the dynamic driver <c><anno>Name</anno></c>.
@@ -390,7 +390,7 @@
</desc>
</func>
<func>
- <name name="load_driver" arity="2"/>
+ <name name="load_driver" arity="2" since=""/>
<fsummary>Load a driver.</fsummary>
<desc>
<p>Works essentially as <c>load/2</c>, but loads the driver
@@ -413,7 +413,7 @@
</desc>
</func>
<func>
- <name name="loaded_drivers" arity="0"/>
+ <name name="loaded_drivers" arity="0" since=""/>
<fsummary>List loaded drivers.</fsummary>
<desc>
<p>Returns a list of all the available drivers, both
@@ -425,7 +425,7 @@
</desc>
</func>
<func>
- <name name="monitor" arity="2"/>
+ <name name="monitor" arity="2" since=""/>
<fsummary>Create a monitor for a driver.</fsummary>
<desc>
<p>Creates a driver monitor and works in many
@@ -588,7 +588,7 @@
</desc>
</func>
<func>
- <name name="reload" arity="2"/>
+ <name name="reload" arity="2" since=""/>
<fsummary>Replace a driver.</fsummary>
<desc>
<p>Reloads the driver named <c><anno>Name</anno></c> from a possibly
@@ -626,7 +626,7 @@
</desc>
</func>
<func>
- <name name="reload_driver" arity="2"/>
+ <name name="reload_driver" arity="2" since=""/>
<fsummary>Replace a driver.</fsummary>
<desc>
<p>Works exactly as <seealso marker="#reload/2"><c>reload/2</c></seealso>,
@@ -644,7 +644,7 @@
</desc>
</func>
<func>
- <name name="try_load" arity="3"/>
+ <name name="try_load" arity="3" since=""/>
<fsummary>Load a driver.</fsummary>
<desc>
<p>Provides more control than the
@@ -931,7 +931,7 @@
</desc>
</func>
<func>
- <name name="try_unload" arity="2"/>
+ <name name="try_unload" arity="2" since=""/>
<fsummary>Unload a driver.</fsummary>
<desc>
<p>This is the low-level function to unload (or decrement
@@ -1116,7 +1116,7 @@
</desc>
</func>
<func>
- <name name="unload" arity="1"/>
+ <name name="unload" arity="1" since=""/>
<fsummary>Unload a driver.</fsummary>
<desc>
<p>Unloads, or at least dereferences the driver named
@@ -1143,7 +1143,7 @@
</desc>
</func>
<func>
- <name name="unload_driver" arity="1"/>
+ <name name="unload_driver" arity="1" since=""/>
<fsummary>Unload a driver.</fsummary>
<desc>
<p>Unloads, or at least dereferences the driver named
diff --git a/lib/kernel/doc/src/erl_epmd.xml b/lib/kernel/doc/src/erl_epmd.xml
index 8b076cd2d7..2adbf11a28 100644
--- a/lib/kernel/doc/src/erl_epmd.xml
+++ b/lib/kernel/doc/src/erl_epmd.xml
@@ -28,7 +28,7 @@
<date>2018-02-19</date>
<rev>A</rev>
</header>
- <module>erl_epmd</module>
+ <module since="OTP R14B">erl_epmd</module>
<modulesummary>
Erlang interface towards epmd
</modulesummary>
@@ -41,7 +41,7 @@
<funcs>
<func>
- <name name="start_link" arity="0"/>
+ <name name="start_link" arity="0" since="OTP 21.0"/>
<fsummary>Callback for erl_distribution supervisor.</fsummary>
<desc>
<p>This function is invoked as this module is added as a child of the
@@ -50,8 +50,8 @@
</func>
<func>
- <name name="register_node" arity="2"/>
- <name name="register_node" arity="3"/>
+ <name name="register_node" arity="2" since="OTP 21.0"/>
+ <name name="register_node" arity="3" since="OTP 21.0"/>
<fsummary>Registers the node with <c>epmd</c>.</fsummary>
<desc>
<p>Registers the node with <c>epmd</c> and tells epmd what port will be
@@ -62,8 +62,8 @@
</func>
<func>
- <name name="port_please" arity="2"/>
- <name name="port_please" arity="3"/>
+ <name name="port_please" arity="2" since="OTP 21.0"/>
+ <name name="port_please" arity="3" since="OTP 21.0"/>
<fsummary>Returns the port number for a given node.</fsummary>
<desc>
<p>Requests the distribution port for the given node of an EPMD
@@ -73,7 +73,7 @@
</func>
<func>
- <name name="address_please" arity="3"/>
+ <name name="address_please" arity="3" since="OTP 21.0"/>
<fsummary>Returns address and port.</fsummary>
<desc>
<p>Called by the distribution module. Resolves the <c>Host</c> to an IP
@@ -84,7 +84,7 @@
</func>
<func>
- <name name="names" arity="1"/>
+ <name name="names" arity="1" since="OTP 21.0"/>
<fsummary>Names of Erlang nodes at a host.</fsummary>
<desc>
<p>Called by <seealso marker="net_adm"><c>net_adm:names/0</c></seealso>.
diff --git a/lib/kernel/doc/src/error_handler.xml b/lib/kernel/doc/src/error_handler.xml
index e5639487dc..eb01e87aee 100644
--- a/lib/kernel/doc/src/error_handler.xml
+++ b/lib/kernel/doc/src/error_handler.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>error_handler</module>
+ <module since="">error_handler</module>
<modulesummary>Default system error handler.</modulesummary>
<description>
<p>This module defines what happens when certain types
@@ -38,7 +38,7 @@
</description>
<funcs>
<func>
- <name name="raise_undef_exception" arity="3"/>
+ <name name="raise_undef_exception" arity="3" since="OTP R16B"/>
<fsummary>Raise an undef exception.</fsummary>
<type_desc variable="Args">
A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
@@ -51,7 +51,7 @@
</desc>
</func>
<func>
- <name name="undefined_function" arity="3"/>
+ <name name="undefined_function" arity="3" since=""/>
<fsummary>Called when an undefined function is encountered.</fsummary>
<type_desc variable="Args">
A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
@@ -93,7 +93,7 @@
</desc>
</func>
<func>
- <name name="undefined_lambda" arity="3"/>
+ <name name="undefined_lambda" arity="3" since=""/>
<fsummary>Called when an undefined lambda (fun) is encountered.</fsummary>
<type_desc variable="Args">
A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index c3d68fd79f..c170b4fa34 100644
--- a/lib/kernel/doc/src/error_logger.xml
+++ b/lib/kernel/doc/src/error_logger.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>error_logger</module>
+ <module since="">error_logger</module>
<modulesummary>Erlang error logger.</modulesummary>
<description>
@@ -76,8 +76,8 @@
</datatypes>
<funcs>
<func>
- <name name="add_report_handler" arity="1"/>
- <name name="add_report_handler" arity="2"/>
+ <name name="add_report_handler" arity="1" since=""/>
+ <name name="add_report_handler" arity="2" since=""/>
<fsummary>Add an event handler to the error logger.</fsummary>
<desc>
<p>Adds a new event handler to the error logger. The event
@@ -96,7 +96,7 @@
</desc>
</func>
<func>
- <name name="delete_report_handler" arity="1"/>
+ <name name="delete_report_handler" arity="1" since=""/>
<fsummary>Delete an event handler from the error logger.</fsummary>
<desc>
<p>Deletes an event handler from the error logger by calling
@@ -108,9 +108,9 @@
</desc>
</func>
<func>
- <name name="error_msg" arity="1"/>
- <name name="error_msg" arity="2"/>
- <name name="format" arity="2"/>
+ <name name="error_msg" arity="1" since=""/>
+ <name name="error_msg" arity="2" since=""/>
+ <name name="format" arity="2" since=""/>
<fsummary>Log a standard error event.</fsummary>
<desc>
<p>Log a standard error event. The <c><anno>Format</anno></c>
@@ -142,7 +142,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="error_report" arity="1"/>
+ <name name="error_report" arity="1" since=""/>
<fsummary>Log a standard error event.</fsummary>
<desc>
<p>Log a standard error event. Error logger forwards the event
@@ -169,7 +169,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="error_report" arity="2"/>
+ <name name="error_report" arity="2" since=""/>
<fsummary>Log a user-defined error event.</fsummary>
<desc>
<p>Log a user-defined error event. Error logger forwards the
@@ -191,7 +191,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="get_format_depth" arity="0"/>
+ <name name="get_format_depth" arity="0" since="OTP 20.0"/>
<fsummary>Get the value of the Kernel application variable
<c>error_logger_format_depth</c>.</fsummary>
<desc>
@@ -211,8 +211,8 @@ ok</pre>
</desc>
</func>
<func>
- <name name="info_msg" arity="1"/>
- <name name="info_msg" arity="2"/>
+ <name name="info_msg" arity="1" since=""/>
+ <name name="info_msg" arity="2" since=""/>
<fsummary>Log a standard information event.</fsummary>
<desc>
<p>Log a standard information event. The <c><anno>Format</anno></c>
@@ -244,7 +244,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="info_report" arity="1"/>
+ <name name="info_report" arity="1" since=""/>
<fsummary>Log a standard information event.</fsummary>
<desc>
<p>Log a standard information event. Error logger forwards the
@@ -271,7 +271,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="info_report" arity="2"/>
+ <name name="info_report" arity="2" since=""/>
<fsummary>Log a user-defined information event.</fsummary>
<desc>
<p>Log a user-defined information event. Error logger forwards
@@ -294,9 +294,9 @@ ok</pre>
</desc>
</func>
<func>
- <name name="logfile" arity="1" clause_i="1"/>
- <name name="logfile" arity="1" clause_i="2"/>
- <name name="logfile" arity="1" clause_i="3"/>
+ <name name="logfile" arity="1" clause_i="1" since=""/>
+ <name name="logfile" arity="1" clause_i="2" since=""/>
+ <name name="logfile" arity="1" clause_i="3" since=""/>
<fsummary>Enable or disable error printouts to a file.</fsummary>
<type variable="Filename"/>
<type variable="OpenReason" name_i="1"/>
@@ -346,7 +346,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="tty" arity="1"/>
+ <name name="tty" arity="1" since=""/>
<fsummary>Enable or disable printouts to the terminal.</fsummary>
<desc>
<p>Enables (<c><anno>Flag</anno> == true</c>) or disables
@@ -363,7 +363,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="warning_map" arity="0"/>
+ <name name="warning_map" arity="0" since=""/>
<fsummary>Return the current mapping for warning events.</fsummary>
<desc>
<p>Returns the current mapping for warning events. Events sent
@@ -400,8 +400,8 @@ ok</pre>
</desc>
</func>
<func>
- <name name="warning_msg" arity="1"/>
- <name name="warning_msg" arity="2"/>
+ <name name="warning_msg" arity="1" since=""/>
+ <name name="warning_msg" arity="2" since=""/>
<fsummary>Log a standard warning event.</fsummary>
<desc>
<p>Log a standard warning event. The <c><anno>Format</anno></c>
@@ -429,7 +429,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="warning_report" arity="1"/>
+ <name name="warning_report" arity="1" since=""/>
<fsummary>Log a standard warning event.</fsummary>
<desc>
<p>Log a standard warning event. Error logger forwards the event
@@ -446,7 +446,7 @@ ok</pre>
</desc>
</func>
<func>
- <name name="warning_report" arity="2"/>
+ <name name="warning_report" arity="2" since=""/>
<fsummary>Log a user-defined warning event.</fsummary>
<desc>
<p>Log a user-defined warning event. Error logger forwards the
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 9acaf6b41e..fc25e83d40 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>file</module>
+ <module since="">file</module>
<modulesummary>File interface module.</modulesummary>
<description>
<p>This module provides an interface to the file system.</p>
@@ -186,7 +186,7 @@
<funcs>
<func>
- <name name="advise" arity="4"/>
+ <name name="advise" arity="4" since="OTP R14B"/>
<fsummary>Predeclare an access pattern for file data.</fsummary>
<type name="posix_file_advise"/>
<desc>
@@ -197,7 +197,7 @@
</desc>
</func>
<func>
- <name name="allocate" arity="3"/>
+ <name name="allocate" arity="3" since="OTP R16B"/>
<fsummary>Allocate file space.</fsummary>
<desc>
<p><c>allocate/3</c> can be used to preallocate space for a file.</p>
@@ -209,7 +209,7 @@
</desc>
</func>
<func>
- <name name="change_group" arity="2"/>
+ <name name="change_group" arity="2" since=""/>
<fsummary>Change group of a file.</fsummary>
<desc>
<p>Changes group of a file. See
@@ -217,7 +217,7 @@
</desc>
</func>
<func>
- <name name="change_mode" arity="2"/>
+ <name name="change_mode" arity="2" since="OTP R14B"/>
<fsummary>Change permissions of a file.</fsummary>
<desc>
<p>Changes permissions of a file. See
@@ -225,7 +225,7 @@
</desc>
</func>
<func>
- <name name="change_owner" arity="2"/>
+ <name name="change_owner" arity="2" since=""/>
<fsummary>Change owner of a file.</fsummary>
<desc>
<p>Changes owner of a file. See
@@ -233,7 +233,7 @@
</desc>
</func>
<func>
- <name name="change_owner" arity="3"/>
+ <name name="change_owner" arity="3" since=""/>
<fsummary>Change owner and group of a file.</fsummary>
<desc>
<p>Changes owner and group of a file. See
@@ -241,7 +241,7 @@
</desc>
</func>
<func>
- <name name="change_time" arity="2"/>
+ <name name="change_time" arity="2" since=""/>
<fsummary>Change the modification time of a file.</fsummary>
<desc>
<p>Changes the modification and access times of a file. See
@@ -249,7 +249,7 @@
</desc>
</func>
<func>
- <name name="change_time" arity="3"/>
+ <name name="change_time" arity="3" since=""/>
<fsummary>Change the modification and last access time of a file.</fsummary>
<desc>
<p>Changes the modification and last access times of a file. See
@@ -257,7 +257,7 @@
</desc>
</func>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close a file.</fsummary>
<desc>
<p>Closes the file referenced by <c><anno>IoDevice</anno></c>. It mostly
@@ -270,7 +270,7 @@
</desc>
</func>
<func>
- <name name="consult" arity="1"/>
+ <name name="consult" arity="1" since=""/>
<fsummary>Read Erlang terms from a file.</fsummary>
<desc>
<p>Reads Erlang terms, separated by '.', from
@@ -308,8 +308,8 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="copy" arity="2"/>
- <name name="copy" arity="3"/>
+ <name name="copy" arity="2" since=""/>
+ <name name="copy" arity="3" since=""/>
<fsummary>Copy file contents.</fsummary>
<desc>
<p>Copies <c><anno>ByteCount</anno></c> bytes from
@@ -346,7 +346,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="datasync" arity="1"/>
+ <name name="datasync" arity="1" since="OTP R14B"/>
<fsummary>Synchronize the in-memory data of a file, ignoring most of its metadata, with that on the physical medium.</fsummary>
<desc>
<p>Ensures that any buffers kept by the operating system
@@ -369,7 +369,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="del_dir" arity="1"/>
+ <name name="del_dir" arity="1" since=""/>
<fsummary>Delete a directory.</fsummary>
<desc>
<p>Tries to delete directory <c><anno>Dir</anno></c>.
@@ -405,7 +405,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="delete" arity="1"/>
+ <name name="delete" arity="1" since=""/>
<fsummary>Delete a file.</fsummary>
<desc>
<p>Tries to delete file <c><anno>Filename</anno></c>.
@@ -442,7 +442,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="eval" arity="1"/>
+ <name name="eval" arity="1" since=""/>
<fsummary>Evaluate Erlang expressions in a file.</fsummary>
<desc>
<p>Reads and evaluates Erlang expressions, separated by '.' (or
@@ -476,7 +476,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="eval" arity="2"/>
+ <name name="eval" arity="2" since=""/>
<fsummary>Evaluate Erlang expressions in a file.</fsummary>
<desc>
<p>The same as <c>eval/1</c>, but the variable bindings
@@ -486,7 +486,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Return a descriptive string for an error reason.</fsummary>
<desc>
<p>Given the error reason returned by any function in this
@@ -494,7 +494,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="get_cwd" arity="0"/>
+ <name name="get_cwd" arity="0" since=""/>
<fsummary>Get the current working directory.</fsummary>
<desc>
<p>Returns <c>{ok, <anno>Dir</anno>}</c>, where <c><anno>Dir</anno></c>
@@ -516,7 +516,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="get_cwd" arity="1"/>
+ <name name="get_cwd" arity="1" since=""/>
<fsummary>Get the current working directory for the specified drive.</fsummary>
<desc>
<p>Returns <c>{ok, <anno>Dir</anno>}</c> or
@@ -547,7 +547,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="list_dir" arity="1"/>
+ <name name="list_dir" arity="1" since=""/>
<fsummary>List files in a directory.</fsummary>
<desc>
<p>Lists all files in a directory, <em>except</em> files
@@ -578,7 +578,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="list_dir_all" arity="1"/>
+ <name name="list_dir_all" arity="1" since="OTP R16B"/>
<fsummary>List all files in a directory.</fsummary>
<desc>
<p><marker id="list_dir_all"/>Lists all the files in a directory,
@@ -603,7 +603,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="make_dir" arity="1"/>
+ <name name="make_dir" arity="1" since=""/>
<fsummary>Make a directory.</fsummary>
<desc>
<p>Tries to create directory <c><anno>Dir</anno></c>. Missing parent
@@ -637,7 +637,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="make_link" arity="2"/>
+ <name name="make_link" arity="2" since=""/>
<fsummary>Make a hard link to a file.</fsummary>
<desc>
<p>Makes a hard link from <c><anno>Existing</anno></c> to
@@ -666,7 +666,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="make_symlink" arity="2"/>
+ <name name="make_symlink" arity="2" since=""/>
<fsummary>Make a symbolic link to a file or directory.</fsummary>
<desc>
<p>Creates a symbolic link <c><anno>New</anno></c> to
@@ -702,7 +702,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="native_name_encoding" arity="0"/>
+ <name name="native_name_encoding" arity="0" since="OTP R14B01"/>
<fsummary>Return the configured filename encoding of the VM.</fsummary>
<desc>
<p><marker id="native_name_encoding"/>Returns
@@ -714,7 +714,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="open" arity="2"/>
+ <name name="open" arity="2" since=""/>
<fsummary>Open a file.</fsummary>
<desc>
<p>Opens file <c><anno>File</anno></c> in the mode determined
@@ -997,7 +997,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="path_consult" arity="2"/>
+ <name name="path_consult" arity="2" since=""/>
<fsummary>Read Erlang terms from a file.</fsummary>
<desc>
<p>Searches the path <c><anno>Path</anno></c> (a list of directory
@@ -1039,7 +1039,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="path_eval" arity="2"/>
+ <name name="path_eval" arity="2" since=""/>
<fsummary>Evaluate Erlang expressions in a file.</fsummary>
<desc>
<p>Searches the path <c><anno>Path</anno></c> (a list of directory
@@ -1085,7 +1085,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="path_open" arity="3"/>
+ <name name="path_open" arity="3" since=""/>
<fsummary>Open a file.</fsummary>
<desc>
<p>Searches the path <c><anno>Path</anno></c> (a list of directory
@@ -1114,7 +1114,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="path_script" arity="2"/>
+ <name name="path_script" arity="2" since=""/>
<fsummary>Evaluate and return the value of Erlang expressions in a file.</fsummary>
<desc>
<p>Searches the path <c><anno>Path</anno></c> (a list of directory
@@ -1158,7 +1158,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="path_script" arity="3"/>
+ <name name="path_script" arity="3" since=""/>
<fsummary>Evaluate and return the value of Erlang expressions in a file.</fsummary>
<desc>
<p>The same as <c>path_script/2</c> but the variable bindings
@@ -1168,7 +1168,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="pid2name" arity="1"/>
+ <name name="pid2name" arity="1" since=""/>
<fsummary>Return the name of the file handled by a pid.</fsummary>
<desc>
<p>If <c><anno>Pid</anno></c> is an I/O device, that is, a pid returned from
@@ -1193,7 +1193,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="position" arity="2"/>
+ <name name="position" arity="2" since=""/>
<fsummary>Set position in a file.</fsummary>
<desc>
<p>Sets the position of the file referenced by <c><anno>IoDevice</anno></c>
@@ -1245,7 +1245,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="pread" arity="2"/>
+ <name name="pread" arity="2" since=""/>
<fsummary>Read from a file at certain positions.</fsummary>
<desc>
<p>Performs a sequence of <c>pread/3</c> in one operation,
@@ -1263,7 +1263,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="pread" arity="3"/>
+ <name name="pread" arity="3" since=""/>
<fsummary>Read from a file at a certain position.</fsummary>
<desc>
<p>Combines <c>position/2</c> and <c>read/2</c> in one
@@ -1283,7 +1283,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="pwrite" arity="2"/>
+ <name name="pwrite" arity="2" since=""/>
<fsummary>Write to a file at certain positions.</fsummary>
<desc>
<p>Performs a sequence of <c>pwrite/3</c> in one operation,
@@ -1298,7 +1298,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="pwrite" arity="3"/>
+ <name name="pwrite" arity="3" since=""/>
<fsummary>Write to a file at a certain position.</fsummary>
<desc>
<p>Combines <c>position/2</c> and <c>write/2</c> in one
@@ -1317,7 +1317,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="read" arity="2"/>
+ <name name="read" arity="2" since=""/>
<fsummary>Read from a file.</fsummary>
<desc>
<p>Reads <c><anno>Number</anno></c> bytes/characters from the file
@@ -1371,7 +1371,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="read_file" arity="1"/>
+ <name name="read_file" arity="1" since=""/>
<fsummary>Read a file.</fsummary>
<desc>
<p>Returns <c>{ok, <anno>Binary</anno>}</c>, where
@@ -1407,8 +1407,8 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="read_file_info" arity="1"/>
- <name name="read_file_info" arity="2"/>
+ <name name="read_file_info" arity="1" since=""/>
+ <name name="read_file_info" arity="2" since="OTP R15B"/>
<fsummary>Retrieve information about a file.</fsummary>
<desc>
<p>Retrieves information about a file. Returns
@@ -1562,7 +1562,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="read_line" arity="1"/>
+ <name name="read_line" arity="1" since=""/>
<fsummary>Read a line from a file.</fsummary>
<desc>
<p>Reads a line of bytes/characters from the file referenced by
@@ -1619,7 +1619,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="read_link" arity="1"/>
+ <name name="read_link" arity="1" since=""/>
<fsummary>See what a link is pointing to.</fsummary>
<desc>
<p><marker id="read_link_all"/>Returns
@@ -1649,7 +1649,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="read_link_all" arity="1"/>
+ <name name="read_link_all" arity="1" since="OTP R16B"/>
<fsummary>See what a link is pointing to.</fsummary>
<desc>
<p>Returns <c>{ok, <anno>Filename</anno>}</c> if
@@ -1677,8 +1677,8 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="read_link_info" arity="1"/>
- <name name="read_link_info" arity="2"/>
+ <name name="read_link_info" arity="1" since=""/>
+ <name name="read_link_info" arity="2" since="OTP R15B"/>
<fsummary>Retrieve information about a link or file.</fsummary>
<desc>
<p>Works like
@@ -1699,7 +1699,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="rename" arity="2"/>
+ <name name="rename" arity="2" since=""/>
<fsummary>Rename a file.</fsummary>
<desc>
<p>Tries to rename the file <c><anno>Source</anno></c> to
@@ -1762,7 +1762,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="script" arity="1"/>
+ <name name="script" arity="1" since=""/>
<fsummary>Evaluate and return the value of Erlang expressions in a file.</fsummary>
<desc>
<p>Reads and evaluates Erlang expressions, separated by '.' (or
@@ -1797,7 +1797,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="script" arity="2"/>
+ <name name="script" arity="2" since=""/>
<fsummary>Evaluate and return the value of Erlang expressions in a file.</fsummary>
<desc>
<p>The same as <c>script/1</c> but the variable bindings
@@ -1807,7 +1807,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="sendfile" arity="2"/>
+ <name name="sendfile" arity="2" since="OTP R15B"/>
<fsummary>Send a file to a socket.</fsummary>
<desc>
<p>Sends the file <c>Filename</c> to <c>Socket</c>.
@@ -1816,7 +1816,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="sendfile" arity="5"/>
+ <name name="sendfile" arity="5" since="OTP R15B"/>
<fsummary>Send a file to a socket.</fsummary>
<type name="sendfile_option"/>
<desc>
@@ -1843,7 +1843,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="set_cwd" arity="1"/>
+ <name name="set_cwd" arity="1" since=""/>
<fsummary>Set the current working directory.</fsummary>
<desc>
<p>Sets the current working directory of the file server to
@@ -1890,7 +1890,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="sync" arity="1"/>
+ <name name="sync" arity="1" since=""/>
<fsummary>Synchronize the in-memory state of a file with that on the physical medium.</fsummary>
<desc>
<p>Ensures that any buffers kept by the operating system
@@ -1906,7 +1906,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="truncate" arity="1"/>
+ <name name="truncate" arity="1" since=""/>
<fsummary>Truncate a file.</fsummary>
<desc>
<p>Truncates the file referenced by <c><anno>IoDevice</anno></c> at
@@ -1915,7 +1915,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="write" arity="2"/>
+ <name name="write" arity="2" since=""/>
<fsummary>Write to a file.</fsummary>
<desc>
<p>Writes <c><anno>Bytes</anno></c> to the file referenced by
@@ -1941,7 +1941,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="write_file" arity="2"/>
+ <name name="write_file" arity="2" since=""/>
<fsummary>Write a file.</fsummary>
<desc>
<p>Writes the contents of the <c>iodata</c> term <c><anno>Bytes</anno></c>
@@ -1978,7 +1978,7 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="write_file" arity="3"/>
+ <name name="write_file" arity="3" since=""/>
<fsummary>Write a file.</fsummary>
<desc>
<p>Same as <c>write_file/2</c>, but takes a third argument
@@ -1989,8 +1989,8 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name name="write_file_info" arity="2"/>
- <name name="write_file_info" arity="3"/>
+ <name name="write_file_info" arity="2" since=""/>
+ <name name="write_file_info" arity="3" since="OTP R15B"/>
<fsummary>Change file information.</fsummary>
<desc>
<p>Changes file information. Returns <c>ok</c> if successful,
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 737800c6b1..f70d6c24db 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2016</year>
+ <year>2007</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>gen_sctp.xml</file>
</header>
- <module>gen_sctp</module>
+ <module since="">gen_sctp</module>
<modulesummary>Functions for communicating with sockets using the SCTP
protocol.</modulesummary>
<description>
@@ -100,7 +100,7 @@
<funcs>
<func>
- <name name="abort" arity="2"/>
+ <name name="abort" arity="2" since=""/>
<fsummary>Abnormally terminate the association specified by
<c>Assoc</c>, without flushing of unsent data.</fsummary>
<desc>
@@ -113,7 +113,7 @@
</func>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close the socket and all associations on it.</fsummary>
<desc>
<p>Closes the socket and all associations on it. The unsent
@@ -128,7 +128,7 @@
</func>
<func>
- <name name="connect" arity="4"/>
+ <name name="connect" arity="4" since=""/>
<fsummary>Same as <c>connect(Socket, Addr, Port, Opts, infinity)</c>.</fsummary>
<desc>
<p>Same as <c>connect(<anno>Socket</anno>, <anno>Addr</anno>,
@@ -137,7 +137,7 @@
</func>
<func>
- <name name="connect" arity="5"/>
+ <name name="connect" arity="5" since=""/>
<fsummary>Establish a new association for socket <c>Socket</c>, with a
peer (SCTP server socket).</fsummary>
<desc>
@@ -213,7 +213,7 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="connect_init" arity="4"/>
+ <name name="connect_init" arity="4" since="OTP R13B04"/>
<fsummary>Same as <c>connect_init(Socket, Addr, Port, Opts, infinity)</c>..</fsummary>
<desc>
<p>Same as <c>connect_init(<anno>Socket</anno>, <anno>Addr</anno>,
@@ -222,7 +222,7 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="connect_init" arity="5"/>
+ <name name="connect_init" arity="5" since="OTP R13B04"/>
<fsummary>Initiate a new association for socket <c>Socket</c>, with a
peer (SCTP server socket).</fsummary>
<desc>
@@ -248,7 +248,7 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="controlling_process" arity="2"/>
+ <name name="controlling_process" arity="2" since=""/>
<fsummary>Assign a new controlling process pid to the socket.</fsummary>
<desc>
<p>Assigns a new controlling process <c><anno>Pid</anno></c> to
@@ -259,7 +259,7 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="eof" arity="2"/>
+ <name name="eof" arity="2" since=""/>
<fsummary>Gracefully terminate the association specified by <c>Assoc</c>,
with flushing of all unsent data.</fsummary>
<desc>
@@ -272,7 +272,7 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="error_string" arity="1"/>
+ <name name="error_string" arity="1" since=""/>
<fsummary>Translate an SCTP error number into a string.</fsummary>
<desc>
<p>Translates an SCTP error number from, for example,
@@ -283,8 +283,8 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="listen" arity="2" clause_i="1"/>
- <name name="listen" arity="2" clause_i="2"/>
+ <name name="listen" arity="2" clause_i="1" since=""/>
+ <name name="listen" arity="2" clause_i="2" since="OTP R15B"/>
<fsummary>Set up a socket to listen.</fsummary>
<desc>
<p>Sets up a socket to listen on the IP address and port number
@@ -300,10 +300,10 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="open" arity="0"/>
- <name name="open" arity="1" clause_i="1"/>
- <name name="open" arity="1" clause_i="2"/>
- <name name="open" arity="2"/>
+ <name name="open" arity="0" since=""/>
+ <name name="open" arity="1" clause_i="1" since=""/>
+ <name name="open" arity="1" clause_i="2" since=""/>
+ <name name="open" arity="2" since=""/>
<fsummary>Create an SCTP socket and binds it to local addresses.</fsummary>
<desc>
<p>Creates an SCTP socket and binds it to the local addresses
@@ -331,11 +331,42 @@ connect(Socket, Ip, Port>,
with <anno>SockType</anno> <c>seqpacket</c>, and with reasonably large
<seealso marker="inet#option-sndbuf">kernel</seealso> and driver
<seealso marker="inet#option-buffer">buffers</seealso>.</p>
+ <p>
+ If the socket is in
+ <seealso marker="#option-active">passive</seealso>
+ mode data can be received through the
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ calls.
+ </p>
+ <p>
+ If the socket is in
+ <seealso marker="#option-active">active</seealso>
+ mode data received data is delivered to the controlling process
+ as messages:
+ </p>
+ <code type="none">
+{sctp, <anno>Socket</anno>, FromIP, FromPort, {AncData, Data}}
+ </code>
+ <p>
+ See
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ for a description of the message fields.
+ </p>
+ <note>
+ <p>
+ This message format unfortunately differs slightly from the
+ <seealso marker="gen_udp#open/1"><c>gen_udp</c></seealso>
+ message format with ancillary data,
+ and from the
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ return tuple format.
+ </p>
+ </note>
</desc>
</func>
<func>
- <name name="peeloff" arity="2"/>
+ <name name="peeloff" arity="2" since="OTP R15B"/>
<fsummary>Peel off a type <c>stream</c> socket from a type
<c>seqpacket</c> one.</fsummary>
<desc>
@@ -356,8 +387,8 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="recv" arity="1"/>
- <name name="recv" arity="2"/>
+ <name name="recv" arity="1" since=""/>
+ <name name="recv" arity="2" since=""/>
<fsummary>Receive a message from a socket.</fsummary>
<desc>
<p>Receives the <c><anno>Data</anno></c> message from any association
@@ -380,6 +411,19 @@ connect(Socket, Ip, Port>,
socket option
<seealso marker="#option-sctp_get_peer_addr_info"><c>sctp_get_peer_addr_info</c></seealso>,
but this does still not produce the stream number).</p>
+ <p>
+ <c><anno>AncData</anno></c> may also contain
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ from the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>,
+ if that is supported by the platform for the socket.
+ </p>
<p>The <c><anno>Data</anno></c> received can be a <c>binary()</c>
or a <c>list()</c> of bytes (integers in the range 0 through 255)
depending on the socket mode, or an SCTP event.</p>
@@ -488,7 +532,7 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="send" arity="3"/>
+ <name name="send" arity="3" since=""/>
<fsummary>Send a message using an <c>#sctp_sndrcvinfo{}</c>record.</fsummary>
<desc>
<p>Sends the <c><anno>Data</anno></c> message with all sending
@@ -503,7 +547,7 @@ connect(Socket, Ip, Port>,
</func>
<func>
- <name name="send" arity="4"/>
+ <name name="send" arity="4" since=""/>
<fsummary>Send a message over an existing association and specified
stream.</fsummary>
<desc>
@@ -544,12 +588,25 @@ connect(Socket, Ip, Port>,
<seealso marker="#recv/1"><c>recv</c></seealso> call
to retrieve the available data from the socket.</p>
</item>
+ <item>
+ <p>
+ If <c>true|once|N</c> (active modes)
+ received data or events are sent to the owning process.
+ See <seealso marker="#open/0"><c>open/0..2</c></seealso>
+ for the message format.
+ </p>
+ </item>
<item>
- <p>If <c>true</c> (full active mode), the pending data or events are
- sent to the owning process.</p>
- <p>Notice that this can cause the message queue to overflow,
- as there is no way to throttle the sender in this case
- (no flow control).</p>
+ <p>
+ If <c>true</c> (full active mode) there is no flow control.
+ </p>
+ <note>
+ <p>
+ Note that this can cause the message queue to overflow
+ causing for example the virtual machine
+ to run out of memory and crash.
+ </p>
+ </note>
</item>
<item>
<p>If <c>once</c>, only one message is automatically placed
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index e6104b0c76..fc16473393 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -27,7 +27,7 @@
<date>1997-10-24</date>
<rev>A</rev>
</header>
- <module>gen_tcp</module>
+ <module since="">gen_tcp</module>
<modulesummary>Interface to TCP/IP sockets.</modulesummary>
<description>
<p>This module provides functions for communicating
@@ -70,6 +70,32 @@ do_recv(Sock, Bs) ->
<name name="option"/>
</datatype>
<datatype>
+ <name name="pktoptions_value"/>
+ <desc>
+ <p>
+ If the platform implements the IPv4 option
+ <c>IP_PKTOPTIONS</c>, or the IPv6 option
+ <c>IPV6_PKTOPTIONS</c> or <c>IPV6_2292PKTOPTIONS</c> for the socket
+ this value is returned from
+ <seealso marker="inet#getopts/2"><c>inet:getopts/2</c></seealso>
+ when called with the option name
+ <seealso marker="#type-option_name"><c>pktoptions</c></seealso>.
+ </p>
+ <note>
+ <p>
+ This option appears to be VERY Linux specific,
+ and its existence in future Linux kernel versions
+ is also worrying since the option is part of RFC 2292
+ which is since long (2003) obsoleted by RFC 3542
+ that <em>explicitly</em> removes this possibility to get
+ packet information from a stream socket.
+ For comparision: it has existed in FreeBSD but is now removed,
+ at least since FreeBSD 10.
+ </p>
+ </note>
+ </desc>
+ </datatype>
+ <datatype>
<name name="option_name"/>
</datatype>
<datatype>
@@ -90,8 +116,8 @@ do_recv(Sock, Bs) ->
<funcs>
<func>
- <name name="accept" arity="1"/>
- <name name="accept" arity="2"/>
+ <name name="accept" arity="1" since=""/>
+ <name name="accept" arity="2" since=""/>
<fsummary>Accept an incoming connection request on a listening socket.</fsummary>
<type_desc variable="ListenSocket">Returned by
<seealso marker="#listen/2"><c>listen/2</c></seealso>.
@@ -137,7 +163,7 @@ do_recv(Sock, Bs) ->
</func>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close a TCP socket.</fsummary>
<desc>
<p>Closes a TCP socket.</p>
@@ -162,8 +188,8 @@ do_recv(Sock, Bs) ->
</func>
<func>
- <name name="connect" arity="3"/>
- <name name="connect" arity="4"/>
+ <name name="connect" arity="3" since=""/>
+ <name name="connect" arity="4" since=""/>
<fsummary>Connect to a TCP port.</fsummary>
<desc>
<p>Connects to a server on TCP port <c><anno>Port</anno></c> on the host
@@ -242,7 +268,7 @@ do_recv(Sock, Bs) ->
</func>
<func>
- <name name="controlling_process" arity="2"/>
+ <name name="controlling_process" arity="2" since=""/>
<fsummary>Change controlling process of a socket.</fsummary>
<desc>
<p>Assigns a new controlling process <c><anno>Pid</anno></c> to
@@ -266,7 +292,7 @@ do_recv(Sock, Bs) ->
</func>
<func>
- <name name="listen" arity="2"/>
+ <name name="listen" arity="2" since=""/>
<fsummary>Set up a socket to listen on a port.</fsummary>
<desc>
<p>Sets up a socket to listen on port <c><anno>Port</anno></c> on
@@ -323,8 +349,8 @@ do_recv(Sock, Bs) ->
</func>
<func>
- <name name="recv" arity="2"/>
- <name name="recv" arity="3"/>
+ <name name="recv" arity="2" since=""/>
+ <name name="recv" arity="3" since=""/>
<fsummary>Receive a packet from a passive socket.</fsummary>
<type_desc variable="HttpPacket">See the description of
<c>HttpPacket</c> in
@@ -349,7 +375,7 @@ do_recv(Sock, Bs) ->
</func>
<func>
- <name name="send" arity="2"/>
+ <name name="send" arity="2" since=""/>
<fsummary>Send a packet.</fsummary>
<desc>
<p>Sends a packet on a socket.</p>
@@ -360,7 +386,7 @@ do_recv(Sock, Bs) ->
</func>
<func>
- <name name="shutdown" arity="2"/>
+ <name name="shutdown" arity="2" since=""/>
<fsummary>Asynchronously close a socket.</fsummary>
<desc>
<p>Closes a socket in one or two directions.</p>
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index f79566ef71..d20fc1fdfd 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -28,7 +28,7 @@
<date>1997-12-03</date>
<rev>A</rev>
</header>
- <module>gen_udp</module>
+ <module since="">gen_udp</module>
<modulesummary>Interface to UDP sockets.</modulesummary>
<description>
<p>This module provides functions for communicating
@@ -53,7 +53,7 @@
<funcs>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close a UDP socket.</fsummary>
<desc>
<p>Closes a UDP socket.</p>
@@ -61,7 +61,7 @@
</func>
<func>
- <name name="controlling_process" arity="2"/>
+ <name name="controlling_process" arity="2" since=""/>
<fsummary>Change controlling process of a socket.</fsummary>
<desc>
<p>Assigns a new controlling process <c><anno>Pid</anno></c> to
@@ -77,8 +77,8 @@
</func>
<func>
- <name name="open" arity="1"/>
- <name name="open" arity="2"/>
+ <name name="open" arity="1" since=""/>
+ <name name="open" arity="2" since=""/>
<fsummary>Associate a UDP port number with the process calling it.</fsummary>
<desc>
<p>Associates a UDP port number (<c><anno>Port</anno></c>) with the
@@ -147,7 +147,21 @@
at the opened port, if the socket is in an active mode, the packets
are delivered as messages to the controlling process:</p>
<code type="none">
-{udp, Socket, IP, InPortNo, Packet}</code>
+{udp, Socket, IP, InPortNo, Packet} % Without ancillary data
+{udp, Socket, IP, InPortNo, AncData, Packet} % With ancillary data
+ </code>
+ <p>
+ The message contains an <c>AncData</c> field
+ if any of the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>
+ are active, otherwise it does not.
+ </p>
+ <p>
+ </p>
<p>If the socket is not in an active mode, data can be
retrieved through the
<seealso marker="#recv/2"><c>recv/2,3</c></seealso> calls.
@@ -175,18 +189,31 @@
</func>
<func>
- <name name="recv" arity="2"/>
- <name name="recv" arity="3"/>
+ <name name="recv" arity="2" since=""/>
+ <name name="recv" arity="3" since=""/>
<fsummary>Receive a packet from a passive socket.</fsummary>
<desc>
- <p>Receives a packet from a socket in passive mode. Optional parameter
+ <p>
+ Receives a packet from a socket in passive mode. Optional parameter
<c><anno>Timeout</anno></c> specifies a time-out in milliseconds.
- Defaults to <c>infinity</c>.</p>
+ Defaults to <c>infinity</c>.
+ </p>
+ <p>
+ If any of the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>
+ are active, the <c><anno>RecvData</anno></c> tuple contains an
+ <c><anno>AncData</anno></c> field,
+ otherwise it does not.
+ </p>
</desc>
</func>
<func>
- <name name="send" arity="4"/>
+ <name name="send" arity="4" since=""/>
<fsummary>Send a packet.</fsummary>
<desc>
<p>
diff --git a/lib/kernel/doc/src/global.xml b/lib/kernel/doc/src/global.xml
index 4442741f54..dfe71de5ce 100644
--- a/lib/kernel/doc/src/global.xml
+++ b/lib/kernel/doc/src/global.xml
@@ -28,7 +28,7 @@
<date>1997-11-17</date>
<rev></rev>
</header>
- <module>global</module>
+ <module since="">global</module>
<modulesummary>A global name registration facility.</modulesummary>
<description>
<p>This module consists of the following services:</p>
@@ -100,8 +100,8 @@
<funcs>
<func>
- <name name="del_lock" arity="1"/>
- <name name="del_lock" arity="2"/>
+ <name name="del_lock" arity="1" since=""/>
+ <name name="del_lock" arity="2" since=""/>
<fsummary>Delete a lock.</fsummary>
<desc>
<p>Deletes the lock <c><anno>Id</anno></c> synchronously.</p>
@@ -109,7 +109,7 @@
</func>
<func>
- <name name="notify_all_name" arity="3"/>
+ <name name="notify_all_name" arity="3" since=""/>
<fsummary>Name resolving function that notifies both pids.</fsummary>
<desc>
<p>Can be used as a name resolving function for
@@ -123,7 +123,7 @@
</func>
<func>
- <name name="random_exit_name" arity="3"/>
+ <name name="random_exit_name" arity="3" since=""/>
<fsummary>Name resolving function that kills one pid.</fsummary>
<desc>
<p>Can be used as a name resolving function for
@@ -136,7 +136,7 @@
</func>
<func>
- <name name="random_notify_name" arity="3"/>
+ <name name="random_notify_name" arity="3" since=""/>
<fsummary>Name resolving function that notifies one pid.</fsummary>
<desc>
<p>Can be used as a name resolving function for
@@ -150,8 +150,8 @@
</func>
<func>
- <name name="re_register_name" arity="2"/>
- <name name="re_register_name" arity="3"/>
+ <name name="re_register_name" arity="2" since=""/>
+ <name name="re_register_name" arity="3" since=""/>
<fsummary>Atomically re-register a name.</fsummary>
<type name="method"/>
<type_desc name="method">{<c>Module</c>, <c>Function</c>}
@@ -167,8 +167,8 @@
</func>
<func>
- <name name="register_name" arity="2"/>
- <name name="register_name" arity="3"/>
+ <name name="register_name" arity="2" since=""/>
+ <name name="register_name" arity="3" since=""/>
<fsummary>Globally register a name for a pid.</fsummary>
<type name="method"/>
<type_desc name="method">{<c>Module</c>, <c>Function</c>} is also
@@ -221,7 +221,7 @@
</func>
<func>
- <name name="registered_names" arity="0"/>
+ <name name="registered_names" arity="0" since=""/>
<fsummary>All globally registered names.</fsummary>
<desc>
<p>Returns a list of all globally registered names.</p>
@@ -229,7 +229,7 @@
</func>
<func>
- <name name="send" arity="2"/>
+ <name name="send" arity="2" since=""/>
<fsummary>Send a message to a globally registered pid.</fsummary>
<desc>
<p>Sends message <c><anno>Msg</anno></c> to the pid globally registered
@@ -241,9 +241,9 @@
</func>
<func>
- <name name="set_lock" arity="1"/>
- <name name="set_lock" arity="2"/>
- <name name="set_lock" arity="3"/>
+ <name name="set_lock" arity="1" since=""/>
+ <name name="set_lock" arity="2" since=""/>
+ <name name="set_lock" arity="3" since=""/>
<fsummary>Set a lock on the specified nodes.</fsummary>
<type name="id"/>
<type name="retries"/>
@@ -287,7 +287,7 @@
</func>
<func>
- <name name="sync" arity="0"/>
+ <name name="sync" arity="0" since=""/>
<fsummary>Synchronize the global name server.</fsummary>
<desc>
<p>Synchronizes the global name server with all nodes known to
@@ -302,9 +302,9 @@
</func>
<func>
- <name name="trans" arity="2"/>
- <name name="trans" arity="3"/>
- <name name="trans" arity="4"/>
+ <name name="trans" arity="2" since=""/>
+ <name name="trans" arity="3" since=""/>
+ <name name="trans" arity="4" since=""/>
<fsummary>Micro transaction facility.</fsummary>
<type name="retries"/>
<type name="trans_fun"/>
@@ -322,7 +322,7 @@
</func>
<func>
- <name name="unregister_name" arity="1"/>
+ <name name="unregister_name" arity="1" since=""/>
<fsummary>Remove a globally registered name for a pid.</fsummary>
<desc>
<p>Removes the globally registered name <c><anno>Name</anno></c> from
@@ -331,7 +331,7 @@
</func>
<func>
- <name name="whereis_name" arity="1"/>
+ <name name="whereis_name" arity="1" since=""/>
<fsummary>Get the pid with a specified globally registered name.</fsummary>
<desc>
<p>Returns the pid with the globally registered name
diff --git a/lib/kernel/doc/src/global_group.xml b/lib/kernel/doc/src/global_group.xml
index 8f947b9adf..74d15cd476 100644
--- a/lib/kernel/doc/src/global_group.xml
+++ b/lib/kernel/doc/src/global_group.xml
@@ -28,7 +28,7 @@
<date>1998-12-18</date>
<rev>B</rev>
</header>
- <module>global_group</module>
+ <module since="">global_group</module>
<modulesummary>Grouping nodes to global name registration groups.</modulesummary>
<description>
<p>This module makes it possible to partition the nodes of a
@@ -105,7 +105,7 @@
<funcs>
<func>
- <name name="global_groups" arity="0"/>
+ <name name="global_groups" arity="0" since=""/>
<fsummary>Return the global group names.</fsummary>
<desc>
<p>Returns a tuple containing the name of the global group that
@@ -116,7 +116,7 @@
</func>
<func>
- <name name="info" arity="0"/>
+ <name name="info" arity="0" since=""/>
<fsummary>Information about global groups.</fsummary>
<type name="info_item"/>
<type name="sync_state"/>
@@ -173,7 +173,7 @@
</func>
<func>
- <name name="monitor_nodes" arity="1"/>
+ <name name="monitor_nodes" arity="1" since=""/>
<fsummary>Subscribe to node status changes.</fsummary>
<desc>
<p>Depending on <c><anno>Flag</anno></c>, the calling process
@@ -187,7 +187,7 @@
</func>
<func>
- <name name="own_nodes" arity="0"/>
+ <name name="own_nodes" arity="0" since=""/>
<fsummary>Return the group nodes.</fsummary>
<desc>
<p>Returns the names of all group nodes, regardless of their
@@ -196,7 +196,7 @@
</func>
<func>
- <name name="registered_names" arity="1"/>
+ <name name="registered_names" arity="1" since=""/>
<fsummary>Return globally registered names.</fsummary>
<desc>
<p>Returns a list of all names that are globally registered
@@ -205,8 +205,8 @@
</func>
<func>
- <name name="send" arity="2"/>
- <name name="send" arity="3"/>
+ <name name="send" arity="2" since=""/>
+ <name name="send" arity="3" since=""/>
<fsummary>Send a message to a globally registered pid.</fsummary>
<desc>
<p>Searches for <c><anno>Name</anno></c>, globally registered on
@@ -224,7 +224,7 @@
</func>
<func>
- <name name="sync" arity="0"/>
+ <name name="sync" arity="0" since=""/>
<fsummary>Synchronize the group nodes.</fsummary>
<desc>
<p>Synchronizes the group nodes, that is, the global name
@@ -242,8 +242,8 @@
</func>
<func>
- <name name="whereis_name" arity="1"/>
- <name name="whereis_name" arity="2"/>
+ <name name="whereis_name" arity="1" since=""/>
+ <name name="whereis_name" arity="2" since=""/>
<fsummary>Get the pid with a specified globally registered name.</fsummary>
<desc>
<p>Searches for <c><anno>Name</anno></c>, globally registered on
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index ad1a2ffeb9..4243b1ffe8 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -28,7 +28,7 @@
<date>1998-01-28</date>
<rev>A</rev>
</header>
- <module>heart</module>
+ <module since="">heart</module>
<modulesummary>Heartbeat monitoring of an Erlang runtime system.</modulesummary>
<description>
<p>This modules contains the interface to the <c>heart</c> process.
@@ -119,7 +119,7 @@
<funcs>
<func>
- <name name="set_cmd" arity="1"/>
+ <name name="set_cmd" arity="1" since=""/>
<fsummary>Set a temporary reboot command.</fsummary>
<desc>
<p>Sets a temporary reboot command. This command is used if
@@ -136,7 +136,7 @@
</func>
<func>
- <name name="clear_cmd" arity="0"/>
+ <name name="clear_cmd" arity="0" since=""/>
<fsummary>Clear the temporary boot command.</fsummary>
<desc>
<p>Clears the temporary boot command. If the system terminates,
@@ -145,7 +145,7 @@
</func>
<func>
- <name name="get_cmd" arity="0"/>
+ <name name="get_cmd" arity="0" since=""/>
<fsummary>Get the temporary reboot command.</fsummary>
<desc>
<p>Gets the temporary reboot command. If the command is cleared,
@@ -154,7 +154,7 @@
</func>
<func>
- <name name="set_callback" arity="2"/>
+ <name name="set_callback" arity="2" since="OTP 18.3"/>
<fsummary>Set a validation callback</fsummary>
<desc>
<p> This validation callback will be executed before any
@@ -166,14 +166,14 @@
</desc>
</func>
<func>
- <name name="clear_callback" arity="0"/>
+ <name name="clear_callback" arity="0" since="OTP 18.3"/>
<fsummary>Clear the validation callback</fsummary>
<desc>
<p>Removes the validation callback call before heartbeats.</p>
</desc>
</func>
<func>
- <name name="get_callback" arity="0"/>
+ <name name="get_callback" arity="0" since="OTP 18.3"/>
<fsummary>Get the validation callback</fsummary>
<desc>
<p>Get the validation callback. If the callback is cleared, <c>none</c> will be returned.</p>
@@ -181,7 +181,7 @@
</func>
<func>
- <name name="set_options" arity="1"/>
+ <name name="set_options" arity="1" since="OTP 18.3"/>
<fsummary>Set a list of options</fsummary>
<desc>
<p> Valid options <c>set_options</c> are: </p>
@@ -199,7 +199,7 @@
</desc>
</func>
<func>
- <name name="get_options" arity="0"/>
+ <name name="get_options" arity="0" since="OTP 18.3"/>
<fsummary>Get the temporary reboot command</fsummary>
<desc>
<p>Returns <c>{ok, Options}</c> where <c>Options</c> is a list of current options enabled for heart.
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index e6a7962c5a..5e33bbc3ff 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -28,7 +28,7 @@
<date>1998-02-04</date>
<rev>A</rev>
</header>
- <module>inet</module>
+ <module since="">inet</module>
<modulesummary>Access to TCP/IP protocols.</modulesummary>
<description>
<p>This module provides access to TCP/IP protocols.</p>
@@ -177,6 +177,100 @@ fe80::204:acff:fe17:bf38
</desc>
</datatype>
<datatype>
+ <name name="ancillary_data"/>
+ <desc>
+ <p>
+ Ancillary data received with the data packet
+ or read with the socket option
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ from a TCP socket.
+ </p>
+ <p>
+ The value(s) correspond to the currently active socket
+ <seealso marker="#type-socket_setopt">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ and
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="getifaddrs_ifopts"/>
+ <desc>
+ <p>
+ Interface address description list returned from
+ <seealso marker="#getifaddrs/0"><c>getifaddrs/0,1</c></seealso>
+ for a named interface, translated from the returned
+ data of the POSIX API function <c>getaddrinfo()</c>.
+ </p>
+ <p>
+ <c><anno>Hwaddr</anno></c> is hardware dependent,
+ for example, on Ethernet interfaces it is
+ the 6-byte Ethernet address (MAC address (EUI-48 address)).
+ </p>
+ <p>
+ The tuples <c>{addr,<anno>Addr</anno>}</c>,
+ <c>{netmask,<anno>Netmask</anno>}</c>, and possibly
+ <c>{broadaddr,<anno>Broadaddr</anno>}</c> or
+ <c>{dstaddr,<anno>Dstaddr</anno>}</c>
+ are repeated in the list
+ if the interface has got multiple addresses.
+ An interface may have multiple <c>{flag,_}</c> tuples
+ for example if it has different flags
+ for different address families.
+ Multiple <c>{hwaddr,<anno>Hwaddr</anno>}</c> tuples
+ is hard to say anything definite about, though.
+ The tuple <c>{flag,<anno>Flags</anno>}</c> is mandatory,
+ all others are optional.
+ </p>
+ <p>
+ Do not rely too much on the order
+ of <c><anno>Flags</anno></c> atoms
+ or the <c><anno>Ifopt</anno></c> tuples.
+ There are however some rules:
+ </p>
+ <list type="bulleted">
+ <item><p>
+ A <c>{flag,_}</c> tuple applies to all other tuples that follow.
+ </p></item>
+ <item><p>
+ Immediately after <c>{addr,_}</c> follows <c>{netmask,_}</c>.
+ </p></item>
+ <item><p>
+ Immediately thereafter may <c>{broadaddr,_}</c> follow
+ if <c>broadcast</c> is member of <c><anno>Flags</anno></c>,
+ or <c>{dstaddr,_}</c> if <c>pointtopoint</c>
+ is member of <c><anno>Flags</anno></c>.
+ Both <c>{dstaddr,_}</c> and <c>{broadaddr,_}</c>
+ does not occur for the same <c>{addr,_}</c>.
+ </p></item>
+ <item><p>
+ Any <c>{netmask,_}</c>, <c>{broadaddr,_}</c>, or
+ <c>{dstaddr,_}</c> tuples that follow an
+ <c>{addr,<anno>Addr</anno>}</c>
+ tuple concerns the address <c><anno>Addr</anno></c>.
+ </p></item>
+ </list>
+ <p>
+ The tuple <c>{hwaddr,_}</c> is not returned on Solaris, as the
+ hardware address historically belongs to the link layer
+ and it is not returned by the Solaris API function
+ <c>getaddrinfo()</c>.
+ </p>
+ <warning>
+ <p>
+ On Windows, the data is fetched from different
+ OS API functions, so the <c><anno>Netmask</anno></c>
+ and <c><anno>Broadaddr</anno></c> values may be calculated,
+ just as some <c><anno>Flags</anno></c> values.
+ </p>
+ </warning>
+ </desc>
+ </datatype>
+ <datatype>
<name name="posix"/>
<desc>
<p>An atom that is named from the POSIX error codes used in Unix,
@@ -200,11 +294,14 @@ fe80::204:acff:fe17:bf38
<datatype>
<name name="socket_protocol"/>
</datatype>
+ <datatype>
+ <name name="stat_option"/>
+ </datatype>
</datatypes>
<funcs>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close a socket of any type.</fsummary>
<desc>
<p>Closes a socket of any type.</p>
@@ -212,7 +309,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Return a descriptive string for an error reason.</fsummary>
<desc>
<p>Returns a diagnostic error string. For possible POSIX values and
@@ -222,7 +319,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="get_rc" arity="0"/>
+ <name name="get_rc" arity="0" since=""/>
<fsummary>Return a list of IP configuration parameters.</fsummary>
<desc>
<p>
@@ -241,7 +338,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="getaddr" arity="2"/>
+ <name name="getaddr" arity="2" since=""/>
<fsummary>Return the IP address for a host.</fsummary>
<desc>
<p>Returns the IP address for <c><anno>Host</anno></c> as a tuple of
@@ -251,7 +348,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="getaddrs" arity="2"/>
+ <name name="getaddrs" arity="2" since=""/>
<fsummary>Return the IP addresses for a host.</fsummary>
<desc>
<p>Returns a list of all IP addresses for <c><anno>Host</anno></c>.
@@ -261,7 +358,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="gethostbyaddr" arity="1"/>
+ <name name="gethostbyaddr" arity="1" since=""/>
<fsummary>Return a hostent record for the host with the specified
address.</fsummary>
<desc>
@@ -270,7 +367,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="gethostbyname" arity="1"/>
+ <name name="gethostbyname" arity="1" since=""/>
<fsummary>Return a hostent record for the host with the specified name.
</fsummary>
<desc>
@@ -282,7 +379,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="gethostbyname" arity="2"/>
+ <name name="gethostbyname" arity="2" since=""/>
<fsummary>Return a hostent record for the host with the specified name.
</fsummary>
<desc>
@@ -292,7 +389,7 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="gethostname" arity="0"/>
+ <name name="gethostname" arity="0" since=""/>
<fsummary>Return the local hostname.</fsummary>
<desc>
<p>Returns the local hostname. Never fails.</p>
@@ -300,51 +397,81 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name name="getifaddrs" arity="0"/>
+ <name name="getifaddrs" arity="0" since="OTP R14B01"/>
<fsummary>Return a list of interfaces and their addresses.</fsummary>
<desc>
- <p>Returns a list of 2-tuples containing interface names and the
- interface addresses. <c><anno>Ifname</anno></c> is a Unicode string.
- <c><anno>Hwaddr</anno></c> is hardware dependent, for example, on
- Ethernet interfaces
- it is the 6-byte Ethernet address (MAC address (EUI-48 address)).</p>
- <p>The tuples <c>{addr,<anno>Addr</anno>}</c>, <c>{netmask,_}</c>, and
- <c>{broadaddr,_}</c> are repeated in the result list if the interface
- has multiple addresses. If you come across an interface with
- multiple <c>{flag,_}</c> or <c>{hwaddr,_}</c> tuples, you have
- a strange interface or possibly a bug in this function. The tuple
- <c>{flag,_}</c> is mandatory, all others are optional.</p>
- <p>Do not rely too much on the order of <c><anno>Flag</anno></c> atoms
- or <c><anno>Ifopt</anno></c> tuples. There are however some rules:</p>
- <list type="bulleted">
- <item><p>Immediately after
- <c>{addr,_}</c> follows <c>{netmask,_}</c>.</p></item>
- <item><p>Immediately thereafter follows <c>{broadaddr,_}</c> if flag
- <c>broadcast</c> is <em>not</em> set and flag
- <c>pointtopoint</c> <em>is</em> set.</p></item>
- <item><p>Any <c>{netmask,_}</c>, <c>{broadaddr,_}</c>, or
- <c>{dstaddr,_}</c> tuples that follow an <c>{addr,_}</c>
- tuple concerns that address.</p></item>
- </list>
- <p>The tuple <c>{hwaddr,_}</c> is not returned on Solaris, as the
- hardware address historically belongs to the link layer and only
- the superuser can read such addresses.</p>
- <warning>
- <p>On Windows, the data is fetched from different OS API functions,
- so the <c><anno>Netmask</anno></c> and <c><anno>Broadaddr</anno></c>
- values can be calculated, just as some <c><anno>Flag</anno></c>
- values. Report flagrant bugs.</p>
- </warning>
+ <p>
+ Returns a list of 2-tuples containing interface names and
+ the interfaces' addresses. <c><anno>Ifname</anno></c>
+ is a Unicode string and
+ <c><anno>Ifopts</anno></c> is a list of
+ interface address description tuples.
+ </p>
+ <p>
+ The interface address description tuples
+ are documented under the type of the
+ <seealso marker="#type-getifaddrs_ifopts">
+ <c><anno>Ifopts</anno></c>
+ </seealso>
+ value.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">getifaddrs(Opts) ->
+ {ok, [{Ifname, Ifopts}]} | {error, Posix}
+ </name>
+ <fsummary>Return a list of interfaces and their addresses.</fsummary>
+ <type>
+ <v>
+ Opts = [{netns, Namespace}]
+ </v>
+ <v>
+ Namespace =
+ <seealso marker="file#type-filename_all">
+ file:filename_all()
+ </seealso>
+ </v>
+ <v>Ifname = string()</v>
+ <v>
+ Ifopts =
+ <seealso marker="#type-getifaddrs_ifopts">
+ getifaddrs_ifopts()
+ </seealso>
+ </v>
+ <v>Posix = <seealso marker="#type-posix">posix()</seealso></v>
+ </type>
+ <desc>
+ <p>
+ The same as
+ <seealso marker="#getifaddrs/0"><c>getifaddrs/0</c></seealso>
+ but the <c>Option</c>
+ <c>{netns, Namespace}</c> sets a network namespace
+ for the OS call, on platforms that supports that feature.
+ </p>
+ <p>
+ See the socket option
+ <seealso marker="#option-netns">
+ <c>{netns, Namespace}</c>
+ </seealso>
+ under
+ <seealso marker="#setopts/2"><c>setopts/2</c></seealso>.
+ </p>
</desc>
</func>
<func>
- <name name="getopts" arity="2"/>
+ <name name="getopts" arity="2" since=""/>
<fsummary>Get one or more options for a socket.</fsummary>
<desc>
<p>Gets one or more options for a socket. For a list of available
options, see
- <seealso marker="#setopts/2"><c>setopts/2</c></seealso>.</p>
+ <seealso marker="#setopts/2"><c>setopts/2</c></seealso>.
+ See also the description for the type
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>gen_tcp:pktoptions_value()</c>
+ </seealso>.</p>
<p>The number of elements in the returned
<c><anno>OptionValues</anno></c>
list does not necessarily correspond to the number of options
@@ -360,7 +487,7 @@ fe80::204:acff:fe17:bf38
socket options not (explicitly) supported by the emulator. The
use of raw socket options makes the code non-portable, but
allows the Erlang programmer to take advantage of unusual features
- present on the current platform.</p>
+ present on a particular platform.</p>
<p><c>RawOptReq</c> consists of tag <c>raw</c> followed
by the protocol level, the option number, and either a binary
or the size, in bytes, of the
@@ -405,8 +532,8 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="getstat" arity="1"/>
- <name name="getstat" arity="2"/>
+ <name name="getstat" arity="1" since=""/>
+ <name name="getstat" arity="2" since=""/>
<fsummary>Get one or more statistic options for a socket.</fsummary>
<type name="stat_option"/>
<desc>
@@ -462,9 +589,9 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="i" arity="0" />
- <name name="i" arity="1" />
- <name name="i" arity="2" />
+ <name name="i" arity="0" since="OTP 21.0"/>
+ <name name="i" arity="1" since="OTP 21.0"/>
+ <name name="i" arity="2" since="OTP 21.0"/>
<fsummary>Displays information and statistics about sockets on the terminal</fsummary>
<desc>
<p>
@@ -517,7 +644,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="ntoa" arity="1" />
+ <name name="ntoa" arity="1" since="OTP R16B02"/>
<fsummary>Convert IPv6/IPV4 address to ASCII.</fsummary>
<desc>
<p>Parses an
@@ -527,7 +654,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="parse_address" arity="1" />
+ <name name="parse_address" arity="1" since="OTP R16B"/>
<fsummary>Parse an IPv4 or IPv6 address.</fsummary>
<desc>
<p>Parses an IPv4 or IPv6 address string and returns an
@@ -538,7 +665,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="parse_ipv4_address" arity="1" />
+ <name name="parse_ipv4_address" arity="1" since="OTP R16B"/>
<fsummary>Parse an IPv4 address.</fsummary>
<desc>
<p>Parses an IPv4 address string and returns an
@@ -548,7 +675,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="parse_ipv4strict_address" arity="1" />
+ <name name="parse_ipv4strict_address" arity="1" since="OTP R16B"/>
<fsummary>Parse an IPv4 address strict.</fsummary>
<desc>
<p>Parses an IPv4 address string containing four fields, that is,
@@ -559,7 +686,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="parse_ipv6_address" arity="1" />
+ <name name="parse_ipv6_address" arity="1" since="OTP R16B"/>
<fsummary>Parse an IPv6 address.</fsummary>
<desc>
<p>Parses an IPv6 address string and returns an
@@ -570,7 +697,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="parse_ipv6strict_address" arity="1" />
+ <name name="parse_ipv6strict_address" arity="1" since="OTP R16B"/>
<fsummary>Parse an IPv6 address strict.</fsummary>
<desc>
<p>Parses an IPv6 address string and returns an
@@ -580,7 +707,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="ipv4_mapped_ipv6_address" arity="1" />
+ <name name="ipv4_mapped_ipv6_address" arity="1" since="OTP 21.0"/>
<fsummary>Convert to and from IPv4-mapped IPv6 address.</fsummary>
<desc>
<p>
@@ -593,7 +720,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="parse_strict_address" arity="1" />
+ <name name="parse_strict_address" arity="1" since="OTP R16B"/>
<fsummary>Parse an IPv4 or IPv6 address strict.</fsummary>
<desc>
<p>Parses an IPv4 or IPv6 address string and returns an
@@ -604,7 +731,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="peername" arity="1"/>
+ <name name="peername" arity="1" since=""/>
<fsummary>Return the address and port for the other end of a connection.
</fsummary>
<desc>
@@ -617,7 +744,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="peernames" arity="1"/>
+ <name name="peernames" arity="1" since="OTP R16B03"/>
<fsummary>Return all address/port numbers for the other end of a
connection.</fsummary>
<desc>
@@ -631,7 +758,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="peernames" arity="2"/>
+ <name name="peernames" arity="2" since="OTP R16B03"/>
<fsummary>Return all address/port numbers for the other end of a
connection.</fsummary>
<desc>
@@ -650,7 +777,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="port" arity="1"/>
+ <name name="port" arity="1" since=""/>
<fsummary>Return the local port number for a socket.</fsummary>
<desc>
<p>Returns the local port number for a socket.</p>
@@ -658,7 +785,7 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
- <name name="setopts" arity="2"/>
+ <name name="setopts" arity="2" since=""/>
<fsummary>Set one or more options for a socket.</fsummary>
<desc>
<p>Sets one or more options for a socket.</p>
@@ -734,22 +861,23 @@ get_tcpi_sacked(Sock) ->
</item>
<tag><c>{buffer, Size}</c></tag>
<item>
- <p>The size of the user-level software buffer used by
- the driver.
- Not to be confused with options <c>sndbuf</c>
+ <p>The size of the user-level buffer used by
+ the driver. Not to be confused with options <c>sndbuf</c>
and <c>recbuf</c>, which correspond to the
- Kernel socket buffers. It is recommended
- to have <c>val(buffer) &gt;= max(val(sndbuf),val(recbuf))</c> to
+ Kernel socket buffers. For TCP it is recommended
+ to have <c>val(buffer) &gt;= val(recbuf)</c> to
avoid performance issues because of unnecessary copying.
+ For UDP the same recommendation applies, but the max should
+ not be larger than the MTU of the network path.
<c>val(buffer)</c> is automatically set to the above
- maximum when values <c>sndbuf</c> or <c>recbuf</c> are set.
- However, as the sizes set for <c>sndbuf</c> and <c>recbuf</c>
+ maximum when <c>recbuf</c> is set.
+ However, as the size set for <c>recbuf</c>
usually become larger, you are encouraged to use
<seealso marker="#getopts/2"><c>getopts/2</c></seealso>
to analyze the behavior of your operating system.</p>
<p>Note that this is also the maximum amount of data that can be
- received from a single recv call. If you are using higher than
- normal MTU consider setting buffer higher.</p>
+ received from a single recv call. If you are using higher than
+ normal MTU consider setting buffer higher.</p>
</item>
<tag><c>{delay_send, Boolean}</c></tag>
<item>
@@ -924,20 +1052,29 @@ get_tcpi_sacked(Sock) ->
</item>
<tag><c>{mode, Mode :: binary | list}</c></tag>
<item>
- <p>Received <c>Packet</c> is delivered as defined by <c>Mode</c>.
+ <p>
+ Received <c>Packet</c> is delivered as defined by <c>Mode</c>.
</p>
</item>
- <tag><c>{netns, Namespace :: file:filename_all()}</c></tag>
+ <tag>
+ <marker id="option-netns"/>
+ <c>{netns, Namespace :: file:filename_all()}</c>
+ </tag>
<item>
- <p>Sets a network namespace for the socket. Parameter
+ <p>
+ Sets a network namespace for the socket. Parameter
<c>Namespace</c> is a filename defining the namespace, for
example, <c>"/var/run/netns/example"</c>, typically created by
command <c>ip netns add example</c>. This option must be used in
a function call that creates a socket, that is,
<seealso marker="gen_tcp#connect/3"><c>gen_tcp:connect/3,4</c></seealso>,
<seealso marker="gen_tcp#listen/2"><c>gen_tcp:listen/2</c></seealso>,
- <seealso marker="gen_udp#open/1"><c>gen_udp:open/1,2</c></seealso>, or
- <seealso marker="gen_sctp#open/0"><c>gen_sctp:open/0,1,2</c></seealso>.</p>
+ <seealso marker="gen_udp#open/1"><c>gen_udp:open/1,2</c></seealso>
+ or
+ <seealso marker="gen_sctp#open/0"><c>gen_sctp:open/0,1,2</c></seealso>,
+ and also
+ <seealso marker="#getifaddrs/1"><c>getifaddrs/1</c></seealso>.
+ </p>
<p>This option uses the Linux-specific syscall
<c>setns()</c>, such as in Linux kernel 3.0 or later,
and therefore only exists when the runtime system
@@ -1013,6 +1150,18 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
is turned on for the socket, which means that also small
amounts of data are sent immediately.</p>
</item>
+ <tag><c>{nopush, Boolean}</c>(TCP/IP sockets)</tag>
+ <item>
+ <p>This translates to <c>TCP_NOPUSH</c> on BSD and
+ to <c>TCP_CORK</c> on Linux.</p>
+ <p>If <c>Boolean == true</c>, the corresponding option
+ is turned on for the socket, which means that small
+ amounts of data are accumulated until a full MSS-worth
+ of data is available or this option is turned off.</p>
+ <p>Note that while <c>TCP_NOPUSH</c> socket option is available on OSX, its semantics
+ is very different (e.g., unsetting it does not cause immediate send
+ of accumulated data). Hence, <c>nopush</c> option is intentionally ignored on OSX.</p>
+ </item>
<tag><c>{packet, PacketType}</c>(TCP/IP sockets)</tag>
<item>
<p><marker id="packet"/>Defines the type of packets to use for a socket.
@@ -1114,6 +1263,100 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
the socket. You are encouraged to use
<seealso marker="#getopts/2"><c>getopts/2</c></seealso>
to retrieve the size set by your operating system.</p>
+ <marker id="option-recvtclass"></marker>
+ </item>
+ <tag><c>{recvtclass, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TCLASS</c> value on platforms that implements
+ the protocol <c>IPPROTO_IPV6</c>
+ option <c>IPV6_RECVTCLASS</c> or <c>IPV6_2292RECVTCLASS</c>
+ for the socket.
+ The value is returned as a <c>{tclass,TCLASS}</c> tuple
+ regardless of if the platform returns an <c>IPV6_TCLASS</c>
+ or an <c>IPV6_RECVTCLASS</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TCLASS</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TCLASS</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
+ <marker id="option-recvtos"></marker>
+ </item>
+ <tag><c>{recvtos, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TOS</c> value on platforms that implements
+ the protocol <c>IPPROTO_IP</c> option <c>IP_RECVTOS</c>
+ for the socket.
+ The value is returned as a <c>{tos,TOS}</c> tuple
+ regardless of if the platform returns an <c>IP_TOS</c>
+ or an <c>IP_RECVTOS</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TOS</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TOS</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
+ <marker id="option-recvttl"></marker>
+ </item>
+ <tag><c>{recvttl, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TTL</c> value on platforms that implements
+ the protocol <c>IPPROTO_IP</c> option <c>IP_RECVTTL</c>
+ for the socket.
+ The value is returned as a <c>{ttl,TTL}</c> tuple
+ regardless of if the platform returns an <c>IP_TTL</c>
+ or an <c>IP_RECVTTL</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TTL</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TTL</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
</item>
<tag><c>{reuseaddr, Boolean}</c></tag>
<item>
@@ -1246,7 +1489,7 @@ inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),]]></code>
</func>
<func>
- <name name="sockname" arity="1"/>
+ <name name="sockname" arity="1" since=""/>
<fsummary>Return the local address and port number for a socket.
</fsummary>
<desc>
@@ -1259,7 +1502,7 @@ inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),]]></code>
</func>
<func>
- <name name="socknames" arity="1"/>
+ <name name="socknames" arity="1" since="OTP R16B03"/>
<fsummary>Return all local address/port numbers for a socket.</fsummary>
<desc>
<p>Equivalent to
@@ -1269,7 +1512,7 @@ inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),]]></code>
</func>
<func>
- <name name="socknames" arity="2"/>
+ <name name="socknames" arity="2" since="OTP R16B03"/>
<fsummary>Return all local address/port numbers for a socket.</fsummary>
<desc>
<p>Returns a list of all local address/port number pairs for a socket
diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml
index 351d86a93a..1904e371f7 100644
--- a/lib/kernel/doc/src/inet_res.xml
+++ b/lib/kernel/doc/src/inet_res.xml
@@ -28,7 +28,7 @@
<date>2009-09-11</date>
<rev>A</rev>
</header>
- <module>inet_res</module>
+ <module since="">inet_res</module>
<modulesummary>A rudimentary DNS client.</modulesummary>
<description>
<p>This module performs DNS name resolving to recursive name servers.</p>
@@ -185,8 +185,8 @@ inet_dns:record_type(_) -> undefined.</pre>
<funcs>
<func>
- <name name="getbyname" arity="2"/>
- <name name="getbyname" arity="3"/>
+ <name name="getbyname" arity="2" since=""/>
+ <name name="getbyname" arity="3" since=""/>
<fsummary>Resolve a DNS record of the specified type for the specified
host.</fsummary>
<desc>
@@ -205,8 +205,8 @@ inet_dns:record_type(_) -> undefined.</pre>
</func>
<func>
- <name name="gethostbyaddr" arity="1"/>
- <name name="gethostbyaddr" arity="2"/>
+ <name name="gethostbyaddr" arity="1" since=""/>
+ <name name="gethostbyaddr" arity="2" since=""/>
<fsummary>Return a hostent record for the host with the specified
address.</fsummary>
<desc>
@@ -217,9 +217,9 @@ inet_dns:record_type(_) -> undefined.</pre>
</func>
<func>
- <name name="gethostbyname" arity="1"/>
- <name name="gethostbyname" arity="2"/>
- <name name="gethostbyname" arity="3"/>
+ <name name="gethostbyname" arity="1" since=""/>
+ <name name="gethostbyname" arity="2" since=""/>
+ <name name="gethostbyname" arity="3" since=""/>
<fsummary>Return a hostent record for the host with the specified name.
</fsummary>
<desc>
@@ -235,9 +235,9 @@ inet_dns:record_type(_) -> undefined.</pre>
</func>
<func>
- <name name="lookup" arity="3"/>
- <name name="lookup" arity="4"/>
- <name name="lookup" arity="5"/>
+ <name name="lookup" arity="3" since=""/>
+ <name name="lookup" arity="4" since=""/>
+ <name name="lookup" arity="5" since=""/>
<fsummary>Resolve the DNS data for the record of the specified type
and class for the specified name.</fsummary>
<desc>
@@ -257,9 +257,9 @@ inet_dns:record_type(_) -> undefined.</pre>
</func>
<func>
- <name name="resolve" arity="3"/>
- <name name="resolve" arity="4"/>
- <name name="resolve" arity="5"/>
+ <name name="resolve" arity="3" since=""/>
+ <name name="resolve" arity="4" since=""/>
+ <name name="resolve" arity="5" since=""/>
<fsummary>Resolve a DNS record of the specified type and class
for the specified name.</fsummary>
<desc>
@@ -326,9 +326,9 @@ example_lookup(Name, Class, Type) ->
<funcs>
<func>
- <name name="nslookup" arity="3"/>
- <name name="nslookup" arity="4" clause_i="1"/>
- <name name="nslookup" arity="4" clause_i="2"/>
+ <name name="nslookup" arity="3" since=""/>
+ <name name="nslookup" arity="4" clause_i="1" since=""/>
+ <name name="nslookup" arity="4" clause_i="2" since=""/>
<fsummary>Resolve a DNS record of the specified type and class for the
specified name.</fsummary>
<type variable="Name"/>
@@ -344,8 +344,8 @@ example_lookup(Name, Class, Type) ->
</func>
<func>
- <name name="nnslookup" arity="4"/>
- <name name="nnslookup" arity="5"/>
+ <name name="nnslookup" arity="4" since=""/>
+ <name name="nnslookup" arity="5" since=""/>
<fsummary>Resolve a DNS record of the specified type and class
for the specified name.</fsummary>
<desc>
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index 3914226a3e..dbd83e1a6e 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -192,7 +192,7 @@
<p>To change the primary log level at runtime, use
<seealso marker="logger#set_primary_config/2">
<c>logger:set_primary_config(level, Level)</c></seealso>.</p>
- <p>Defaults to <c>info</c>.</p>
+ <p>Defaults to <c>notice</c>.</p>
</item>
<tag><marker id="logger_sasl_compatible"/>
<c>logger_sasl_compatible = true | false</c></tag>
@@ -310,24 +310,31 @@
<tag><c>net_ticktime = TickTime</c></tag>
<item>
<marker id="net_ticktime"></marker>
- <p>Specifies the <c>net_kernel</c> tick time. <c>TickTime</c>
- is specified in seconds. Once every <c>TickTime/4</c> second, all
- connected nodes are ticked (if anything else is written
- to a node). If nothing is received from another node
- within the last four tick times, that node is considered
- to be down. This ensures that nodes that are not responding,
- for reasons such as hardware errors, are considered to be
- down.</p>
- <p>The time <c>T</c>, in which a node that is not responding is
- detected, is calculated as <c><![CDATA[MinT < T < MaxT]]></c>, where:</p>
+ <p>Specifies the <c>net_kernel</c> tick time in seconds. This is the
+ approximate time a connected node may be unresponsive until it is
+ considered down and thereby disconnected.</p>
+ <p>Once every <c>TickTime/4</c> seconds, each connected node is ticked
+ if nothing has been sent to it during that last <c>TickTime/4</c>
+ interval. A tick is a small package sent on the connection. A connected
+ node is considered to be down if no ticks or payload packages have been
+ received during the last four <c>TickTime/4</c> intervals. This ensures
+ that nodes that are not responding, for reasons such as hardware errors,
+ are considered to be down.</p>
+ <p>As the availability is only checked every <c>TickTime/4</c> seconds,
+ the actual time <c>T</c> a node have been unresponsive when
+ detected may vary between <c>MinT</c> and <c>MaxT</c>,
+ where:</p>
<code type="none">
MinT = TickTime - TickTime / 4
MaxT = TickTime + TickTime / 4</code>
- <p><c>TickTime</c> defaults to <c>60</c> (seconds). Thus,
- <c><![CDATA[45 < T < 75]]></c> seconds.</p>
- <p>Notice that <em>all</em> communicating nodes are to have the <em>same</em>
- <c>TickTime</c> value specified.</p>
- <p>Normally, a terminating node is detected immediately.</p>
+ <p><c>TickTime</c> defaults to <c>60</c> seconds. Thus,
+ <c><![CDATA[45 < T < 75]]></c> seconds.</p>
+ <p>Notice that <em>all</em> communicating nodes are to have the
+ <em>same</em> <c>TickTime</c> value specified, as it determines both the
+ frequency of outgoing ticks and the expected frequency of incominging
+ ticks.</p>
+ <p>Normally, a terminating node is detected immediately by the transport
+ protocol (like TCP/IP).</p>
</item>
<tag><c>shutdown_timeout = integer() | infinity</c></tag>
<item>
@@ -503,11 +510,13 @@ MaxT = TickTime + TickTime / 4</code>
parameters for Logger are not set.</p>
<taglist>
<tag><c>error_logger</c></tag>
- <item>Replaced by setting the type of the default
- <seealso marker="logger_std_h#type"><c>logger_std_h</c></seealso>
- to the same value. Example:
+ <item>Replaced by setting the <seealso
+ marker="logger_std_h#type"><c>type</c></seealso>, and possibly
+ <seealso marker="logger_std_h#file"><c>file</c></seealso> and
+ <seealso marker="logger_std_h#modes"><c>modes</c></seealso>
+ parameters of the default <c>logger_std_h</c> handler. Example:
<code type="none">
-erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{type=>{file,"/tmp/erlang.log"}}}}]'
+erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{file=>"/tmp/erlang.log"}}}]'
</code>
</item>
<tag><c>error_logger_format_depth</c></tag>
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml
index 33f1919de0..5bdfcf91db 100644
--- a/lib/kernel/doc/src/logger.xml
+++ b/lib/kernel/doc/src/logger.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>logger.xml</file>
</header>
- <module>logger</module>
+ <module since="OTP 21.0">logger</module>
<modulesummary>API module for Logger, the standard logging facility
in Erlang/OTP.</modulesummary>
@@ -66,7 +66,7 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
[{kernel,
[{logger,
[{handler, default, logger_std_h,
- #{config => #{type => {file, "path/to/file.log"}}}}]}]}].
+ #{config => #{file => "path/to/file.log"}}}]}]}].
</code>
<p>
For more information about:
@@ -98,46 +98,6 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
<datatypes>
<datatype>
- <name name="primary_config"/>
- <desc>
- <p>Primary configuration data for Logger. The following
- default values apply:</p>
- <list>
- <item><c>level => info</c></item>
- <item><c>filter_default => log</c></item>
- <item><c>filters => []</c></item>
- </list>
- </desc>
- </datatype>
- <datatype>
- <name name="handler_config"/>
- <desc>
- <p>Handler configuration data for Logger. The following
- default values apply:</p>
- <list>
- <item><c>level => all</c></item>
- <item><c>filter_default => log</c></item>
- <item><c>filters => []</c></item>
- <item><c>formatter => {logger_formatter, DefaultFormatterConfig</c>}</item>
- </list>
- <p>In addition to these, the following fields are
- automatically inserted by Logger, values taken from the
- two first parameters
- to <seealso marker="#add_handler-3"><c>add_handler/3</c></seealso>:</p>
- <list>
- <item><c>id => HandlerId</c></item>
- <item><c>module => Module</c></item>
- </list>
- <p>Handler specific configuration data is inserted by the
- handler callback itself, in a sub structure associated with
- the field named <c>config</c>.</p>
- <p>See the <seealso marker="logger_formatter#type-config">
- <c>logger_formatter(3)</c></seealso> manual page for
- information about the default configuration for this
- formatter.</p>
- </desc>
- </datatype>
- <datatype>
<name name="filter"/>
<desc>
<p>A filter which can be installed as a handler filter, or as
@@ -172,6 +132,39 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</desc>
</datatype>
<datatype>
+ <name name="handler_config"/>
+ <desc>
+ <p>Handler configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => all</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ <item><c>formatter => {logger_formatter, DefaultFormatterConfig</c>}</item>
+ </list>
+ <p>In addition to these, the following fields are
+ automatically inserted by Logger, values taken from the
+ two first parameters
+ to <seealso marker="#add_handler-3"><c>add_handler/3</c></seealso>:</p>
+ <list>
+ <item><c>id => HandlerId</c></item>
+ <item><c>module => Module</c></item>
+ </list>
+ <p>These are read-only and cannot be changed in runtime.</p>
+ <p>Handler specific configuration data is inserted by the
+ handler callback itself, in a sub structure associated with
+ the field named <c>config</c>. See
+ the <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>
+ and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>
+ manual pages for information about the specifc configuration
+ for these handlers.</p>
+ <p>See the <seealso marker="logger_formatter#type-config">
+ <c>logger_formatter(3)</c></seealso> manual page for
+ information about the default configuration for this
+ formatter.</p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="handler_id"/>
<desc>
<p>A unique identifier for a handler instance.</p>
@@ -197,7 +190,7 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
<list>
<item><c>pid => self()</c></item>
<item><c>gl => group_leader()</c></item>
- <item><c>time => erlang:system_time(microsecond)</c></item>
+ <item><c>time => logger:timestamp()</c></item>
</list>
<p>When a log macro is used, Logger also inserts location
information:</p>
@@ -234,7 +227,10 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
a <seealso marker="#type-report"><c>report()</c></seealso>,
the <c>report_cb</c> key can be associated with a fun
(report callback) that converts the report to a format
- string and arguments. See
+ string and arguments, or directly to a string. See the
+ type definition
+ of <seealso marker="#type-report_cb"><c>report_cb()</c></seealso>,
+ and
section <seealso marker="logger_chapter#log_message">Log
Message</seealso> in the User's Guide for more
information about report callbacks.</p>
@@ -249,24 +245,61 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</desc>
</datatype>
<datatype>
+ <name name="olp_config"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="primary_config"/>
+ <desc>
+ <p>Primary configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => info</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ </list>
+ </desc>
+ </datatype>
+ <datatype>
<name name="report"/>
<desc>
<p></p>
</desc>
</datatype>
<datatype>
+ <name name="report_cb"/>
+ <desc>
+ <p>A fun which converts a <seealso marker="#type-report"><c>report()</c>
+ </seealso> to a format string and arguments, or directly to a string.
+ See section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the User's Guide for more
+ information.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report_cb_config"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="timestamp"/>
<desc>
<p>A timestamp produced
- with <seealso marker="erts:erlang#system_time-1">
- <c>erlang:system_time(microsecond)</c></seealso>.</p>
+ with <seealso marker="#timestamp-0">
+ <c>logger:timestamp()</c></seealso>.</p>
</desc>
</datatype>
</datatypes>
<section>
<title>Macros</title>
- <p>The following macros are defined:</p>
+ <p>The following macros are defined in <c>logger.hrl</c>, which
+ is included in a module with the directive</p>
+ <code>
+ -include_lib("kernel/include/logger.hrl").</code>
<list>
<item><c>?LOG_EMERGENCY(StringOrReport[,Metadata])</c></item>
@@ -285,13 +318,16 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
<item><c>?LOG_INFO(FunOrFormat,Args[,Metadata])</c></item>
<item><c>?LOG_DEBUG(StringOrReport[,Metadata])</c></item>
<item><c>?LOG_DEBUG(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG(Level,StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG(Level,FunOrFormat,Args[,Metadata])</c></item>
</list>
<p>All macros expand to a call to Logger, where <c>Level</c> is
- taken from the macro name, and location data is added to the
- metadata. See the description of
+ taken from the macro name, or from the first argument in the
+ case of the <c>?LOG</c> macro. Location data is added to the
+ metadata as described under
the <seealso marker="#type-metadata"><c>metadata()</c></seealso>
- type for more information about the location data.</p>
+ type definition.</p>
<p>The call is wrapped in a case statement and will be evaluated
only if <c>Level</c> is equal to or below the configured log
@@ -304,9 +340,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</section>
<funcs>
<func>
- <name>emergency(StringOrReport[,Metadata])</name>
- <name>emergency(Format,Args[,Metadata])</name>
- <name>emergency(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">emergency(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">emergency(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">emergency(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>emergency</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -315,9 +351,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name>alert(StringOrReport[,Metadata])</name>
- <name>alert(Format,Args[,Metadata])</name>
- <name>alert(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">alert(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">alert(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">alert(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>alert</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -326,9 +362,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name>critical(StringOrReport[,Metadata])</name>
- <name>critical(Format,Args[,Metadata])</name>
- <name>critical(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">critical(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">critical(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">critical(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>critical</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -337,9 +373,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name>error(StringOrReport[,Metadata])</name>
- <name>error(Format,Args[,Metadata])</name>
- <name>error(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">error(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">error(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">error(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>error</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -348,9 +384,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name>warning(StringOrReport[,Metadata])</name>
- <name>warning(Format,Args[,Metadata])</name>
- <name>warning(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">warning(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">warning(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">warning(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>warning</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -359,9 +395,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name>notice(StringOrReport[,Metadata])</name>
- <name>notice(Format,Args[,Metadata])</name>
- <name>notice(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">notice(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">notice(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">notice(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>notice</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -370,9 +406,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name>info(StringOrReport[,Metadata])</name>
- <name>info(Format,Args[,Metadata])</name>
- <name>info(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">info(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">info(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">info(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>info</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -381,9 +417,9 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name>debug(StringOrReport[,Metadata])</name>
- <name>debug(Format,Args[,Metadata])</name>
- <name>debug(Fun,FunArgs[,Metadata])</name>
+ <name since="OTP 21.0">debug(StringOrReport[,Metadata])</name>
+ <name since="OTP 21.0">debug(Format,Args[,Metadata])</name>
+ <name since="OTP 21.0">debug(Fun,FunArgs[,Metadata])</name>
<fsummary>Logs the given message as level <c>debug</c>.</fsummary>
<desc>
<p>Equivalent to
@@ -392,12 +428,12 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name name="log" arity="2"/>
- <name name="log" arity="3" clause_i="1"/>
- <name name="log" arity="3" clause_i="2"/>
- <name name="log" arity="3" clause_i="3"/>
- <name name="log" arity="4" clause_i="1"/>
- <name name="log" arity="4" clause_i="2"/>
+ <name name="log" arity="2" since="OTP 21.0"/>
+ <name name="log" arity="3" clause_i="1" since="OTP 21.0"/>
+ <name name="log" arity="3" clause_i="2" since="OTP 21.0"/>
+ <name name="log" arity="3" clause_i="3" since="OTP 21.0"/>
+ <name name="log" arity="4" clause_i="1" since="OTP 21.0"/>
+ <name name="log" arity="4" clause_i="2" since="OTP 21.0"/>
<fsummary>Logs the given message.</fsummary>
<type variable="Level"/>
<type variable="StringOrReport" name_i="1"/>
@@ -418,7 +454,7 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</section>
<funcs>
<func>
- <name name="add_handler" arity="3"/>
+ <name name="add_handler" arity="3" since="OTP 21.0"/>
<fsummary>Add a handler with the given configuration.</fsummary>
<desc>
<p>Add a handler with the given configuration.</p>
@@ -429,7 +465,7 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name name="add_handler_filter" arity="3"/>
+ <name name="add_handler_filter" arity="3" since="OTP 21.0"/>
<fsummary>Add a filter to the specified handler.</fsummary>
<desc>
<p>Add a filter to the specified handler.</p>
@@ -470,7 +506,7 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name name="add_handlers" arity="1" clause_i="1"/>
+ <name name="add_handlers" arity="1" clause_i="1" since="OTP 21.0"/>
<fsummary>Set up log handlers from the application's
configuration parameters.</fsummary>
<desc>
@@ -480,7 +516,7 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</func>
<func>
- <name name="add_handlers" arity="1" clause_i="2"/>
+ <name name="add_handlers" arity="1" clause_i="2" since="OTP 21.0"/>
<fsummary>Setup logger handlers.</fsummary>
<type name="config_handler"/>
<desc>
@@ -500,7 +536,7 @@ start(_, []) ->
Error -> Error
end.</code>
<p>This reads the <c>logger</c> configuration parameter from
- the <c>my_all</c> application and starts the configured
+ the <c>my_app</c> application and starts the configured
handlers. The contents of the configuration use the same
rules as the
<seealso marker="logger_chapter#handler-configuration">logger handler configuration</seealso>.
@@ -523,7 +559,7 @@ start(_, []) ->
</func>
<func>
- <name name="add_primary_filter" arity="2"/>
+ <name name="add_primary_filter" arity="2" since="OTP 21.0"/>
<fsummary>Add a primary filter to Logger.</fsummary>
<desc>
<p>Add a primary filter to Logger.</p>
@@ -564,16 +600,16 @@ start(_, []) ->
</func>
<func>
- <name name="get_config" arity="0"/>
+ <name name="get_config" arity="0" since="OTP 21.0"/>
<fsummary>Look up the current Logger configuration</fsummary>
<desc>
- <p>Look up all current Logger configuration, including primary
- and handler configuration, and module level settings.</p>
+ <p>Look up all current Logger configuration, including primary,
+ handler, and proxy configuration, and module level settings.</p>
</desc>
</func>
<func>
- <name name="get_handler_config" arity="0"/>
+ <name name="get_handler_config" arity="0" since="OTP 21.0"/>
<fsummary>Look up the current configuration for all handlers.</fsummary>
<desc>
<p>Look up the current configuration for all handlers.</p>
@@ -581,7 +617,7 @@ start(_, []) ->
</func>
<func>
- <name name="get_handler_config" arity="1"/>
+ <name name="get_handler_config" arity="1" since="OTP 21.0"/>
<fsummary>Look up the current configuration for the given
handler.</fsummary>
<desc>
@@ -590,7 +626,7 @@ start(_, []) ->
</func>
<func>
- <name name="get_handler_ids" arity="0"/>
+ <name name="get_handler_ids" arity="0" since="OTP 21.0"/>
<fsummary>Look up the identities for all installed handlers.</fsummary>
<desc>
<p>Look up the identities for all installed handlers.</p>
@@ -598,7 +634,7 @@ start(_, []) ->
</func>
<func>
- <name name="get_primary_config" arity="0"/>
+ <name name="get_primary_config" arity="0" since="OTP 21.0"/>
<fsummary>Look up the current primary configuration for Logger.</fsummary>
<desc>
<p>Look up the current primary configuration for Logger.</p>
@@ -606,7 +642,18 @@ start(_, []) ->
</func>
<func>
- <name name="get_module_level" arity="0"/>
+ <name name="get_proxy_config" arity="0" since="OTP 21.3"/>
+ <fsummary>Look up the current configuration for the Logger proxy.</fsummary>
+ <desc>
+ <p>Look up the current configuration for the Logger proxy.</p>
+ <p>For more information about the proxy, see
+ section <seealso marker="logger_chapter#proxy">Logger
+ Proxy</seealso> in the Kernel User's Guide.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_module_level" arity="0" since="OTP 21.0"/>
<fsummary>Look up all current module levels.</fsummary>
<desc>
<p>Look up all current module levels. Returns a list
@@ -618,7 +665,7 @@ start(_, []) ->
</func>
<func>
- <name name="get_module_level" arity="1"/>
+ <name name="get_module_level" arity="1" since="OTP 21.0"/>
<fsummary>Look up the current level for the given modules.</fsummary>
<desc>
<p>Look up the current level for the given modules. Returns a
@@ -630,7 +677,7 @@ start(_, []) ->
</func>
<func>
- <name name="get_process_metadata" arity="0"/>
+ <name name="get_process_metadata" arity="0" since="OTP 21.0"/>
<fsummary>Retrieve data set with set_process_metadata/1.</fsummary>
<desc>
<p>Retrieve data set
@@ -642,7 +689,16 @@ start(_, []) ->
</func>
<func>
- <name name="remove_handler" arity="1"/>
+ <name name="i" arity="0" since="OTP 21.3"/>
+ <name name="i" arity="1" since="OTP 21.3"/>
+ <fsummary>Pretty print the Logger configuration.</fsummary>
+ <desc>
+ <p>Pretty print the Logger configuration.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remove_handler" arity="1" since="OTP 21.0"/>
<fsummary>Remove the handler with the specified identity.</fsummary>
<desc>
<p>Remove the handler identified by <c><anno>HandlerId</anno></c>.</p>
@@ -650,7 +706,7 @@ start(_, []) ->
</func>
<func>
- <name name="remove_handler_filter" arity="2"/>
+ <name name="remove_handler_filter" arity="2" since="OTP 21.0"/>
<fsummary>Remove a filter from the specified handler.</fsummary>
<desc>
<p>Remove the filter identified
@@ -660,7 +716,7 @@ start(_, []) ->
</func>
<func>
- <name name="remove_primary_filter" arity="1"/>
+ <name name="remove_primary_filter" arity="1" since="OTP 21.0"/>
<fsummary>Remove a primary filter from Logger.</fsummary>
<desc>
<p>Remove the primary filter identified
@@ -669,7 +725,18 @@ start(_, []) ->
</func>
<func>
- <name name="set_handler_config" arity="2"/>
+ <name name="set_application_level" arity="2" since="OTP 21.1"/>
+ <fsummary>Set the log level for all modules in the specified application.</fsummary>
+ <desc>
+ <p>Set the log level for all the modules of the specified application.</p>
+ <p>This function is a convenience function that calls
+ <seealso marker="#set_module_level/2">logger:set_module_level/2</seealso>
+ for each module associated with an application.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_handler_config" arity="2" since="OTP 21.0"/>
<fsummary>Set configuration data for the specified handler.</fsummary>
<desc>
<p>Set configuration data for the specified handler. This
@@ -690,20 +757,43 @@ start(_, []) ->
</func>
<func>
- <name name="set_handler_config" arity="3"/>
+ <name name="set_handler_config" arity="3" clause_i="1" since="OTP 21.0"/>
+ <name name="set_handler_config" arity="3" clause_i="2" since="OTP 21.0"/>
+ <name name="set_handler_config" arity="3" clause_i="3" since="OTP 21.0"/>
+ <name name="set_handler_config" arity="3" clause_i="4" since="OTP 21.0"/>
+ <name name="set_handler_config" arity="3" clause_i="5" since="OTP 21.0"/>
<fsummary>Add or update configuration data for the specified
handler.</fsummary>
+ <type variable="HandlerId"/>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
+ <type variable="Formatter" name_i="4"/>
+ <type variable="Config" name_i="5"/>
+ <type variable="Return"/>
<desc>
<p>Add or update configuration data for the specified
handler. If the given <c><anno>Key</anno></c> already
exists, its associated value will be changed
- to <c><anno>Value</anno></c>. If it does not exist, it will
+ to the given value. If it does not exist, it will
be added.</p>
+ <p>If the value is incomplete, which for example can be the
+ case for the <c>config</c> key, it is up to the handler
+ implementation how the unspecified parts are set. For all
+ handlers in the Kernel application, unspecified data for
+ the <c>config</c> key is set to default values. To update
+ only specified data, and keep the existing configuration for
+ the rest, use <seealso marker="#update_handler_config-3">
+ <c>update_handler_config/3</c></seealso>.</p>
+ <p>See the definition of
+ the <seealso marker="#type-handler_config">
+ <c>handler_config()</c></seealso> type for more
+ information about the different parameters.</p>
</desc>
</func>
<func>
- <name name="set_primary_config" arity="1"/>
+ <name name="set_primary_config" arity="1" since="OTP 21.0"/>
<fsummary>Set primary configuration data for Logger.</fsummary>
<desc>
<p>Set primary configuration data for Logger. This
@@ -721,22 +811,47 @@ start(_, []) ->
</func>
<func>
- <name name="set_primary_config" arity="2"/>
+ <name name="set_primary_config" arity="2" clause_i="1" since="OTP 21.0"/>
+ <name name="set_primary_config" arity="2" clause_i="2" since="OTP 21.0"/>
+ <name name="set_primary_config" arity="2" clause_i="3" since="OTP 21.0"/>
<fsummary>Add or update primary configuration data for Logger.</fsummary>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
<desc>
<p>Add or update primary configuration data for Logger. If the
given <c><anno>Key</anno></c> already exists, its associated
- value will be changed to <c><anno>Value</anno></c>. If it
- does not exist, it will be added.</p>
+ value will be changed to the given value. If it does not
+ exist, it will be added.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_proxy_config" arity="1" since="OTP 21.3"/>
+ <fsummary>Set configuration data for the Logger proxy.</fsummary>
+ <desc>
+ <p>Set configuration data for the Logger proxy. This
+ overwrites the current proxy configuration. Keys that are not
+ specified in the <c><anno>Config</anno></c> map gets default
+ values.</p>
+ <p>To modify the existing configuration,
+ use <seealso marker="#update_proxy_config-1">
+ <c>update_proxy_config/1</c></seealso>, or, if a more
+ complex merge is needed, read the current configuration
+ with <seealso marker="#get_proxy_config-0"><c>get_proxy_config/0</c>
+ </seealso>, then do the merge before writing the new
+ configuration back with this function.</p>
+ <p>For more information about the proxy, see
+ section <seealso marker="logger_chapter#proxy">Logger
+ Proxy</seealso> in the Kernel User's Guide.</p>
</desc>
</func>
<func>
- <name name="set_module_level" arity="2"/>
+ <name name="set_module_level" arity="2" since="OTP 21.0"/>
<fsummary>Set the log level for the specified modules.</fsummary>
<desc>
- <p>Set the log level for the
- specified modules.</p>
+ <p>Set the log level for the specified modules.</p>
<p>The log level for a module overrides the primary log level
of Logger for log events originating from the module in
question. Notice, however, that it does not override the
@@ -773,7 +888,7 @@ start(_, []) ->
</func>
<func>
- <name name="set_process_metadata" arity="1"/>
+ <name name="set_process_metadata" arity="1" since="OTP 21.0"/>
<fsummary>Set metadata to use when logging from current process.</fsummary>
<desc>
<p>Set metadata which Logger shall automatically insert in
@@ -792,7 +907,18 @@ start(_, []) ->
</func>
<func>
- <name name="unset_module_level" arity="0"/>
+ <name name="unset_application_level" arity="1" since="OTP 21.1"/>
+ <fsummary>Unset the log level for all modules in the specified application.</fsummary>
+ <desc>
+ <p>Unset the log level for all the modules of the specified application.</p>
+ <p>This function is a convinience function that calls
+ <seealso marker="#unset_module_level/1">logger:unset_module_level/2</seealso>
+ for each module associated with an application.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_module_level" arity="0" since="OTP 21.0"/>
<fsummary>Remove module specific log settings for all modules.</fsummary>
<desc>
<p>Remove module specific log settings. After this, the
@@ -801,7 +927,7 @@ start(_, []) ->
</func>
<func>
- <name name="unset_module_level" arity="1"/>
+ <name name="unset_module_level" arity="1" since="OTP 21.0"/>
<fsummary>Remove module specific log settings for the given
modules.</fsummary>
<desc>
@@ -811,7 +937,7 @@ start(_, []) ->
</func>
<func>
- <name name="unset_process_metadata" arity="0"/>
+ <name name="unset_process_metadata" arity="0" since="OTP 21.0"/>
<fsummary>Delete data set with set_process_metadata/1.</fsummary>
<desc>
<p>Delete data set
@@ -823,7 +949,7 @@ start(_, []) ->
</func>
<func>
- <name name="update_formatter_config" arity="2"/>
+ <name name="update_formatter_config" arity="2" since="OTP 21.0"/>
<fsummary>Update the formatter configuration for the specified handler.</fsummary>
<desc>
<p>Update the formatter configuration for the specified handler.</p>
@@ -838,7 +964,7 @@ start(_, []) ->
</func>
<func>
- <name name="update_formatter_config" arity="3"/>
+ <name name="update_formatter_config" arity="3" since="OTP 21.0"/>
<fsummary>Update the formatter configuration for the specified handler.</fsummary>
<desc>
<p>Update the formatter configuration for the specified handler.</p>
@@ -849,7 +975,7 @@ start(_, []) ->
</func>
<func>
- <name name="update_handler_config" arity="2"/>
+ <name name="update_handler_config" arity="2" since="OTP 21.0"/>
<fsummary>Update configuration data for the specified handler.</fsummary>
<desc>
<p>Update configuration data for the specified handler. This function
@@ -865,7 +991,43 @@ logger:set_handler_config(HandlerId, maps:merge(Old, Config)).
</func>
<func>
- <name name="update_primary_config" arity="1"/>
+ <name name="update_handler_config" arity="3" clause_i="1" since="OTP 21.2"/>
+ <name name="update_handler_config" arity="3" clause_i="2" since="OTP 21.2"/>
+ <name name="update_handler_config" arity="3" clause_i="3" since="OTP 21.2"/>
+ <name name="update_handler_config" arity="3" clause_i="4" since="OTP 21.2"/>
+ <name name="update_handler_config" arity="3" clause_i="5" since="OTP 21.2"/>
+ <fsummary>Add or update configuration data for the specified
+ handler.</fsummary>
+ <type variable="HandlerId"/>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
+ <type variable="Formatter" name_i="4"/>
+ <type variable="Config" name_i="5"/>
+ <type variable="Return"/>
+ <desc>
+ <p>Add or update configuration data for the specified
+ handler. If the given <c><anno>Key</anno></c> already
+ exists, its associated value will be changed
+ to the given value. If it does not exist, it will
+ be added.</p>
+ <p>If the value is incomplete, which for example can be the
+ case for the <c>config</c> key, it is up to the handler
+ implementation how the unspecified parts are set. For all
+ handlers in the Kernel application, unspecified data for
+ the <c>config</c> key is not changed. To reset unspecified
+ data to default values,
+ use <seealso marker="#set_handler_config-3">
+ <c>set_handler_config/3</c></seealso>.</p>
+ <p>See the definition of
+ the <seealso marker="#type-handler_config">
+ <c>handler_config()</c></seealso> type for more
+ information about the different parameters.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_primary_config" arity="1" since="OTP 21.0"/>
<fsummary>Update primary configuration data for Logger.</fsummary>
<desc>
<p>Update primary configuration data for Logger. This function
@@ -881,7 +1043,7 @@ logger:set_primary_config(maps:merge(Old, Config)).
</func>
<func>
- <name name="update_process_metadata" arity="1"/>
+ <name name="update_process_metadata" arity="1" since="OTP 21.0"/>
<fsummary>Set or update metadata to use when logging from
current process.</fsummary>
<desc>
@@ -898,6 +1060,25 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
</seealso>.</p>
</desc>
</func>
+
+ <func>
+ <name name="update_proxy_config" arity="1" since="OTP 21.3"/>
+ <fsummary>Update configuration data for the Logger proxy.</fsummary>
+ <desc>
+ <p>Update configuration data for the Logger proxy. This function
+ behaves as if it was implemented as follows:</p>
+ <code type="erl">
+Old = logger:get_proxy_config(),
+logger:set_proxy_config(maps:merge(Old, Config)).
+ </code>
+ <p>To overwrite the existing configuration without any merge,
+ use <seealso marker="#set_proxy_config-1"><c>set_proxy_config/1</c>
+ </seealso>.</p>
+ <p>For more information about the proxy, see
+ section <seealso marker="logger_chapter#proxy">Logger
+ Proxy</seealso> in the Kernel User's Guide.</p>
+ </desc>
+ </func>
</funcs>
<section>
@@ -906,7 +1087,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
</section>
<funcs>
<func>
- <name name="compare_levels" arity="2"/>
+ <name name="compare_levels" arity="2" since="OTP 21.0"/>
<fsummary>Compare the severity of two log levels.</fsummary>
<desc>
<p>Compare the severity of two log levels. Returns <c>gt</c>
@@ -917,7 +1098,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
</func>
<func>
- <name name="format_report" arity="1"/>
+ <name name="format_report" arity="1" since="OTP 21.0"/>
<fsummary>Convert a log message on report form to {Format, Args}.</fsummary>
<desc>
<p>Convert a log message on report form to <c>{Format,
@@ -936,6 +1117,24 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
a key-value list before formatting as such.</p>
</desc>
</func>
+
+ <func>
+ <name name="timestamp" arity="0" since="OTP 21.3"/>
+ <fsummary>Return a timestamp to insert in meta data for a log
+ event.</fsummary>
+ <desc>
+ <p>Return a timestamp that can be inserted as the <c>time</c>
+ field in the meta data for a log event. It is produced with
+ <seealso marker="kernel:os#system_time-1">
+ <c>os:system_time(microsecond)</c></seealso>.</p>
+ <p>Notice that Logger automatically inserts a timestamp in the
+ meta data unless it already exists. This function is
+ exported for the rare case when the timestamp must be taken
+ at a different point in time than when the log event is
+ issued.</p>
+ </desc>
+ </func>
+
</funcs>
<section>
@@ -947,7 +1146,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
<funcs>
<func>
- <name>HModule:adding_handler(Config1) -> {ok, Config2} | {error,
+ <name since="OTP 21.0">HModule:adding_handler(Config1) -> {ok, Config2} | {error,
Reason}</name>
<fsummary>An instance of this handler is about to be added.</fsummary>
<type>
@@ -973,10 +1172,11 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
</func>
<func>
- <name>HModule:changing_config(Config1, Config2) -> {ok, Config3} | {error, Reason}</name>
+ <name since="OTP 21.2">HModule:changing_config(SetOrUpdate, OldConfig, NewConfig) -> {ok, Config} | {error, Reason}</name>
<fsummary>The configuration for this handler is about to change.</fsummary>
<type>
- <v>Config1 = Config2 = Config3 =
+ <v>SetOrUpdate = set | update</v>
+ <v>OldConfig = NewConfig = Config =
<seealso marker="#type-handler_config">handler_config()</seealso></v>
<v>Reason = term()</v>
</type>
@@ -985,19 +1185,52 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
<p>The function is called on a temporary process when the
configuration for a handler is about to change. The purpose
is to verify and act on the new configuration.</p>
- <p><c>Config1</c> is the existing configuration
- and <c>Config2</c> is the new configuration.</p>
+ <p><c>OldConfig</c> is the existing configuration
+ and <c>NewConfig</c> is the new configuration.</p>
<p>The handler identity is associated with the <c>id</c> key
- in <c>Config1</c>.</p>
+ in <c>OldConfig</c>.</p>
+ <p><c>SetOrUpdate</c> has the value <c>set</c> if the
+ configuration change originates from a call to
+ <seealso marker="#set_handler_config-2">
+ <c>set_handler_config/2,3</c></seealso>, and <c>update</c>
+ if it originates from <seealso marker="#update_handler_config-2">
+ <c>update_handler_config/2,3</c></seealso>. The handler can
+ use this parameteter to decide how to update the value of
+ the <c>config</c> field, that is, the handler specific
+ configuration data. Typically, if <c>SetOrUpdate</c>
+ equals <c>set</c>, values that are not specified must be
+ given their default values. If <c>SetOrUpdate</c>
+ equals <c>update</c>, the values found in <c>OldConfig</c>
+ must be used instead.</p>
<p>If everything succeeds, the callback function must return a
- possibly adjusted configuration in <c>{ok,Config3}</c>.</p>
+ possibly adjusted configuration in <c>{ok,Config}</c>.</p>
<p>If the configuration is faulty, the callback function must
return <c>{error,Reason}</c>.</p>
</desc>
</func>
<func>
- <name>HModule:log(LogEvent, Config) -> void()</name>
+ <name since="OTP 21.2">HModule:filter_config(Config) -> FilteredConfig</name>
+ <fsummary>Remove internal data from configuration.</fsummary>
+ <type>
+ <v>Config = FilteredConfig =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called when one of the Logger API functions
+ for fetching the handler configuration is called, for
+ example
+ <seealso marker="#get_handler_config-1">
+ <c>logger:get_handler_config/1</c></seealso>.</p>
+ <p>It allows the handler to remove internal data fields from
+ its configuration data before it is returned to the
+ caller.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.0">HModule:log(LogEvent, Config) -> void()</name>
<fsummary>Log the given log event.</fsummary>
<type>
<v>LogEvent =
@@ -1020,7 +1253,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
</func>
<func>
- <name>HModule:removing_handler(Config) -> ok</name>
+ <name since="OTP 21.0">HModule:removing_handler(Config) -> ok</name>
<fsummary>The given handler is about to be removed.</fsummary>
<type>
<v>Config =
@@ -1048,7 +1281,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
<funcs>
<func>
- <name>FModule:check_config(FConfig) -> ok | {error, Reason}</name>
+ <name since="OTP 21.0">FModule:check_config(FConfig) -> ok | {error, Reason}</name>
<fsummary>Validate the given formatter configuration.</fsummary>
<type>
<v>FConfig =
@@ -1068,7 +1301,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
<item><seealso marker="logger#set_handler_config-2">
<c>logger:set_handler_config/2,3</c></seealso></item>
<item><seealso marker="logger#update_handler_config-2">
- <c>logger:updata_handler_config/2</c></seealso></item>
+ <c>logger:update_handler_config/2,3</c></seealso></item>
<item><seealso marker="logger#update_formatter_config-2">
<c>logger:update_formatter_config/2</c></seealso></item>
</list>
@@ -1079,7 +1312,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
</desc>
</func>
<func>
- <name>FModule:format(LogEvent, FConfig) -> FormattedLogEntry</name>
+ <name since="OTP 21.0">FModule:format(LogEvent, FConfig) -> FormattedLogEntry</name>
<fsummary>Format the given log event.</fsummary>
<type>
<v>LogEvent =
diff --git a/lib/kernel/doc/src/logger_arch.dia b/lib/kernel/doc/src/logger_arch.dia
new file mode 100644
index 0000000000..97be31856e
--- /dev/null
+++ b/lib/kernel/doc/src/logger_arch.dia
Binary files differ
diff --git a/lib/kernel/doc/src/logger_arch.png b/lib/kernel/doc/src/logger_arch.png
index a3a863c511..70933a5a41 100644
--- a/lib/kernel/doc/src/logger_arch.png
+++ b/lib/kernel/doc/src/logger_arch.png
Binary files differ
diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml
index f4a752bde9..bfd0acf634 100644
--- a/lib/kernel/doc/src/logger_chapter.xml
+++ b/lib/kernel/doc/src/logger_chapter.xml
@@ -69,6 +69,8 @@
figure shows two log handlers, but any number of handlers can be
installed.</p>
+ <!-- The image is edited with dia in logger_arch.dia file,
+ and .png file generated with make target 'png'. -->
<image file="logger_arch.png">
<icaption>Conceptual Overview</icaption>
</image>
@@ -111,7 +113,10 @@
of functions on the form <c>logger:Level/1,2,3</c>, which are
all shortcuts
for <seealso marker="logger#log-2">
- <c>logger:log(Level,Arg1[,Arg2[,Arg3]])</c></seealso>.</p>
+ <c>logger:log(Level,Arg1[,Arg2[,Arg3]])</c></seealso>.</p>
+ <p>The macros are defined in <c>logger.hrl</c>, which is included
+ in a module with the directive</p>
+ <code>-include_lib("kernel/include/logger.hrl").</code>
<p>The difference between using the macros and the exported
functions is that macros add location (originator) information
to the metadata, and performs lazy evaluation by wrapping the
@@ -192,10 +197,28 @@
the log event's <seealso marker="#metadata">metadata</seealso>.
The report callback is a convenience function that
the <seealso marker="#formatters">formatter</seealso> can use
- to convert the report to a format string and arguments. The
+ to convert the report to a format string and arguments, or
+ directly to a string. The
formatter can also use its own conversion function, if no
callback is provided, or if a customized formatting is
desired.</p>
+ <p>The report callback must be a fun with one or two
+ arguments. If it takes one argument, this is the report
+ itself, and the fun returns a format string and arguments:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>) -> {<seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso>,[term()]})</pre>
+ <p>If it takes two arguments, the first is the report, and the
+ second is a map containing extra data that allows direct
+ coversion to a string:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>,<seealso marker="logger#type-report_cb_config"><c>logger:report_cb_config()</c></seealso>) -> <seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c></seealso>)
+ </pre>
+ <p>The fun must obey the <c>depth</c> and <c>chars_limit</c>
+ parameters provided in the second argument, as the formatter can
+ not do anything useful of these parameters with the returned
+ string. The extra data also contains a field named
+ <c>single_line</c>, indicating if the printed log message may
+ contain line breaks or not. This variant is used when the
+ formatting of the report depends on the size or single line
+ parameters.</p>
<p>Example, format string and arguments:</p>
<code>logger:error("The file does not exist: ~ts",[Filename])</code>
<p>Example, string:</p>
@@ -222,7 +245,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},
with <seealso marker="logger#set_process_metadata-1">
<c>logger:set_process_metadata/1</c></seealso>
and <seealso marker="logger#update_process_metadata-1">
- <c>logger:update_process metadata/1</c></seealso>,
+ <c>logger:update_process_metadata/1</c></seealso>,
respectively. This metadata applies to the process on
which these calls are made, and Logger adds the metadata
to all log events issued on that process.</p>
@@ -364,8 +387,8 @@ logger:debug(#{got => connection_request, id => Id, state => State},
<p>In addition to the mandatory callback function <c>log/2</c>, a
handler module can export the optional callback
- functions <c>adding_handler/1</c>, <c>changing_config/2</c>
- and <c>removing_handler/1</c>. See
+ functions <c>adding_handler/1</c>, <c>changing_config/3</c>,
+ <c>filter_config/1</c>, and <c>removing_handler/1</c>. See
section <seealso marker="logger#handler_callback_functions">Handler
Callback Functions</seealso> in the logger(3) manual page for
more information about these function.</p>
@@ -489,7 +512,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},
<c>logger_level</c></seealso>. It is changed during
runtime with <seealso marker="logger#set_primary_config-2">
<c>logger:set_primary_config(level,Level)</c></seealso>.</p>
- <p>Defaults to <c>info</c>.</p>
+ <p>Defaults to <c>notice</c>.</p>
</item>
<tag><c>filters = [{FilterId,Filter}]</c></tag>
<item>
@@ -535,7 +558,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},
<item><seealso marker="logger#set_handler_config-2">
<c>set_handler_config/2,3</c></seealso></item>
<item><seealso marker="logger#update_handler_config-2">
- <c>update_handler_config/2</c></seealso></item>
+ <c>update_handler_config/2,3</c></seealso></item>
<item><seealso marker="logger#add_handler_filter-3">
<c>add_handler_filter/3</c></seealso></item>
<item><seealso marker="logger#remove_handler_filter-2">
@@ -670,8 +693,10 @@ logger:debug(#{got => connection_request, id => Id, state => State},
with <seealso marker="#logger_sasl_compatible">
<c>logger_sasl_compatible</c></seealso>.</p>
<p>With this parameter, you can modify or disable the default
- handler, add custom handlers and primary logger filters, and
- set log levels per module.</p>
+ handler, add custom handlers and primary logger filters, set
+ log levels per module, and modify
+ the <seealso marker="#proxy">proxy</seealso>
+ configuration.</p>
<p><c>Config</c> is any (zero or more) of the following:</p>
<taglist>
<tag><c>{handler, default, undefined}</c></tag>
@@ -684,9 +709,13 @@ logger:debug(#{got => connection_request, id => Id, state => State},
<item>
<p>If <c>HandlerId</c> is <c>default</c>, then this entry
modifies the default handler, equivalent to calling</p>
- <pre><seealso marker="logger#set_handler_config-2">
- logger:set_handler_config(default, Module, HandlerConfig)
- </seealso></pre>
+ <pre><seealso marker="logger#remove_handler-1">
+ logger:remove_handler(default)
+ </seealso></pre>
+ <p>followed by</p>
+ <pre><seealso marker="logger#add_handler-3">
+ logger:add_handler(default, Module, HandlerConfig)
+ </seealso></pre>
<p>For all other values of <c>HandlerId</c>, this entry
adds a new handler, equivalent to calling</p>
<pre><seealso marker="logger:add_handler/3">
@@ -719,6 +748,14 @@ logger:debug(#{got => connection_request, id => Id, state => State},
<p>for each <c>Module</c>.</p>
<p>Multiple entries of this type are allowed.</p>
</item>
+ <tag><c>{proxy, ProxyConfig}</c></tag>
+ <item>
+ <p>Sets the proxy configuration, equivalent to calling</p>
+ <pre><seealso marker="logger#set_proxy_config/1">
+ logger:set_proxy_config(ProxyConfig)
+ </seealso></pre>
+ <p>Only one entry of this type is allowed.</p>
+ </item>
</taglist>
<p>See
section <seealso marker="#config_examples">Configuration
@@ -764,7 +801,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},
[{kernel,
[{logger,
[{handler, default, logger_std_h, % {handler, HandlerId, Module,
- #{config => #{type => {file,"log/erlang.log"}}}} % Config}
+ #{config => #{file => "log/erlang.log"}}} % Config}
]}]}].
</code>
<p>Modify the default handler to print each log event as a
@@ -794,10 +831,10 @@ logger:debug(#{got => connection_request, id => Id, state => State},
[{logger,
[{handler, default, logger_std_h,
#{level => error,
- config => #{type => {file, "log/erlang.log"}}}},
+ config => #{file => "log/erlang.log"}}},
{handler, info, logger_std_h,
#{level => debug,
- config => #{type => {file, "log/debug.log"}}}}
+ config => #{file => "log/debug.log"}}}
]}]}].
</code>
</section>
@@ -967,10 +1004,10 @@ ok</pre>
<p>Then, add a new handler which prints to file. You can use the
handler
module <seealso marker="logger_std_h"><c>logger_std_h</c></seealso>,
- and specify type <c>{file,File}</c>.:</p>
+ and configure it to log to file:</p>
<pre>
-4> <input>Config = #{config => #{type => {file,"./info.log"}}, level => info}.</input>
-#{config => #{type => {file,"./info.log"}},level => info}
+4> <input>Config = #{config => #{file => "./info.log"}, level => info}.</input>
+#{config => #{file => "./info.log"},level => info}
5> <input>logger:add_handler(myhandler, logger_std_h, Config).</input>
ok</pre>
<p>Since <c>filter_default</c> defaults to <c>log</c>, this
@@ -1004,7 +1041,8 @@ ok</pre>
<list>
<item><c>adding_handler(Config)</c></item>
<item><c>removing_handler(Config)</c></item>
- <item><c>changing_config(OldConfig, NewConfig)</c></item>
+ <item><c>changing_config(SetOrUpdate, OldConfig, NewConfig)</c></item>
+ <item><c>filter_config(Config)</c></item>
</list>
<p>When a handler is added, by for example a call
to <seealso marker="logger#add_handler-3">
@@ -1023,11 +1061,18 @@ ok</pre>
<p>When <seealso marker="logger#set_handler_config-2">
<c>logger:set_handler_config/2,3</c></seealso>
or <seealso marker="logger#update_handler_config/2">
- <c>logger:update_handler_config/2</c></seealso> is called,
+ <c>logger:update_handler_config/2,3</c></seealso> is called,
Logger
- calls <c>HModule:changing_config(OldConfig, NewConfig)</c>. If
+ calls <c>HModule:changing_config(SetOrUpdate, OldConfig, NewConfig)</c>. If
this function returns <c>{ok,NewConfig1}</c>, Logger
writes <c>NewConfig1</c> to the configuration database.</p>
+ <p>When <seealso marker="logger#get_config-0">
+ <c>logger:get_config/0</c></seealso> or
+ <seealso marker="logger#get_handler_config-0">
+ <c>logger:get_handler_config/0,1</c></seealso> is called,
+ Logger calls <c>HModule:filter_config(Config)</c>. This function
+ must return the handler configuration where internal data is
+ removed.</p>
<p>A simple handler that prints to the terminal can be implemented
as follows:</p>
@@ -1201,7 +1246,7 @@ do_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) ->
<p>A configuration example:</p>
<code type="none">
logger:add_handler(my_standard_h, logger_std_h,
- #{config => #{type => {file,"./system_info.log"},
+ #{config => #{file => "./system_info.log",
sync_mode_qlen => 100,
drop_mode_qlen => 1000,
flush_qlen => 2000}}).
@@ -1299,9 +1344,50 @@ logger:add_handler(my_disk_log_h, logger_disk_log_h,
</section>
<section>
+ <marker id="proxy"/>
+ <title>Logger Proxy</title>
+ <p>The Logger proxy is an Erlang process which is part of the
+ Kernel application's supervision tree. During startup, the proxy
+ process registers itself as the <c>system_logger</c>, meaning
+ that log events produced by the emulator are sent to this
+ process.</p>
+ <p>When a log event is issued on a process which has its group
+ leader on a remote node, Logger automatically forwards the log
+ event to the group leader's node. To achieve this, it first
+ sends the log event as an Erlang message from the original
+ client process to the proxy on the local node, and the proxy in
+ turn forwards the event to the proxy on the remote node.</p>
+ <p>When receiving a log event, either from the emulator or from a
+ remote node, the proxy calls the Logger API to log the event.</p>
+ <p>The proxy process is overload protected in the same way as
+ described in
+ section <seealso marker="#overload_protection">Protecting the
+ Handler from Overload</seealso>, but with the following default
+ values:</p>
+ <code>
+ #{sync_mode_qlen => 500,
+ drop_mode_qlen => 1000,
+ flush_qlen => 5000,
+ burst_limit_enable => false,
+ overload_kill_enable => false}</code>
+ <p>For log events from the emulator, synchronous message passing
+ mode is not applicable, since all messages are passed
+ asynchronously by the emulator. Drop mode is achieved by setting
+ the <c>system_logger</c> to <c>undefined</c>, forcing the
+ emulator to drop events until it is set back to the proxy pid
+ again.</p>
+ <p>The proxy uses <seealso marker="erts:erlang#send_nosuspend/2">
+ <c>erlang:send_nosuspend/2</c></seealso> when sending log
+ events to a remote node. If the message could not be sent
+ without suspending the sender, it is dropped. This is to avoid
+ blocking the proxy process.</p>
+ </section>
+
+ <section>
<title>See Also</title>
<p>
<seealso marker="disk_log"><c>disk_log(3)</c></seealso>,
+ <seealso marker="erts:erlang"><c>erlang(3)</c></seealso>,
<seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
<seealso marker="logger"><c>logger(3)</c></seealso>,
<seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c></seealso>,
diff --git a/lib/kernel/doc/src/logger_disk_log_h.xml b/lib/kernel/doc/src/logger_disk_log_h.xml
index dfe2ab3275..5b2374690e 100644
--- a/lib/kernel/doc/src/logger_disk_log_h.xml
+++ b/lib/kernel/doc/src/logger_disk_log_h.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>logger_disk_log_h.xml</file>
</header>
- <module>logger_disk_log_h</module>
+ <module since="OTP 21.0">logger_disk_log_h</module>
<modulesummary>A disk_log based handler for Logger</modulesummary>
<description>
@@ -66,6 +66,10 @@
corresponds to the <c>name</c> property in the
<seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
datatype.</p>
+ <p>The value is set when the handler is added, and it can not
+ be changed in runtime.</p>
+ <p>Defaults to the same name as the handler identity, in the
+ current directory.</p>
</item>
<tag><c>type</c></tag>
<item>
@@ -73,6 +77,8 @@
corresponds to the <c>type</c> property in the
<seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
datatype.</p>
+ <p>The value is set when the handler is added, and it can not
+ be changed in runtime.</p>
<p>Defaults to <c>wrap</c>.</p>
</item>
<tag><c>max_no_files</c></tag>
@@ -82,6 +88,8 @@
corresponds to the <c>MaxNoFiles</c> element in the <c>size</c> property in the
<seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
datatype.</p>
+ <p>The value is set when the handler is added, and it can not
+ be changed in runtime.</p>
<p>Defaults to <c>10</c>.</p>
<p>The setting has no effect on a halt log.</p>
</item>
@@ -93,6 +101,8 @@
corresponds to the <c>MaxNoBytes</c> element in the <c>size</c> property in the
<seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
datatype.</p>
+ <p>The value is set when the handler is added, and it can not
+ be changed in runtime.</p>
<p>Defaults to <c>1048576</c> bytes for a wrap log, and
<c>infinity</c> for a halt log.</p>
</item>
@@ -138,7 +148,7 @@ erl -kernel logger '[{handler,default,logger_disk_log_h,
<funcs>
<func>
- <name name="filesync" arity="1" clause_i="1"/>
+ <name name="filesync" arity="1" clause_i="1" since="OTP 21.0"/>
<fsummary>Writes buffered data to disk.</fsummary>
<desc>
<p>Write buffered data to disk.</p>
diff --git a/lib/kernel/doc/src/logger_filters.xml b/lib/kernel/doc/src/logger_filters.xml
index 90f1fcc270..0a02342864 100644
--- a/lib/kernel/doc/src/logger_filters.xml
+++ b/lib/kernel/doc/src/logger_filters.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>logger_filters.xml</file>
</header>
- <module>logger_filters</module>
+ <module since="OTP 21.0">logger_filters</module>
<modulesummary>Filters to use with Logger.</modulesummary>
<description>
@@ -51,7 +51,7 @@
<funcs>
<func>
- <name name="domain" arity="2"/>
+ <name name="domain" arity="2" since="OTP 21.0"/>
<fsummary>Filter log events based on the domain field in
metadata.</fsummary>
<desc>
@@ -152,7 +152,7 @@ ok</code>
</func>
<func>
- <name name="level" arity="2"/>
+ <name name="level" arity="2" since="OTP 21.0"/>
<fsummary>Filter log events based on the log level.</fsummary>
<desc>
<p>This filter provides a way of filtering log events based
@@ -212,7 +212,7 @@ ok</code>
</func>
<func>
- <name name="progress" arity="2"/>
+ <name name="progress" arity="2" since="OTP 21.0"/>
<fsummary>Filter progress reports from supervisor and application_controller.</fsummary>
<desc>
<p>This filter matches all progress reports
@@ -227,7 +227,7 @@ ok</code>
</func>
<func>
- <name name="remote_gl" arity="2"/>
+ <name name="remote_gl" arity="2" since="OTP 21.0"/>
<fsummary>Filter events with group leader on remote node.</fsummary>
<desc>
<p>This filter matches all events originating from a process
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml
index e777afaf86..6dc83d24e1 100644
--- a/lib/kernel/doc/src/logger_formatter.xml
+++ b/lib/kernel/doc/src/logger_formatter.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>logger_formatter.xml</file>
</header>
- <module>logger_formatter</module>
+ <module since="OTP 21.0">logger_formatter</module>
<modulesummary>Default formatter for Logger.</modulesummary>
<description>
@@ -78,7 +78,7 @@
format controls ~p and ~w are replaced with ~P and ~W,
respectively, and the value is used as the depth
parameter. For details, see
- <seealso marker="stdlib:io#format-2">io:format/2,3</seealso>
+ <seealso marker="stdlib:io#format-2"><c>io:format/2,3</c></seealso>
in STDLIB.</p>
<p>Defaults to <c>unlimited</c>.</p>
</item>
@@ -105,7 +105,8 @@
by <c>chars_limit</c> or <c>depth</c>, it is truncated.</p>
<p>Defaults to <c>unlimited</c>.</p>
</item>
- <tag><c>report_cb = fun((</c><seealso marker="logger#type-report"><c>logger:report()</c></seealso><c>) -> {</c><seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso><c>, [term()]})</c></tag>
+ <tag><c>report_cb = </c><seealso marker="logger#type-report_cb">
+ <c>logger:report_cb()</c></seealso></tag>
<item>
<p>A report callback is used by the formatter to transform
log messages on report form to a format string and
@@ -119,16 +120,19 @@
both the default report callback, and any report
callback found in metadata. That is, all reports are
converted by this configured function.</p>
- <p>The value must be a function with arity 1,
- returning <c>{Format,Args}</c>, and it will be called
- with a report as only argument.</p>
</item>
<tag><c>single_line = boolean()</c></tag>
<item>
- <p>If set to <c>true</c>, all newlines in the message are
- replaced with <c>", "</c>, and white spaces following
- directly after newlines are removed. Notice that newlines
- added by the <c>template</c> parameter are not replaced.</p>
+ <p>If set to <c>true</c>, each log event is printed as a
+ single line. To achieve this, <c>logger_formatter</c>
+ sets the field width to <c>0</c> for all <c>~p</c>
+ and <c>~P</c> control sequences in the format a string
+ (see <seealso marker="stdlib:io#format-2">
+ <c>io:format/2</c></seealso>), and replaces all
+ newlines in the message with <c>", "</c>. White spaces
+ following directly after newlines are removed. Notice
+ that newlines added by the <c>template</c> parameter are
+ not replaced.</p>
<p>Defaults to <c>true</c>.</p>
</item>
<tag><marker id="template"/>
@@ -285,7 +289,7 @@ exit_reason: "It crashed"</code>
<funcs>
<func>
- <name name="check_config" arity="1"/>
+ <name name="check_config" arity="1" since="OTP 21.0"/>
<fsummary>Validates the given formatter configuration.</fsummary>
<desc>
<p>The function is called by Logger when the formatter
@@ -299,14 +303,14 @@ exit_reason: "It crashed"</code>
<item><seealso marker="logger#set_handler_config-2">
<c>logger:set_handler_config/2,3</c></seealso></item>
<item><seealso marker="logger#update_handler_config-2">
- <c>logger:updata_handler_config/2</c></seealso></item>
+ <c>logger:update_handler_config/2</c></seealso></item>
<item><seealso marker="logger#update_formatter_config-2">
<c>logger:update_formatter_config/2</c></seealso></item>
</list>
</desc>
</func>
<func>
- <name name="format" arity="2"/>
+ <name name="format" arity="2" since="OTP 21.0"/>
<fsummary>Formats the given message.</fsummary>
<desc>
<p>This the formatter callback function to be called from
diff --git a/lib/kernel/doc/src/logger_std_h.xml b/lib/kernel/doc/src/logger_std_h.xml
index b526ed037d..5ed1a2f210 100644
--- a/lib/kernel/doc/src/logger_std_h.xml
+++ b/lib/kernel/doc/src/logger_std_h.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>logger_std_h.xml</file>
</header>
- <module>logger_std_h</module>
+ <module since="OTP 21.0">logger_std_h</module>
<modulesummary>Standard handler for Logger.</modulesummary>
<description>
@@ -55,30 +55,116 @@
is stored in a sub map with the key <c>config</c>, and can contain the
following parameters:</p>
<taglist>
- <tag><marker id="type"/><c>type</c></tag>
+ <tag><marker id="type"/><c>type = standard_io | standard_error | file</c></tag>
<item>
- <p>This has the value <c>standard_io</c>, <c>standard_error</c>,
- <c>{file,LogFileName}</c>, or <c>{file,LogFileName,LogFileOpts}</c>.</p>
- <p> Defaults to <c>standard_io</c>.</p>
- <p>It is recommended not to specify <c>LogFileOpts</c> unless absolutely
- necessary. The default options used by the handler to open a file for logging are
- <c>raw</c>, <c>append</c>, and <c>delayed_write</c>. Notice that the standard
- handler does not have support for circular logging. Use the disk_log handler,
- <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>,
- for this.</p>
+ <p>Specifies the log destination.</p>
+ <p>The value is set when the handler is added, and it can not
+ be changed in runtime.</p>
+ <p>Defaults to <c>standard_io</c>, unless
+ parameter <seealso marker="#file"><c>file</c></seealso> is
+ given, in which case it defaults to <c>file</c>.</p>
</item>
- <tag><c>filesync_repeat_interval</c></tag>
+ <tag><marker id="file"/><c>file = </c><seealso marker="file#type-filename"><c>file:filename()</c></seealso></tag>
+ <item>
+ <p>This specifies the name of the log file when the handler is
+ of type <c>file</c>.</p>
+ <p>The value is set when the handler is added, and it can not
+ be changed in runtime.</p>
+ <p>Defaults to the same name as the handler identity, in the
+ current directory.</p>
+ </item>
+ <tag><marker id="modes"/><c>modes = [</c><seealso marker="file#type-mode"><c>file:mode()</c></seealso><c>]</c></tag>
+ <item>
+ <p>This specifies the file modes to use when opening the log
+ file,
+ see <seealso marker="file#open-2"><c>file:open/2</c></seealso>.
+ If <c>modes</c> are not specified, the default list used
+ is <c>[raw,append,delayed_write]</c>. If <c>modes</c> are
+ specified, the list replaces the default modes list with the
+ following adjustments:</p>
+ <list>
+ <item>
+ If <c>raw</c> is not found in the list, it is added.
+ </item>
+ <item>
+ If none of <c>write</c>, <c>append</c> or <c>exclusive</c> is
+ found in the list, <c>append</c> is added.</item>
+ <item>If none of <c>delayed_write</c>
+ or <c>{delayed_write,Size,Delay}</c> is found in the
+ list, <c>delayed_write</c> is added.</item>
+ </list>
+ <p>Log files are always UTF-8 encoded. The encoding can not be
+ changed by setting the mode <c>{encoding,Encoding}</c>.</p>
+ <p>The value is set when the handler is added, and it can not
+ be changed in runtime.</p>
+ <p>Defaults to <c>[raw,append,delayed_write]</c>.</p>
+ </item>
+ <tag><marker id="max_no_bytes"/><c>max_no_bytes = pos_integer() | infinity</c></tag>
+ <item>
+ <p>This parameter specifies if the log file should be rotated
+ or not. The value <c>infinity</c> means the log file will
+ grow indefinitely, while an integer value specifies at which
+ file size (bytes) the file is rotated.</p>
+ <p>Defaults to <c>infinity</c>.</p>
+ </item>
+ <tag><marker id="max_no_files"/><c>max_no_files = non_neg_integer()</c></tag>
+ <item>
+ <p>This parameter specifies the number of rotated log file
+ archives to keep. This has meaning only
+ if <seealso marker="#max_no_bytes"><c>max_no_bytes</c></seealso>
+ is set to an integer value.</p>
+ <p>The log archives are
+ named <c>FileName.0</c>, <c>FileName.1</c>,
+ ... <c>FileName.N</c>, where <c>FileName</c> is the name of
+ the current log file. <c>FileName.0</c> is the newest of the
+ archives. The maximum value for <c>N</c> is the value
+ of <c>max_no_files</c> minus 1.</p>
+ <p>Notice that setting this value to <c>0</c> does not turn of
+ rotation. It only specifies that no archives are kept.</p>
+ <p>Defaults to <c>0</c>.</p>
+ </item>
+ <tag><marker id="compress_on_rotate"/><c>compress_on_rotate = boolean()</c></tag>
+ <item>
+ <p>This parameter specifies if the rotated log file archives
+ shall be compressed or not. If set to <c>true</c>, all
+ archives are compressed with <c>gzip</c>, and renamed
+ to <c>FileName.N.gz</c></p>
+ <p><c>compress_on_rotate</c> has no meaning if <seealso
+ marker="#max_no_bytes"><c>max_no_bytes</c></seealso> has the
+ value <c>infinity</c>.</p>
+ <p>Defaults to <c>false</c>.</p>
+ </item>
+ <tag><marker id="file_check"/><c>file_check = non_neg_integer()</c></tag>
+ <item>
+ <p>When <c>logger_std_h</c> logs to a file, it reads the file
+ information of the log file prior to each write
+ operation. This is to make sure the file still exists and
+ has the same inode as when it was opened. This implies some
+ performance loss, but ensures that no log events are lost in
+ the case when the file has been removed or renamed by an
+ external actor.</p>
+ <p>In order to allow minimizing the performance loss, the
+ <c>file_check</c> parameter can be set to a positive integer
+ value, <c>N</c>. The handler will then skip reading the file
+ information prior to writing, as long as no more
+ than <c>N</c> milliseconds have passed since it was last
+ read.</p>
+ <p>Notice that the risk of loosing log events grows when
+ the <c>file_check</c> value grows.</p>
+ <p>Defaults to 0.</p>
+ </item>
+ <tag><c>filesync_repeat_interval = pos_integer() | no_repeat</c></tag>
<item>
<p>This value, in milliseconds, specifies how often the handler does
a file sync operation to write buffered data to disk. The handler attempts
the operation repeatedly, but only performs a new sync if something has
actually been logged.</p>
- <p>Defaults to <c>5000</c> milliseconds.</p>
<p>If <c>no_repeat</c> is set as value, the repeated file sync operation
is disabled, and it is the operating system settings that determine
how quickly or slowly data is written to disk. The user can also call
the <seealso marker="logger_std_h#filesync-1"><c>filesync/1</c></seealso>
function to perform a file sync.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
</item>
</taglist>
<p>Other configuration parameters exist, to be used for customizing
@@ -86,12 +172,13 @@
standard handler and the disk_log handler, and are documented in the
<seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
</seealso>.</p>
- <p>Notice that if changing the configuration of the handler in runtime,
- the <c>type</c> parameter must not be modified.</p>
+ <p>Notice that if changing the configuration of the handler in
+ runtime, the <c>type</c>, <c>file</c>, or <c>modes</c> parameters
+ must not be modified.</p>
<p>Example of adding a standard handler:</p>
<code type="none">
logger:add_handler(my_standard_h, logger_std_h,
- #{config => #{type => {file,"./system_info.log"},
+ #{config => #{file => "./system_info.log",
filesync_repeat_interval => 1000}}).
</code>
<p>To set the default handler, that starts initially with
@@ -99,7 +186,7 @@ logger:add_handler(my_standard_h, logger_std_h,
change the Kernel default logger configuration. Example:</p>
<code type="none">
erl -kernel logger '[{handler,default,logger_std_h,
- #{config => #{type => {file,"./log.log"}}}}]'
+ #{config => #{file => "./log.log"}}}]'
</code>
<p>An example of how to replace the standard handler with a disk_log handler
at startup is found in the
@@ -110,7 +197,7 @@ erl -kernel logger '[{handler,default,logger_std_h,
<funcs>
<func>
- <name name="filesync" arity="1" clause_i="1"/>
+ <name name="filesync" arity="1" clause_i="1" since="OTP 21.0"/>
<fsummary>Writes buffered data to disk.</fsummary>
<desc>
<p>Write buffered data to disk.</p>
diff --git a/lib/kernel/doc/src/net_adm.xml b/lib/kernel/doc/src/net_adm.xml
index 6957a3b5e4..c3e1619f1b 100644
--- a/lib/kernel/doc/src/net_adm.xml
+++ b/lib/kernel/doc/src/net_adm.xml
@@ -28,7 +28,7 @@
<date>1996-09-10</date>
<rev>A</rev>
</header>
- <module>net_adm</module>
+ <module since="">net_adm</module>
<modulesummary>Various Erlang net administration routines.</modulesummary>
<description>
<p>This module contains various network utility functions.</p>
@@ -36,7 +36,7 @@
<funcs>
<func>
- <name name="dns_hostname" arity="1"/>
+ <name name="dns_hostname" arity="1" since=""/>
<fsummary>Official name of a host.</fsummary>
<desc>
<p>Returns the official name of <c><anno>Host</anno></c>, or
@@ -46,7 +46,7 @@
</func>
<func>
- <name name="host_file" arity="0"/>
+ <name name="host_file" arity="0" since=""/>
<fsummary>Read file <c>.hosts.erlang</c>.</fsummary>
<desc>
<p>Reads file <c>.hosts.erlang</c>, see section
@@ -58,7 +58,7 @@
</func>
<func>
- <name name="localhost" arity="0"/>
+ <name name="localhost" arity="0" since=""/>
<fsummary>Name of the local host.</fsummary>
<desc>
<p>Returns the name of the local host. If Erlang was started
@@ -68,8 +68,8 @@
</func>
<func>
- <name name="names" arity="0"/>
- <name name="names" arity="1"/>
+ <name name="names" arity="0" since=""/>
+ <name name="names" arity="1" since=""/>
<fsummary>Names of Erlang nodes at a host.</fsummary>
<desc>
<p>Similar to <c>epmd -names</c>, see
@@ -86,7 +86,7 @@
</func>
<func>
- <name name="ping" arity="1"/>
+ <name name="ping" arity="1" since=""/>
<fsummary>Set up a connection to a node.</fsummary>
<desc>
<p>Sets up a connection to <c><anno>Node</anno></c>. Returns
@@ -95,8 +95,8 @@
</func>
<func>
- <name name="world" arity="0"/>
- <name name="world" arity="1"/>
+ <name name="world" arity="0" since=""/>
+ <name name="world" arity="1" since=""/>
<fsummary>Lookup and connect to all nodes at all hosts in
<c>.hosts.erlang</c>.</fsummary>
<type name="verbosity"/>
@@ -117,8 +117,8 @@
</func>
<func>
- <name name="world_list" arity="1"/>
- <name name="world_list" arity="2"/>
+ <name name="world_list" arity="1" since=""/>
+ <name name="world_list" arity="2" since=""/>
<fsummary>Lookup and connect to all nodes at specified hosts.</fsummary>
<type name="verbosity"/>
<desc>
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index a30d28d55a..419d3cad84 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -28,7 +28,7 @@
<date>1996-09-10</date>
<rev>A</rev>
</header>
- <module>net_kernel</module>
+ <module since="">net_kernel</module>
<modulesummary>Erlang networking kernel.</modulesummary>
<description>
<p>The net kernel is a system process, registered as
@@ -81,7 +81,7 @@ $ <input>erl -sname foobar</input></pre>
<funcs>
<func>
- <name name="allow" arity="1"/>
+ <name name="allow" arity="1" since=""/>
<fsummary>Permit access to a specified set of nodes</fsummary>
<desc>
<p>Permits access to the specified set of nodes.</p>
@@ -98,17 +98,19 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
- <name name="connect_node" arity="1"/>
+ <name name="connect_node" arity="1" since=""/>
<fsummary>Establish a connection to a node.</fsummary>
<desc>
<p>Establishes a connection to <c><anno>Node</anno></c>. Returns
- <c>true</c> if successful, <c>false</c> if not, and <c>ignored</c>
- if the local node is not alive.</p>
+ <c>true</c> if a connection was established or was already
+ established or if <c><anno>Node</anno></c> is the local node
+ itself. Returns <c>false</c> if the connection attempt failed, and
+ <c>ignored</c> if the local node is not alive.</p>
</desc>
</func>
<func>
- <name name="get_net_ticktime" arity="0"/>
+ <name name="get_net_ticktime" arity="0" since=""/>
<fsummary>Get <c>net_ticktime</c>.</fsummary>
<desc>
<p>Gets <c>net_ticktime</c> (see
@@ -129,7 +131,7 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
- <name name="getopts" arity="2"/>
+ <name name="getopts" arity="2" since="OTP 19.1"/>
<fsummary>Get distribution socket options.</fsummary>
<desc>
<p>Get one or more options for the distribution socket
@@ -144,8 +146,8 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
- <name name="monitor_nodes" arity="1"/>
- <name name="monitor_nodes" arity="2"/>
+ <name name="monitor_nodes" arity="1" since=""/>
+ <name name="monitor_nodes" arity="2" since=""/>
<fsummary>Subscribe to node status change messages.</fsummary>
<desc>
<p>The calling process subscribes or unsubscribes to node
@@ -265,8 +267,8 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
- <name name="set_net_ticktime" arity="1"/>
- <name name="set_net_ticktime" arity="2"/>
+ <name name="set_net_ticktime" arity="1" since=""/>
+ <name name="set_net_ticktime" arity="2" since=""/>
<fsummary>Set <c>net_ticktime</c>.</fsummary>
<desc>
<p>Sets <c>net_ticktime</c> (see
@@ -322,7 +324,7 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
- <name name="setopts" arity="2"/>
+ <name name="setopts" arity="2" since="OTP 19.1"/>
<fsummary>Set distribution socket options.</fsummary>
<desc>
<p>Set one or more options for distribution sockets.
@@ -343,9 +345,9 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
- <name>start([Name]) -> {ok, pid()} | {error, Reason}</name>
- <name>start([Name, NameType]) -> {ok, pid()} | {error, Reason}</name>
- <name>start([Name, NameType, Ticktime]) -> {ok, pid()} | {error, Reason}</name>
+ <name since="">start([Name]) -> {ok, pid()} | {error, Reason}</name>
+ <name since="">start([Name, NameType]) -> {ok, pid()} | {error, Reason}</name>
+ <name since="">start([Name, NameType, Ticktime]) -> {ok, pid()} | {error, Reason}</name>
<fsummary>Turn an Erlang runtime system into a distributed node.</fsummary>
<type>
<v>Name = atom()</v>
@@ -362,7 +364,7 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
- <name name="stop" arity="0"/>
+ <name name="stop" arity="0" since=""/>
<fsummary>Turn a node into a non-distributed Erlang runtime system.</fsummary>
<desc>
<p>Turns a distributed node into a non-distributed node. For
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index e1ef8ab387..61bd598145 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -31,6 +31,458 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 6.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a performance regression when reading files
+ opened with the <c>compressed</c> flag.</p>
+ <p>
+ Own Id: OTP-15706 Aux Id: ERIERL-336 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If for example the <c>/etc/hosts</c> did not come into
+ existence until after the kernel application had started,
+ its content was never read. This bug has now been
+ corrected.</p>
+ <p>
+ Own Id: OTP-14702 Aux Id: PR-2066 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug where doing <c>seq_trace:reset_trace()</c> while
+ another process was doing a garbage collection could
+ cause the run-time system to segfault.</p>
+ <p>
+ Own Id: OTP-15490</p>
+ </item>
+ <item>
+ <p>
+ Fix <c>erl_epmd:port_please</c> spec to include
+ <c>atom()</c> and <c>string()</c>.</p>
+ <p>
+ Own Id: OTP-15557 Aux Id: PR-2117 </p>
+ </item>
+ <item>
+ <p>
+ The Logger handler logger_std_h now keeps track of the
+ inode of its log file in order to re-open the file if the
+ inode changes. This may happen, for instance, if the log
+ file is opened and saved by an editor.</p>
+ <p>
+ Own Id: OTP-15578 Aux Id: ERL-850 </p>
+ </item>
+ <item>
+ <p>
+ When user specific file modes are given to the logger
+ handler <c>logger_std_h</c>, they were earlier accepted
+ without any control. This is now changes, so Logger will
+ adjust the file modes as follows:</p>
+ <p>
+ - If <c>raw</c> is not found in the list, it is
+ added.<br/> - If none of <c>write</c>, <c>append</c> or
+ <c>exclusive</c> are found in the list, <c>append</c> is
+ added.<br/> - If none of <c>delayed_write</c> or
+ <c>{delayed_write,Size,Delay}</c> are found in the list,
+ <c>delayed_write</c> is added.</p>
+ <p>
+ Own Id: OTP-15602</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The standard logger handler, <c>logger_std_h</c>, now has
+ a new internal feature for log rotation. The rotation
+ scheme is as follows:</p>
+ <p>
+ The log file to which the handler currently writes always
+ has the same name, i.e. the name which is configured for
+ the handler. The archived files have the same name, but
+ with extension ".N", where N is an integer. The newest
+ archive has extension ".0", and the oldest archive has
+ the highest number. </p>
+ <p>
+ The size at which the log file is rotated, and the number
+ of archive files that are kept, is specified with the
+ handler specific configuration parameters
+ <c>max_no_bytes</c> and <c>max_no_files</c> respectively. </p>
+ <p>
+ Archives can be compressed, in which case they get a
+ ".gz" file extension after the integer. Compression is
+ specified with the handler specific configuration
+ parameter <c>compress_on_rotate</c>.</p>
+ <p>
+ Own Id: OTP-15479</p>
+ </item>
+ <item>
+ <p>
+ The new functions <c>logger:i/0</c> and <c>logger:i/1</c>
+ are added. These provide the same information as
+ <c>logger:get_config/0</c> and other
+ <c>logger:get_*_config</c> functions, but the information
+ is more logically sorted and more readable.</p>
+ <p>
+ Own Id: OTP-15600</p>
+ </item>
+ <item>
+ <p>
+ Logger is now protected against overload due to massive
+ amounts of log events from the emulator or from remote
+ nodes.</p>
+ <p>
+ Own Id: OTP-15601</p>
+ </item>
+ <item>
+ <p>
+ Logger now uses os:system_time/1 instead of
+ erlang:system_time/1 to generate log event timestamps.</p>
+ <p>
+ Own Id: OTP-15625</p>
+ </item>
+ <item>
+ <p>
+ Add functions <c>application:set_env/1,2</c> and
+ <c>application:set_env/2</c>. These take a list of
+ application configuration parameters, and the behaviour
+ is equivalent to calling <c>application:set_env/4</c>
+ individually for each application/key combination, except
+ it is more efficient.</p>
+ <p>
+ <c>set_env/1,2</c> warns about duplicated applications or
+ keys. The warning is also emitted during boot, if
+ applications or keys are duplicated within one
+ configuration file, e.g. sys.config.</p>
+ <p>
+ Own Id: OTP-15642 Aux Id: PR-2164 </p>
+ </item>
+ <item>
+ <p>
+ Handler specific configuration parameters for the
+ standard handler <c>logger_std_h</c> are changed to be
+ more intuitive and more similar to the disk_log handler.</p>
+ <p>
+ Earlier there was only one parameter, <c>type</c>, which
+ could have the values <c>standard_io</c>,
+ <c>standard_error</c>, <c>{file,FileName}</c> or
+ <c>{file,FileName,Modes}</c>.</p>
+ <p>
+ This is now changed, so the following parameters are
+ allowed:</p>
+ <p>
+ <c>type = standard_io | standard_error | file</c><br/>
+ <c>file = file:filename()</c><br/> <c>modes =
+ [file:mode()]</c></p>
+ <p>
+ All parameters are optional. <c>type</c> defaults to
+ <c>standard_io</c>, unless a file name is given, in which
+ case it defaults to <c>file</c>. If <c>type</c> is set to
+ <c>file</c>, the file name defaults to the same as the
+ handler id.</p>
+ <p>
+ The potential incompatibility is that
+ <c>logger:get_config/0</c> and
+ <c>logger:get_handler_config/1</c> now returns the new
+ parameters, even if the configuration was set with the
+ old variant, e.g. <c>#{type=>{file,FileName}}</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15662</p>
+ </item>
+ <item>
+ <p>
+ The new configuration parameter <c>file_check</c> is
+ added to the Logger handler <c>logger_std_h</c>. This
+ parameter specifies how long (in milliseconds) the
+ handler may wait before checking if the log file still
+ exists and the inode is the same as when it was opened.</p>
+ <p>
+ The default value is 0, which means that this check is
+ done prior to each write operation. Setting a higher
+ number may improve performance, but adds the risk of
+ loosing log events.</p>
+ <p>
+ Own Id: OTP-15663</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Setting the <c>recbuf</c> size of an inet socket the
+ <c>buffer</c> is also automatically increased. Fix a bug
+ where the auto adjustment of inet buffer size would be
+ triggered even if an explicit inet buffer size had
+ already been set.</p>
+ <p>
+ Own Id: OTP-15651 Aux Id: ERIERL-304 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A new function, <c>logger:update_handler_config/3</c> is
+ added, and the handler callback <c>changing_config</c>
+ now has a new argument, <c>SetOrUpdate</c>, which
+ indicates if the configuration change comes from
+ <c>set_handler_config/2,3</c> or
+ <c>update_handler_config/2,3</c>.</p>
+ <p>
+ This allows the handler to consistently merge the new
+ configuration with the old (if the change comes from
+ <c>update_handler_config/2,3</c>) or with the default (if
+ the change comes from <c>set_handler_config/2,3</c>).</p>
+ <p>
+ The built-in handlers <c>logger_std_h</c> and
+ <c>logger_disk_log_h</c> are updated accordingly. A bug
+ which could cause inconsistency between the handlers'
+ internal state and the stored configuration is also
+ corrected.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15364</p>
+ </item>
+ <item>
+ <p>
+ Fix fallback when custom erl_epmd client does not
+ implement address_please.</p>
+ <p>
+ Own Id: OTP-15388 Aux Id: PR-1983 </p>
+ </item>
+ <item>
+ <p>
+ The logger ets table did not have the
+ <c>read_concurrency</c> option. This is now added.</p>
+ <p>
+ Own Id: OTP-15453 Aux Id: ERL-782 </p>
+ </item>
+ <item>
+ <p>
+ During system start, logger has a simple handler which
+ prints to stdout. After the kernel supervision is
+ started, this handler is removed and replaced by the
+ default handler. Due to a bug, logger earlier issued a
+ debug printout saying it received an unexpected message,
+ which was the EXIT message from the simple handler's
+ process. This is now corrected. The simple handler's
+ process now unlinks from the logger process before
+ terminating.</p>
+ <p>
+ Own Id: OTP-15466 Aux Id: ERL-788 </p>
+ </item>
+ <item>
+ <p>
+ The logger handler <c>logger_std_h</c> would not
+ re-create it's log file if it was removed. Due to this it
+ could not be used with tools like 'logrotate'. This is
+ now corrected.</p>
+ <p>
+ Own Id: OTP-15469</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A function <c>inet:getifaddrs/1</c> that takes a list
+ with a namespace option has been added, for platforms
+ that support that feature, for example Linux (only?).</p>
+ <p>
+ Own Id: OTP-15121 Aux Id: ERIERL-189, PR-1974 </p>
+ </item>
+ <item>
+ <p>Added the <c>nopush</c> option for TCP sockets, which
+ corresponds to <c>TCP_NOPUSH</c> on *BSD and
+ <c>TCP_CORK</c> on Linux.</p>
+ <p>This is also used internally in <c>file:sendfile</c>
+ to reduce latency on subsequent send operations.</p>
+ <p>
+ Own Id: OTP-15357 Aux Id: ERL-698 </p>
+ </item>
+ <item>
+ <p>
+ Optimize handling of send_delay for tcp sockes to better
+ work with the new pollthread implementation introduced in
+ OTP-21.</p>
+ <p>
+ Own Id: OTP-15471 Aux Id: ERIERL-229 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug causing net_kernel process crash on connection
+ attempt from node with name identical to local node.</p>
+ <p>
+ Own Id: OTP-15438 Aux Id: ERL-781 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The values <c>all</c> and <c>none</c> are documented as
+ valid value for the Kernel configuration parameter
+ <c>logger_level</c>, but would cause a crash during node
+ start. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15143</p>
+ </item>
+ <item>
+ <p>
+ Fix some potential buggy behavior in how ticks are sent
+ on inter node distribution connections. Tick is now sent
+ to c-node even if there are unsent buffered data, as
+ c-nodes need ticks in order to send reply ticks. The
+ amount of sent data was also calculated wrongly when
+ ticks were suppressed due to unsent buffered data.</p>
+ <p>
+ Own Id: OTP-15162 Aux Id: ERIERL-191 </p>
+ </item>
+ <item>
+ <p>
+ Non semantic change in dist_util.erl to silence dialyzer
+ warning.</p>
+ <p>
+ Own Id: OTP-15170</p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>net_kernel:connect_node(node())</c> to return
+ <c>true</c> (and do nothing) as it always has before
+ OTP-21.0. Also documented this successful "self connect"
+ as the expected behavior.</p>
+ <p>
+ Own Id: OTP-15182 Aux Id: ERL-643 </p>
+ </item>
+ <item>
+ <p>
+ The single_line option on logger_formatter would in some
+ cases add an unwanted comma after the association arrows
+ in a map. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15228</p>
+ </item>
+ <item>
+ <p>
+ Improved robustness of distribution connection setup. In
+ OTP-21.0 a truly asynchronous connection setup was
+ introduced. This is further improvement on that work to
+ make the emulator more robust and also be able to recover
+ in cases when involved Erlang processes misbehave.</p>
+ <p>
+ Own Id: OTP-15297 Aux Id: OTP-15279, OTP-15280 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new macro, <c>?LOG(Level,...)</c>, is added. This is
+ equivalent to the existing <c>?LOG_&lt;LEVEL&gt;(...)</c>
+ macros.</p>
+ <p>
+ A new variant of Logger report callback is added, which
+ takes an extra argument containing options for size
+ limiting and line breaks. Module <c>proc_lib</c> in
+ <c>STDLIB</c> uses this for crash reports.</p>
+ <p>
+ Logger configuration is now checked a bit more for
+ errors.</p>
+ <p>
+ Own Id: OTP-15132</p>
+ </item>
+ <item>
+ <p>
+ The socket options <c>recvtos</c>, <c>recvttl</c>,
+ <c>recvtclass</c> and <c>pktoptions</c> have been
+ implemented in the socket modules. See the documentation
+ for the <c>gen_tcp</c>, <c>gen_udp</c> and <c>inet</c>
+ modules. Note that support for these in the runtime
+ system is platform dependent. Especially for
+ <c>pktoptions</c> which is very Linux specific and
+ obsoleted by the RFCs that defined it.</p>
+ <p>
+ Own Id: OTP-15145 Aux Id: ERIERL-187 </p>
+ </item>
+ <item>
+ <p>
+ Add <c>logger:set_application_level/2</c> for setting the
+ logger level of all modules in one application.</p>
+ <p>
+ Own Id: OTP-15146</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed bug in <c>net_kernel</c> that could cause an
+ emulator crash if certain connection attempts failed. Bug
+ exists since kernel-6.0 (OTP-21.0).</p>
+ <p>
+ Own Id: OTP-15280 Aux Id: ERIERL-226, OTP-15279 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 6.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -314,6 +766,42 @@
</section>
+<section><title>Kernel 5.4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Non semantic change in dist_util.erl to silence dialyzer
+ warning.</p>
+ <p>
+ Own Id: OTP-15170</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix some potential buggy behavior in how ticks are sent
+ on inter node distribution connections. Tick is now sent
+ to c-node even if there are unsent buffered data, as
+ c-nodes need ticks in order to send reply ticks. The
+ amount of sent data was calculated wrongly when ticks
+ where suppressed due to unsent buffered data.</p>
+ <p>
+ Own Id: OTP-15162 Aux Id: ERIERL-191 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 5.4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index c95e615c6b..0500e4cfb3 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>os</module>
+ <module since="">os</module>
<modulesummary>Operating system-specific functions.</modulesummary>
<description>
<p>The functions in this module are operating system-specific.
@@ -134,8 +134,8 @@
<funcs>
<func>
- <name name="cmd" arity="1"/>
- <name name="cmd" arity="2"/>
+ <name name="cmd" arity="1" since=""/>
+ <name name="cmd" arity="2" since="OTP 20.2.3"/>
<fsummary>Execute a command in a shell of the target OS.</fsummary>
<desc>
<p>Executes <c><anno>Command</anno></c> in a command shell of the
@@ -173,8 +173,8 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="find_executable" arity="1"/>
- <name name="find_executable" arity="2"/>
+ <name name="find_executable" arity="1" since=""/>
+ <name name="find_executable" arity="2" since=""/>
<fsummary>Absolute filename of a program.</fsummary>
<desc>
<p>These two functions look up an executable program, with the
@@ -190,7 +190,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="getenv" arity="0"/>
+ <name name="getenv" arity="0" since=""/>
<fsummary>List all environment variables.</fsummary>
<desc>
<p>Returns a list of all environment variables.
@@ -205,7 +205,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="getenv" arity="1"/>
+ <name name="getenv" arity="1" since=""/>
<fsummary>Get the value of an environment variable.</fsummary>
<desc>
<p>Returns the <c><anno>Value</anno></c> of the environment variable
@@ -220,7 +220,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="getenv" arity="2"/>
+ <name name="getenv" arity="2" since="OTP 18.0"/>
<fsummary>Get the value of an environment variable.</fsummary>
<desc>
<p>Returns the <c><anno>Value</anno></c> of the environment variable
@@ -235,7 +235,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="getpid" arity="0"/>
+ <name name="getpid" arity="0" since=""/>
<fsummary>Return the process identifier of the emulator
process.</fsummary>
<desc>
@@ -251,7 +251,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="putenv" arity="2"/>
+ <name name="putenv" arity="2" since=""/>
<fsummary>Set a new value for an environment variable.</fsummary>
<desc>
<p>Sets a new <c><anno>Value</anno></c> for environment variable
@@ -277,7 +277,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="set_signal" arity="2"/>
+ <name name="set_signal" arity="2" since="OTP 20.0"/>
<fsummary>Enables or disables handling of OS signals.</fsummary>
<desc>
<p>Enables or disables OS signals.</p>
@@ -304,7 +304,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="system_time" arity="0"/>
+ <name name="system_time" arity="0" since="OTP 18.0"/>
<fsummary>Current OS system time.</fsummary>
<desc>
<p>Returns the current
@@ -317,7 +317,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="system_time" arity="1"/>
+ <name name="system_time" arity="1" since="OTP 18.0"/>
<fsummary>Current OS system time.</fsummary>
<desc>
<p>Returns the current
@@ -332,7 +332,7 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</func>
<func>
- <name name="timestamp" arity="0"/>
+ <name name="timestamp" arity="0" since=""/>
<fsummary>Current OS system time on the <c>erlang:timestamp/0</c> format.</fsummary>
<type_desc variable="Timestamp">Timestamp = {MegaSecs, Secs, MicroSecs}</type_desc>
<desc>
@@ -373,7 +373,7 @@ calendar:now_to_universal_time(TS),
</func>
<func>
- <name name="perf_counter" arity="0"/>
+ <name name="perf_counter" arity="0" since="OTP 19.0"/>
<fsummary>Returns a performance counter</fsummary>
<desc>
<p>Returns the current performance counter value in <c>perf_counter</c>
@@ -383,7 +383,7 @@ calendar:now_to_universal_time(TS),
</desc>
</func>
<func>
- <name name="perf_counter" arity="1"/>
+ <name name="perf_counter" arity="1" since="OTP 19.0"/>
<fsummary>Returns a performance counter</fsummary>
<desc><p>Returns a performance counter that can be used as a very fast and
high resolution timestamp. This counter is read directly from the hardware or operating
@@ -397,7 +397,7 @@ calendar:now_to_universal_time(TS),
</desc>
</func>
<func>
- <name name="type" arity="0"/>
+ <name name="type" arity="0" since=""/>
<fsummary>Return the OS family and, in some cases, the OS name of the
current OS.</fsummary>
<desc>
@@ -417,7 +417,7 @@ calendar:now_to_universal_time(TS),
</func>
<func>
- <name name="unsetenv" arity="1"/>
+ <name name="unsetenv" arity="1" since="OTP R16B03"/>
<fsummary>Delete an environment variable.</fsummary>
<desc>
<p>Deletes the environment variable <c><anno>VarName</anno></c>.</p>
@@ -429,7 +429,7 @@ calendar:now_to_universal_time(TS),
</func>
<func>
- <name name="version" arity="0"/>
+ <name name="version" arity="0" since=""/>
<fsummary>Return the OS versions.</fsummary>
<desc>
<p>Returns the OS version.
diff --git a/lib/kernel/doc/src/pg2.xml b/lib/kernel/doc/src/pg2.xml
index 0631b317b4..058d711756 100644
--- a/lib/kernel/doc/src/pg2.xml
+++ b/lib/kernel/doc/src/pg2.xml
@@ -32,7 +32,7 @@
<rev>A2</rev>
<file>pg2.xml</file>
</header>
- <module>pg2</module>
+ <module since="">pg2</module>
<modulesummary>Distributed named process groups.</modulesummary>
<description>
<p>This module implements process groups. Each message can be sent
@@ -66,7 +66,7 @@
<funcs>
<func>
- <name name="create" arity="1"/>
+ <name name="create" arity="1" since=""/>
<fsummary>Create a new, empty process group.</fsummary>
<desc>
<p>Creates a new, empty process group. The group is globally
@@ -75,7 +75,7 @@
</func>
<func>
- <name name="delete" arity="1"/>
+ <name name="delete" arity="1" since=""/>
<fsummary>Delete a process group.</fsummary>
<desc>
<p>Deletes a process group.</p>
@@ -83,7 +83,7 @@
</func>
<func>
- <name name="get_closest_pid" arity="1"/>
+ <name name="get_closest_pid" arity="1" since=""/>
<fsummary>Common dispatch function.</fsummary>
<desc>
<p>A useful dispatch function that can be used from
@@ -93,7 +93,7 @@
</func>
<func>
- <name name="get_local_members" arity="1"/>
+ <name name="get_local_members" arity="1" since=""/>
<fsummary>Return all local processes in a group.</fsummary>
<desc>
<p>Returns all processes running on the local node in the
@@ -104,7 +104,7 @@
</func>
<func>
- <name name="get_members" arity="1"/>
+ <name name="get_members" arity="1" since=""/>
<fsummary>Return all processes in a group.</fsummary>
<desc>
<p>Returns all processes in the group <c>Name</c>. This
@@ -114,7 +114,7 @@
</func>
<func>
- <name name="join" arity="2"/>
+ <name name="join" arity="2" since=""/>
<fsummary>Join a process to a group.</fsummary>
<desc>
<p>Joins the process <c>Pid</c> to the group <c>Name</c>.
@@ -124,7 +124,7 @@
</func>
<func>
- <name name="leave" arity="2"/>
+ <name name="leave" arity="2" since=""/>
<fsummary>Make a process leave a group.</fsummary>
<desc>
<p>Makes the process <c>Pid</c> leave the group <c>Name</c>.
@@ -134,8 +134,8 @@
</func>
<func>
- <name name="start" arity="0"/>
- <name name="start_link" arity="0"/>
+ <name name="start" arity="0" since=""/>
+ <name name="start_link" arity="0" since=""/>
<fsummary>Start the <c>pg2</c> server.</fsummary>
<desc>
<p>Starts the <c>pg2</c> server. Normally, the server does not need
@@ -149,7 +149,7 @@
</func>
<func>
- <name name="which_groups" arity="0"/>
+ <name name="which_groups" arity="0" since=""/>
<fsummary>Return a list of all known groups.</fsummary>
<desc>
<p>Returns a list of all known groups.</p>
diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml
index fab616e630..c55454506e 100644
--- a/lib/kernel/doc/src/rpc.xml
+++ b/lib/kernel/doc/src/rpc.xml
@@ -28,7 +28,7 @@
<date>1996-09-10</date>
<rev>A</rev>
</header>
- <module>rpc</module>
+ <module since="">rpc</module>
<modulesummary>Remote Procedure Call services.</modulesummary>
<description>
<p>This module contains services similar to Remote
@@ -51,7 +51,7 @@
<funcs>
<func>
- <name name="abcast" arity="2"/>
+ <name name="abcast" arity="2" since=""/>
<fsummary>Broadcast a message asynchronously to a registered process on
all nodes.</fsummary>
<desc>
@@ -61,7 +61,7 @@
</func>
<func>
- <name name="abcast" arity="3"/>
+ <name name="abcast" arity="3" since=""/>
<fsummary>Broadcast a message asynchronously to a registered process on
specific nodes.</fsummary>
<desc>
@@ -72,7 +72,7 @@
</func>
<func>
- <name name="async_call" arity="4"/>
+ <name name="async_call" arity="4" since=""/>
<fsummary>Evaluate a function call on a node, asynchronous
version.</fsummary>
<desc>
@@ -98,7 +98,7 @@
</func>
<func>
- <name name="block_call" arity="4"/>
+ <name name="block_call" arity="4" since=""/>
<fsummary>Evaluate a function call on a node in the RPC server's
context.</fsummary>
<desc>
@@ -115,7 +115,7 @@
</func>
<func>
- <name name="block_call" arity="5"/>
+ <name name="block_call" arity="5" since=""/>
<fsummary>Evaluate a function call on a node in the RPC server's
context.</fsummary>
<desc>
@@ -127,7 +127,7 @@
</func>
<func>
- <name name="call" arity="4"/>
+ <name name="call" arity="4" since=""/>
<fsummary>Evaluate a function call on a node.</fsummary>
<desc>
<p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
@@ -138,7 +138,7 @@
</func>
<func>
- <name name="call" arity="5"/>
+ <name name="call" arity="5" since=""/>
<fsummary>Evaluate a function call on a node.</fsummary>
<desc>
<p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
@@ -158,7 +158,7 @@
</func>
<func>
- <name name="cast" arity="4"/>
+ <name name="cast" arity="4" since=""/>
<fsummary>Run a function on a node ignoring the result.</fsummary>
<desc>
<p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
@@ -171,7 +171,7 @@
</func>
<func>
- <name name="eval_everywhere" arity="3"/>
+ <name name="eval_everywhere" arity="3" since=""/>
<fsummary>Run a function on all nodes, ignoring the result.</fsummary>
<desc>
<p>Equivalent to <c>eval_everywhere([node()|nodes()],
@@ -181,7 +181,7 @@
</func>
<func>
- <name name="eval_everywhere" arity="4"/>
+ <name name="eval_everywhere" arity="4" since=""/>
<fsummary>Run a function on specific nodes, ignoring the
result.</fsummary>
<desc>
@@ -192,7 +192,7 @@
</func>
<func>
- <name name="multi_server_call" arity="2"/>
+ <name name="multi_server_call" arity="2" since=""/>
<fsummary>Interact with the servers on a number of nodes.</fsummary>
<desc>
<p>Equivalent to <c>multi_server_call([node()|nodes()],
@@ -201,7 +201,7 @@
</func>
<func>
- <name name="multi_server_call" arity="3"/>
+ <name name="multi_server_call" arity="3" since=""/>
<fsummary>Interact with the servers on a number of nodes.</fsummary>
<desc>
<p>Can be used when interacting with servers called
@@ -224,7 +224,7 @@
</func>
<func>
- <name name="multicall" arity="3"/>
+ <name name="multicall" arity="3" since=""/>
<fsummary>Evaluate a function call on a number of nodes.</fsummary>
<desc>
<p>Equivalent to <c>multicall([node()|nodes()], <anno>Module</anno>,
@@ -233,7 +233,7 @@
</func>
<func>
- <name name="multicall" arity="4" clause_i="1"/>
+ <name name="multicall" arity="4" clause_i="1" since=""/>
<fsummary>Evaluate a function call on a number of nodes.</fsummary>
<desc>
<p>Equivalent to <c>multicall(<anno>Nodes</anno>, <anno>Module</anno>,
@@ -242,7 +242,7 @@
</func>
<func>
- <name name="multicall" arity="4" clause_i="2"/>
+ <name name="multicall" arity="4" clause_i="2" since=""/>
<fsummary>Evaluate a function call on a number of nodes.</fsummary>
<desc>
<p>Equivalent to <c>multicall([node()|nodes()], <anno>Module</anno>,
@@ -252,7 +252,7 @@
</func>
<func>
- <name name="multicall" arity="5"/>
+ <name name="multicall" arity="5" since=""/>
<fsummary>Evaluate a function call on a number of nodes.</fsummary>
<desc>
<p>In contrast to an RPC, a multicall is an RPC that is sent
@@ -288,7 +288,7 @@
</func>
<func>
- <name name="nb_yield" arity="1"/>
+ <name name="nb_yield" arity="1" since=""/>
<fsummary>Deliver the result of evaluating a function call on a node
(non-blocking).</fsummary>
<desc>
@@ -297,7 +297,7 @@
</func>
<func>
- <name name="nb_yield" arity="2"/>
+ <name name="nb_yield" arity="2" since=""/>
<fsummary>Deliver the result of evaluating a function call on a node
(non-blocking).</fsummary>
<desc>
@@ -315,7 +315,7 @@
</func>
<func>
- <name name="parallel_eval" arity="1"/>
+ <name name="parallel_eval" arity="1" since=""/>
<fsummary>Evaluate many function calls on all nodes in
parallel.</fsummary>
<desc>
@@ -328,7 +328,7 @@
</func>
<func>
- <name name="pinfo" arity="1"/>
+ <name name="pinfo" arity="1" since=""/>
<fsummary>Information about a process.</fsummary>
<desc>
<p>Location transparent version of the BIF
@@ -337,8 +337,8 @@
</func>
<func>
- <name name="pinfo" arity="2" clause_i="1"/>
- <name name="pinfo" arity="2" clause_i="2"/>
+ <name name="pinfo" arity="2" clause_i="1" since=""/>
+ <name name="pinfo" arity="2" clause_i="2" since=""/>
<fsummary>Information about a process.</fsummary>
<desc>
<p>Location transparent version of the BIF
@@ -347,7 +347,7 @@
</func>
<func>
- <name name="pmap" arity="3"/>
+ <name name="pmap" arity="3" since=""/>
<fsummary>Parallel evaluation of mapping a function over a
list.</fsummary>
<desc>
@@ -360,7 +360,7 @@
</func>
<func>
- <name name="sbcast" arity="2"/>
+ <name name="sbcast" arity="2" since=""/>
<fsummary>Broadcast a message synchronously to a registered process on
all nodes.</fsummary>
<desc>
@@ -370,7 +370,7 @@
</func>
<func>
- <name name="sbcast" arity="3"/>
+ <name name="sbcast" arity="3" since=""/>
<fsummary>Broadcast a message synchronously to a registered process on
specific nodes.</fsummary>
<desc>
@@ -391,7 +391,7 @@
</func>
<func>
- <name name="server_call" arity="4"/>
+ <name name="server_call" arity="4" since=""/>
<fsummary>Interact with a server on a node.</fsummary>
<desc>
<p>Can be used when interacting with a server called
@@ -410,7 +410,7 @@
</func>
<func>
- <name name="yield" arity="1"/>
+ <name name="yield" arity="1" since=""/>
<fsummary>Deliver the result of evaluating a function call on a node
(blocking).</fsummary>
<desc>
diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml
index 1a4a74419a..aa29223dd0 100644
--- a/lib/kernel/doc/src/seq_trace.xml
+++ b/lib/kernel/doc/src/seq_trace.xml
@@ -28,7 +28,7 @@
<date>1998-04-16</date>
<rev>A</rev>
</header>
- <module>seq_trace</module>
+ <module since="">seq_trace</module>
<modulesummary>Sequential tracing of messages.</modulesummary>
<description>
<p>Sequential tracing makes it possible to trace all messages
@@ -51,7 +51,7 @@
</datatypes>
<funcs>
<func>
- <name name="set_token" arity="1"/>
+ <name name="set_token" arity="1" since=""/>
<fsummary>Set the trace token</fsummary>
<desc>
<p>Sets the trace token for the calling process to <c><anno>Token</anno></c>.
@@ -71,7 +71,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="set_token" arity="2"/>
+ <name name="set_token" arity="2" since=""/>
<fsummary>Set a component of the trace token</fsummary>
<type name="component"/>
<type name="flag"/>
@@ -158,7 +158,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="get_token" arity="0"/>
+ <name name="get_token" arity="0" since=""/>
<fsummary>Return the value of the trace token</fsummary>
<desc>
<p>Returns the value of the trace token for the calling process.
@@ -169,7 +169,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="get_token" arity="1"/>
+ <name name="get_token" arity="1" since=""/>
<fsummary>Return the value of a trace token component</fsummary>
<type name="component"/>
<type name="flag"/>
@@ -182,7 +182,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="print" arity="1"/>
+ <name name="print" arity="1" since=""/>
<fsummary>Put the Erlang term <c>TraceInfo</c>into the sequential trace output</fsummary>
<desc>
<p>Puts the Erlang term <c><anno>TraceInfo</anno></c> into the sequential
@@ -192,7 +192,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="print" arity="2"/>
+ <name name="print" arity="2" since=""/>
<fsummary>Put the Erlang term <c>TraceInfo</c>into the sequential trace output</fsummary>
<desc>
<p>Same as <c>print/1</c> with the additional condition that
@@ -201,7 +201,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="reset_trace" arity="0"/>
+ <name name="reset_trace" arity="0" since=""/>
<fsummary>Stop all sequential tracing on the local node</fsummary>
<desc>
<p>Sets the trace token to empty for all processes on the
@@ -213,7 +213,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="set_system_tracer" arity="1"/>
+ <name name="set_system_tracer" arity="1" since=""/>
<fsummary>Set the system tracer</fsummary>
<type name="tracer"/>
<desc>
@@ -227,7 +227,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name name="get_system_tracer" arity="0"/>
+ <name name="get_system_tracer" arity="0" since=""/>
<fsummary>Return the pid() or port() of the current system tracer.</fsummary>
<type name="tracer"/>
<desc>
diff --git a/lib/kernel/doc/src/wrap_log_reader.xml b/lib/kernel/doc/src/wrap_log_reader.xml
index 7fb9c1c023..5f37e7ec5f 100644
--- a/lib/kernel/doc/src/wrap_log_reader.xml
+++ b/lib/kernel/doc/src/wrap_log_reader.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>wrap_log_reader.sgml</file>
</header>
- <module>wrap_log_reader</module>
+ <module since="">wrap_log_reader</module>
<modulesummary>A service to read internally formatted wrap disk logs.
</modulesummary>
<description>
@@ -65,8 +65,8 @@
<funcs>
<func>
- <name name="chunk" arity="1"/>
- <name name="chunk" arity="2"/>
+ <name name="chunk" arity="1" since=""/>
+ <name name="chunk" arity="2" since=""/>
<fsummary>Read a chunk of objects written to a wrap log.</fsummary>
<type name="chunk_ret"/>
<desc>
@@ -105,7 +105,7 @@
</func>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close a log.</fsummary>
<desc>
<p>Closes a log file properly.</p>
@@ -113,8 +113,8 @@
</func>
<func>
- <name name="open" arity="1"/>
- <name name="open" arity="2"/>
+ <name name="open" arity="1" since=""/>
+ <name name="open" arity="2" since=""/>
<fsummary>Open a log file.</fsummary>
<type name="open_ret"/>
<desc>
diff --git a/lib/kernel/include/logger.hrl b/lib/kernel/include/logger.hrl
index 2143ccd297..b09977e0f2 100644
--- a/lib/kernel/include/logger.hrl
+++ b/lib/kernel/include/logger.hrl
@@ -32,6 +32,10 @@
-define(LOG_DEBUG(A,B),?DO_LOG(debug,[A,B])).
-define(LOG_DEBUG(A,B,C),?DO_LOG(debug,[A,B,C])).
+-define(LOG(L,A),?DO_LOG(L,[A])).
+-define(LOG(L,A,B),?DO_LOG(L,[A,B])).
+-define(LOG(L,A,B,C),?DO_LOG(L,[A,B,C])).
+
-define(LOCATION,#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},
line=>?LINE,
file=>?FILE}).
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index c595c25341..3d1506ea08 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -112,11 +112,14 @@ MODULES = \
logger \
logger_backend \
logger_config \
- logger_std_h \
+ logger_handler_watcher \
+ logger_std_h \
logger_disk_log_h \
logger_h_common \
logger_filters \
logger_formatter \
+ logger_olp \
+ logger_proxy \
logger_server \
logger_simple_h \
logger_sup \
@@ -150,7 +153,7 @@ INTERNAL_HRL_FILES= application_master.hrl disk_log.hrl \
inet_dns.hrl inet_res.hrl \
inet_boot.hrl inet_config.hrl inet_int.hrl \
inet_dns_record_adts.hrl \
- logger_internal.hrl logger_h_common.hrl
+ logger_internal.hrl logger_olp.hrl logger_h_common.hrl
ERL_FILES= $(MODULES:%=%.erl)
@@ -278,6 +281,8 @@ $(EBIN)/logger_config.beam: logger_internal.hrl ../include/logger.hrl
$(EBIN)/logger_disk_log_h.beam: logger_h_common.hrl logger_internal.hrl ../include/logger.hrl ../include/file.hrl
$(EBIN)/logger_filters.beam: logger_internal.hrl ../include/logger.hrl
$(EBIN)/logger_formatter.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_olp.beam: logger_olp.hrl logger_internal.hrl
+$(EBIN)/logger_proxy.beam: logger_internal.hrl
$(EBIN)/logger_server.beam: logger_internal.hrl ../include/logger.hrl
$(EBIN)/logger_simple_h.beam: logger_internal.hrl ../include/logger.hrl
$(EBIN)/logger_std_h.beam: logger_h_common.hrl logger_internal.hrl ../include/logger.hrl ../include/file.hrl
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index bc6be2f8f5..5c2e981e4b 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -25,7 +25,7 @@
which_applications/0, which_applications/1,
loaded_applications/0, permit/2]).
-export([ensure_started/1, ensure_started/2]).
--export([set_env/3, set_env/4, unset_env/2, unset_env/3]).
+-export([set_env/1, set_env/2, set_env/3, set_env/4, unset_env/2, unset_env/3]).
-export([get_env/1, get_env/2, get_env/3, get_all_env/0, get_all_env/1]).
-export([get_key/1, get_key/2, get_all_key/0, get_all_key/1]).
-export([get_application/0, get_application/1, info/0]).
@@ -279,6 +279,26 @@ loaded_applications() ->
info() ->
application_controller:info().
+-spec set_env(Config) -> 'ok' when
+ Config :: [{Application, Env}],
+ Application :: atom(),
+ Env :: [{Par :: atom(), Val :: term()}].
+
+set_env(Config) when is_list(Config) ->
+ set_env(Config, []).
+
+-spec set_env(Config, Opts) -> 'ok' when
+ Config :: [{Application, Env}],
+ Application :: atom(),
+ Env :: [{Par :: atom(), Val :: term()}],
+ Opts :: [{timeout, timeout()} | {persistent, boolean()}].
+
+set_env(Config, Opts) when is_list(Config), is_list(Opts) ->
+ case application_controller:set_env(Config, Opts) of
+ ok -> ok;
+ {error, Msg} -> erlang:error({badarg, Msg}, [Config, Opts])
+ end.
+
-spec set_env(Application, Par, Val) -> 'ok' when
Application :: atom(),
Par :: atom(),
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index a074d2e74b..9a8091fb2e 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -26,7 +26,7 @@
control_application/1,
change_application_data/2, prep_config_change/0, config_change/1,
which_applications/0, which_applications/1,
- loaded_applications/0, info/0,
+ loaded_applications/0, info/0, set_env/2,
get_pid_env/2, get_env/2, get_pid_all_env/1, get_all_env/1,
get_pid_key/2, get_key/2, get_pid_all_key/1, get_all_key/1,
get_master/1, get_application/1, get_application_module/1,
@@ -345,9 +345,6 @@ get_all_env(AppName) ->
map(fun([Key, Val]) -> {Key, Val} end,
ets:match(ac_tab, {{env, AppName, '$1'}, '$2'})).
-
-
-
get_pid_key(Master, Key) ->
case ets:match(ac_tab, {{application_master, '$1'}, Master}) of
[[AppName]] -> get_key(AppName, Key);
@@ -461,6 +458,15 @@ permit_application(ApplName, Flag) ->
{permit_application, ApplName, Flag},
infinity).
+set_env(Config, Opts) ->
+ case check_conf_data(Config) of
+ ok ->
+ Timeout = proplists:get_value(timeout, Opts, 5000),
+ gen_server:call(?AC, {set_env, Config, Opts}, Timeout);
+
+ {error, _} = Error ->
+ Error
+ end.
set_env(AppName, Key, Val) ->
gen_server:call(?AC, {set_env, AppName, Key, Val, []}).
@@ -528,19 +534,17 @@ check_conf_data([]) ->
check_conf_data(ConfData) when is_list(ConfData) ->
[Application | ConfDataRem] = ConfData,
case Application of
- {kernel, List} when is_list(List) ->
- case check_para_kernel(List) of
- ok ->
- check_conf_data(ConfDataRem);
- Error1 ->
- Error1
- end;
{AppName, List} when is_atom(AppName), is_list(List) ->
- case check_para(List, atom_to_list(AppName)) of
- ok ->
- check_conf_data(ConfDataRem);
- Error2 ->
- Error2
+ case lists:keymember(AppName, 1, ConfDataRem) of
+ true ->
+ ?LOG_WARNING("duplicate application config: " ++ atom_to_list(AppName));
+ false ->
+ ok
+ end,
+
+ case check_para(List, AppName) of
+ ok -> check_conf_data(ConfDataRem);
+ Error -> Error
end;
{AppName, List} when is_list(List) ->
ErrMsg = "application: "
@@ -553,36 +557,40 @@ check_conf_data(ConfData) when is_list(ConfData) ->
++ "; parameters must be a list",
{error, ErrMsg};
Else ->
- ErrMsg = "invalid application name: " ++
- lists:flatten(io_lib:format(" ~tp",[Else])),
+ ErrMsg = "invalid application config: "
+ ++ lists:flatten(io_lib:format("~tp",[Else])),
{error, ErrMsg}
end;
check_conf_data(_ConfData) ->
- {error, 'configuration must be a list ended by <dot><whitespace>'}.
-
+ {error, "configuration must be a list ended by <dot><whitespace>"}.
-%% Special check of distributed parameter for kernel
-check_para_kernel([]) ->
+
+check_para([], _AppName) ->
ok;
-check_para_kernel([{distributed, Apps} | ParaList]) when is_list(Apps) ->
- case check_distributed(Apps) of
- {error, _ErrorMsg} = Error ->
- Error;
- _ ->
- check_para_kernel(ParaList)
+check_para([{Para, Val} | ParaList], AppName) when is_atom(Para) ->
+ case lists:keymember(Para, 1, ParaList) of
+ true ->
+ ?LOG_WARNING("application: " ++ atom_to_list(AppName) ++
+ "; duplicate parameter: " ++ atom_to_list(Para));
+ false ->
+ ok
+ end,
+
+ case check_para_value(Para, Val, AppName) of
+ ok -> check_para(ParaList, AppName);
+ {error, _} = Error -> Error
end;
-check_para_kernel([{distributed, _Apps} | _ParaList]) ->
- {error, "application: kernel; erroneous parameter: distributed"};
-check_para_kernel([{Para, _Val} | ParaList]) when is_atom(Para) ->
- check_para_kernel(ParaList);
-check_para_kernel([{Para, _Val} | _ParaList]) ->
- {error, "application: kernel; invalid parameter: " ++
+check_para([{Para, _Val} | _ParaList], AppName) ->
+ {error, "application: " ++ atom_to_list(AppName) ++ "; invalid parameter name: " ++
lists:flatten(io_lib:format("~tp",[Para]))};
-check_para_kernel(Else) ->
- {error, "application: kernel; invalid parameter list: " ++
+check_para([Else | _ParaList], AppName) ->
+ {error, "application: " ++ atom_to_list(AppName) ++ "; invalid parameter: " ++
lists:flatten(io_lib:format("~tp",[Else]))}.
-
+check_para_value(distributed, Apps, kernel) -> check_distributed(Apps);
+check_para_value(_Para, _Val, _AppName) -> ok.
+
+%% Special check of distributed parameter for kernel
check_distributed([]) ->
ok;
check_distributed([{App, List} | Apps]) when is_atom(App), is_list(List) ->
@@ -595,18 +603,6 @@ check_distributed(_Else) ->
{error, "application: kernel; erroneous parameter: distributed"}.
-check_para([], _AppName) ->
- ok;
-check_para([{Para, _Val} | ParaList], AppName) when is_atom(Para) ->
- check_para(ParaList, AppName);
-check_para([{Para, _Val} | _ParaList], AppName) ->
- {error, "application: " ++ AppName ++ "; invalid parameter: " ++
- lists:flatten(io_lib:format("~tp",[Para]))};
-check_para([Else | _ParaList], AppName) ->
- {error, "application: " ++ AppName ++ "; invalid parameter: " ++
- lists:flatten(io_lib:format("~tp",[Else]))}.
-
-
-type calls() :: 'info' | 'prep_config_change' | 'which_applications'
| {'config_change' | 'control_application' |
'load_application' | 'start_type' | 'stop_application' |
@@ -863,6 +859,16 @@ handle_call(which_applications, _From, S) ->
end, S#state.running),
{reply, Reply, S};
+handle_call({set_env, Config, Opts}, _From, S) ->
+ _ = [add_env(AppName, Env) || {AppName, Env} <- Config],
+
+ case proplists:get_value(persistent, Opts, false) of
+ true ->
+ {reply, ok, S#state{conf_data = merge_env(S#state.conf_data, Config)}};
+ false ->
+ {reply, ok, S}
+ end;
+
handle_call({set_env, AppName, Key, Val, Opts}, _From, S) ->
ets:insert(ac_tab, {{env, AppName, Key}, Val}),
case proplists:get_value(persistent, Opts, false) of
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 1b4a67ecb7..68e1205301 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1434,19 +1434,25 @@ all_loaded(Db) ->
-spec error_msg(io:format(), [term()]) -> 'ok'.
error_msg(Format, Args) ->
+ %% This is equal to calling logger:error/3 which we don't want to
+ %% do from code_server. We don't want to call logger:timestamp()
+ %% either.
logger ! {log,error,Format,Args,
#{pid=>self(),
gl=>group_leader(),
- time=>erlang:system_time(microsecond),
+ time=>os:system_time(microsecond),
error_logger=>#{tag=>error}}},
ok.
-spec info_msg(io:format(), [term()]) -> 'ok'.
info_msg(Format, Args) ->
+ %% This is equal to calling logger:info/3 which we don't want to
+ %% do from code_server. We don't want to call logger:timestamp()
+ %% either.
logger ! {log,info,Format,Args,
#{pid=>self(),
gl=>group_leader(),
- time=>erlang:system_time(microsecond),
+ time=>os:system_time(microsecond),
error_logger=>#{tag=>info_msg}}},
ok.
diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl
index b7e8868911..7a14e2635c 100644
--- a/lib/kernel/src/erl_epmd.erl
+++ b/lib/kernel/src/erl_epmd.erl
@@ -77,8 +77,8 @@ stop() ->
%%
-spec port_please(Name, Host) -> {ok, Port, Version} | noport when
- Name :: string(),
- Host :: inet:ip_address(),
+ Name :: atom() | string(),
+ Host :: atom() | string() | inet:ip_address(),
Port :: non_neg_integer(),
Version :: non_neg_integer().
@@ -86,8 +86,8 @@ port_please(Node, Host) ->
port_please(Node, Host, infinity).
-spec port_please(Name, Host, Timeout) -> {ok, Port, Version} | noport when
- Name :: string(),
- Host :: inet:ip_address(),
+ Name :: atom() | string(),
+ Host :: atom() | string() | inet:ip_address(),
Timeout :: non_neg_integer() | infinity,
Port :: non_neg_integer(),
Version :: non_neg_integer().
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index a7e7f19167..e324be5290 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -74,8 +74,8 @@ start() ->
type => worker,
modules => dynamic},
case supervisor:start_child(logger_sup, ErrorLogger) of
- {ok,_} ->
- ok;
+ {ok,Pid} ->
+ ok = logger_handler_watcher:register_handler(?MODULE,Pid);
Error ->
Error
end;
@@ -95,9 +95,14 @@ start_link() ->
%%% Stop the event manager
-spec stop() -> ok.
stop() ->
- _ = supervisor:terminate_child(logger_sup,?MODULE),
- _ = supervisor:delete_child(logger_sup,?MODULE),
- ok.
+ case whereis(?MODULE) of
+ undefined ->
+ ok;
+ _Pid ->
+ _ = gen_event:stop(?MODULE,{shutdown,stopped},infinity),
+ _ = supervisor:delete_child(logger_sup,?MODULE),
+ ok
+ end.
%%%-----------------------------------------------------------------
%%% Callbacks for logger
@@ -142,14 +147,27 @@ do_log(Level,{report,Msg},#{?MODULE:=#{tag:=Tag}}=Meta) ->
_ ->
%% From logger call which added error_logger data to
%% obtain backwards compatibility with error_logger:*_msg/1,2
- RCBFun=maps:get(report_cb,Meta,fun logger:format_report/1),
- try RCBFun(Msg) of
- {F,A} when is_list(F), is_list(A) ->
- {F,A};
- Other ->
- {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
- catch C:R ->
- {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ case maps:get(report_cb,Meta,fun logger:format_report/1) of
+ RCBFun when is_function(RCBFun,1) ->
+ try RCBFun(Msg) of
+ {F,A} when is_list(F), is_list(A) ->
+ {F,A};
+ Other ->
+ {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
+ catch C:R ->
+ {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ end;
+ RCBFun when is_function(RCBFun,2) ->
+ try RCBFun(Msg,#{depth=>get_format_depth(),
+ chars_limit=>unlimited,
+ single_line=>false}) of
+ Chardata when ?IS_STRING(Chardata) ->
+ {"~ts",[Chardata]};
+ Other ->
+ {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
+ catch C:R ->
+ {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ end
end
end,
notify(Level,Tag,Format,Args,Meta);
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index bf795ee9c6..d893d44079 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -66,7 +66,12 @@
{sctp_set_peer_primary_addr, #sctp_setpeerprim{}} |
{sctp_status, #sctp_status{}} |
{sndbuf, non_neg_integer()} |
- {tos, non_neg_integer()}.
+ {tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()}.
-type option_name() ::
active |
buffer |
@@ -97,7 +102,12 @@
sctp_set_peer_primary_addr |
sctp_status |
sndbuf |
- tos.
+ tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl.
-type sctp_socket() :: port().
-export_type([assoc_id/0, option/0, option_name/0, sctp_socket/0]).
@@ -365,7 +375,7 @@ send(S, AssocChange, Stream, Data) ->
Socket :: sctp_socket(),
FromIP :: inet:ip_address(),
FromPort :: inet:port_number(),
- AncData :: [#sctp_sndrcvinfo{}],
+ AncData :: [#sctp_sndrcvinfo{} | inet:ancillary_data()],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
@@ -382,7 +392,7 @@ recv(S) ->
Timeout :: timeout(),
FromIP :: inet:ip_address(),
FromPort :: inet:port_number(),
- AncData :: [#sctp_sndrcvinfo{}],
+ AncData :: [#sctp_sndrcvinfo{} | inet:ancillary_data()],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index c61411e814..7f7833ec23 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -62,7 +62,14 @@
{show_econnreset, boolean()} |
{sndbuf, non_neg_integer()} |
{tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()} |
{ipv6_v6only, boolean()}.
+-type pktoptions_value() ::
+ {pktoptions, inet:ancillary_data()}.
-type option_name() ::
active |
buffer |
@@ -81,6 +88,7 @@
nodelay |
packet |
packet_size |
+ pktoptions |
priority |
{raw,
Protocol :: non_neg_integer(),
@@ -94,6 +102,12 @@
show_econnreset |
sndbuf |
tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl |
+ pktoptions |
ipv6_v6only.
-type connect_option() ::
{ip, inet:socket_address()} |
@@ -119,7 +133,7 @@
-type socket() :: port().
-export_type([option/0, option_name/0, connect_option/0, listen_option/0,
- socket/0]).
+ socket/0, pktoptions_value/0]).
%%
%% Connect a socket
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 44eef9f3c5..d6e8652e77 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -51,6 +51,11 @@
{reuseaddr, boolean()} |
{sndbuf, non_neg_integer()} |
{tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()} |
{ipv6_v6only, boolean()}.
-type option_name() ::
active |
@@ -76,6 +81,12 @@
reuseaddr |
sndbuf |
tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl |
+ pktoptions |
ipv6_v6only.
-type socket() :: port().
@@ -147,11 +158,13 @@ send(S, Packet) when is_port(S) ->
end.
-spec recv(Socket, Length) ->
- {ok, {Address, Port, Packet}} | {error, Reason} when
+ {ok, RecvData} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
+ RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
+ AncData :: inet:ancillary_data(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
@@ -164,12 +177,14 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
end.
-spec recv(Socket, Length, Timeout) ->
- {ok, {Address, Port, Packet}} | {error, Reason} when
+ {ok, RecvData} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
Timeout :: timeout(),
+ RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
+ AncData :: inet:ancillary_data(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 73c53b9011..9f22eb6aaa 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -76,7 +76,7 @@
-export_type([address_family/0, socket_protocol/0, hostent/0, hostname/0, ip4_address/0,
ip6_address/0, ip_address/0, port_number/0,
local_address/0, socket_address/0, returned_non_ip_address/0,
- socket_setopt/0, socket_getopt/0,
+ socket_setopt/0, socket_getopt/0, ancillary_data/0,
posix/0, socket/0, stat_option/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -154,6 +154,15 @@
'running' | 'multicast' | 'loopback']} |
{'hwaddr', ether_address()}.
+-type getifaddrs_ifopts() ::
+ [Ifopt :: {flags, Flags :: [up | broadcast | loopback |
+ pointtopoint | running | multicast]} |
+ {addr, Addr :: ip_address()} |
+ {netmask, Netmask :: ip_address()} |
+ {broadaddr, Broadaddr :: ip_address()} |
+ {dstaddr, Dstaddr :: ip_address()} |
+ {hwaddr, Hwaddr :: [byte()]}].
+
-type address_family() :: 'inet' | 'inet6' | 'local'.
-type socket_protocol() :: 'tcp' | 'udp' | 'sctp'.
-type socket_type() :: 'stream' | 'dgram' | 'seqpacket'.
@@ -163,6 +172,9 @@
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
+-type ancillary_data() ::
+ [ {'tos', byte()} | {'tclass', byte()} | {'ttl', byte()} ].
+
%%% ---------------------------------
-spec get_rc() -> [{Par :: atom(), Val :: any()} |
@@ -302,7 +314,7 @@ setopts(Socket, Opts) ->
{'ok', OptionValues} | {'error', posix()} when
Socket :: socket(),
Options :: [socket_getopt()],
- OptionValues :: [socket_setopt()].
+ OptionValues :: [socket_setopt() | gen_tcp:pktoptions_value()].
getopts(Socket, Opts) ->
case prim_inet:getopts(Socket, Opts) of
@@ -318,32 +330,32 @@ getopts(Socket, Opts) ->
Other
end.
--spec getifaddrs(Socket :: socket()) ->
- {'ok', [string()]} | {'error', posix()}.
-
+-spec getifaddrs(
+ [Option :: {netns, Namespace :: file:filename_all()}]
+ | socket()) ->
+ {'ok', [{Ifname :: string(),
+ Ifopts :: getifaddrs_ifopts()}]}
+ | {'error', posix()}.
+getifaddrs(Opts) when is_list(Opts) ->
+ withsocket(fun(S) -> prim_inet:getifaddrs(S) end, Opts);
getifaddrs(Socket) ->
prim_inet:getifaddrs(Socket).
--spec getifaddrs() -> {ok, Iflist} | {error, posix()} when
- Iflist :: [{Ifname,[Ifopt]}],
- Ifname :: string(),
- Ifopt :: {flags,[Flag]} | {addr,Addr} | {netmask,Netmask}
- | {broadaddr,Broadaddr} | {dstaddr,Dstaddr}
- | {hwaddr,Hwaddr},
- Flag :: up | broadcast | loopback | pointtopoint
- | running | multicast,
- Addr :: ip_address(),
- Netmask :: ip_address(),
- Broadaddr :: ip_address(),
- Dstaddr :: ip_address(),
- Hwaddr :: [byte()].
-
+-spec getifaddrs() ->
+ {'ok', [{Ifname :: string(),
+ Ifopts :: getifaddrs_ifopts()}]}
+ | {'error', posix()}.
getifaddrs() ->
withsocket(fun(S) -> prim_inet:getifaddrs(S) end).
--spec getiflist(Socket :: socket()) ->
- {'ok', [string()]} | {'error', posix()}.
+-spec getiflist(
+ [Option :: {netns, Namespace :: file:filename_all()}]
+ | socket()) ->
+ {'ok', [string()]} | {'error', posix()}.
+
+getiflist(Opts) when is_list(Opts) ->
+ withsocket(fun(S) -> prim_inet:getiflist(S) end, Opts);
getiflist(Socket) ->
prim_inet:getiflist(Socket).
@@ -360,11 +372,19 @@ getiflist() ->
ifget(Socket, Name, Opts) ->
prim_inet:ifget(Socket, Name, Opts).
--spec ifget(Name :: string() | atom(), Opts :: [if_getopt()]) ->
+-spec ifget(
+ Name :: string() | atom(),
+ Opts :: [if_getopt() |
+ {netns, Namespace :: file:filename_all()}]) ->
{'ok', [if_getopt_result()]} | {'error', posix()}.
ifget(Name, Opts) ->
- withsocket(fun(S) -> prim_inet:ifget(S, Name, Opts) end).
+ {NSOpts,IFOpts} =
+ lists:partition(
+ fun ({netns,_}) -> true;
+ (_) -> false
+ end, Opts),
+ withsocket(fun(S) -> prim_inet:ifget(S, Name, IFOpts) end, NSOpts).
-spec ifset(Socket :: socket(),
Name :: string() | atom(),
@@ -374,11 +394,19 @@ ifget(Name, Opts) ->
ifset(Socket, Name, Opts) ->
prim_inet:ifset(Socket, Name, Opts).
--spec ifset(Name :: string() | atom(), Opts :: [if_setopt()]) ->
+-spec ifset(
+ Name :: string() | atom(),
+ Opts :: [if_setopt() |
+ {netns, Namespace :: file:filename_all()}]) ->
'ok' | {'error', posix()}.
ifset(Name, Opts) ->
- withsocket(fun(S) -> prim_inet:ifset(S, Name, Opts) end).
+ {NSOpts,IFOpts} =
+ lists:partition(
+ fun ({netns,_}) -> true;
+ (_) -> false
+ end, Opts),
+ withsocket(fun(S) -> prim_inet:ifset(S, Name, IFOpts) end, NSOpts).
-spec getif() ->
{'ok', [{ip_address(), ip_address() | 'undefined', ip_address()}]} |
@@ -388,10 +416,14 @@ getif() ->
withsocket(fun(S) -> getif(S) end).
%% backwards compatible getif
--spec getif(Socket :: socket()) ->
+-spec getif(
+ [Option :: {netns, Namespace :: file:filename_all()}]
+ | socket()) ->
{'ok', [{ip_address(), ip_address() | 'undefined', ip_address()}]} |
{'error', posix()}.
+getif(Opts) when is_list(Opts) ->
+ withsocket(fun(S) -> getif(S) end, Opts);
getif(Socket) ->
case prim_inet:getiflist(Socket) of
{ok, IfList} ->
@@ -412,7 +444,10 @@ getif(Socket) ->
end.
withsocket(Fun) ->
- case inet_udp:open(0,[]) of
+ withsocket(Fun, []).
+%%
+withsocket(Fun, Opts) ->
+ case inet_udp:open(0, Opts) of
{ok,Socket} ->
Res = Fun(Socket),
inet_udp:close(Socket),
@@ -722,6 +757,7 @@ stats() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
connect_options() ->
[tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
+ recvtos, recvtclass, ttl, recvttl,
header, active, packet, packet_size, buffer, mode, deliver, line_delimiter,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw,
@@ -790,6 +826,7 @@ con_add(Name, Val, #connect_opts{} = R, Opts, AllOpts) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
listen_options() ->
[tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
+ recvtos, recvtclass, ttl, recvttl,
header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send,
@@ -870,7 +907,7 @@ tcp_module_1(Opts, Address) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
udp_options() ->
[tos, tclass, priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode,
- deliver, ipv6_v6only,
+ recvtos, recvtclass, ttl, recvttl, deliver, ipv6_v6only,
broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop,
add_membership, drop_membership, read_packets,raw,
high_msgq_watermark, low_msgq_watermark, bind_to_device].
@@ -940,8 +977,10 @@ udp_module(Opts) ->
% (*) passing of open FDs ("fdopen") is not supported.
sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
- mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf,
- recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
+ mode, active, buffer, tos, tclass, ttl,
+ priority, dontroute, reuseaddr, linger,
+ recvtos, recvtclass, recvttl,
+ sndbuf, recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
bind_to_device,
% Other options are SCTP-specific (though they may be similar to their
diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl
index a0d5d3df70..347b8b9a1b 100644
--- a/lib/kernel/src/inet6_tcp.erl
+++ b/lib/kernel/src/inet6_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -167,7 +167,7 @@ listen(Port, Opts) ->
%% Accept
%%
accept(L) ->
- case prim_inet:accept(L) of
+ case prim_inet:accept(L, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
@@ -175,13 +175,15 @@ accept(L) ->
end.
accept(L, Timeout) ->
- case prim_inet:accept(L, Timeout) of
+ case prim_inet:accept(L, Timeout, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
Error -> Error
end.
+accept_family_opts() -> [tclass, recvtclass].
+
%%
%% Create a port/socket from a file descriptor
%%
diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl
index 6cbb6ac2da..3f5a2ea5ee 100644
--- a/lib/kernel/src/inet_db.erl
+++ b/lib/kernel/src/inet_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1223,7 +1223,10 @@ handle_set_file(Option, Fname, TagTm, TagInfo, ParseFun, From,
{ok, B, _} -> B;
_ -> <<>>
end;
- _ -> <<>>
+ _ ->
+ ets:insert(Db, {TagInfo, undefined}),
+ TimeZero = - (?RES_FILE_UPDATE_TM + 1), % Early enough
+ ets:insert(Db, {TagTm, TimeZero})
end,
handle_set_file(ParseFun, Bin, From, State);
false -> {reply,error,State}
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 357e27826c..f6525d7261 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -157,6 +157,12 @@
-define(INET_LOPT_LINE_DELIM, 40).
-define(INET_OPT_TCLASS, 41).
-define(INET_OPT_BIND_TO_DEVICE, 42).
+-define(INET_OPT_RECVTOS, 43).
+-define(INET_OPT_RECVTCLASS, 44).
+-define(INET_OPT_PKTOPTIONS, 45).
+-define(INET_OPT_TTL, 46).
+-define(INET_OPT_RECVTTL, 47).
+-define(TCP_OPT_NOPUSH, 48).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl
index dac6b3119d..f1e3116856 100644
--- a/lib/kernel/src/inet_tcp.erl
+++ b/lib/kernel/src/inet_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -164,7 +164,7 @@ listen(Port, Opts) ->
%% Accept
%%
accept(L) ->
- case prim_inet:accept(L) of
+ case prim_inet:accept(L, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
@@ -172,13 +172,15 @@ accept(L) ->
end.
accept(L, Timeout) ->
- case prim_inet:accept(L, Timeout) of
+ case prim_inet:accept(L, Timeout, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
Error -> Error
end.
+accept_family_opts() -> [tos, ttl, recvtos, recvttl].
+
%%
%% Create a port/socket from a file descriptor
%%
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index d1701afdaa..c37212b0f9 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -450,7 +450,7 @@ get_tcp_address(Driver, Socket) ->
get_address_resolver(EpmdModule) ->
case erlang:function_exported(EpmdModule, address_please, 3) of
true -> {EpmdModule, address_please};
- _ -> {inet, getaddr}
+ _ -> {erl_epmd, address_please}
end.
%% ------------------------------------------------------------
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 47dd7c03d5..6bd5518a37 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -67,6 +67,9 @@
logger_filters,
logger_formatter,
logger_h_common,
+ logger_handler_watcher,
+ logger_olp,
+ logger_proxy,
logger_server,
logger_simple_h,
logger_std_h,
@@ -129,6 +132,7 @@
kernel_refc,
kernel_sup,
logger,
+ logger_handler_watcher,
logger_sup,
net_kernel,
net_sup,
@@ -144,6 +148,6 @@
{logger_sasl_compatible, false}
]},
{mod, {kernel, []}},
- {runtime_dependencies, ["erts-10.0", "stdlib-3.5", "sasl-3.0"]}
+ {runtime_dependencies, ["erts-10.2.5", "stdlib-3.5", "sasl-3.0"]}
]
}.
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index 305a1c788c..aca3247c8f 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -16,13 +16,52 @@
%% limitations under the License.
%%
%% %CopyrightEnd%
+%%
+%% We allow upgrade from, and downgrade to all previous
+%% versions from the following OTP releases:
+%% - OTP 20
+%% - OTP 21
+%%
+%% We also allow upgrade from, and downgrade to all
+%% versions that have branched off from the above
+%% stated previous versions.
+%%
{"%VSN%",
- %% Up from - max one major revision back
- [{<<"5\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.0
- {<<"5\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.1+
- {<<"6\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-21
- %% Down to - max one major revision back
- [{<<"5\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.0
- {<<"5\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.1+
- {<<"6\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-21
-}.
+ [{<<"^5\\.3$">>,[restart_new_emulator]},
+ {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^5\\.4$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.0$">>,[restart_new_emulator]},
+ {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.1$">>,[restart_new_emulator]},
+ {<<"^6\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.2$">>,[restart_new_emulator]},
+ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.3$">>,[restart_new_emulator]},
+ {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
+ [{<<"^5\\.3$">>,[restart_new_emulator]},
+ {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^5\\.4$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.0$">>,[restart_new_emulator]},
+ {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.1$">>,[restart_new_emulator]},
+ {<<"^6\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.2$">>,[restart_new_emulator]},
+ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.3$">>,[restart_new_emulator]},
+ {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl
index 0a9b1672ec..38bd2f481c 100644
--- a/lib/kernel/src/logger.erl
+++ b/lib/kernel/src/logger.erl
@@ -39,13 +39,18 @@
remove_primary_filter/1, remove_handler_filter/2,
set_module_level/2,
unset_module_level/1, unset_module_level/0,
+ set_application_level/2, unset_application_level/1,
get_module_level/0, get_module_level/1,
set_primary_config/1, set_primary_config/2,
set_handler_config/2, set_handler_config/3,
- update_primary_config/1, update_handler_config/2,
+ set_proxy_config/1,
+ update_primary_config/1,
+ update_handler_config/2, update_handler_config/3,
+ update_proxy_config/1,
update_formatter_config/2, update_formatter_config/3,
get_primary_config/0, get_handler_config/1,
get_handler_config/0, get_handler_ids/0, get_config/0,
+ get_proxy_config/0,
add_handlers/1]).
%% Private configuration
@@ -55,6 +60,8 @@
-export([compare_levels/2]).
-export([set_process_metadata/1, update_process_metadata/1,
unset_process_metadata/0, get_process_metadata/0]).
+-export([i/0, i/1]).
+-export([timestamp/0]).
%% Basic report formatting
-export([format_report/1, format_otp_report/1]).
@@ -74,6 +81,11 @@
-type level() :: emergency | alert | critical | error |
warning | notice | info | debug.
-type report() :: map() | [{atom(),term()}].
+-type report_cb() :: fun((report()) -> {io:format(),[term()]}) |
+ fun((report(),report_cb_config()) -> unicode:chardata()).
+-type report_cb_config() :: #{depth := pos_integer() | unlimited,
+ chars_limit := pos_integer() | unlimited,
+ single_line := boolean()}.
-type msg_fun() :: fun((term()) -> {io:format(),[term()]} |
report() |
unicode:chardata()).
@@ -84,7 +96,7 @@
file => file:filename(),
line => non_neg_integer(),
domain => [atom()],
- report_cb => fun((report()) -> {io:format(),[term()]}),
+ report_cb => report_cb(),
atom() => term()}.
-type location() :: #{mfa := {module(),atom(),non_neg_integer()},
file := file:filename(),
@@ -110,10 +122,41 @@
-type config_handler() :: {handler, handler_id(), module(), handler_config()}.
--export_type([log_event/0,level/0,report/0,msg_fun/0,metadata/0,
- primary_config/0,handler_config/0,handler_id/0,
- filter_id/0,filter/0,filter_arg/0,filter_return/0,
- config_handler/0,formatter_config/0]).
+-type config_logger() :: [{handler,default,undefined} |
+ config_handler() |
+ {filters,log | stop,[{filter_id(),filter()}]} |
+ {module_level,level(),[module()]}].
+
+-type olp_config() :: #{sync_mode_qlen => non_neg_integer(),
+ drop_mode_qlen => pos_integer(),
+ flush_qlen => pos_integer(),
+ burst_limit_enable => boolean(),
+ burst_limit_max_count => pos_integer(),
+ burst_limit_window_time => pos_integer(),
+ overload_kill_enable => boolean(),
+ overload_kill_qlen => pos_integer(),
+ overload_kill_mem_size => pos_integer(),
+ overload_kill_restart_after =>
+ non_neg_integer() | infinity}.
+
+-export_type([log_event/0,
+ level/0,
+ report/0,
+ report_cb/0,
+ report_cb_config/0,
+ msg_fun/0,
+ metadata/0,
+ primary_config/0,
+ handler_config/0,
+ handler_id/0,
+ filter_id/0,
+ filter/0,
+ filter_arg/0,
+ filter_return/0,
+ config_handler/0,
+ formatter_config/0,
+ olp_config/0,
+ timestamp/0]).
%%%-----------------------------------------------------------------
%%% API
@@ -313,6 +356,10 @@ internal_log(Level,Term) when is_atom(Level) ->
erlang:display_string("Logger - "++ atom_to_list(Level) ++ ": "),
erlang:display(Term).
+-spec timestamp() -> timestamp().
+timestamp() ->
+ os:system_time(microsecond).
+
%%%-----------------------------------------------------------------
%%% Configuration
-spec add_primary_filter(FilterId,Filter) -> ok | {error,term()} when
@@ -352,9 +399,12 @@ add_handler(HandlerId,Module,Config) ->
remove_handler(HandlerId) ->
logger_server:remove_handler(HandlerId).
--spec set_primary_config(Key,Value) -> ok | {error,term()} when
- Key :: atom(),
- Value :: term().
+-spec set_primary_config(level,Level) -> ok | {error,term()} when
+ Level :: level() | all | none;
+ (filter_default,FilterDefault) -> ok | {error,term()} when
+ FilterDefault :: log | stop;
+ (filters,Filters) -> ok | {error,term()} when
+ Filters :: [{filter_id(),filter()}].
set_primary_config(Key,Value) ->
logger_server:set_config(primary,Key,Value).
@@ -363,10 +413,27 @@ set_primary_config(Key,Value) ->
set_primary_config(Config) ->
logger_server:set_config(primary,Config).
--spec set_handler_config(HandlerId,Key,Value) -> ok | {error,term()} when
+
+-spec set_handler_config(HandlerId,level,Level) -> Return when
HandlerId :: handler_id(),
- Key :: atom(),
- Value :: term().
+ Level :: level() | all | none,
+ Return :: ok | {error,term()};
+ (HandlerId,filter_default,FilterDefault) -> Return when
+ HandlerId :: handler_id(),
+ FilterDefault :: log | stop,
+ Return :: ok | {error,term()};
+ (HandlerId,filters,Filters) -> Return when
+ HandlerId :: handler_id(),
+ Filters :: [{filter_id(),filter()}],
+ Return :: ok | {error,term()};
+ (HandlerId,formatter,Formatter) -> Return when
+ HandlerId :: handler_id(),
+ Formatter :: {module(), formatter_config()},
+ Return :: ok | {error,term()};
+ (HandlerId,config,Config) -> Return when
+ HandlerId :: handler_id(),
+ Config :: term(),
+ Return :: ok | {error,term()}.
set_handler_config(HandlerId,Key,Value) ->
logger_server:set_config(HandlerId,Key,Value).
@@ -376,17 +443,50 @@ set_handler_config(HandlerId,Key,Value) ->
set_handler_config(HandlerId,Config) ->
logger_server:set_config(HandlerId,Config).
+-spec set_proxy_config(Config) -> ok | {error,term()} when
+ Config :: olp_config().
+set_proxy_config(Config) ->
+ logger_server:set_config(proxy,Config).
+
-spec update_primary_config(Config) -> ok | {error,term()} when
Config :: primary_config().
update_primary_config(Config) ->
logger_server:update_config(primary,Config).
+-spec update_handler_config(HandlerId,level,Level) -> Return when
+ HandlerId :: handler_id(),
+ Level :: level() | all | none,
+ Return :: ok | {error,term()};
+ (HandlerId,filter_default,FilterDefault) -> Return when
+ HandlerId :: handler_id(),
+ FilterDefault :: log | stop,
+ Return :: ok | {error,term()};
+ (HandlerId,filters,Filters) -> Return when
+ HandlerId :: handler_id(),
+ Filters :: [{filter_id(),filter()}],
+ Return :: ok | {error,term()};
+ (HandlerId,formatter,Formatter) -> Return when
+ HandlerId :: handler_id(),
+ Formatter :: {module(), formatter_config()},
+ Return :: ok | {error,term()};
+ (HandlerId,config,Config) -> Return when
+ HandlerId :: handler_id(),
+ Config :: term(),
+ Return :: ok | {error,term()}.
+update_handler_config(HandlerId,Key,Value) ->
+ logger_server:update_config(HandlerId,Key,Value).
+
-spec update_handler_config(HandlerId,Config) -> ok | {error,term()} when
HandlerId :: handler_id(),
Config :: handler_config().
update_handler_config(HandlerId,Config) ->
logger_server:update_config(HandlerId,Config).
+-spec update_proxy_config(Config) -> ok | {error,term()} when
+ Config :: olp_config().
+update_proxy_config(Config) ->
+ logger_server:update_config(proxy,Config).
+
-spec get_primary_config() -> Config when
Config :: primary_config().
get_primary_config() ->
@@ -398,8 +498,10 @@ get_primary_config() ->
Config :: handler_config().
get_handler_config(HandlerId) ->
case logger_config:get(?LOGGER_TABLE,HandlerId) of
- {ok,{_,Config}} ->
- {ok,Config};
+ {ok,#{module:=Module}=Config} ->
+ {ok,try Module:filter_config(Config)
+ catch _:_ -> Config
+ end};
Error ->
Error
end.
@@ -418,6 +520,12 @@ get_handler_ids() ->
{ok,#{handlers:=HandlerIds}} = logger_config:get(?LOGGER_TABLE,primary),
HandlerIds.
+-spec get_proxy_config() -> Config when
+ Config :: olp_config().
+get_proxy_config() ->
+ {ok,Config} = logger_config:get(?LOGGER_TABLE,proxy),
+ Config.
+
-spec update_formatter_config(HandlerId,FormatterConfig) ->
ok | {error,term()} when
HandlerId :: handler_id(),
@@ -452,6 +560,27 @@ unset_module_level(Modules) ->
unset_module_level() ->
logger_server:unset_module_level().
+-spec set_application_level(Application,Level) -> ok | {error, not_loaded} when
+ Application :: atom(),
+ Level :: level() | all | none.
+set_application_level(App,Level) ->
+ case application:get_key(App, modules) of
+ {ok, Modules} ->
+ set_module_level(Modules, Level);
+ undefined ->
+ {error, {not_loaded, App}}
+ end.
+
+-spec unset_application_level(Application) -> ok | {error, not_loaded} when
+ Application :: atom().
+unset_application_level(App) ->
+ case application:get_key(App, modules) of
+ {ok, Modules} ->
+ unset_module_level(Modules);
+ undefined ->
+ {error, {not_loaded, App}}
+ end.
+
-spec get_module_level(Modules) -> [{Module,Level}] when
Modules :: [Module] | Module,
Module :: module(),
@@ -517,12 +646,150 @@ unset_process_metadata() ->
-spec get_config() -> #{primary=>primary_config(),
handlers=>[handler_config()],
+ proxy=>olp_config(),
module_levels=>[{module(),level() | all | none}]}.
get_config() ->
#{primary=>get_primary_config(),
handlers=>get_handler_config(),
+ proxy=>get_proxy_config(),
module_levels=>lists:keysort(1,get_module_level())}.
+-spec i() -> ok.
+i() ->
+ #{primary := Primary,
+ handlers := HandlerConfigs,
+ proxy := Proxy,
+ module_levels := Modules} = get_config(),
+ M = modifier(),
+ i_primary(Primary,M),
+ i_handlers(HandlerConfigs,M),
+ i_proxy(Proxy,M),
+ i_modules(Modules,M).
+
+-spec i(What) -> ok when
+ What :: primary | handlers | proxy | modules | handler_id().
+i(primary) ->
+ i_primary(get_primary_config(),modifier());
+i(handlers) ->
+ i_handlers(get_handler_config(),modifier());
+i(proxy) ->
+ i_proxy(get_proxy_config(),modifier());
+i(modules) ->
+ i_modules(get_module_level(),modifier());
+i(HandlerId) when is_atom(HandlerId) ->
+ case get_handler_config(HandlerId) of
+ {ok,HandlerConfig} ->
+ i_handlers([HandlerConfig],modifier());
+ Error ->
+ Error
+ end;
+i(What) ->
+ erlang:error(badarg,[What]).
+
+
+i_primary(#{level := Level,
+ filters := Filters,
+ filter_default := FilterDefault},
+ M) ->
+ io:format("Primary configuration: ~n",[]),
+ io:format(" Level: ~p~n",[Level]),
+ io:format(" Filter Default: ~p~n", [FilterDefault]),
+ io:format(" Filters: ~n", []),
+ print_filters(" ",Filters,M).
+
+i_handlers(HandlerConfigs,M) ->
+ io:format("Handler configuration: ~n", []),
+ print_handlers(HandlerConfigs,M).
+
+i_proxy(Proxy,M) ->
+ io:format("Proxy configuration: ~n", []),
+ print_custom(" ",Proxy,M).
+
+i_modules(Modules,M) ->
+ io:format("Level set per module: ~n", []),
+ print_module_levels(Modules,M).
+
+encoding() ->
+ case lists:keyfind(encoding, 1, io:getopts()) of
+ false -> latin1;
+ {encoding, Enc} -> Enc
+ end.
+
+modifier() ->
+ modifier(encoding()).
+
+modifier(latin1) -> "";
+modifier(_) -> "t".
+
+print_filters(Indent, {Id, {Fun, Arg}}, M) ->
+ io:format("~sId: ~"++M++"p~n"
+ "~s Fun: ~"++M++"p~n"
+ "~s Arg: ~"++M++"p~n",
+ [Indent, Id, Indent, Fun, Indent, Arg]);
+print_filters(Indent,[],_M) ->
+ io:format("~s(none)~n",[Indent]);
+print_filters(Indent,Filters,M) ->
+ [print_filters(Indent,Filter,M) || Filter <- Filters],
+ ok.
+
+print_handlers(#{id := Id,
+ module := Module,
+ level := Level,
+ filters := Filters, filter_default := FilterDefault,
+ formatter := {FormatterModule,FormatterConfig}} = Config, M) ->
+ io:format(" Id: ~"++M++"p~n"
+ " Module: ~p~n"
+ " Level: ~p~n"
+ " Formatter:~n"
+ " Module: ~p~n"
+ " Config:~n",
+ [Id, Module, Level, FormatterModule]),
+ print_custom(" ",FormatterConfig,M),
+ io:format(" Filter Default: ~p~n"
+ " Filters:~n",
+ [FilterDefault]),
+ print_filters(" ",Filters,M),
+ case maps:find(config,Config) of
+ {ok,HandlerConfig} ->
+ io:format(" Handler Config:~n"),
+ print_custom(" ",HandlerConfig,M);
+ error ->
+ ok
+ end,
+ MyKeys = [filter_default, filters, formatter, level, module, id, config],
+ case maps:without(MyKeys,Config) of
+ Empty when Empty==#{} ->
+ ok;
+ Unhandled ->
+ io:format(" Custom Config:~n"),
+ print_custom(" ",Unhandled,M)
+ end;
+print_handlers([], _M) ->
+ io:format(" (none)~n");
+print_handlers(HandlerConfigs, M) ->
+ [print_handlers(HandlerConfig, M) || HandlerConfig <- HandlerConfigs],
+ ok.
+
+print_custom(Indent, {Key, Value}, M) ->
+ io:format("~s~"++M++"p: ~"++M++"p~n",[Indent,Key,Value]);
+print_custom(Indent, Map, M) when is_map(Map) ->
+ print_custom(Indent,lists:keysort(1,maps:to_list(Map)), M);
+print_custom(Indent, List, M) when is_list(List), is_tuple(hd(List)) ->
+ [print_custom(Indent, X, M) || X <- List],
+ ok;
+print_custom(Indent, Value, M) ->
+ io:format("~s~"++M++"p~n",[Indent,Value]).
+
+print_module_levels({Module,Level},M) ->
+ io:format(" Module: ~"++M++"p~n"
+ " Level: ~p~n",
+ [Module,Level]);
+print_module_levels([],_M) ->
+ io:format(" (none)~n");
+print_module_levels(Modules,M) ->
+ [print_module_levels(Module,M) || Module <- Modules],
+ ok.
+
-spec internal_init_logger() -> ok | {error,term()}.
%% This function is responsible for config of the logger
%% This is done before add_handlers because we want the
@@ -530,19 +797,21 @@ get_config() ->
%% tree is started.
internal_init_logger() ->
try
+ Env = get_logger_env(kernel),
+ check_logger_config(kernel,Env),
ok = logger:set_primary_config(level, get_logger_level()),
- ok = logger:set_primary_config(filter_default, get_primary_filter_default()),
+ ok = logger:set_primary_config(filter_default,
+ get_primary_filter_default(Env)),
[case logger:add_primary_filter(Id, Filter) of
ok -> ok;
{error, Reason} -> throw(Reason)
- end || {Id, Filter} <- get_primary_filters()],
+ end || {Id, Filter} <- get_primary_filters(Env)],
- _ = [[case logger:set_module_level(Module, Level) of
- ok -> ok;
- {error, Reason} -> throw(Reason)
- end || Module <- Modules]
- || {module_level, Level, Modules} <- get_logger_env()],
+ [case logger:set_module_level(Modules, Level) of
+ ok -> ok;
+ {error, Reason} -> throw(Reason)
+ end || {module_level, Level, Modules} <- Env],
case logger:set_handler_config(simple,filters,
get_default_handler_filters()) of
@@ -550,24 +819,24 @@ internal_init_logger() ->
{error,{not_found,simple}} -> ok
end,
- init_kernel_handlers()
+ init_kernel_handlers(Env)
catch throw:Reason ->
?LOG_ERROR("Invalid logger config: ~p", [Reason]),
{error, {bad_config, {kernel, Reason}}}
end.
--spec init_kernel_handlers() -> ok | {error,term()}.
+-spec init_kernel_handlers(config_logger()) -> ok | {error,term()}.
%% Setup the kernel environment variables to be correct
%% The actual handlers are started by a call to add_handlers.
-init_kernel_handlers() ->
+init_kernel_handlers(Env) ->
try
- case get_logger_type() of
+ case get_logger_type(Env) of
{ok,silent} ->
ok = logger:remove_handler(simple);
{ok,false} ->
ok;
{ok,Type} ->
- init_default_config(Type)
+ init_default_config(Type,Env)
end
catch throw:Reason ->
?LOG_ERROR("Invalid default handler config: ~p", [Reason]),
@@ -581,11 +850,25 @@ init_kernel_handlers() ->
%% This function is responsible for resolving the handler config
%% and then starting the correct handlers. This is done after the
%% kernel supervisor tree has been started as it needs the logger_sup.
+add_handlers(kernel) ->
+ Env = get_logger_env(kernel),
+ case get_proxy_opts(Env) of
+ undefined ->
+ add_handlers(kernel,Env);
+ Opts ->
+ case set_proxy_config(Opts) of
+ ok -> add_handlers(kernel,Env);
+ {error, Reason} -> {error,{bad_proxy_config,Reason}}
+ end
+ end;
add_handlers(App) when is_atom(App) ->
- add_handlers(application:get_env(App, logger, []));
+ add_handlers(App,get_logger_env(App));
add_handlers(HandlerConfig) ->
+ add_handlers(application:get_application(),HandlerConfig).
+
+add_handlers(App,HandlerConfig) ->
try
- check_logger_config(HandlerConfig),
+ check_logger_config(App,HandlerConfig),
DefaultAdded =
lists:foldl(
fun({handler, default = Id, Module, Config}, _)
@@ -599,17 +882,22 @@ add_handlers(HandlerConfig) ->
({handler, Id, Module, Config}, Default) ->
setup_handler(Id, Module, Config),
Default orelse Id == default;
- (_, Default) -> Default
+ (_,Default) -> Default
end, false, HandlerConfig),
%% If a default handler was added we try to remove the simple_logger
%% If the simple logger exists it will replay its log events
%% to the handler(s) added in the fold above.
- _ = [case logger:remove_handler(simple) of
- ok -> ok;
- {error,{not_found,simple}} -> ok
- end || DefaultAdded],
+ [case logger:remove_handler(simple) of
+ ok -> ok;
+ {error,{not_found,simple}} -> ok
+ end || DefaultAdded],
ok
- catch throw:Reason ->
+ catch throw:Reason0 ->
+ Reason =
+ case App of
+ undefined -> Reason0;
+ _ -> {App,Reason0}
+ end,
?LOG_ERROR("Invalid logger handler config: ~p", [Reason]),
{error, {bad_config, {handler, Reason}}}
end.
@@ -620,26 +908,37 @@ setup_handler(Id, Module, Config) ->
{error, Reason} -> throw(Reason)
end.
-check_logger_config(_) ->
- ok.
-
--spec get_logger_type() -> {ok, standard_io | false | silent |
- {file, file:name_all()} |
- {file, file:name_all(), [file:mode()]}}.
-get_logger_type() ->
+check_logger_config(_,[]) ->
+ ok;
+check_logger_config(App,[{handler,_,_,_}|Env]) ->
+ check_logger_config(App,Env);
+check_logger_config(kernel,[{handler,default,undefined}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(kernel,[{filters,_,_}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(kernel,[{module_level,_,_}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(kernel,[{proxy,_}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(_,Bad) ->
+ throw(Bad).
+
+-spec get_logger_type(config_logger()) ->
+ {ok, standard_io | false | silent |
+ {file, file:name_all()} |
+ {file, file:name_all(), [file:mode()]}}.
+get_logger_type(Env) ->
case application:get_env(kernel, error_logger) of
{ok, tty} ->
{ok, standard_io};
{ok, {file, File}} when is_list(File) ->
{ok, {file, File}};
- {ok, {file, File, Modes}} when is_list(File), is_list(Modes) ->
- {ok, {file, File, Modes}};
{ok, false} ->
{ok, false};
{ok, silent} ->
{ok, silent};
undefined ->
- case lists:member({handler,default,undefined}, get_logger_env()) of
+ case lists:member({handler,default,undefined}, Env) of
true ->
{ok, false};
false ->
@@ -651,62 +950,68 @@ get_logger_type() ->
get_logger_level() ->
case application:get_env(kernel,logger_level,info) of
- Level when ?IS_LEVEL(Level) ->
+ Level when ?IS_LEVEL(Level); Level=:=all; Level=:=none ->
Level;
Level ->
throw({logger_level, Level})
end.
-get_primary_filter_default() ->
- case lists:keyfind(filters,1,get_logger_env()) of
+get_primary_filter_default(Env) ->
+ case lists:keyfind(filters,1,Env) of
{filters,Default,_} ->
Default;
false ->
log
end.
-get_primary_filters() ->
- lists:foldl(
- fun({filters, _, Filters}, _Acc) ->
- Filters;
- (_, Acc) ->
- Acc
- end, [], get_logger_env()).
+get_primary_filters(Env) ->
+ case [F || F={filters,_,_} <- Env] of
+ [{filters,_,Filters}] ->
+ case lists:all(fun({_,_}) -> true; (_) -> false end,Filters) of
+ true -> Filters;
+ false -> throw({invalid_filters,Filters})
+ end;
+ [] -> [];
+ _ -> throw({multiple_filters,Env})
+ end.
+
+get_proxy_opts(Env) ->
+ case [P || P={proxy,_} <- Env] of
+ [{proxy,Opts}] -> Opts;
+ [] -> undefined;
+ _ -> throw({multiple_proxies,Env})
+ end.
%% This function looks at the kernel logger environment
%% and updates it so that the correct logger is configured
-init_default_config(Type) when Type==standard_io;
- Type==standard_error;
- element(1,Type)==file ->
- Env = get_logger_env(),
+init_default_config(Type,Env) when Type==standard_io;
+ Type==standard_error;
+ element(1,Type)==file ->
DefaultFormatter = #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}},
DefaultConfig = DefaultFormatter#{config=>#{type=>Type}},
NewLoggerEnv =
case lists:keyfind(default, 2, Env) of
- {handler, default, Module, Config} ->
- lists:map(
- fun({handler, default, logger_std_h, _}) ->
- %% Only want to add the logger_std_h config
- %% if not configured by user AND the default
- %% handler is still the logger_std_h.
- {handler, default, Module, maps:merge(DefaultConfig,Config)};
- ({handler, default, logger_disk_log_h, _}) ->
- %% Add default formatter. The point of this
- %% is to get the expected formatter config
- %% for the default handler, since this
- %% differs from the default values that
- %% logger_formatter itself adds.
- {handler, default, logger_disk_log_h, maps:merge(DefaultFormatter,Config)};
- (Other) ->
- Other
- end, Env);
+ {handler, default, logger_std_h, Config} ->
+ %% Only want to add the logger_std_h config
+ %% if not configured by user AND the default
+ %% handler is still the logger_std_h.
+ lists:keyreplace(default, 2, Env,
+ {handler, default, logger_std_h,
+ maps:merge(DefaultConfig,Config)});
+ {handler, default, Module,Config} ->
+ %% Add default formatter. The point of this
+ %% is to get the expected formatter config
+ %% for the default handler, since this
+ %% differs from the default values that
+ %% logger_formatter itself adds.
+ lists:keyreplace(default, 2, Env,
+ {handler, default, Module,
+ maps:merge(DefaultFormatter,Config)});
_ ->
%% Nothing has been configured, use default
[{handler, default, logger_std_h, DefaultConfig} | Env]
end,
- application:set_env(kernel, logger, NewLoggerEnv, [{timeout,infinity}]);
-init_default_config(Type) ->
- throw({illegal_logger_type,Type}).
+ application:set_env(kernel, logger, NewLoggerEnv, [{timeout,infinity}]).
get_default_handler_filters() ->
case application:get_env(kernel, logger_sasl_compatible, false) of
@@ -716,8 +1021,8 @@ get_default_handler_filters() ->
?DEFAULT_HANDLER_FILTERS([otp,sasl])
end.
-get_logger_env() ->
- application:get_env(kernel, logger, []).
+get_logger_env(App) ->
+ application:get_env(App, logger, []).
%%%-----------------------------------------------------------------
%%% Internal
@@ -773,30 +1078,30 @@ log_allowed(Location,Level,Msg,Meta0) when is_map(Meta0) ->
maps:merge(Location,maps:merge(proc_meta(),Meta0))),
case node(maps:get(gl,Meta)) of
Node when Node=/=node() ->
- log_remote(Node,Level,Msg,Meta),
- do_log_allowed(Level,Msg,Meta);
+ log_remote(Node,Level,Msg,Meta);
_ ->
- do_log_allowed(Level,Msg,Meta)
- end.
+ ok
+ end,
+ do_log_allowed(Level,Msg,Meta,tid()).
-do_log_allowed(Level,{Format,Args}=Msg,Meta)
+do_log_allowed(Level,{Format,Args}=Msg,Meta,Tid)
when ?IS_LEVEL(Level),
is_list(Format),
is_list(Args),
is_map(Meta) ->
- logger_backend:log_allowed(#{level=>Level,msg=>Msg,meta=>Meta},tid());
-do_log_allowed(Level,Report,Meta)
+ logger_backend:log_allowed(#{level=>Level,msg=>Msg,meta=>Meta},Tid);
+do_log_allowed(Level,Report,Meta,Tid)
when ?IS_LEVEL(Level),
?IS_REPORT(Report),
is_map(Meta) ->
logger_backend:log_allowed(#{level=>Level,msg=>{report,Report},meta=>Meta},
- tid());
-do_log_allowed(Level,String,Meta)
+ Tid);
+do_log_allowed(Level,String,Meta,Tid)
when ?IS_LEVEL(Level),
?IS_STRING(String),
is_map(Meta) ->
logger_backend:log_allowed(#{level=>Level,msg=>{string,String},meta=>Meta},
- tid()).
+ Tid).
tid() ->
ets:whereis(?LOGGER_TABLE).
@@ -806,7 +1111,7 @@ log_remote(Node,Level,Msg,Meta) ->
log_remote(Node,{log,Level,Msg,Meta}).
log_remote(Node,Request) ->
- {logger,Node} ! Request,
+ logger_proxy:log({remote,Node,Request}),
ok.
add_default_metadata(Meta) ->
@@ -830,7 +1135,7 @@ proc_meta() ->
default(pid) -> self();
default(gl) -> group_leader();
-default(time) -> erlang:system_time(microsecond).
+default(time) -> timestamp().
%% Remove everything upto and including this module from the stacktrace
filter_stacktrace(Module,[{Module,_,_,_}|_]) ->
diff --git a/lib/kernel/src/logger_backend.erl b/lib/kernel/src/logger_backend.erl
index 4d7bd6b2a0..432c671afd 100644
--- a/lib/kernel/src/logger_backend.erl
+++ b/lib/kernel/src/logger_backend.erl
@@ -41,7 +41,7 @@ log_allowed(Log, Tid) ->
call_handlers(#{level:=Level}=Log,[Id|Handlers],Tid) ->
case logger_config:get(Tid,Id,Level) of
- {ok,{Module,Config}} ->
+ {ok,#{module:=Module}=Config} ->
Filters = maps:get(filters,Config,[]),
case apply_filters(Id,Log,Filters,Config) of
stop ->
diff --git a/lib/kernel/src/logger_config.erl b/lib/kernel/src/logger_config.erl
index 55427dce5a..5024d20cfe 100644
--- a/lib/kernel/src/logger_config.erl
+++ b/lib/kernel/src/logger_config.erl
@@ -22,8 +22,8 @@
-export([new/1,delete/2,
exist/2,
allow/2,allow/3,
- get/2, get/3, get/1,
- create/3, create/4, set/3,
+ get/2, get/3,
+ create/3, set/3,
set_module_level/3,unset_module_level/2,
get_module_level/1,cache_module_level/2,
level_to_int/1]).
@@ -31,7 +31,9 @@
-include("logger_internal.hrl").
new(Name) ->
- _ = ets:new(Name,[set,protected,named_table,{write_concurrency,true}]),
+ _ = ets:new(Name,[set,protected,named_table,
+ {read_concurrency,true},
+ {write_concurrency,true}]),
ets:whereis(Name).
delete(Tid,Id) ->
@@ -64,31 +66,30 @@ get(Tid,What) ->
case ets:lookup(Tid,table_key(What)) of
[{_,_,Config}] ->
{ok,Config};
- [{_,_,Config,Module}] ->
- {ok,{Module,Config}};
+ [{_,Config}] when What=:=proxy ->
+ {ok,Config};
[] ->
{error,{not_found,What}}
end.
get(Tid,What,Level) ->
- MS = [{{table_key(What),'$1','$2'}, % primary config
- [{'>=','$1',level_to_int(Level)}],
- ['$2']},
- {{table_key(What),'$1','$2','$3'}, % handler config
+ MS = [{{table_key(What),'$1','$2'},
[{'>=','$1',level_to_int(Level)}],
- [{{'$3','$2'}}]}],
+ ['$2']}],
case ets:select(Tid,MS) of
[] -> error;
[Data] -> {ok,Data}
end.
-create(Tid,What,Module,Config) ->
- LevelInt = level_to_int(maps:get(level,Config)),
- ets:insert(Tid,{table_key(What),LevelInt,Config,Module}).
+create(Tid,proxy,Config) ->
+ ets:insert(Tid,{table_key(proxy),Config});
create(Tid,What,Config) ->
LevelInt = level_to_int(maps:get(level,Config)),
ets:insert(Tid,{table_key(What),LevelInt,Config}).
+set(Tid,proxy,Config) ->
+ ets:insert(Tid,{table_key(proxy),Config}),
+ ok;
set(Tid,What,Config) ->
LevelInt = level_to_int(maps:get(level,Config)),
%% Should do this only if the level has actually changed. Possibly
@@ -129,13 +130,6 @@ cache_module_level(Tid,Module) ->
ets:insert_new(Tid,{Module,{GlobalLevelInt,cached}}),
ok.
-get(Tid) ->
- {ok,Primary} = get(Tid,primary),
- HMS = [{{table_key('$1'),'_','$2','$3'},[],[{{'$1','$3','$2'}}]}],
- Handlers = ets:select(Tid,HMS),
- Modules = get_module_level(Tid),
- {Primary,Handlers,Modules}.
-
level_to_int(none) -> ?LOG_NONE;
level_to_int(emergency) -> ?EMERGENCY;
level_to_int(alert) -> ?ALERT;
@@ -161,5 +155,6 @@ int_to_level(?LOG_ALL) -> all.
%%%-----------------------------------------------------------------
%%% Internal
+table_key(proxy) -> ?PROXY_KEY;
table_key(primary) -> ?PRIMARY_KEY;
table_key(HandlerId) -> {?HANDLER_KEY,HandlerId}.
diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl
index 0a72654e11..47b39da900 100644
--- a/lib/kernel/src/logger_disk_log_h.erl
+++ b/lib/kernel/src/logger_disk_log_h.erl
@@ -19,183 +19,117 @@
%%
-module(logger_disk_log_h).
--behaviour(gen_server).
-
-include("logger.hrl").
-include("logger_internal.hrl").
-include("logger_h_common.hrl").
%%% API
--export([start_link/3, info/1, filesync/1, reset/1]).
+-export([filesync/1]).
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
+%% logger_h_common callbacks
+-export([init/2, check_config/4, reset_state/2,
+ filesync/3, write/4, handle_info/3, terminate/3]).
%% logger callbacks
--export([log/2, adding_handler/1, removing_handler/1, changing_config/2]).
-
-%% handler internal
--export([log_handler_info/4]).
+-export([log/2, adding_handler/1, removing_handler/1, changing_config/3,
+ filter_config/1]).
%%%===================================================================
%%% API
%%%===================================================================
%%%-----------------------------------------------------------------
-%%% Start a disk_log handler process and link to caller.
-%%% This function is called by the kernel supervisor when this
-%%% handler process gets added (as a result of calling add/3).
--spec start_link(Name, Config, HandlerState) -> {ok,Pid} | {error,Reason} when
- Name :: atom(),
- Config :: logger:handler_config(),
- HandlerState :: map(),
- Pid :: pid(),
- Reason :: term().
-
-start_link(Name, Config, HandlerState) ->
- proc_lib:start_link(?MODULE,init,[[Name,Config,HandlerState]]).
-
-%%%-----------------------------------------------------------------
%%%
-spec filesync(Name) -> ok | {error,Reason} when
Name :: atom(),
Reason :: handler_busy | {badarg,term()}.
-filesync(Name) when is_atom(Name) ->
- try
- gen_server:call(?name_to_reg_name(?MODULE,Name),
- disk_log_sync, ?DEFAULT_CALL_TIMEOUT)
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
filesync(Name) ->
- {error,{badarg,{filesync,[Name]}}}.
+ logger_h_common:filesync(?MODULE,Name).
+
+%%%===================================================================
+%%% logger callbacks
+%%%===================================================================
%%%-----------------------------------------------------------------
-%%%
--spec info(Name) -> Info | {error,Reason} when
- Name :: atom(),
- Info :: term(),
- Reason :: handler_busy | {badarg,term()}.
+%%% Handler being added
+adding_handler(Config) ->
+ logger_h_common:adding_handler(Config).
+
+%%%-----------------------------------------------------------------
+%%% Updating handler config
+changing_config(SetOrUpdate, OldConfig, NewConfig) ->
+ logger_h_common:changing_config(SetOrUpdate, OldConfig, NewConfig).
-info(Name) when is_atom(Name) ->
- try
- gen_server:call(?name_to_reg_name(?MODULE,Name),
- info, ?DEFAULT_CALL_TIMEOUT)
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
-info(Name) ->
- {error,{badarg,{info,[Name]}}}.
+%%%-----------------------------------------------------------------
+%%% Handler being removed
+removing_handler(Config) ->
+ logger_h_common:removing_handler(Config).
%%%-----------------------------------------------------------------
-%%%
--spec reset(Name) -> ok | {error,Reason} when
- Name :: atom(),
- Reason :: handler_busy | {badarg,term()}.
+%%% Log a string or report
+-spec log(LogEvent, Config) -> ok when
+ LogEvent :: logger:log_event(),
+ Config :: logger:handler_config().
-reset(Name) when is_atom(Name) ->
- try
- gen_server:call(?name_to_reg_name(?MODULE,Name),
- reset, ?DEFAULT_CALL_TIMEOUT)
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
-reset(Name) ->
- {error,{badarg,{reset,[Name]}}}.
+log(LogEvent, Config) ->
+ logger_h_common:log(LogEvent, Config).
+%%%-----------------------------------------------------------------
+%%% Remove internal fields from configuration
+filter_config(Config) ->
+ logger_h_common:filter_config(Config).
%%%===================================================================
-%%% logger callbacks
+%%% logger_h_common callbacks
%%%===================================================================
-
-%%%-----------------------------------------------------------------
-%%% Handler being added
-adding_handler(#{id:=Name}=Config) ->
- case check_config(adding, Config) of
- {ok, Config1} ->
- %% create initial handler state by merging defaults with config
- HConfig = maps:get(config, Config1, #{}),
- HState = maps:merge(get_init_state(), HConfig),
- case logger_h_common:overload_levels_ok(HState) of
- true ->
- start(Name, Config1, HState);
- false ->
- #{sync_mode_qlen := SMQL,
- drop_mode_qlen := DMQL,
- flush_qlen := FQL} = HState,
- {error,{invalid_levels,{SMQL,DMQL,FQL}}}
- end;
+init(Name, #{file:=File,type:=Type,max_no_bytes:=MNB,max_no_files:=MNF}) ->
+ case open_disk_log(Name, File, Type, MNB, MNF) of
+ ok ->
+ {ok,#{log_opts => #{file => File,
+ type => Type,
+ max_no_bytes => MNB,
+ max_no_files => MNF},
+ prev_log_result => ok,
+ prev_sync_result => ok,
+ prev_disk_log_info => undefined}};
Error ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% Updating handler config
-changing_config(OldConfig = #{id:=Name, config:=OldHConfig},
- NewConfig = #{id:=Name, config:=NewHConfig}) ->
- #{type:=Type, file:=File, max_no_files:=MaxFs,
- max_no_bytes:=MaxBytes} = OldHConfig,
- case NewHConfig of
- #{type:=Type, file:=File, max_no_files:=MaxFs,
- max_no_bytes:=MaxBytes} ->
- changing_config1(OldConfig, NewConfig);
- _ ->
- {error,{illegal_config_change,OldConfig,NewConfig}}
- end;
-changing_config(OldConfig, NewConfig) ->
- {error,{illegal_config_change,OldConfig,NewConfig}}.
-
-changing_config1(OldConfig=#{config:=OldHConfig}, NewConfig) ->
- case check_config(changing, NewConfig) of
- {ok,NewConfig1 = #{config:=NewHConfig}} ->
- #{handler_pid:=HPid,
- mode_tab:=ModeTab} = OldHConfig,
- NewHConfig1 = NewHConfig#{handler_pid=>HPid,
- mode_tab=>ModeTab},
- NewConfig2 = NewConfig1#{config=>NewHConfig1},
- try gen_server:call(HPid, {change_config,OldConfig,NewConfig2},
- ?DEFAULT_CALL_TIMEOUT) of
- ok -> {ok,NewConfig2};
- HError -> HError
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
- Error ->
- Error
+check_config(Name,set,undefined,HConfig0) ->
+ HConfig=merge_default_logopts(Name,maps:merge(get_default_config(),HConfig0)),
+ check_config(HConfig);
+check_config(_Name,SetOrUpdate,OldHConfig,NewHConfig0) ->
+ WriteOnce = maps:with([type,file,max_no_files,max_no_bytes],OldHConfig),
+ Default =
+ case SetOrUpdate of
+ set ->
+ %% Do not reset write-once fields to defaults
+ maps:merge(get_default_config(),WriteOnce);
+ update ->
+ OldHConfig
+ end,
+
+ NewHConfig = maps:merge(Default,NewHConfig0),
+
+ %% Fail if write-once fields are changed
+ case maps:with([type,file,max_no_files,max_no_bytes],NewHConfig) of
+ WriteOnce ->
+ check_config(NewHConfig);
+ Other ->
+ {Old,New} = logger_server:diff_maps(WriteOnce,Other),
+ {error,{illegal_config_change,?MODULE,Old,New}}
end.
-check_config(adding, #{id:=Name}=Config) ->
- %% merge handler specific config data
- HConfig = merge_default_logopts(Name, maps:get(config, Config, #{})),
+check_config(HConfig) ->
case check_h_config(maps:to_list(HConfig)) of
ok ->
- {ok,Config#{config=>HConfig}};
- Error ->
- Error
- end;
-check_config(changing, Config) ->
- HConfig = maps:get(config, Config, #{}),
- case check_h_config(maps:to_list(HConfig)) of
- ok -> {ok,Config};
- Error -> Error
+ {ok,HConfig};
+ {error,{Key,Value}} ->
+ {error,{invalid_config,?MODULE,#{Key=>Value}}}
end.
-merge_default_logopts(Name, HConfig) ->
- Type = maps:get(type, HConfig, wrap),
- {DefaultNoFiles,DefaultNoBytes} =
- case Type of
- halt -> {undefined,infinity};
- _wrap -> {10,1048576}
- end,
- {ok,Dir} = file:get_cwd(),
- Defaults = #{file => filename:join(Dir,Name),
- max_no_files => DefaultNoFiles,
- max_no_bytes => DefaultNoBytes,
- type => Type},
- maps:merge(Defaults, HConfig).
-
check_h_config([{file,File}|Config]) when is_list(File) ->
check_h_config(Config);
check_h_config([{max_no_files,undefined}|Config]) ->
@@ -208,445 +142,59 @@ check_h_config([{max_no_bytes,N}|Config]) when is_integer(N), N>0 ->
check_h_config(Config);
check_h_config([{type,Type}|Config]) when Type==wrap; Type==halt ->
check_h_config(Config);
-check_h_config([Other | Config]) ->
- case logger_h_common:check_common_config(Other) of
- valid ->
- check_h_config(Config);
- invalid ->
- {error,{invalid_config,?MODULE,Other}}
- end;
+check_h_config([Other | _]) ->
+ {error,Other};
check_h_config([]) ->
ok.
-%%%-----------------------------------------------------------------
-%%% Handler being removed
-removing_handler(#{id:=Name}) ->
- stop(Name).
+get_default_config() ->
+ #{}.
-%%%-----------------------------------------------------------------
-%%% Log a string or report
--spec log(LogEvent, Config) -> ok | dropped when
- LogEvent :: logger:log_event(),
- Config :: logger:handler_config().
+merge_default_logopts(Name, HConfig) ->
+ Type = maps:get(type, HConfig, wrap),
+ {DefaultNoFiles,DefaultNoBytes} =
+ case Type of
+ halt -> {undefined,infinity};
+ _wrap -> {10,1048576}
+ end,
+ {ok,Dir} = file:get_cwd(),
+ Defaults = #{file => filename:join(Dir,Name),
+ max_no_files => DefaultNoFiles,
+ max_no_bytes => DefaultNoBytes,
+ type => Type},
+ maps:merge(Defaults, HConfig).
-log(LogEvent, Config = #{id := Name,
- config := #{handler_pid := HPid,
- mode_tab := ModeTab}}) ->
- %% if the handler has crashed, we must drop this event
- %% and hope the handler restarts so we can try again
- true = is_process_alive(HPid),
- Bin = logger_h_common:log_to_binary(LogEvent, Config),
- logger_h_common:call_cast_or_drop(Name, HPid, ModeTab, Bin).
+filesync(Name,_Mode,State) ->
+ Result = ?disk_log_sync(Name),
+ maybe_notify_error(Name, filesync, Result, prev_sync_result, State).
-%%%===================================================================
-%%% gen_server callbacks
-%%%===================================================================
+write(Name, Mode, Bin, State) ->
+ Result = ?disk_log_write(Name, Mode, Bin),
+ maybe_notify_error(Name, log, Result, prev_log_result, State).
-init([Name,
- Config = #{config := HConfig = #{file:=File,
- type:=Type,
- max_no_bytes:=MNB,
- max_no_files:=MNF}},
- State = #{dl_sync_int := DLSyncInt}]) ->
-
- RegName = ?name_to_reg_name(?MODULE,Name),
- register(RegName, self()),
- process_flag(trap_exit, true),
- process_flag(message_queue_data, off_heap),
-
- ?init_test_hooks(),
- ?start_observation(Name),
-
- LogOpts = #{file=>File, type=>Type, max_no_bytes=>MNB, max_no_files=>MNF},
- case open_disk_log(Name, File, Type, MNB, MNF) of
- ok ->
- try ets:new(Name, [public]) of
- ModeTab ->
- ?set_mode(ModeTab, async),
- T0 = ?timestamp(),
- State1 =
- ?merge_with_stats(State#{
- id => Name,
- mode_tab => ModeTab,
- mode => async,
- dl_sync => DLSyncInt,
- log_opts => LogOpts,
- last_qlen => 0,
- last_log_ts => T0,
- burst_win_ts => T0,
- burst_msg_count => 0,
- last_op => sync,
- prev_log_result => ok,
- prev_sync_result => ok,
- prev_disk_log_info => undefined}),
- Config1 =
- Config#{config => HConfig#{handler_pid => self(),
- mode_tab => ModeTab}},
- proc_lib:init_ack({ok,self(),Config1}),
- gen_server:cast(self(), repeated_disk_log_sync),
- case logger_h_common:unset_restart_flag(Name, ?MODULE) of
- true ->
- %% inform about restart
- gen_server:cast(self(), {log_handler_info,
- "Handler ~p restarted",
- [Name]});
- false ->
- %% initial start
- ok
- end,
- enter_loop(Config1, State1)
- catch
- _:Error ->
- unregister(RegName),
- logger_h_common:error_notify({open_disk_log,Name,Error}),
- proc_lib:init_ack(Error)
- end;
- Error ->
- unregister(RegName),
- logger_h_common:error_notify({open_disk_log,Name,Error}),
- proc_lib:init_ack(Error)
- end.
-
-enter_loop(_Config,State) ->
- gen_server:enter_loop(?MODULE,[],State).
-
-%% This is the synchronous log event.
-handle_call({log, Bin}, _From, State) ->
- {Result,State1} = do_log(Bin, call, State),
- %% Result == ok | dropped
- {reply, Result, State1};
-
-handle_call(disk_log_sync, _From, State = #{id := Name}) ->
- State1 = #{prev_sync_result := Result} = disk_log_sync(Name, State),
- {reply, Result, State1};
-
-handle_call({change_config,_OldConfig,NewConfig}, _From,
- State = #{filesync_repeat_interval := FSyncInt0}) ->
- HConfig = maps:get(config, NewConfig, #{}),
- State1 = #{sync_mode_qlen := SMQL,
- drop_mode_qlen := DMQL,
- flush_qlen := FQL} = maps:merge(State, HConfig),
- case logger_h_common:overload_levels_ok(State1) of
- true ->
- _ =
- case maps:get(filesync_repeat_interval, HConfig, undefined) of
- undefined ->
- ok;
- no_repeat ->
- _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
- State,
- undefined));
- FSyncInt0 ->
- ok;
- _FSyncInt1 ->
- _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
- State,
- undefined)),
- _ = gen_server:cast(self(), repeated_disk_log_sync)
- end,
- {reply, ok, State1};
- false ->
- {reply, {error,{invalid_levels,{SMQL,DMQL,FQL}}}, State}
- end;
-
-handle_call(info, _From, State) ->
- {reply, State, State};
-
-handle_call(reset, _From, State) ->
- State1 = ?merge_with_stats(State),
- {reply, ok, State1#{last_qlen => 0,
- last_log_ts => ?timestamp(),
- prev_log_result => ok,
- prev_sync_result => ok,
- prev_disk_log_info => undefined}};
-
-handle_call(stop, _From, State) ->
- {stop, {shutdown,stopped}, ok, State}.
-
-
-%% This is the asynchronous log event.
-handle_cast({log, Bin}, State) ->
- {_,State1} = do_log(Bin, cast, State),
- {noreply, State1};
-
-handle_cast({log_handler_info, Format, Args}, State = #{id:=Name}) ->
- log_handler_info(Name, Format, Args, State),
- {noreply, State};
-
-%% If FILESYNC_REPEAT_INTERVAL is set to a millisec value, this
-%% clause gets called repeatedly by the handler. In order to
-%% guarantee that a filesync *always* happens after the last log
-%% event, the repeat operation must be active!
-handle_cast(repeated_disk_log_sync,
- State = #{id := Name,
- filesync_repeat_interval := FSyncInt,
- last_op := LastOp}) ->
- State1 =
- if is_integer(FSyncInt) ->
- %% only do filesync if something has been
- %% written since last time we checked
- NewState = if LastOp == sync ->
- State;
- true ->
- disk_log_sync(Name, State)
- end,
- {ok,TRef} =
- timer:apply_after(FSyncInt, gen_server,cast,
- [self(),repeated_disk_log_sync]),
- NewState#{rep_sync_tref => TRef, last_op => sync};
- true ->
- State
- end,
- {noreply,State1}.
+reset_state(_Name, State) ->
+ State#{prev_log_result => ok,
+ prev_sync_result => ok,
+ prev_disk_log_info => undefined}.
%% The disk log owner must handle status messages from disk_log.
-handle_info({disk_log, _Node, _Log, {wrap,_NoLostItems}}, State) ->
- {noreply, State};
-handle_info({disk_log, _Node, Log, Info = {truncated,_NoLostItems}},
- State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
- error_notify_new(Info, PrevInfo, {disk_log,Name,Log,Info}),
- {noreply, State#{prev_disk_log_info => Info}};
-handle_info({disk_log, _Node, Log, Info = {blocked_log,_Items}},
- State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
- error_notify_new(Info, PrevInfo, {disk_log,Name,Log,Info}),
- {noreply, State#{prev_disk_log_info => Info}};
-handle_info({disk_log, _Node, Log, full},
- State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
- error_notify_new(full, PrevInfo, {disk_log,Name,Log,full}),
- {noreply, State#{prev_disk_log_info => full}};
-handle_info({disk_log, _Node, Log, Info = {error_status,_Status}},
- State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
- error_notify_new(Info, PrevInfo, {disk_log,Name,Log,Info}),
- {noreply, State#{prev_disk_log_info => Info}};
-
-handle_info({'EXIT',_Pid,_Why}, State = #{id := _Name}) ->
- {noreply, State};
-
-handle_info(_, State) ->
- {noreply, State}.
-
-terminate(Reason, State = #{id := Name}) ->
- _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref, State,
- undefined)),
+handle_info(Name, {disk_log, _Node, Log, Info={truncated,_NoLostItems}}, State) ->
+ maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
+handle_info(Name, {disk_log, _Node, Log, Info = {blocked_log,_Items}}, State) ->
+ maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
+handle_info(Name, {disk_log, _Node, Log, Info = full}, State) ->
+ maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
+handle_info(Name, {disk_log, _Node, Log, Info = {error_status,_Status}}, State) ->
+ maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
+handle_info(_, _, State) ->
+ State.
+
+terminate(Name, _Reason, _State) ->
_ = close_disk_log(Name, normal),
- unregister(?name_to_reg_name(?MODULE, Name)),
- logger_h_common:stop_or_restart(Name, Reason, State).
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
+ ok.
%%%-----------------------------------------------------------------
%%% Internal functions
-
-%%%-----------------------------------------------------------------
-%%%
-get_init_state() ->
- #{sync_mode_qlen => ?SYNC_MODE_QLEN,
- drop_mode_qlen => ?DROP_MODE_QLEN,
- flush_qlen => ?FLUSH_QLEN,
- burst_limit_enable => ?BURST_LIMIT_ENABLE,
- burst_limit_max_count => ?BURST_LIMIT_MAX_COUNT,
- burst_limit_window_time => ?BURST_LIMIT_WINDOW_TIME,
- overload_kill_enable => ?OVERLOAD_KILL_ENABLE,
- overload_kill_qlen => ?OVERLOAD_KILL_QLEN,
- overload_kill_mem_size => ?OVERLOAD_KILL_MEM_SIZE,
- overload_kill_restart_after => ?OVERLOAD_KILL_RESTART_AFTER,
- dl_sync_int => ?CONTROLLER_SYNC_INTERVAL,
- filesync_ok_qlen => ?FILESYNC_OK_QLEN,
- filesync_repeat_interval => ?FILESYNC_REPEAT_INTERVAL}.
-
-%%%-----------------------------------------------------------------
-%%% Add a disk_log handler to the logger.
-%%% This starts a dedicated handler process which should always
-%%% exist if the handler is registered with logger (and should not
-%%% exist if the handler is not registered).
-%%%
-%%% Config is the logger:handler_config() map. Handler specific parameters
-%%% should be provided with a sub map associated with a key named
-%%% 'config', e.g:
-%%%
-%%% Config = #{config => #{sync_mode_qlen => 50}
-%%%
-%%% The 'config' sub map will also contain parameters for configuring
-%%% the disk_log:
-%%%
-%%% Config = #{config => #{file => file:filename(),
-%%% max_no_bytes => integer(),
-%%% max_no_files => integer(),
-%%% type => wrap | halt}}.
-%%%
-%%% If type == halt, then max_no_files is ignored.
-%%%
-%%% The disk_log handler process is linked to logger_sup, which is
-%%% part of the kernel application's supervision tree.
-start(Name, Config, HandlerState) ->
- LoggerDLH =
- #{id => Name,
- start => {?MODULE, start_link, [Name,Config,HandlerState]},
- restart => temporary,
- shutdown => 2000,
- type => worker,
- modules => [?MODULE]},
- case supervisor:start_child(logger_sup, LoggerDLH) of
- {ok,_Pid,Config1} ->
- {ok,Config1};
- Error ->
- Error
- end.
-
-%%%-----------------------------------------------------------------
-%%% Stop and remove the handler.
-stop(Name) ->
- case whereis(?name_to_reg_name(?MODULE,Name)) of
- undefined ->
- ok;
- Pid ->
- %% We don't want to do supervisor:terminate_child here
- %% since we need to distinguish this explicit stop from a
- %% system termination in order to avoid circular attempts
- %% at removing the handler (implying deadlocks and
- %% timeouts).
- _ = gen_server:call(Pid, stop),
- _ = supervisor:delete_child(logger_sup, Name),
- ok
- end.
-
-%%%-----------------------------------------------------------------
-%%% Logging and overload control.
--define(update_dl_sync(C, Interval),
- if C == 0 -> Interval;
- true -> C-1 end).
-
-%% check for overload between every event (and set Mode to async,
-%% sync or drop accordingly), but never flush the whole mailbox
-%% before LogWindowSize events have been handled
-do_log(Bin, CallOrCast, State = #{id:=Name, mode := Mode0}) ->
- T1 = ?timestamp(),
-
- %% check if the handler is getting overloaded, or if it's
- %% recovering from overload (the check must be done for each
- %% event to react quickly to large bursts of events and
- %% to ensure that the handler can never end up in drop mode
- %% with an empty mailbox, which would stop operation)
- {Mode1,QLen,Mem,State1} = logger_h_common:check_load(State),
-
- if (Mode1 == drop) andalso (Mode0 =/= drop) ->
- log_handler_info(Name, "Handler ~p switched to drop mode",
- [Name], State);
- (Mode0 == drop) andalso ((Mode1 == async) orelse (Mode1 == sync)) ->
- log_handler_info(Name, "Handler ~p switched to ~w mode",
- [Name,Mode1], State);
- true ->
- ok
- end,
-
- %% kill the handler if it can't keep up with the load
- logger_h_common:kill_if_choked(Name, QLen, Mem, ?MODULE, State),
-
- if Mode1 == flush ->
- flush(Name, QLen, T1, State1);
- true ->
- write(Name, Mode1, T1, Bin, CallOrCast, State1)
- end.
-
-%% this function is called by do_log/3 after an overload check
-%% has been performed, where QLen > FlushQLen
-flush(Name, _QLen0, T1, State=#{last_log_ts := _T0, mode_tab := ModeTab}) ->
- %% flush messages in the mailbox (a limited number in
- %% order to not cause long delays)
- NewFlushed = logger_h_common:flush_log_events(?FLUSH_MAX_N),
-
- %% write info in log about flushed messages
- log_handler_info(Name, "Handler ~p flushed ~w log events",
- [Name,NewFlushed], State),
-
- %% because of the receive loop when flushing messages, the
- %% handler will be scheduled out often and the mailbox could
- %% grow very large, so we'd better check the queue again here
- {_,_QLen1} = process_info(self(), message_queue_len),
- ?observe(Name,{max_qlen,_QLen1}),
-
- %% Add 1 for the current log event
- ?observe(Name,{flushed,NewFlushed+1}),
-
- State1 = ?update_max_time(?diff_time(T1,_T0),State),
- {dropped,?update_other(flushed,FLUSHED,NewFlushed,
- State1#{mode => ?set_mode(ModeTab,async),
- last_qlen => 0,
- last_log_ts => T1})}.
-
-%% this function is called to write to disk_log
-write(Name, Mode, T1, Bin, _CallOrCast,
- State = #{mode_tab := ModeTab,
- dl_sync := DLSync,
- dl_sync_int := DLSyncInt,
- last_qlen := LastQLen,
- last_log_ts := T0}) ->
- %% check if we need to limit the number of writes
- %% during a burst of log events
- {DoWrite,BurstWinT,BurstMsgCount} = logger_h_common:limit_burst(State),
-
- %% only send a synhrounous event to the disk_log process
- %% every DLSyncInt time, to give the handler time between
- %% writes so it can keep up with incoming messages
- {Status,LastQLen1,State1} =
- if DoWrite, DLSync == 0 ->
- ?observe(Name,{_CallOrCast,1}),
- NewState = disk_log_write(Name, Bin, State),
- {ok, element(2,process_info(self(),message_queue_len)),
- NewState};
- DoWrite ->
- ?observe(Name,{_CallOrCast,1}),
- NewState = disk_log_write(Name, Bin, State),
- {ok, LastQLen, NewState};
- not DoWrite ->
- ?observe(Name,{flushed,1}),
- {dropped, LastQLen, State}
- end,
-
- %% Check if the time since the previous log event is long enough -
- %% and the queue length small enough - to assume the mailbox has
- %% been emptied, and if so, do filesync operation and reset mode to
- %% async. Note that this is the best we can do to detect an idle
- %% handler without setting a timer after each log call/cast. If the
- %% time between two consecutive log events is fast and no new
- %% event comes in after the last one, idle state won't be detected!
- Time = ?diff_time(T1,T0),
- {Mode1,BurstMsgCount1,State2} =
- if (LastQLen1 < ?FILESYNC_OK_QLEN) andalso
- (Time > ?IDLE_DETECT_TIME_USEC) ->
- {?change_mode(ModeTab,Mode,async), 0, disk_log_sync(Name,State1)};
- true ->
- {Mode, BurstMsgCount,State1}
- end,
-
- State3 =
- ?update_calls_or_casts(_CallOrCast,1,State2),
- State4 =
- ?update_max_time(Time,
- State3#{mode => Mode1,
- last_qlen := LastQLen1,
- last_log_ts => T1,
- burst_win_ts => BurstWinT,
- burst_msg_count => BurstMsgCount1,
- dl_sync => ?update_dl_sync(DLSync,DLSyncInt)}),
- {Status,State4}.
-
-
-log_handler_info(Name, Format, Args, State) ->
- Config =
- case logger:get_handler_config(Name) of
- {ok,Conf} -> Conf;
- _ -> #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}
- end,
- Meta = #{time=>erlang:system_time(microsecond)},
- Bin = logger_h_common:log_to_binary(#{level => notice,
- msg => {Format,Args},
- meta => Meta}, Config),
- _ = disk_log_write(Name, Bin, State),
- ok.
-
-
open_disk_log(Name, File, Type, MaxNoBytes, MaxNoFiles) ->
case filelib:ensure_dir(File) of
ok ->
@@ -679,43 +227,26 @@ close_disk_log(Name, _) ->
_ = disk_log:lclose(Name),
ok.
-disk_log_write(Name, Bin, State) ->
- case ?disk_log_blog(Name, Bin) of
- ok ->
- State#{prev_log_result => ok, last_op => write};
- LogError ->
- _ = case maps:get(prev_log_result, State) of
- LogError ->
- %% don't report same error twice
- ok;
- _ ->
- LogOpts = maps:get(log_opts, State),
- logger_h_common:error_notify({Name,log,
- LogOpts,
- LogError})
- end,
- State#{prev_log_result => LogError}
- end.
-
-disk_log_sync(Name, State) ->
- case ?disk_log_sync(Name) of
- ok ->
- State#{prev_sync_result => ok, last_op => sync};
- SyncError ->
- _ = case maps:get(prev_sync_result, State) of
- SyncError ->
- %% don't report same error twice
- ok;
- _ ->
- LogOpts = maps:get(log_opts, State),
- logger_h_common:error_notify({Name,filesync,
- LogOpts,
- SyncError})
- end,
- State#{prev_sync_result => SyncError}
- end.
+disk_log_write(Name, sync, Bin) ->
+ disk_log:blog(Name, Bin);
+disk_log_write(Name, async, Bin) ->
+ disk_log:balog(Name, Bin).
+
+%%%-----------------------------------------------------------------
+%%% Print error messages, but don't repeat the same message
+maybe_notify_error(Name, Op, Result, Key, #{log_opts:=LogOpts}=State) ->
+ {Result,error_notify_new({Name, Op, LogOpts, Result}, Result, Key, State)}.
-error_notify_new(Info,Info, _Term) ->
+maybe_notify_status(Name, Log, Info, Key, State) ->
+ error_notify_new({disk_log, Name, Log, Info}, Info, Key, State).
+
+error_notify_new(Term, What, Key, State) ->
+ error_notify_new(What, maps:get(Key,State), Term),
+ State#{Key => What}.
+
+error_notify_new(ok,_Prev,_Term) ->
+ ok;
+error_notify_new(Same,Same,_Term) ->
ok;
-error_notify_new(_Info0,_Info1, Term) ->
+error_notify_new(_New,_Prev,Term) ->
logger_h_common:error_notify(Term).
diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl
index 456b0c9e8d..8696adbd72 100644
--- a/lib/kernel/src/logger_formatter.erl
+++ b/lib/kernel/src/logger_formatter.erl
@@ -26,16 +26,16 @@
%%%-----------------------------------------------------------------
%%% Types
--type config() :: #{chars_limit=>pos_integer()| unlimited,
- depth=>pos_integer() | unlimited,
- legacy_header=>boolean(),
- max_size=>pos_integer() | unlimited,
- report_cb=>fun((logger:report()) -> {io:format(),[term()]}),
- single_line=>boolean(),
- template=>template(),
- time_designator=>byte(),
- time_offset=>integer()|[byte()]}.
--type template() :: [metakey()|{metakey(),template(),template()}|string()].
+-type config() :: #{chars_limit => pos_integer() | unlimited,
+ depth => pos_integer() | unlimited,
+ legacy_header => boolean(),
+ max_size => pos_integer() | unlimited,
+ report_cb => logger:report_cb(),
+ single_line => boolean(),
+ template => template(),
+ time_designator => byte(),
+ time_offset => integer() | [byte()]}.
+-type template() :: [metakey() | {metakey(),template(),template()} | string()].
-type metakey() :: atom() | [atom()].
%%%-----------------------------------------------------------------
@@ -64,7 +64,7 @@ format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0)
Config;
Size0 ->
Size =
- case Size0 - string:length([B,A]) of
+ case Size0 - io_lib:chars_length([B,A]) of
S when S>=0 -> S;
_ -> 0
end,
@@ -75,15 +75,38 @@ format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0)
true ->
%% Trim leading and trailing whitespaces, and replace
%% newlines with ", "
- re:replace(string:trim(MsgStr0),",?\r?\n\s*",", ",
- [{return,list},global]);
+ T = lists:reverse(
+ trim(
+ lists:reverse(
+ trim(MsgStr0,false)),true)),
+ re:replace(T,",?\r?\n\s*",", ",
+ [{return,list},global,unicode]);
_false ->
MsgStr0
end;
true ->
""
end,
- truncate(B ++ MsgStr ++ A,maps:get(max_size,Config)).
+ truncate(B,MsgStr,A,maps:get(max_size,Config)).
+
+trim([H|T],Rev) when H==$\s; H==$\r; H==$\n ->
+ trim(T,Rev);
+trim([H|T],false) when is_list(H) ->
+ case trim(H,false) of
+ [] ->
+ trim(T,false);
+ TrimmedH ->
+ [TrimmedH|T]
+ end;
+trim([H|T],true) when is_list(H) ->
+ case trim(lists:reverse(H),true) of
+ [] ->
+ trim(T,true);
+ TrimmedH ->
+ [lists:reverse(TrimmedH)|T]
+ end;
+trim(String,_) ->
+ String.
do_format(Level,Data,[level|Format],Config) ->
[to_string(level,Level,Config)|do_format(Level,Data,Format,Config)];
@@ -119,93 +142,167 @@ value(_,_) ->
to_string(time,Time,Config) ->
format_time(Time,Config);
-to_string(mfa,MFA,_Config) ->
- format_mfa(MFA);
-to_string(_,Value,_Config) ->
- to_string(Value).
+to_string(mfa,MFA,Config) ->
+ format_mfa(MFA,Config);
+to_string(_,Value,Config) ->
+ to_string(Value,Config).
-to_string(X) when is_atom(X) ->
+to_string(X,_) when is_atom(X) ->
atom_to_list(X);
-to_string(X) when is_integer(X) ->
+to_string(X,_) when is_integer(X) ->
integer_to_list(X);
-to_string(X) when is_pid(X) ->
+to_string(X,_) when is_pid(X) ->
pid_to_list(X);
-to_string(X) when is_reference(X) ->
+to_string(X,_) when is_reference(X) ->
ref_to_list(X);
-to_string(X) when is_list(X) ->
- case io_lib:printable_unicode_list(lists:flatten(X)) of
+to_string(X,Config) when is_list(X) ->
+ case printable_list(lists:flatten(X)) of
true -> X;
- _ -> io_lib:format("~tp",[X])
+ _ -> io_lib:format(p(Config),[X])
end;
-to_string(X) ->
- io_lib:format("~tp",[X]).
+to_string(X,Config) ->
+ io_lib:format(p(Config),[X]).
+
+printable_list([]) ->
+ false;
+printable_list(X) ->
+ io_lib:printable_list(X).
format_msg({string,Chardata},Meta,Config) ->
format_msg({"~ts",[Chardata]},Meta,Config);
-format_msg({report,_}=Msg,Meta,#{report_cb:=Fun}=Config) when is_function(Fun,1) ->
+format_msg({report,_}=Msg,Meta,#{report_cb:=Fun}=Config)
+ when is_function(Fun,1); is_function(Fun,2) ->
format_msg(Msg,Meta#{report_cb=>Fun},maps:remove(report_cb,Config));
format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,1) ->
try Fun(Report) of
{Format,Args} when is_list(Format), is_list(Args) ->
format_msg({Format,Args},maps:remove(report_cb,Meta),Config);
Other ->
- format_msg({"REPORT_CB ERROR: ~tp; Returned: ~tp",
+ P = p(Config),
+ format_msg({"REPORT_CB/1 ERROR: "++P++"; Returned: "++P,
+ [Report,Other]},Meta,Config)
+ catch C:R:S ->
+ P = p(Config),
+ format_msg({"REPORT_CB/1 CRASH: "++P++"; Reason: "++P,
+ [Report,{C,R,logger:filter_stacktrace(?MODULE,S)}]},
+ Meta,Config)
+ end;
+format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,2) ->
+ try Fun(Report,maps:with([depth,chars_limit,single_line],Config)) of
+ Chardata when ?IS_STRING(Chardata) ->
+ try chardata_to_list(Chardata) % already size limited by report_cb
+ catch _:_ ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 ERROR: "++P++"; Returned: "++P,
+ [Report,Chardata]},Meta,Config)
+ end;
+ Other ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 ERROR: "++P++"; Returned: "++P,
[Report,Other]},Meta,Config)
- catch C:R ->
- format_msg({"REPORT_CB CRASH: ~tp; Reason: ~tp",
- [Report,{C,R}]},Meta,Config)
+ catch C:R:S ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 CRASH: "++P++"; Reason: "++P,
+ [Report,{C,R,logger:filter_stacktrace(?MODULE,S)}]},
+ Meta,Config)
end;
format_msg({report,Report},Meta,Config) ->
format_msg({report,Report},
Meta#{report_cb=>fun logger:format_report/1},
Config);
-format_msg(Msg,_Meta,#{depth:=Depth,chars_limit:=CharsLimit}) ->
- limit_size(Msg, Depth, CharsLimit).
-
-limit_size(Msg,Depth,unlimited) ->
- limit_size(Msg,Depth,[]);
-limit_size(Msg,Depth,CharsLimit) when is_integer(CharsLimit) ->
- limit_size(Msg,Depth,[{chars_limit,CharsLimit}]);
-limit_size({Format,Args},unlimited,Opts) when is_list(Opts) ->
- try io_lib:format(Format,Args,Opts)
- catch _:_ ->
- io_lib:format("FORMAT ERROR: ~tp - ~tp",[Format,Args],Opts)
- end;
-limit_size({Format0,Args},Depth,Opts) when is_integer(Depth) ->
+format_msg(Msg,_Meta,#{depth:=Depth,chars_limit:=CharsLimit,
+ single_line:=Single}) ->
+ Opts = chars_limit_to_opts(CharsLimit),
+ format_msg(Msg, Depth, Opts, Single).
+
+chars_limit_to_opts(unlimited) -> [];
+chars_limit_to_opts(CharsLimit) -> [{chars_limit,CharsLimit}].
+
+format_msg({Format0,Args},Depth,Opts,Single) ->
try
Format1 = io_lib:scan_format(Format0, Args),
- Format = limit_format(Format1, Depth),
+ Format = reformat(Format1, Depth, Single),
io_lib:build_text(Format,Opts)
- catch _:_ ->
- limit_size({"FORMAT ERROR: ~tp - ~tp",[Format0,Args]},Depth,Opts)
+ catch C:R:S ->
+ P = p(Single),
+ FormatError = "FORMAT ERROR: "++P++" - "++P,
+ case Format0 of
+ FormatError ->
+ %% already been here - avoid failing cyclically
+ erlang:raise(C,R,S);
+ _ ->
+ format_msg({FormatError,[Format0,Args]},Depth,Opts,Single)
+ end
end.
-limit_format([#{control_char:=C0}=M0|T], Depth) when C0 =:= $p;
- C0 =:= $w ->
- C = C0 - ($a - $A), %To uppercase.
- #{args:=Args} = M0,
- M = M0#{control_char:=C,args:=Args++[Depth]},
- [M|limit_format(T, Depth)];
-limit_format([H|T], Depth) ->
- [H|limit_format(T, Depth)];
-limit_format([], _) ->
+reformat(Format,unlimited,false) ->
+ Format;
+reformat([#{control_char:=C}=M|T], Depth, true) when C =:= $p ->
+ [limit_depth(M#{width => 0}, Depth)|reformat(T, Depth, true)];
+reformat([#{control_char:=C}=M|T], Depth, true) when C =:= $P ->
+ [M#{width => 0}|reformat(T, Depth, true)];
+reformat([#{control_char:=C}=M|T], Depth, Single) when C =:= $p; C =:= $w ->
+ [limit_depth(M, Depth)|reformat(T, Depth, Single)];
+reformat([H|T], Depth, Single) ->
+ [H|reformat(T, Depth, Single)];
+reformat([], _, _) ->
[].
-truncate(String,unlimited) ->
- String;
-truncate(String,Size) ->
- Length = string:length(String),
+limit_depth(M0, unlimited) ->
+ M0;
+limit_depth(#{control_char:=C0, args:=Args}=M0, Depth) ->
+ C = C0 - ($a - $A), %To uppercase.
+ M0#{control_char:=C,args:=Args++[Depth]}.
+
+chardata_to_list(Chardata) ->
+ case unicode:characters_to_list(Chardata,unicode) of
+ List when is_list(List) ->
+ List;
+ Error ->
+ throw(Error)
+ end.
+
+truncate(B,Msg,A,unlimited) ->
+ [B,Msg,A];
+truncate(B,Msg,A,Size) ->
+ String = [B,Msg,A],
+ Length = io_lib:chars_length(String),
if Length>Size ->
- case lists:reverse(lists:flatten(String)) of
- [$\n|_] ->
- string:slice(String,0,Size-4)++"...\n";
+ {Last,FlatString} =
+ case A of
+ [] ->
+ case Msg of
+ [] ->
+ {get_last(B),lists:flatten(B)};
+ _ ->
+ {get_last(Msg),lists:flatten([B,Msg])}
+ end;
+ _ ->
+ {get_last(A),lists:flatten(String)}
+ end,
+ case Last of
+ $\n->
+ lists:sublist(FlatString,1,Size-4)++"...\n";
_ ->
- string:slice(String,0,Size-3)++"..."
+ lists:sublist(FlatString,1,Size-3)++"..."
end;
true ->
String
end.
+get_last(L) ->
+ get_first(lists:reverse(L)).
+
+get_first([]) ->
+ error;
+get_first([C|_]) when is_integer(C) ->
+ C;
+get_first([L|Rest]) when is_list(L) ->
+ case get_last(L) of
+ error -> get_first(Rest);
+ First -> First
+ end.
+
%% SysTime is the system time in microseconds
format_time(SysTime,#{time_offset:=Offset,time_designator:=Des})
when is_integer(SysTime) ->
@@ -225,12 +322,12 @@ timestamp_to_datetimemicro(SysTime,Config) when is_integer(SysTime) ->
end,
{Date,Time,Micro,UtcStr}.
-format_mfa({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) ->
+format_mfa({M,F,A},_) when is_atom(M), is_atom(F), is_integer(A) ->
atom_to_list(M)++":"++atom_to_list(F)++"/"++integer_to_list(A);
-format_mfa({M,F,A}) when is_atom(M), is_atom(F), is_list(A) ->
- format_mfa({M,F,length(A)});
-format_mfa(MFA) ->
- to_string(MFA).
+format_mfa({M,F,A},Config) when is_atom(M), is_atom(F), is_list(A) ->
+ format_mfa({M,F,length(A)},Config);
+format_mfa(MFA,Config) ->
+ to_string(MFA,Config).
maybe_add_legacy_header(Level,
#{time:=Timestamp}=Meta,
@@ -280,10 +377,10 @@ month(12) -> "Dec".
%% configuration map
add_default_config(Config0) ->
Default =
- #{legacy_header=>false,
+ #{chars_limit=>unlimited,
error_logger_notice_header=>info,
+ legacy_header=>false,
single_line=>true,
- chars_limit=>unlimited,
time_designator=>$T},
MaxSize = get_max_size(maps:get(max_size,Config0,undefined)),
Depth = get_depth(maps:get(depth,Config0,undefined)),
@@ -369,7 +466,8 @@ do_check_config([{legacy_header,LH}|Config]) when is_boolean(LH) ->
do_check_config([{error_logger_notice_header,ELNH}|Config]) when ELNH == info;
ELNH == notice ->
do_check_config(Config);
-do_check_config([{report_cb,RCB}|Config]) when is_function(RCB,1) ->
+do_check_config([{report_cb,RCB}|Config]) when is_function(RCB,1);
+ is_function(RCB,2) ->
do_check_config(Config);
do_check_config([{template,T}|Config]) ->
case check_template(T) of
@@ -456,3 +554,10 @@ check_timezone(Tz) ->
catch _:_ ->
error
end.
+
+p(#{single_line:=Single}) ->
+ p(Single);
+p(true) ->
+ "~0tp";
+p(false) ->
+ "~tp".
diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl
index a40345dddc..16946ff97c 100644
--- a/lib/kernel/src/logger_h_common.erl
+++ b/lib/kernel/src/logger_h_common.erl
@@ -18,29 +18,362 @@
%% %CopyrightEnd%
%%
-module(logger_h_common).
+-behaviour(gen_server).
-include("logger_h_common.hrl").
-include("logger_internal.hrl").
--export([log_to_binary/2,
- check_common_config/1,
- call_cast_or_drop/4,
- check_load/1,
- limit_burst/1,
- kill_if_choked/5,
- flush_log_events/0,
- flush_log_events/1,
- handler_exit/2,
- set_restart_flag/2,
- unset_restart_flag/2,
- cancel_timer/1,
- stop_or_restart/3,
- overload_levels_ok/1,
- error_notify/1,
- info_notify/1]).
+%% API
+-export([filesync/2]).
+
+%% logger_olp callbacks
+-export([init/1, handle_load/2, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3, notify/2, reset_state/1]).
+
+%% logger callbacks
+-export([log/2, adding_handler/1, removing_handler/1, changing_config/3,
+ filter_config/1]).
+
+%% Library functions for handlers
+-export([error_notify/1]).
+
+-define(OLP_KEYS,[sync_mode_qlen,
+ drop_mode_qlen,
+ flush_qlen,
+ burst_limit_enable,
+ burst_limit_max_count,
+ burst_limit_window_time,
+ overload_kill_enable,
+ overload_kill_qlen,
+ overload_kill_mem_size,
+ overload_kill_restart_after]).
+
+-define(COMMON_KEYS,[filesync_repeat_interval]).
+
+-define(READ_ONLY_KEYS,[olp]).
+
+%%%-----------------------------------------------------------------
+%%% API
+
+%% This function is called by the logger_sup supervisor
+filesync(Module, Name) ->
+ call(Module, Name, filesync).
+
+%%%-----------------------------------------------------------------
+%%% Handler being added
+adding_handler(#{id:=Name,module:=Module}=Config) ->
+ HConfig0 = maps:get(config, Config, #{}),
+ HandlerConfig0 = maps:without(?OLP_KEYS++?COMMON_KEYS,HConfig0),
+ case Module:check_config(Name,set,undefined,HandlerConfig0) of
+ {ok,HandlerConfig} ->
+ ModifiedCommon = maps:with(?COMMON_KEYS,HandlerConfig),
+ CommonConfig0 = maps:with(?COMMON_KEYS,HConfig0),
+ CommonConfig = maps:merge(
+ maps:merge(get_default_config(), CommonConfig0),
+ ModifiedCommon),
+ case check_config(CommonConfig) of
+ ok ->
+ HConfig = maps:merge(CommonConfig,HandlerConfig),
+ OlpOpts = maps:with(?OLP_KEYS,HConfig0),
+ start(OlpOpts, Config#{config => HConfig});
+ {error,Faulty} ->
+ {error,{invalid_config,Module,Faulty}}
+ end;
+ Error ->
+ Error
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Handler being removed
+removing_handler(#{id:=Name, module:=Module, config:=#{olp:=Olp}}) ->
+ case whereis(?name_to_reg_name(Module,Name)) of
+ undefined ->
+ ok;
+ _Pid ->
+ %% We don't want to do supervisor:terminate_child here
+ %% since we need to distinguish this explicit stop from a
+ %% system termination in order to avoid circular attempts
+ %% at removing the handler (implying deadlocks and
+ %% timeouts).
+ %% And we don't need to do supervisor:delete_child, since
+ %% the restart type is temporary, which means that the
+ %% child specification is automatically removed from the
+ %% supervisor when the process dies.
+ _ = logger_olp:stop(Olp),
+ ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Updating handler config
+changing_config(SetOrUpdate,
+ #{id:=Name,config:=OldHConfig,module:=Module},
+ NewConfig0) ->
+ NewHConfig0 = maps:get(config, NewConfig0, #{}),
+ NoHandlerKeys = ?OLP_KEYS++?COMMON_KEYS++?READ_ONLY_KEYS,
+ OldHandlerConfig = maps:without(NoHandlerKeys,OldHConfig),
+ NewHandlerConfig0 = maps:without(NoHandlerKeys,NewHConfig0),
+ case Module:check_config(Name, SetOrUpdate,
+ OldHandlerConfig,NewHandlerConfig0) of
+ {ok, NewHandlerConfig} ->
+ ModifiedCommon = maps:with(?COMMON_KEYS,NewHandlerConfig),
+ NewCommonConfig0 = maps:with(?COMMON_KEYS,NewHConfig0),
+ OldCommonConfig = maps:with(?COMMON_KEYS,OldHConfig),
+ CommonDefault =
+ case SetOrUpdate of
+ set ->
+ get_default_config();
+ update ->
+ OldCommonConfig
+ end,
+ NewCommonConfig = maps:merge(
+ maps:merge(CommonDefault,NewCommonConfig0),
+ ModifiedCommon),
+ case check_config(NewCommonConfig) of
+ ok ->
+ OlpDefault =
+ case SetOrUpdate of
+ set ->
+ logger_olp:get_default_opts();
+ update ->
+ maps:with(?OLP_KEYS,OldHConfig)
+ end,
+ Olp = maps:get(olp,OldHConfig),
+ NewOlpOpts = maps:merge(OlpDefault,
+ maps:with(?OLP_KEYS,NewHConfig0)),
+ case logger_olp:set_opts(Olp,NewOlpOpts) of
+ ok ->
+ logger_olp:cast(Olp, {config_changed,
+ NewCommonConfig,
+ NewHandlerConfig}),
+ ReadOnly = maps:with(?READ_ONLY_KEYS,OldHConfig),
+ NewHConfig =
+ maps:merge(
+ maps:merge(
+ maps:merge(NewCommonConfig,NewHandlerConfig),
+ ReadOnly),
+ NewOlpOpts),
+ NewConfig = NewConfig0#{config=>NewHConfig},
+ {ok,NewConfig};
+ Error ->
+ Error
+ end;
+ {error,Faulty} ->
+ {error,{invalid_config,Module,Faulty}}
+ end;
+ Error ->
+ Error
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Log a string or report
+-spec log(LogEvent, Config) -> ok when
+ LogEvent :: logger:log_event(),
+ Config :: logger:handler_config().
+
+log(LogEvent, Config = #{config := #{olp:=Olp}}) ->
+ %% if the handler has crashed, we must drop this event
+ %% and hope the handler restarts so we can try again
+ true = is_process_alive(logger_olp:get_pid(Olp)),
+ Bin = log_to_binary(LogEvent, Config),
+ logger_olp:load(Olp,Bin).
%%%-----------------------------------------------------------------
-%%% Covert log data on any form to binary
+%%% Remove internal fields from configuration
+filter_config(#{config:=HConfig}=Config) ->
+ Config#{config=>maps:without(?READ_ONLY_KEYS,HConfig)}.
+
+%%%-----------------------------------------------------------------
+%%% Start the handler process
+%%%
+%%% The process must always exist if the handler is registered with
+%%% logger (and must not exist if the handler is not registered).
+%%%
+%%% The handler process is linked to logger_sup, which is part of the
+%%% kernel application's supervision tree.
+start(OlpOpts0, #{id := Name, module:=Module, config:=HConfig} = Config0) ->
+ RegName = ?name_to_reg_name(Module,Name),
+ ChildSpec =
+ #{id => Name,
+ start => {logger_olp, start_link, [RegName,?MODULE,
+ Config0, OlpOpts0]},
+ restart => temporary,
+ shutdown => 2000,
+ type => worker,
+ modules => [?MODULE]},
+ case supervisor:start_child(logger_sup, ChildSpec) of
+ {ok,Pid,Olp} ->
+ ok = logger_handler_watcher:register_handler(Name,Pid),
+ OlpOpts = logger_olp:get_opts(Olp),
+ {ok,Config0#{config=>(maps:merge(HConfig,OlpOpts))#{olp=>Olp}}};
+ {error,{Reason,Ch}} when is_tuple(Ch), element(1,Ch)==child ->
+ {error,Reason};
+ Error ->
+ Error
+ end.
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init(#{id := Name, module := Module, config := HConfig}) ->
+ process_flag(trap_exit, true),
+
+ ?init_test_hooks(),
+
+ case Module:init(Name, HConfig) of
+ {ok,HState} ->
+ %% Storing common config in state to avoid copying
+ %% (sending) the config data for each log message
+ CommonConfig = maps:with(?COMMON_KEYS,HConfig),
+ State = CommonConfig#{id => Name,
+ module => Module,
+ ctrl_sync_count =>
+ ?CONTROLLER_SYNC_INTERVAL,
+ last_op => sync,
+ handler_state => HState},
+ State1 = set_repeated_filesync(State),
+ {ok,State1};
+ Error ->
+ Error
+ end.
+
+%% This is the log event.
+handle_load(Bin, #{id:=Name,
+ module:=Module,
+ handler_state:=HandlerState,
+ ctrl_sync_count := CtrlSync}=State) ->
+ if CtrlSync==0 ->
+ {_,HS1} = Module:write(Name, sync, Bin, HandlerState),
+ State#{handler_state => HS1,
+ ctrl_sync_count => ?CONTROLLER_SYNC_INTERVAL,
+ last_op=>write};
+ true ->
+ {_,HS1} = Module:write(Name, async, Bin, HandlerState),
+ State#{handler_state => HS1,
+ ctrl_sync_count => CtrlSync-1,
+ last_op=>write}
+ end.
+
+handle_call(filesync, _From, State = #{id := Name,
+ module := Module,
+ handler_state := HandlerState}) ->
+ {Result,HandlerState1} = Module:filesync(Name,sync,HandlerState),
+ {reply, Result, State#{handler_state=>HandlerState1, last_op=>sync}}.
+
+%% If FILESYNC_REPEAT_INTERVAL is set to a millisec value, this
+%% clause gets called repeatedly by the handler. In order to
+%% guarantee that a filesync *always* happens after the last log
+%% event, the repeat operation must be active!
+handle_cast(repeated_filesync,State = #{filesync_repeat_interval := no_repeat}) ->
+ %% This clause handles a race condition which may occur when
+ %% config changes filesync_repeat_interval from an integer value
+ %% to no_repeat.
+ {noreply,State};
+handle_cast(repeated_filesync,
+ State = #{id := Name,
+ module := Module,
+ handler_state := HandlerState,
+ last_op := LastOp}) ->
+ State1 =
+ if LastOp == sync ->
+ State;
+ true ->
+ {_,HS} = Module:filesync(Name, async, HandlerState),
+ State#{handler_state => HS, last_op => sync}
+ end,
+ {noreply,set_repeated_filesync(State1)};
+handle_cast({config_changed, CommonConfig, HConfig},
+ State = #{id := Name,
+ module := Module,
+ handler_state := HandlerState,
+ filesync_repeat_interval := OldFSyncInt}) ->
+ State1 =
+ case maps:get(filesync_repeat_interval,CommonConfig) of
+ OldFSyncInt ->
+ State;
+ FSyncInt ->
+ set_repeated_filesync(
+ cancel_repeated_filesync(
+ State#{filesync_repeat_interval=>FSyncInt}))
+ end,
+ HS = try Module:config_changed(Name, HConfig, HandlerState)
+ catch error:undef -> HandlerState
+ end,
+ {noreply, State1#{handler_state => HS}}.
+
+handle_info(Info, #{id := Name, module := Module,
+ handler_state := HandlerState} = State) ->
+ {noreply,State#{handler_state => Module:handle_info(Name,Info,HandlerState)}}.
+
+terminate(overloaded=Reason, #{id:=Name}=State) ->
+ _ = log_handler_info(Name,"Handler ~p overloaded and stopping",[Name],State),
+ do_terminate(Reason,State),
+ ConfigResult = logger:get_handler_config(Name),
+ case ConfigResult of
+ {ok,#{module:=Module}=HConfig0} ->
+ spawn(fun() -> logger:remove_handler(Name) end),
+ HConfig = try Module:filter_config(HConfig0)
+ catch _:_ -> HConfig0
+ end,
+ {ok,fun() -> logger:add_handler(Name,Module,HConfig) end};
+ Error ->
+ error_notify({Name,restart_impossible,Error}),
+ Error
+ end;
+terminate(Reason, State) ->
+ do_terminate(Reason, State).
+
+do_terminate(Reason, State = #{id := Name,
+ module := Module,
+ handler_state := HandlerState}) ->
+ _ = cancel_repeated_filesync(State),
+ _ = Module:terminate(Name, Reason, HandlerState),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+reset_state(#{id:=Name, module:=Module, handler_state:=HandlerState} = State) ->
+ State#{handler_state=>Module:reset_state(Name, HandlerState)}.
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+call(Module, Name, Op) when is_atom(Name) ->
+ case logger_olp:call(?name_to_reg_name(Module,Name), Op) of
+ {error,busy} -> {error,handler_busy};
+ Other -> Other
+ end;
+call(_, Name, Op) ->
+ {error,{badarg,{Op,[Name]}}}.
+
+notify({mode_change,Mode0,Mode1},#{id:=Name}=State) ->
+ log_handler_info(Name,"Handler ~p switched from ~p to ~p mode",
+ [Name,Mode0,Mode1], State);
+notify({flushed,Flushed},#{id:=Name}=State) ->
+ log_handler_info(Name, "Handler ~p flushed ~w log events",
+ [Name,Flushed], State);
+notify(restart,#{id:=Name}=State) ->
+ log_handler_info(Name, "Handler ~p restarted", [Name], State);
+notify(idle,#{id:=Name,module:=Module,handler_state:=HandlerState}=State) ->
+ {_,HS} = Module:filesync(Name,async,HandlerState),
+ State#{handler_state=>HS, last_op=>sync}.
+
+log_handler_info(Name, Format, Args, #{module:=Module,
+ handler_state:=HandlerState}=State) ->
+ Config =
+ case logger:get_handler_config(Name) of
+ {ok,Conf} -> Conf;
+ _ -> #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}
+ end,
+ Meta = #{time=>logger:timestamp()},
+ Bin = log_to_binary(#{level => notice,
+ msg => {Format,Args},
+ meta => Meta}, Config),
+ {_,HS} = Module:write(Name, async, Bin, HandlerState),
+ State#{handler_state=>HS, last_op=>write}.
+
+%%%-----------------------------------------------------------------
+%%% Convert log data on any form to binary
-spec log_to_binary(LogEvent,Config) -> LogString when
LogEvent :: logger:log_event(),
Config :: logger:handler_config(),
@@ -57,13 +390,14 @@ do_log_to_binary(Log,Config) ->
{Formatter,FormatterConfig} =
maps:get(formatter,Config,{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}),
String = try_format(Log,Formatter,FormatterConfig),
- try unicode:characters_to_binary(String)
- catch _:_ ->
+ try string_to_binary(String)
+ catch C2:R2:S2 ->
?LOG_INTERNAL(debug,[{formatter_error,Formatter},
{config,FormatterConfig},
{log_event,Log},
- {bad_return_value,String}]),
- <<"FORMATTER ERROR: bad_return_value">>
+ {bad_return_value,String},
+ {catched,{C2,R2,S2}}]),
+ <<"FORMATTER ERROR: bad return value">>
end.
try_format(Log,Formatter,FormatterConfig) ->
@@ -85,254 +419,45 @@ try_format(Log,Formatter,FormatterConfig) ->
end
end.
-%%%-----------------------------------------------------------------
-%%% Check that the configuration term is valid
-check_common_config({mode_tab,_Tid}) ->
- valid;
-check_common_config({handler_pid,Pid}) when is_pid(Pid) ->
- valid;
-
-check_common_config({sync_mode_qlen,N}) when is_integer(N) ->
- valid;
-check_common_config({drop_mode_qlen,N}) when is_integer(N) ->
- valid;
-check_common_config({flush_qlen,N}) when is_integer(N) ->
- valid;
-
-check_common_config({burst_limit_enable,Bool}) when Bool == true;
- Bool == false ->
- valid;
-check_common_config({burst_limit_max_count,N}) when is_integer(N) ->
- valid;
-check_common_config({burst_limit_window_time,N}) when is_integer(N) ->
- valid;
-
-check_common_config({overload_kill_enable,Bool}) when Bool == true;
- Bool == false ->
- valid;
-check_common_config({overload_kill_qlen,N}) when is_integer(N) ->
- valid;
-check_common_config({overload_kill_mem_size,N}) when is_integer(N) ->
- valid;
-check_common_config({overload_kill_restart_after,NorA}) when is_integer(NorA);
- NorA == infinity ->
- valid;
-
-check_common_config({filesync_repeat_interval,NorA}) when is_integer(NorA);
- NorA == no_repeat ->
- valid;
-check_common_config(_) ->
- invalid.
-
+string_to_binary(String) ->
+ case unicode:characters_to_binary(String) of
+ Binary when is_binary(Binary) ->
+ Binary;
+ Error ->
+ throw(Error)
+ end.
%%%-----------------------------------------------------------------
-%%% Overload Protection
-call_cast_or_drop(_Name, HandlerPid, ModeTab, Bin) ->
- %% If the handler process is getting overloaded, the log event
- %% will be synchronous instead of asynchronous (slows down the
- %% logging tempo of a process doing lots of logging. If the
- %% handler is choked, drop mode is set and no event will be sent.
- try ?get_mode(ModeTab) of
- async ->
- gen_server:cast(HandlerPid, {log,Bin});
- sync ->
- try gen_server:call(HandlerPid, {log,Bin}, ?DEFAULT_CALL_TIMEOUT) of
- %% if return value from call == dropped, the
- %% message has been flushed by handler and should
- %% therefore not be counted as dropped in stats
- ok -> ok;
- dropped -> ok
- catch
- _:{timeout,_} ->
- ?observe(_Name,{dropped,1})
- end;
- drop ->
- ?observe(_Name,{dropped,1})
- catch
- %% if the ETS table doesn't exist (maybe because of a
- %% handler restart), we can only drop the event
- _:_ -> ?observe(_Name,{dropped,1})
- end,
- ok.
-
-handler_exit(_Name, Reason) ->
- exit(Reason).
+%%% Check that the configuration term is valid
+check_config(Config) when is_map(Config) ->
+ check_common_config(maps:to_list(Config)).
-set_restart_flag(Name, Module) ->
- Flag = list_to_atom(lists:concat([Module,"_",Name,"_restarting"])),
- spawn(fun() ->
- register(Flag, self()),
- timer:sleep(infinity)
- end),
+check_common_config([{filesync_repeat_interval,NorA}|Config])
+ when is_integer(NorA); NorA == no_repeat ->
+ check_common_config(Config);
+check_common_config([{Key,Value}|_]) ->
+ {error,#{Key=>Value}};
+check_common_config([]) ->
ok.
-unset_restart_flag(Name, Module) ->
- Flag = list_to_atom(lists:concat([Module,"_",Name,"_restarting"])),
- case whereis(Flag) of
- undefined ->
- false;
- Pid ->
- exit(Pid, kill),
- true
- end.
-
-check_load(State = #{id:=_Name, mode_tab := ModeTab, mode := Mode,
- sync_mode_qlen := SyncModeQLen,
- drop_mode_qlen := DropModeQLen,
- flush_qlen := FlushQLen}) ->
- {_,Mem} = process_info(self(), memory),
- ?observe(_Name,{max_mem,Mem}),
- {_,QLen} = process_info(self(), message_queue_len),
- ?observe(_Name,{max_qlen,QLen}),
- %% When the handler process gets scheduled in, it's impossible
- %% to predict the QLen. We could jump "up" arbitrarily from say
- %% async to sync, async to drop, sync to flush, etc. However, when
- %% the handler process manages the log events (without flushing),
- %% one after the other, we will move "down" from drop to sync and
- %% from sync to async. This way we don't risk getting stuck in
- %% drop or sync mode with an empty mailbox.
- {Mode1,_NewDrops,_NewFlushes} =
- if
- QLen >= FlushQLen ->
- {flush, 0,1};
- QLen >= DropModeQLen ->
- %% Note that drop mode will force log events to
- %% be dropped on the client side (never sent get to
- %% the handler).
- IncDrops = if Mode == drop -> 0; true -> 1 end,
- {?change_mode(ModeTab, Mode, drop), IncDrops,0};
- QLen >= SyncModeQLen ->
- {?change_mode(ModeTab, Mode, sync), 0,0};
- true ->
- {?change_mode(ModeTab, Mode, async), 0,0}
- end,
- State1 = ?update_other(drops,DROPS,_NewDrops,State),
- {Mode1, QLen, Mem,
- ?update_other(flushes,FLUSHES,_NewFlushes,
- State1#{last_qlen => QLen})}.
-
-limit_burst(#{burst_limit_enable := false}) ->
- {true,0,0};
-limit_burst(#{burst_win_ts := BurstWinT0,
- burst_msg_count := BurstMsgCount,
- burst_limit_window_time := BurstLimitWinTime,
- burst_limit_max_count := BurstLimitMaxCnt}) ->
- if (BurstMsgCount >= BurstLimitMaxCnt) ->
- %% the limit for allowed messages has been reached
- BurstWinT1 = ?timestamp(),
- case ?diff_time(BurstWinT1,BurstWinT0) of
- BurstCheckTime when BurstCheckTime < (BurstLimitWinTime*1000) ->
- %% we're still within the burst time frame
- {false,BurstWinT0,BurstMsgCount};
- _BurstCheckTime ->
- %% burst time frame passed, reset counters
- {true,BurstWinT1,0}
- end;
- true ->
- %% the limit for allowed messages not yet reached
- {true,BurstWinT0,BurstMsgCount+1}
- end.
+get_default_config() ->
+ #{filesync_repeat_interval => ?FILESYNC_REPEAT_INTERVAL}.
-kill_if_choked(Name, QLen, Mem, HandlerMod,
- State = #{overload_kill_enable := KillIfOL,
- overload_kill_qlen := OLKillQLen,
- overload_kill_mem_size := OLKillMem}) ->
- if KillIfOL andalso
- ((QLen > OLKillQLen) orelse (Mem > OLKillMem)) ->
- HandlerMod:log_handler_info(Name,
- "Handler ~p overloaded and stopping",
- [Name], State),
- set_restart_flag(Name, HandlerMod),
- handler_exit(Name, {shutdown,{overloaded,Name,QLen,Mem}});
- true ->
- ok
- end.
+set_repeated_filesync(#{filesync_repeat_interval:=FSyncInt} = State)
+ when is_integer(FSyncInt) ->
+ {ok,TRef} = timer:apply_after(FSyncInt, gen_server, cast,
+ [self(),repeated_filesync]),
+ State#{rep_sync_tref=>TRef};
+set_repeated_filesync(State) ->
+ State.
-flush_log_events() ->
- flush_log_events(-1).
-
-flush_log_events(Limit) ->
- process_flag(priority, high),
- Flushed = flush_log_events(0, Limit),
- process_flag(priority, normal),
- Flushed.
-
-flush_log_events(Limit, Limit) ->
- Limit;
-flush_log_events(N, Limit) ->
- %% flush log events but leave other events, such as
- %% filesync, info and change_config, so that these
- %% have a chance to be processed even under heavy load
- receive
- {'$gen_cast',{log,_}} ->
- flush_log_events(N+1, Limit);
- {'$gen_call',{Pid,MRef},{log,_}} ->
- Pid ! {MRef, dropped},
- flush_log_events(N+1, Limit)
- after
- 0 -> N
+cancel_repeated_filesync(State) ->
+ case maps:take(rep_sync_tref,State) of
+ {TRef,State1} ->
+ _ = timer:cancel(TRef),
+ State1;
+ error ->
+ State
end.
-
-cancel_timer(TRef) when is_atom(TRef) -> ok;
-cancel_timer(TRef) -> timer:cancel(TRef).
-
-
-stop_or_restart(Name, {shutdown,Reason={overloaded,_Name,_QLen,_Mem}},
- #{overload_kill_restart_after := RestartAfter}) ->
- %% If we're terminating because of an overload situation (see
- %% logger_h_common:kill_if_choked/4), we need to remove the handler
- %% and set a restart timer. A separate process must perform this
- %% in order to avoid deadlock.
- HandlerPid = self(),
- RemoveAndRestart =
- fun() ->
- MRef = erlang:monitor(process, HandlerPid),
- receive
- {'DOWN',MRef,_,_,_} ->
- ok
- after 30000 ->
- error_notify(Reason),
- exit(HandlerPid, kill)
- end,
- case logger:get_handler_config(Name) of
- {ok,#{module:=HMod}=HConfig} when is_integer(RestartAfter) ->
- _ = logger:remove_handler(Name),
- _ = timer:apply_after(RestartAfter, logger, add_handler,
- [Name,HMod,HConfig]);
- {ok,_} ->
- _ = logger:remove_handler(Name);
- {error,CfgReason} when is_integer(RestartAfter) ->
- error_notify({Name,restart_impossible,CfgReason});
- {error,_} ->
- ok
- end
- end,
- spawn(RemoveAndRestart),
- ok;
-
-stop_or_restart(Name, shutdown, _State) ->
- %% Probably terminated by supervisor. Remove the handler to avoid
- %% error printouts due to failing handler.
- _ = case logger:get_handler_config(Name) of
- {ok,_} ->
- %% Spawning to avoid deadlock
- spawn(logger,remove_handler,[Name]);
- _ ->
- ok
- end,
- ok;
-
-stop_or_restart(_Name, _Reason, _State) ->
- ok.
-
-overload_levels_ok(HandlerConfig) ->
- SMQL = maps:get(sync_mode_qlen, HandlerConfig, ?SYNC_MODE_QLEN),
- DMQL = maps:get(drop_mode_qlen, HandlerConfig, ?DROP_MODE_QLEN),
- FQL = maps:get(flush_qlen, HandlerConfig, ?FLUSH_QLEN),
- (DMQL > 1) andalso (SMQL =< DMQL) andalso (DMQL =< FQL).
-
error_notify(Term) ->
?internal_log(error, Term).
-
-info_notify(Term) ->
- ?internal_log(info, Term).
diff --git a/lib/kernel/src/logger_h_common.hrl b/lib/kernel/src/logger_h_common.hrl
index e0a7b6e3ca..004a61d9d9 100644
--- a/lib/kernel/src/logger_h_common.hrl
+++ b/lib/kernel/src/logger_h_common.hrl
@@ -1,50 +1,22 @@
-
-%%%-----------------------------------------------------------------
-%%% Overload protection configuration
-
-%%! *** NOTE ***
-%%! It's important that:
-%%! SYNC_MODE_QLEN =< DROP_MODE_QLEN =< FLUSH_QLEN
-%%! and that DROP_MODE_QLEN >= 2.
-%%! Otherwise the handler could end up in drop mode with no new
-%%! log requests to process. This would cause all future requests
-%%! to be dropped (no switch to async mode would ever take place).
-
-%% This specifies the message_queue_len value where the log
-%% requests switch from asynchronous casts to synchronous calls.
--define(SYNC_MODE_QLEN, 10).
-%% Above this message_queue_len, log requests will be dropped,
-%% i.e. no log requests get sent to the handler process.
--define(DROP_MODE_QLEN, 200).
-%% Above this message_queue_len, the handler process will flush
-%% its mailbox and only leave this number of messages in it.
--define(FLUSH_QLEN, 1000).
-
-%% Never flush more than this number of messages in one go,
-%% or the handler will be unresponsive for seconds (keep this
-%% number as large as possible or the mailbox could grow large).
--define(FLUSH_MAX_N, 5000).
-
-%% BURST_LIMIT_MAX_COUNT is the max number of log requests allowed
-%% to be written within a BURST_LIMIT_WINDOW_TIME time frame.
--define(BURST_LIMIT_ENABLE, true).
--define(BURST_LIMIT_MAX_COUNT, 500).
--define(BURST_LIMIT_WINDOW_TIME, 1000).
-
-%% This enables/disables the feature to automatically get the
-%% handler terminated if it gets too loaded (and can't keep up).
--define(OVERLOAD_KILL_ENABLE, false).
-%% If the message_queue_len goes above this size even after
-%% flushing has been performed, the handler is terminated.
--define(OVERLOAD_KILL_QLEN, 20000).
-%% If the memory usage exceeds this level
--define(OVERLOAD_KILL_MEM_SIZE, 3000000).
-
-%% This is the default time that the handler will wait before
-%% restarting and accepting new requests. The value 'infinity'
-%% disables restarts.
--define(OVERLOAD_KILL_RESTART_AFTER, 5000).
-%%-define(OVERLOAD_KILL_RESTART_AFTER, infinity).
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
%% The handler sends asynchronous write requests to the process
%% controlling the i/o device, but every once in this interval
@@ -65,12 +37,6 @@
-define(FILESYNC_REPEAT_INTERVAL, 5000).
%%-define(FILESYNC_REPEAT_INTERVAL, no_repeat).
-%% This is the time after last message received that we think/hope
-%% that the handler has an empty mailbox (no new log request has
-%% come in).
--define(IDLE_DETECT_TIME_MSEC, 100).
--define(IDLE_DETECT_TIME_USEC, 100000).
-
%% Default disk log option values
-define(DISK_LOG_TYPE, wrap).
-define(DISK_LOG_MAX_NO_FILES, 10).
@@ -83,43 +49,6 @@
list_to_atom(lists:concat([MODULE,"_",Name]))).
%%%-----------------------------------------------------------------
-%%% Overload protection macros
-
--define(timestamp(), erlang:monotonic_time(microsecond)).
-
--define(get_mode(Tid),
- case ets:lookup(Tid, mode) of
- [{mode,M}] -> M;
- _ -> async
- end).
-
--define(set_mode(Tid, M),
- begin ets:insert(Tid, {mode,M}), M end).
-
--define(change_mode(Tid, M0, M1),
- if M0 == M1 ->
- M0;
- true ->
- ets:insert(Tid, {mode,M1}),
- M1
- end).
-
--define(min(X1, X2),
- if X2 == undefined -> X1;
- X2 < X1 -> X2;
- true -> X1
- end).
-
--define(max(X1, X2),
- if
- X2 == undefined -> X1;
- X2 > X1 -> X2;
- true -> X1
- end).
-
--define(diff_time(OS_T1, OS_T0), OS_T1-OS_T0).
-
-%%%-----------------------------------------------------------------
%%% The test hook macros make it possible to observe and manipulate
%%% internal handler functionality. When enabled, these macros will
%%% slow down execution and therefore should not be include in code
@@ -137,7 +66,7 @@
ets:insert(?TEST_HOOKS_TAB, {internal_log,{logger,internal_log}}),
ets:insert(?TEST_HOOKS_TAB, {file_write,ok}),
ets:insert(?TEST_HOOKS_TAB, {file_datasync,ok}),
- ets:insert(?TEST_HOOKS_TAB, {disk_log_blog,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {disk_log_write,ok}),
ets:insert(?TEST_HOOKS_TAB, {disk_log_sync,ok})).
-define(set_internal_log(MOD_FUNC),
@@ -150,7 +79,7 @@
ets:insert(?TEST_HOOKS_TAB, {internal_log,{logger,internal_log}}),
ets:insert(?TEST_HOOKS_TAB, {file_write,ok}),
ets:insert(?TEST_HOOKS_TAB, {file_datasync,ok}),
- ets:insert(?TEST_HOOKS_TAB, {disk_log_blog,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {disk_log_write,ok}),
ets:insert(?TEST_HOOKS_TAB, {disk_log_sync,ok})).
-define(internal_log(TYPE, TERM),
@@ -171,11 +100,11 @@
[{_,ERROR}] -> ERROR
catch _:_ -> file:datasync(DEVICE) end).
- -define(disk_log_blog(LOG, DATA),
- try ets:lookup(?TEST_HOOKS_TAB, disk_log_blog) of
- [{_,ok}] -> disk_log:blog(LOG, DATA);
+ -define(disk_log_write(LOG, MODE, DATA),
+ try ets:lookup(?TEST_HOOKS_TAB, disk_log_write) of
+ [{_,ok}] -> disk_log_write(LOG, MODE, DATA);
[{_,ERROR}] -> ERROR
- catch _:_ -> disk_log:blog(LOG, DATA) end).
+ catch _:_ -> disk_log_write(LOG, MODE, DATA) end).
-define(disk_log_sync(LOG),
try ets:lookup(?TEST_HOOKS_TAB, disk_log_sync) of
@@ -183,7 +112,6 @@
[{_,ERROR}] -> ERROR
catch _:_ -> disk_log:sync(LOG) end).
- -define(DEFAULT_CALL_TIMEOUT, 5000).
-else. % DEFAULTS!
-define(TEST_HOOKS_TAB, undefined).
@@ -194,70 +122,6 @@
-define(internal_log(TYPE, TERM), logger:internal_log(TYPE, TERM)).
-define(file_write(DEVICE, DATA), file:write(DEVICE, DATA)).
-define(file_datasync(DEVICE), file:datasync(DEVICE)).
- -define(disk_log_blog(LOG, DATA), disk_log:blog(LOG, DATA)).
+ -define(disk_log_write(LOG, MODE, DATA), disk_log_write(LOG, MODE, DATA)).
-define(disk_log_sync(LOG), disk_log:sync(LOG)).
- -define(DEFAULT_CALL_TIMEOUT, 10000).
--endif.
-
-%%%-----------------------------------------------------------------
-%%% These macros enable statistics counters in the state of the
-%%% handler which is useful for analysing the overload protection
-%%% behaviour. These counters should not be included in code to be
-%%% officially released (as some counters will grow very large
-%%% over time).
-
-%%-define(SAVE_STATS, true).
--ifdef(SAVE_STATS).
- -define(merge_with_stats(STATE),
- STATE#{flushes => 0, flushed => 0, drops => 0,
- casts => 0, calls => 0,
- max_qlen => 0, max_time => 0}).
-
- -define(update_max_qlen(QLEN, STATE),
- begin #{max_qlen := QLEN0} = STATE,
- STATE#{max_qlen => ?max(QLEN0,QLEN)} end).
-
- -define(update_calls_or_casts(CALL_OR_CAST, INC, STATE),
- case CALL_OR_CAST of
- cast ->
- #{casts := CASTS0} = STATE,
- STATE#{casts => CASTS0+INC};
- call ->
- #{calls := CALLS0} = STATE,
- STATE#{calls => CALLS0+INC}
- end).
-
- -define(update_max_time(TIME, STATE),
- begin #{max_time := TIME0} = STATE,
- STATE#{max_time => ?max(TIME0,TIME)} end).
-
- -define(update_other(OTHER, VAR, INCVAL, STATE),
- begin #{OTHER := VAR} = STATE,
- STATE#{OTHER => VAR+INCVAL} end).
-
--else. % DEFAULT!
- -define(merge_with_stats(STATE), STATE).
- -define(update_max_qlen(_QLEN, STATE), STATE).
- -define(update_calls_or_casts(_CALL_OR_CAST, _INC, STATE), STATE).
- -define(update_max_time(_TIME, STATE), STATE).
- -define(update_other(_OTHER, _VAR, _INCVAL, STATE), STATE).
--endif.
-
-%%%-----------------------------------------------------------------
-%%% These macros enable callbacks that make it possible to analyse
-%%% the overload protection behaviour from outside the handler
-%%% process (including dropped requests on the client side).
-%%% An external callback module (?OBSERVER_MOD) is required which
-%%% is not part of the kernel application. For this reason, these
-%%% callbacks should not be included in code to be officially released.
-
-%%-define(OBSERVER_MOD, logger_test).
--ifdef(OBSERVER_MOD).
- -define(start_observation(NAME), ?OBSERVER:start_observation(NAME)).
- -define(observe(NAME,EVENT), ?OBSERVER:observe(NAME,EVENT)).
-
--else. % DEFAULT!
- -define(start_observation(_NAME), ok).
- -define(observe(_NAME,_EVENT), ok).
-endif.
-%%! <---
diff --git a/lib/kernel/src/logger_handler_watcher.erl b/lib/kernel/src/logger_handler_watcher.erl
new file mode 100644
index 0000000000..b75c74c643
--- /dev/null
+++ b/lib/kernel/src/logger_handler_watcher.erl
@@ -0,0 +1,113 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_handler_watcher).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+-export([register_handler/2]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {handlers}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+-spec start_link() -> {ok, Pid :: pid()} |
+ {error, Error :: {already_started, pid()}} |
+ {error, Error :: term()} |
+ ignore.
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+-spec register_handler(Id::logger:handler_id(),Pid::pid()) -> ok.
+register_handler(Id,Pid) ->
+ gen_server:call(?SERVER,{register,Id,Pid}).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+-spec init(Args :: term()) -> {ok, State :: term()} |
+ {ok, State :: term(), Timeout :: timeout()} |
+ {ok, State :: term(), hibernate} |
+ {stop, Reason :: term()} |
+ ignore.
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, #state{handlers=[]}}.
+
+-spec handle_call(Request :: term(), From :: {pid(), term()}, State :: term()) ->
+ {reply, Reply :: term(), NewState :: term()} |
+ {reply, Reply :: term(), NewState :: term(), Timeout :: timeout()} |
+ {reply, Reply :: term(), NewState :: term(), hibernate} |
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
+ {stop, Reason :: term(), NewState :: term()}.
+handle_call({register,Id,Pid}, _From, #state{handlers=Hs}=State) ->
+ Ref = erlang:monitor(process,Pid),
+ Hs1 = lists:keystore(Id,1,Hs,{Id,Ref}),
+ {reply, ok, State#state{handlers=Hs1}}.
+
+-spec handle_cast(Request :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+handle_cast(_Request, State) ->
+ {noreply, State}.
+
+-spec handle_info(Info :: timeout() | term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: normal | term(), NewState :: term()}.
+handle_info({'DOWN',Ref,process,_,shutdown}, #state{handlers=Hs}=State) ->
+ case lists:keytake(Ref,2,Hs) of
+ {value,{Id,Ref},Hs1} ->
+ %% Probably terminated by supervisor. Remove the handler to avoid
+ %% error printouts due to failing handler.
+ _ = case logger:get_handler_config(Id) of
+ {ok,_} ->
+ logger:remove_handler(Id);
+ _ ->
+ ok
+ end,
+ {noreply,State#state{handlers=Hs1}};
+ false ->
+ {noreply, State}
+ end;
+handle_info({'DOWN',Ref,process,_,_OtherReason}, #state{handlers=Hs}=State) ->
+ {noreply,State#state{handlers=lists:keydelete(Ref,2,Hs)}};
+handle_info(_Other,State) ->
+ {noreply,State}.
+
+-spec terminate(Reason :: normal | shutdown | {shutdown, term()} | term(),
+ State :: term()) -> any().
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/kernel/src/logger_internal.hrl b/lib/kernel/src/logger_internal.hrl
index d96a4ac78b..e53922e5d3 100644
--- a/lib/kernel/src/logger_internal.hrl
+++ b/lib/kernel/src/logger_internal.hrl
@@ -19,6 +19,7 @@
%%
-include_lib("kernel/include/logger.hrl").
-define(LOGGER_TABLE,logger).
+-define(PROXY_KEY,'$proxy_config$').
-define(PRIMARY_KEY,'$primary_config$').
-define(HANDLER_KEY,'$handler_config$').
-define(LOGGER_META_KEY,'$logger_metadata$').
@@ -40,12 +41,14 @@
-define(DEFAULT_LOGGER_CALL_TIMEOUT, infinity).
--define(LOG_INTERNAL(Level,Report),
+-define(LOG_INTERNAL(Level,Report),?DO_LOG_INTERNAL(Level,[Report])).
+-define(LOG_INTERNAL(Level,Format,Args),?DO_LOG_INTERNAL(Level,[Format,Args])).
+-define(DO_LOG_INTERNAL(Level,Data),
case logger:allow(Level,?MODULE) of
true ->
%% Spawn this to avoid deadlocks
- _ = spawn(logger,macro_log,[?LOCATION,Level,Report,
- logger:add_default_metadata(#{})]),
+ _ = spawn(logger,macro_log,[?LOCATION,Level|Data]++
+ [logger:add_default_metadata(#{})]),
ok;
false ->
ok
diff --git a/lib/kernel/src/logger_olp.erl b/lib/kernel/src/logger_olp.erl
new file mode 100644
index 0000000000..8365383fe2
--- /dev/null
+++ b/lib/kernel/src/logger_olp.erl
@@ -0,0 +1,627 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_olp).
+-behaviour(gen_server).
+
+-include("logger_olp.hrl").
+-include("logger_internal.hrl").
+
+%% API
+-export([start_link/4, load/2, info/1, reset/1, stop/1, restart/1,
+ set_opts/2, get_opts/1, get_default_opts/0, get_pid/1,
+ call/2, cast/2, get_ref/0, get_ref/1]).
+
+%% gen_server and proc_lib callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(OPT_KEYS,[sync_mode_qlen,
+ drop_mode_qlen,
+ flush_qlen,
+ burst_limit_enable,
+ burst_limit_max_count,
+ burst_limit_window_time,
+ overload_kill_enable,
+ overload_kill_qlen,
+ overload_kill_mem_size,
+ overload_kill_restart_after]).
+
+-export_type([olp_ref/0, options/0]).
+
+-opaque olp_ref() :: {atom(),pid(),ets:tid()}.
+
+-type options() :: logger:olp_config().
+
+%%%-----------------------------------------------------------------
+%%% API
+
+-spec start_link(Name,Module,Args,Options) -> {ok,Pid,Olp} | {error,Reason} when
+ Name :: atom(),
+ Module :: module(),
+ Args :: term(),
+ Options :: options(),
+ Pid :: pid(),
+ Olp :: olp_ref(),
+ Reason :: term().
+start_link(Name,Module,Args,Options0) when is_map(Options0) ->
+ Options = maps:merge(get_default_opts(),Options0),
+ case check_opts(Options) of
+ ok ->
+ proc_lib:start_link(?MODULE,init,[[Name,Module,Args,Options]]);
+ Error ->
+ Error
+ end.
+
+-spec load(Olp, Msg) -> ok when
+ Olp :: olp_ref(),
+ Msg :: term().
+load({_Name,Pid,ModeRef},Msg) ->
+ %% If the process is getting overloaded, the message will be
+ %% synchronous instead of asynchronous (slows down the tempo of a
+ %% process causing much load). If the process is choked, drop mode
+ %% is set and no message is sent.
+ try ?get_mode(ModeRef) of
+ async ->
+ gen_server:cast(Pid, {'$olp_load',Msg});
+ sync ->
+ case call(Pid, {'$olp_load',Msg}) of
+ ok ->
+ ok;
+ _Other ->
+ %% dropped or {error,busy}
+ ?observe(_Name,{dropped,1}),
+ ok
+ end;
+ drop ->
+ ?observe(_Name,{dropped,1})
+ catch
+ %% if the ETS table doesn't exist (maybe because of a
+ %% process restart), we can only drop the event
+ _:_ -> ?observe(_Name,{dropped,1})
+ end,
+ ok.
+
+-spec info(Olp) -> map() | {error, busy} when
+ Olp :: atom() | pid() | olp_ref().
+info(Olp) ->
+ call(Olp, info).
+
+-spec reset(Olp) -> ok | {error, busy} when
+ Olp :: atom() | pid() | olp_ref().
+reset(Olp) ->
+ call(Olp, reset).
+
+-spec stop(Olp) -> ok when
+ Olp :: atom() | pid() | olp_ref().
+stop({_Name,Pid,_ModRef}) ->
+ stop(Pid);
+stop(Pid) ->
+ _ = gen_server:call(Pid, stop),
+ ok.
+
+-spec set_opts(Olp, Opts) -> ok | {error,term()} | {error, busy} when
+ Olp :: atom() | pid() | olp_ref(),
+ Opts :: options().
+set_opts(Olp, Opts) ->
+ call(Olp, {set_opts,Opts}).
+
+-spec get_opts(Olp) -> options() | {error, busy} when
+ Olp :: atom() | pid() | olp_ref().
+get_opts(Olp) ->
+ call(Olp, get_opts).
+
+-spec get_default_opts() -> options().
+get_default_opts() ->
+ #{sync_mode_qlen => ?SYNC_MODE_QLEN,
+ drop_mode_qlen => ?DROP_MODE_QLEN,
+ flush_qlen => ?FLUSH_QLEN,
+ burst_limit_enable => ?BURST_LIMIT_ENABLE,
+ burst_limit_max_count => ?BURST_LIMIT_MAX_COUNT,
+ burst_limit_window_time => ?BURST_LIMIT_WINDOW_TIME,
+ overload_kill_enable => ?OVERLOAD_KILL_ENABLE,
+ overload_kill_qlen => ?OVERLOAD_KILL_QLEN,
+ overload_kill_mem_size => ?OVERLOAD_KILL_MEM_SIZE,
+ overload_kill_restart_after => ?OVERLOAD_KILL_RESTART_AFTER}.
+
+-spec restart(fun(() -> any())) -> ok.
+restart(Fun) ->
+ Result =
+ try Fun()
+ catch C:R:S ->
+ {error,{restart_failed,Fun,C,R,S}}
+ end,
+ ?LOG_INTERNAL(debug,[{logger_olp,restart},
+ {result,Result}]),
+ ok.
+
+-spec get_ref() -> olp_ref().
+get_ref() ->
+ get(olp_ref).
+
+-spec get_ref(PidOrName) -> olp_ref() | {error, busy} when
+ PidOrName :: pid() | atom().
+get_ref(PidOrName) ->
+ call(PidOrName,get_ref).
+
+-spec get_pid(olp_ref()) -> pid().
+get_pid({_Name,Pid,_ModeRef}) ->
+ Pid.
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init([Name,Module,Args,Options]) ->
+ register(Name, self()),
+ process_flag(message_queue_data, off_heap),
+
+ ?start_observation(Name),
+
+ try ets:new(Name, [public]) of
+ ModeRef ->
+ OlpRef = {Name,self(),ModeRef},
+ put(olp_ref,OlpRef),
+ try Module:init(Args) of
+ {ok,CBState} ->
+ ?set_mode(ModeRef, async),
+ T0 = ?timestamp(),
+ proc_lib:init_ack({ok,self(),OlpRef}),
+ %% Storing options in state to avoid copying
+ %% (sending) the option data with each message
+ State0 = ?merge_with_stats(
+ Options#{id => Name,
+ idle=> true,
+ module => Module,
+ mode_ref => ModeRef,
+ mode => async,
+ last_qlen => 0,
+ last_load_ts => T0,
+ burst_win_ts => T0,
+ burst_msg_count => 0,
+ cb_state => CBState}),
+ State = reset_restart_flag(State0),
+ gen_server:enter_loop(?MODULE, [], State);
+ Error ->
+ _ = ets:delete(ModeRef),
+ unregister(Name),
+ proc_lib:init_ack(Error)
+ catch
+ _:Error ->
+ _ = ets:delete(ModeRef),
+ unregister(Name),
+ proc_lib:init_ack(Error)
+ end
+ catch
+ _:Error ->
+ unregister(Name),
+ proc_lib:init_ack(Error)
+ end.
+
+%% This is the synchronous load event.
+handle_call({'$olp_load', Msg}, _From, State) ->
+ {Result,State1} = do_load(Msg, call, State#{idle=>false}),
+ %% Result == ok | dropped
+ reply_return(Result,State1);
+
+handle_call(get_ref,_From,#{id:=Name,mode_ref:=ModeRef}=State) ->
+ reply_return({Name,self(),ModeRef},State);
+
+handle_call({set_opts,Opts0},_From,State) ->
+ Opts = maps:merge(maps:with(?OPT_KEYS,State),Opts0),
+ case check_opts(Opts) of
+ ok ->
+ reply_return(ok, maps:merge(State,Opts));
+ Error ->
+ reply_return(Error, State)
+ end;
+
+handle_call(get_opts,_From,State) ->
+ reply_return(maps:with(?OPT_KEYS,State), State);
+
+handle_call(info, _From, State) ->
+ reply_return(State, State);
+
+handle_call(reset, _From, #{module:=Module,cb_state:=CBState}=State) ->
+ State1 = ?merge_with_stats(State),
+ CBState1 = try_callback_call(Module,reset_state,[CBState],CBState),
+ reply_return(ok, State1#{idle => true,
+ last_qlen => 0,
+ last_load_ts => ?timestamp(),
+ cb_state => CBState1});
+
+handle_call(stop, _From, State) ->
+ {stop, {shutdown,stopped}, ok, State};
+
+handle_call(Msg, From, #{module:=Module,cb_state:=CBState}=State) ->
+ case try_callback_call(Module,handle_call,[Msg, From, CBState]) of
+ {reply,Reply,CBState1} ->
+ reply_return(Reply,State#{cb_state=>CBState1});
+ {noreply,CBState1} ->
+ noreply_return(State#{cb_state=>CBState1});
+ {stop, Reason, Reply, CBState1} ->
+ {stop, Reason, Reply, State#{cb_state=>CBState1}};
+ {stop, Reason, CBState1} ->
+ {stop, Reason, State#{cb_state=>CBState1}}
+ end.
+
+%% This is the asynchronous load event.
+handle_cast({'$olp_load', Msg}, State) ->
+ {_Result,State1} = do_load(Msg, cast, State#{idle=>false}),
+ noreply_return(State1);
+
+handle_cast(Msg, #{module:=Module, cb_state:=CBState} = State) ->
+ case try_callback_call(Module,handle_cast,[Msg, CBState]) of
+ {noreply,CBState1} ->
+ noreply_return(State#{cb_state=>CBState1});
+ {stop, Reason, CBState1} ->
+ {stop, Reason, State#{cb_state=>CBState1}}
+ end.
+
+handle_info(timeout, #{mode_ref:=_ModeRef, mode:=Mode} = State) ->
+ State1 = notify(idle,State),
+ State2 = maybe_notify_mode_change(async,State1),
+ {noreply, State2#{idle => true,
+ mode => ?change_mode(_ModeRef, Mode, async),
+ burst_msg_count => 0}};
+handle_info(Msg, #{module := Module, cb_state := CBState} = State) ->
+ case try_callback_call(Module,handle_info,[Msg, CBState]) of
+ {noreply,CBState1} ->
+ noreply_return(State#{cb_state=>CBState1});
+ {stop, Reason, CBState1} ->
+ {stop, Reason, State#{cb_state=>CBState1}};
+ {load,CBState1} ->
+ {_,State1} = do_load(Msg, cast, State#{idle=>false,
+ cb_state=>CBState1}),
+ noreply_return(State1)
+ end.
+
+terminate({shutdown,{overloaded,_QLen,_Mem}},
+ #{id:=Name, module := Module, cb_state := CBState,
+ overload_kill_restart_after := RestartAfter} = State) ->
+ %% We're terminating because of an overload situation (see
+ %% kill_if_choked/3).
+ unregister(Name), %%!!!! to avoid error printout of callback crashed on stop
+ case try_callback_call(Module,terminate,[overloaded,CBState],ok) of
+ {ok,Fun} when is_function(Fun,0), is_integer(RestartAfter) ->
+ set_restart_flag(State),
+ _ = timer:apply_after(RestartAfter,?MODULE,restart,[Fun]),
+ ok;
+ _ ->
+ ok
+ end;
+terminate(Reason, #{id:=Name, module:=Module, cb_state:=CBState}) ->
+ _ = try_callback_call(Module,terminate,[Reason,CBState],ok),
+ unregister(Name),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+-spec call(Olp, term()) -> term() | {error,busy} when
+ Olp :: atom() | pid() | olp_ref().
+call({_Name, Pid, _ModeRef},Msg) ->
+ call(Pid, Msg);
+call(Server, Msg) ->
+ try
+ gen_server:call(Server, Msg)
+ catch
+ _:{timeout,_} -> {error,busy}
+ end.
+
+-spec cast(olp_ref(),term()) -> ok.
+cast({_Name, Pid, _ModeRef},Msg) ->
+ gen_server:cast(Pid, Msg).
+
+%% check for overload between every event (and set Mode to async,
+%% sync or drop accordingly), but never flush the whole mailbox
+%% before LogWindowSize events have been handled
+do_load(Msg, CallOrCast, State) ->
+ T1 = ?timestamp(),
+ State1 = ?update_time(T1,State),
+
+ %% check if the process is getting overloaded, or if it's
+ %% recovering from overload (the check must be done for each
+ %% event to react quickly to large bursts of events and
+ %% to ensure that the handler can never end up in drop mode
+ %% with an empty mailbox, which would stop operation)
+ {Mode1,QLen,Mem,State2} = check_load(State1),
+
+ %% kill the handler if it can't keep up with the load
+ kill_if_choked(QLen, Mem, State2),
+
+ if Mode1 == flush ->
+ flush(T1, State2);
+ true ->
+ handle_load(Mode1, T1, Msg, CallOrCast, State2)
+ end.
+
+%% this function is called by do_load/3 after an overload check
+%% has been performed, where QLen > FlushQLen
+flush(T1, State=#{id := _Name, mode := Mode, last_load_ts := _T0, mode_ref := ModeRef}) ->
+ %% flush load messages in the mailbox (a limited number in order
+ %% to not cause long delays)
+ NewFlushed = flush_load(?FLUSH_MAX_N),
+
+ %% write info in log about flushed messages
+ State1=notify({flushed,NewFlushed},State),
+
+ %% because of the receive loop when flushing messages, the
+ %% handler will be scheduled out often and the mailbox could
+ %% grow very large, so we'd better check the queue again here
+ {_,QLen1} = process_info(self(), message_queue_len),
+ ?observe(_Name,{max_qlen,QLen1}),
+
+ %% Add 1 for the current log event
+ ?observe(_Name,{flushed,NewFlushed+1}),
+
+ State2 = ?update_max_time(?diff_time(T1,_T0),State1),
+ State3 = ?update_max_qlen(QLen1,State2),
+ State4 = maybe_notify_mode_change(async,State3),
+ {dropped,?update_other(flushed,FLUSHED,NewFlushed,
+ State4#{mode => ?change_mode(ModeRef,Mode,async),
+ last_qlen => QLen1,
+ last_load_ts => T1})}.
+
+%% this function is called to actually handle the message
+handle_load(Mode, T1, Msg, _CallOrCast,
+ State = #{id := _Name,
+ module := Module,
+ cb_state := CBState,
+ last_qlen := LastQLen,
+ last_load_ts := _T0}) ->
+ %% check if we need to limit the number of writes
+ %% during a burst of log events
+ {DoWrite,State1} = limit_burst(State),
+
+ {Result,LastQLen1,CBState1} =
+ if DoWrite ->
+ ?observe(_Name,{_CallOrCast,1}),
+ CBS = try_callback_call(Module,handle_load,[Msg,CBState]),
+ {ok,element(2, process_info(self(), message_queue_len)),CBS};
+ true ->
+ ?observe(_Name,{flushed,1}),
+ {dropped,LastQLen,CBState}
+ end,
+ State2 = State1#{cb_state=>CBState1},
+
+ State3 = State2#{mode => Mode},
+ State4 = ?update_calls_or_casts(_CallOrCast,1,State3),
+ State5 = ?update_max_qlen(LastQLen1,State4),
+ State6 =
+ ?update_max_time(?diff_time(T1,_T0),
+ State5#{last_qlen := LastQLen1,
+ last_load_ts => T1}),
+ State7 = case Result of
+ ok ->
+ S = ?update_freq(T1,State6),
+ ?update_other(writes,WRITES,1,S);
+ _ ->
+ State6
+ end,
+ {Result,State7}.
+
+
+%%%-----------------------------------------------------------------
+%%% Check that the options are valid
+check_opts(Options) when is_map(Options) ->
+ case do_check_opts(maps:to_list(Options)) of
+ ok ->
+ case overload_levels_ok(Options) of
+ true ->
+ ok;
+ false ->
+ Faulty = maps:with([sync_mode_qlen,
+ drop_mode_qlen,
+ flush_qlen],Options),
+ {error,{invalid_olp_levels,Faulty}}
+ end;
+ {error,Key,Value} ->
+ {error,{invalid_olp_config,#{Key=>Value}}}
+ end.
+
+do_check_opts([{sync_mode_qlen,N}|Options]) when is_integer(N) ->
+ do_check_opts(Options);
+do_check_opts([{drop_mode_qlen,N}|Options]) when is_integer(N) ->
+ do_check_opts(Options);
+do_check_opts([{flush_qlen,N}|Options]) when is_integer(N) ->
+ do_check_opts(Options);
+do_check_opts([{burst_limit_enable,Bool}|Options]) when is_boolean(Bool) ->
+ do_check_opts(Options);
+do_check_opts([{burst_limit_max_count,N}|Options]) when is_integer(N) ->
+ do_check_opts(Options);
+do_check_opts([{burst_limit_window_time,N}|Options]) when is_integer(N) ->
+ do_check_opts(Options);
+do_check_opts([{overload_kill_enable,Bool}|Options]) when is_boolean(Bool) ->
+ do_check_opts(Options);
+do_check_opts([{overload_kill_qlen,N}|Options]) when is_integer(N) ->
+ do_check_opts(Options);
+do_check_opts([{overload_kill_mem_size,N}|Options]) when is_integer(N) ->
+ do_check_opts(Options);
+do_check_opts([{overload_kill_restart_after,NorA}|Options])
+ when is_integer(NorA); NorA == infinity ->
+ do_check_opts(Options);
+do_check_opts([{Key,Value}|_]) ->
+ {error,Key,Value};
+do_check_opts([]) ->
+ ok.
+
+set_restart_flag(#{id := Name, module := Module}) ->
+ Flag = list_to_atom(lists:concat([Module,"_",Name,"_restarting"])),
+ spawn(fun() ->
+ register(Flag, self()),
+ timer:sleep(infinity)
+ end),
+ ok.
+
+reset_restart_flag(#{id := Name, module := Module} = State) ->
+ Flag = list_to_atom(lists:concat([Module,"_",Name,"_restarting"])),
+ case whereis(Flag) of
+ undefined ->
+ State;
+ Pid ->
+ exit(Pid, kill),
+ notify(restart,State)
+ end.
+
+check_load(State = #{id:=_Name, mode_ref := ModeRef, mode := Mode,
+ sync_mode_qlen := SyncModeQLen,
+ drop_mode_qlen := DropModeQLen,
+ flush_qlen := FlushQLen}) ->
+ {_,Mem} = process_info(self(), memory),
+ ?observe(_Name,{max_mem,Mem}),
+ {_,QLen} = process_info(self(), message_queue_len),
+ ?observe(_Name,{max_qlen,QLen}),
+ %% When the handler process gets scheduled in, it's impossible
+ %% to predict the QLen. We could jump "up" arbitrarily from say
+ %% async to sync, async to drop, sync to flush, etc. However, when
+ %% the handler process manages the log events (without flushing),
+ %% one after the other, we will move "down" from drop to sync and
+ %% from sync to async. This way we don't risk getting stuck in
+ %% drop or sync mode with an empty mailbox.
+ {Mode1,_NewDrops,_NewFlushes} =
+ if
+ QLen >= FlushQLen ->
+ {flush, 0,1};
+ QLen >= DropModeQLen ->
+ %% Note that drop mode will force load messages to
+ %% be dropped on the client side (never sent to
+ %% the olp process).
+ IncDrops = if Mode == drop -> 0; true -> 1 end,
+ {?change_mode(ModeRef, Mode, drop), IncDrops,0};
+ QLen >= SyncModeQLen ->
+ {?change_mode(ModeRef, Mode, sync), 0,0};
+ true ->
+ {?change_mode(ModeRef, Mode, async), 0,0}
+ end,
+ State1 = ?update_other(drops,DROPS,_NewDrops,State),
+ State2 = ?update_max_qlen(QLen,State1),
+ State3 = ?update_max_mem(Mem,State2),
+ State4 = maybe_notify_mode_change(Mode1,State3),
+ {Mode1, QLen, Mem,
+ ?update_other(flushes,FLUSHES,_NewFlushes,
+ State4#{last_qlen => QLen})}.
+
+limit_burst(#{burst_limit_enable := false}=State) ->
+ {true,State};
+limit_burst(#{burst_win_ts := BurstWinT0,
+ burst_msg_count := BurstMsgCount,
+ burst_limit_window_time := BurstLimitWinTime,
+ burst_limit_max_count := BurstLimitMaxCnt} = State) ->
+ if (BurstMsgCount >= BurstLimitMaxCnt) ->
+ %% the limit for allowed messages has been reached
+ BurstWinT1 = ?timestamp(),
+ case ?diff_time(BurstWinT1,BurstWinT0) of
+ BurstCheckTime when BurstCheckTime < (BurstLimitWinTime*1000) ->
+ %% we're still within the burst time frame
+ {false,?update_other(burst_drops,BURSTS,1,State)};
+ _BurstCheckTime ->
+ %% burst time frame passed, reset counters
+ {true,State#{burst_win_ts => BurstWinT1,
+ burst_msg_count => 0}}
+ end;
+ true ->
+ %% the limit for allowed messages not yet reached
+ {true,State#{burst_win_ts => BurstWinT0,
+ burst_msg_count => BurstMsgCount+1}}
+ end.
+
+kill_if_choked(QLen, Mem, #{overload_kill_enable := KillIfOL,
+ overload_kill_qlen := OLKillQLen,
+ overload_kill_mem_size := OLKillMem}) ->
+ if KillIfOL andalso
+ ((QLen > OLKillQLen) orelse (Mem > OLKillMem)) ->
+ exit({shutdown,{overloaded,QLen,Mem}});
+ true ->
+ ok
+ end.
+
+flush_load(Limit) ->
+ process_flag(priority, high),
+ Flushed = flush_load(0, Limit),
+ process_flag(priority, normal),
+ Flushed.
+
+flush_load(Limit, Limit) ->
+ Limit;
+flush_load(N, Limit) ->
+ %% flush log events but leave other events, such as info, reset
+ %% and stop, so that these have a chance to be processed even
+ %% under heavy load
+ receive
+ {'$gen_cast',{'$olp_load',_}} ->
+ flush_load(N+1, Limit);
+ {'$gen_call',{Pid,MRef},{'$olp_load',_}} ->
+ Pid ! {MRef, dropped},
+ flush_load(N+1, Limit);
+ {log,_,_,_,_} ->
+ flush_load(N+1, Limit);
+ {log,_,_,_} ->
+ flush_load(N+1, Limit)
+ after
+ 0 -> N
+ end.
+
+overload_levels_ok(Options) ->
+ SMQL = maps:get(sync_mode_qlen, Options, ?SYNC_MODE_QLEN),
+ DMQL = maps:get(drop_mode_qlen, Options, ?DROP_MODE_QLEN),
+ FQL = maps:get(flush_qlen, Options, ?FLUSH_QLEN),
+ (DMQL > 1) andalso (SMQL =< DMQL) andalso (DMQL =< FQL).
+
+maybe_notify_mode_change(drop,#{mode:=Mode0}=State)
+ when Mode0=/=drop ->
+ notify({mode_change,Mode0,drop},State);
+maybe_notify_mode_change(Mode1,#{mode:=drop}=State)
+ when Mode1==async; Mode1==sync ->
+ notify({mode_change,drop,Mode1},State);
+maybe_notify_mode_change(_,State) ->
+ State.
+
+notify(Note,#{module:=Module,cb_state:=CBState}=State) ->
+ CBState1 = try_callback_call(Module,notify,[Note,CBState],CBState),
+ State#{cb_state=>CBState1}.
+
+try_callback_call(Module, Function, Args) ->
+ try_callback_call(Module, Function, Args, '$no_default_return').
+
+try_callback_call(Module, Function, Args, DefRet) ->
+ try apply(Module, Function, Args)
+ catch
+ throw:R -> R;
+ error:undef:S when DefRet=/='$no_default_return' ->
+ case S of
+ [{Module,Function,Args,_}|_] ->
+ DefRet;
+ _ ->
+ erlang:raise(error,undef,S)
+ end
+ end.
+
+noreply_return(#{idle:=true}=State) ->
+ {noreply,State};
+noreply_return(#{idle:=false}=State) ->
+ {noreply,State,?IDLE_DETECT_TIME}.
+
+reply_return(Reply,#{idle:=true}=State) ->
+ {reply,Reply,State};
+reply_return(Reply,#{idle:=false}=State) ->
+ {reply,Reply,State,?IDLE_DETECT_TIME}.
diff --git a/lib/kernel/src/logger_olp.hrl b/lib/kernel/src/logger_olp.hrl
new file mode 100644
index 0000000000..d68b5c048d
--- /dev/null
+++ b/lib/kernel/src/logger_olp.hrl
@@ -0,0 +1,185 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-----------------------------------------------------------------
+%%% Overload protection configuration
+
+%%! *** NOTE ***
+%%! It's important that:
+%%! SYNC_MODE_QLEN =< DROP_MODE_QLEN =< FLUSH_QLEN
+%%! and that DROP_MODE_QLEN >= 2.
+%%! Otherwise the process could end up in drop mode with no new
+%%! log requests to process. This would cause all future requests
+%%! to be dropped (no switch to async mode would ever take place).
+
+%% This specifies the message_queue_len value where the log
+%% requests switch from asynchronous casts to synchronous calls.
+-define(SYNC_MODE_QLEN, 10).
+%% Above this message_queue_len, log requests will be dropped,
+%% i.e. no log requests get sent to the process.
+-define(DROP_MODE_QLEN, 200).
+%% Above this message_queue_len, the process will flush its mailbox
+%% and only leave this number of messages in it.
+-define(FLUSH_QLEN, 1000).
+
+%% Never flush more than this number of messages in one go, or the
+%% process will be unresponsive for seconds (keep this number as large
+%% as possible or the mailbox could grow large).
+-define(FLUSH_MAX_N, 5000).
+
+%% BURST_LIMIT_MAX_COUNT is the max number of log requests allowed
+%% to be written within a BURST_LIMIT_WINDOW_TIME time frame.
+-define(BURST_LIMIT_ENABLE, true).
+-define(BURST_LIMIT_MAX_COUNT, 500).
+-define(BURST_LIMIT_WINDOW_TIME, 1000).
+
+%% This enables/disables the feature to automatically terminate the
+%% process if it gets too loaded (and can't keep up).
+-define(OVERLOAD_KILL_ENABLE, false).
+%% If the message_queue_len goes above this size even after
+%% flushing has been performed, the process is terminated.
+-define(OVERLOAD_KILL_QLEN, 20000).
+%% If the memory usage exceeds this level, the process is terminated.
+-define(OVERLOAD_KILL_MEM_SIZE, 3000000).
+
+%% This is the default time to wait before restarting and accepting
+%% new requests. The value 'infinity' disables restarts.
+-define(OVERLOAD_KILL_RESTART_AFTER, 5000).
+
+%% This is the time in milliseconds after last load message received
+%% that we notify the callback about being idle.
+-define(IDLE_DETECT_TIME, 100).
+
+%%%-----------------------------------------------------------------
+%%% Overload protection macros
+
+-define(timestamp(), erlang:monotonic_time(microsecond)).
+
+-define(get_mode(Tid),
+ case ets:lookup(Tid, mode) of
+ [{mode,M}] -> M;
+ _ -> async
+ end).
+
+-define(set_mode(Tid, M),
+ begin ets:insert(Tid, {mode,M}), M end).
+
+-define(change_mode(Tid, M0, M1),
+ if M0 == M1 ->
+ M0;
+ true ->
+ ets:insert(Tid, {mode,M1}),
+ M1
+ end).
+
+-define(max(X1, X2),
+ if
+ X2 == undefined -> X1;
+ X2 > X1 -> X2;
+ true -> X1
+ end).
+
+-define(diff_time(OS_T1, OS_T0), OS_T1-OS_T0).
+
+%%%-----------------------------------------------------------------
+%%% These macros enable statistics counters in the state of the
+%%% process, which is useful for analysing the overload protection
+%%% behaviour. These counters should not be included in code to be
+%%% officially released (as some counters will grow very large over
+%%% time).
+
+%% -define(SAVE_STATS, true).
+-ifdef(SAVE_STATS).
+ -define(merge_with_stats(STATE),
+ begin
+ TIME = ?timestamp(),
+ STATE#{start => TIME, time => {TIME,0},
+ flushes => 0, flushed => 0, drops => 0,
+ burst_drops => 0, casts => 0, calls => 0,
+ writes => 0, max_qlen => 0, max_time => 0,
+ max_mem => 0, freq => {TIME,0,0}} end).
+
+ -define(update_max_qlen(QLEN, STATE),
+ begin #{max_qlen := QLEN0} = STATE,
+ STATE#{max_qlen => ?max(QLEN0,QLEN)} end).
+
+ -define(update_max_mem(MEM, STATE),
+ begin #{max_mem := MEM0} = STATE,
+ STATE#{max_mem => ?max(MEM0,MEM)} end).
+
+ -define(update_calls_or_casts(CALL_OR_CAST, INC, STATE),
+ case CALL_OR_CAST of
+ cast ->
+ #{casts := CASTS0} = STATE,
+ STATE#{casts => CASTS0+INC};
+ call ->
+ #{calls := CALLS0} = STATE,
+ STATE#{calls => CALLS0+INC}
+ end).
+
+ -define(update_max_time(TIME, STATE),
+ begin #{max_time := TIME0} = STATE,
+ STATE#{max_time => ?max(TIME0,TIME)} end).
+
+ -define(update_other(OTHER, VAR, INCVAL, STATE),
+ begin #{OTHER := VAR} = STATE,
+ STATE#{OTHER => VAR+INCVAL} end).
+
+ -define(update_freq(TIME,STATE),
+ begin
+ case STATE of
+ #{freq := {START, 49, _}} ->
+ STATE#{freq => {TIME, 0, trunc(1000000*50/(?diff_time(TIME,START)))}};
+ #{freq := {START, N, FREQ}} ->
+ STATE#{freq => {START, N+1, FREQ}}
+ end end).
+
+ -define(update_time(TIME,STATE),
+ begin #{start := START} = STATE,
+ STATE#{time => {TIME,trunc((?diff_time(TIME,START))/1000000)}} end).
+
+-else. % DEFAULT!
+ -define(merge_with_stats(STATE), STATE).
+ -define(update_max_qlen(_QLEN, STATE), STATE).
+ -define(update_max_mem(_MEM, STATE), STATE).
+ -define(update_calls_or_casts(_CALL_OR_CAST, _INC, STATE), STATE).
+ -define(update_max_time(_TIME, STATE), STATE).
+ -define(update_other(_OTHER, _VAR, _INCVAL, STATE), STATE).
+ -define(update_freq(_TIME, STATE), STATE).
+ -define(update_time(_TIME, STATE), STATE).
+-endif.
+
+%%%-----------------------------------------------------------------
+%%% These macros enable callbacks that make it possible to analyse the
+%%% overload protection behaviour from outside the process (including
+%%% dropped requests on the client side). An external callback module
+%%% (?OBSERVER_MOD) is required which is not part of the kernel
+%%% application. For this reason, these callbacks should not be
+%%% included in code to be officially released.
+
+%%-define(OBSERVER_MOD, logger_test).
+-ifdef(OBSERVER_MOD).
+ -define(start_observation(NAME), ?OBSERVER:start_observation(NAME)).
+ -define(observe(NAME,EVENT), ?OBSERVER:observe(NAME,EVENT)).
+
+-else. % DEFAULT!
+ -define(start_observation(_NAME), ok).
+ -define(observe(_NAME,_EVENT), ok).
+-endif.
diff --git a/lib/kernel/src/logger_proxy.erl b/lib/kernel/src/logger_proxy.erl
new file mode 100644
index 0000000000..24b293805c
--- /dev/null
+++ b/lib/kernel/src/logger_proxy.erl
@@ -0,0 +1,165 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_proxy).
+
+%% API
+-export([start_link/0, restart/0, log/1, child_spec/0, get_default_config/0]).
+
+%% logger_olp callbacks
+-export([init/1, handle_load/2, handle_info/2, terminate/2,
+ notify/2]).
+
+-include("logger_internal.hrl").
+
+-define(SERVER,?MODULE).
+
+%%%-----------------------------------------------------------------
+%%% API
+-spec log(RemoteLog) -> ok when
+ RemoteLog :: {remote,node(),LogEvent},
+ LogEvent :: {log,Level,Format,Args,Meta} |
+ {log,Level,StringOrReport,Meta},
+ Level :: logger:level(),
+ Format :: io:format(),
+ Args :: list(term()),
+ StringOrReport :: unicode:chardata() | logger:report(),
+ Meta :: logger:metadata().
+log(RemoteLog) ->
+ Olp = persistent_term:get(?MODULE),
+ case logger_olp:get_pid(Olp) =:= self() of
+ true ->
+ %% This happens when the log event comes from the
+ %% emulator, and the group leader is on a remote node.
+ _ = handle_load(RemoteLog, no_state),
+ ok;
+ false ->
+ logger_olp:load(Olp, RemoteLog)
+ end.
+
+%% Called by supervisor
+-spec start_link() -> {ok,pid(),logger_olp:olp_ref()} | {error,term()}.
+start_link() ->
+ %% Notice that sync_mode is only used when logging to remote node,
+ %% i.e. when the log/2 API function is called.
+ %%
+ %% When receiving log events from the emulator or from a remote
+ %% node, the log event is sent as a message to this process, and
+ %% thus received directly in handle_info/2. This means that the
+ %% mode (async/sync/drop) is not read before the message is
+ %% sent. Thus sync mode is never entered, and drop mode is
+ %% implemented by setting the system_logger flag to undefined (see
+ %% notify/2)
+ %%
+ %% Burst limit is disabled, since this is only a proxy and we
+ %% don't want to limit bursts twice (here and in the handler).
+ logger_olp:start_link(?SERVER,?MODULE,[],logger:get_proxy_config()).
+
+%% Fun used for restarting this process after it has been killed due
+%% to overload (must set overload_kill_enable=>true in opts)
+restart() ->
+ case supervisor:start_child(logger_sup, child_spec()) of
+ {ok,_Pid,Olp} ->
+ {ok,Olp};
+ {error,{Reason,Ch}} when is_tuple(Ch), element(1,Ch)==child ->
+ {error,Reason};
+ Error ->
+ Error
+ end.
+
+%% Called internally and by logger_sup
+child_spec() ->
+ Name = ?SERVER,
+ #{id => Name,
+ start => {?MODULE, start_link, []},
+ restart => temporary,
+ shutdown => 2000,
+ type => worker,
+ modules => [?MODULE]}.
+
+get_default_config() ->
+ OlpDefault = logger_olp:get_default_opts(),
+ OlpDefault#{sync_mode_qlen=>500,
+ drop_mode_qlen=>1000,
+ flush_qlen=>5000,
+ burst_limit_enable=>false}.
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init([]) ->
+ process_flag(trap_exit, true),
+ _ = erlang:system_flag(system_logger,self()),
+ persistent_term:put(?MODULE,logger_olp:get_ref()),
+ {ok,no_state}.
+
+%% Log event to send to the node where the group leader of it's client resides
+handle_load({remote,Node,Log},State) ->
+ %% If the connection is overloaded (send_nosuspend returns false),
+ %% we drop the message.
+ _ = erlang:send_nosuspend({?SERVER,Node},Log),
+ State;
+%% Log event to log on this node
+handle_load({log,Level,Format,Args,Meta},State) ->
+ try_log([Level,Format,Args,Meta]),
+ State;
+handle_load({log,Level,Report,Meta},State) ->
+ try_log([Level,Report,Meta]),
+ State.
+
+%% Log event sent to this process e.g. from the emulator - it is really load
+handle_info(Log,State) when is_tuple(Log), element(1,Log)==log ->
+ {load,State}.
+
+terminate(overloaded, _State) ->
+ _ = erlang:system_flag(system_logger,undefined),
+ {ok,fun ?MODULE:restart/0};
+terminate(_Reason, _State) ->
+ _ = erlang:system_flag(system_logger,whereis(logger)),
+ ok.
+
+notify({mode_change,Mode0,Mode1},State) ->
+ _ = if Mode1=:=drop -> % entering drop mode
+ erlang:system_flag(system_logger,undefined);
+ Mode0=:=drop -> % leaving drop mode
+ erlang:system_flag(system_logger,self());
+ true ->
+ ok
+ end,
+ ?LOG_INTERNAL(notice,"~w switched from ~w to ~w mode",[?MODULE,Mode0,Mode1]),
+ State;
+notify({flushed,Flushed},State) ->
+ ?LOG_INTERNAL(notice, "~w flushed ~w log events",[?MODULE,Flushed]),
+ State;
+notify(restart,State) ->
+ ?LOG_INTERNAL(notice, "~w restarted", [?MODULE]),
+ State;
+notify(_Note,State) ->
+ State.
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+try_log(Args) ->
+ try apply(logger,log,Args)
+ catch C:R:S ->
+ ?LOG_INTERNAL(debug,[{?MODULE,log_failed},
+ {log,Args},
+ {reason,{C,R,S}}])
+ end.
diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl
index 28e31d46ea..722246e82c 100644
--- a/lib/kernel/src/logger_server.erl
+++ b/lib/kernel/src/logger_server.erl
@@ -22,14 +22,17 @@
-behaviour(gen_server).
%% API
--export([start_link/0,
- add_handler/3, remove_handler/1,
+-export([start_link/0, add_handler/3, remove_handler/1,
add_filter/2, remove_filter/2,
set_module_level/2, unset_module_level/0,
unset_module_level/1, cache_module_level/1,
- set_config/2, set_config/3, update_config/2,
+ set_config/2, set_config/3,
+ update_config/2, update_config/3,
update_formatter_config/2]).
+%% Helper
+-export([diff_maps/2]).
+
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2]).
@@ -39,7 +42,7 @@
-define(SERVER, logger).
-define(LOGGER_SERVER_TAG, '$logger_cb_process').
--record(state, {tid, async_req, async_req_queue}).
+-record(state, {tid, async_req, async_req_queue, remote_logger}).
%%%===================================================================
%%% API
@@ -83,7 +86,7 @@ set_module_level(Modules,Level) when is_list(Modules) ->
Error -> Error
end;
false ->
- {error,{not_a_list_of_modles,Modules}}
+ {error,{not_a_list_of_modules,Modules}}
end;
set_module_level(Modules,_) ->
{error,{not_a_list_of_modules,Modules}}.
@@ -96,7 +99,7 @@ unset_module_level(Modules) when is_list(Modules) ->
true ->
call({unset_module_level,Modules});
false ->
- {error,{not_a_list_of_modles,Modules}}
+ {error,{not_a_list_of_modules,Modules}}
end;
unset_module_level(Modules) ->
{error,{not_a_list_of_modules,Modules}}.
@@ -105,12 +108,25 @@ cache_module_level(Module) ->
gen_server:cast(?SERVER,{cache_module_level,Module}).
set_config(Owner,Key,Value) ->
- update_config(Owner,#{Key=>Value}).
+ case sanity_check(Owner,Key,Value) of
+ ok ->
+ call({change_config,set,Owner,Key,Value});
+ Error ->
+ Error
+ end.
set_config(Owner,Config) ->
case sanity_check(Owner,Config) of
ok ->
- call({set_config,Owner,Config});
+ call({change_config,set,Owner,Config});
+ Error ->
+ Error
+ end.
+
+update_config(Owner,Key,Value) ->
+ case sanity_check(Owner,Key,Value) of
+ ok ->
+ call({change_config,update,Owner,Key,Value});
Error ->
Error
end.
@@ -118,7 +134,7 @@ set_config(Owner,Config) ->
update_config(Owner, Config) ->
case sanity_check(Owner,Config) of
ok ->
- call({update_config,Owner,Config});
+ call({change_config,update,Owner,Config});
Error ->
Error
end.
@@ -138,6 +154,8 @@ init([]) ->
process_flag(trap_exit, true),
put(?LOGGER_SERVER_TAG,true),
Tid = logger_config:new(?LOGGER_TABLE),
+ %% Store initial proxy config. logger_proxy reads config from here at startup.
+ logger_config:create(Tid,proxy,logger_proxy:get_default_config()),
PrimaryConfig = maps:merge(default_config(primary),
#{handlers=>[simple]}),
logger_config:create(Tid,primary,PrimaryConfig),
@@ -146,7 +164,7 @@ init([]) ->
filters=>?DEFAULT_HANDLER_FILTERS}),
%% If this fails, then the node should crash
{ok,SimpleConfig} = logger_simple_h:adding_handler(SimpleConfig0),
- logger_config:create(Tid,simple,logger_simple_h,SimpleConfig),
+ logger_config:create(Tid,simple,SimpleConfig),
{ok, #state{tid=Tid, async_req_queue = queue:new()}}.
handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) ->
@@ -165,11 +183,11 @@ handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) ->
%% to find out if this is a valid handler
case erlang:function_exported(Module, log, 2) of
true ->
- logger_config:create(Tid,Id,Module,HConfig1),
- {ok,Config} = do_get_config(Tid,primary),
+ logger_config:create(Tid,Id,HConfig1),
+ {ok,Config} = logger_config:get(Tid,primary),
Handlers = maps:get(handlers,Config,[]),
- do_set_config(Tid,primary,
- Config#{handlers=>[Id|Handlers]});
+ logger_config:set(Tid,primary,
+ Config#{handlers=>[Id|Handlers]});
false ->
{error,{invalid_handler,
{function_not_exported,
@@ -181,8 +199,8 @@ handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) ->
end;
handle_call({remove_handler,HandlerId}, From, #state{tid=Tid}=State) ->
case logger_config:get(Tid,HandlerId) of
- {ok,{Module,HConfig}} ->
- {ok,Config} = do_get_config(Tid,primary),
+ {ok,#{module:=Module}=HConfig} ->
+ {ok,Config} = logger_config:get(Tid,primary),
Handlers0 = maps:get(handlers,Config,[]),
Handlers = lists:delete(HandlerId,Handlers0),
call_h_async(
@@ -191,7 +209,7 @@ handle_call({remove_handler,HandlerId}, From, #state{tid=Tid}=State) ->
call_h(Module,removing_handler,[HConfig],ok)
end,
fun(_Res) ->
- do_set_config(Tid,primary,Config#{handlers=>Handlers}),
+ logger_config:set(Tid,primary,Config#{handlers=>Handlers}),
logger_config:delete(Tid,HandlerId),
ok
end,From,State);
@@ -204,36 +222,90 @@ handle_call({add_filter,Id,Filter}, _From,#state{tid=Tid}=State) ->
handle_call({remove_filter,Id,FilterId}, _From, #state{tid=Tid}=State) ->
Reply = do_remove_filter(Tid,Id,FilterId),
{reply,Reply,State};
-handle_call({update_config,Id,NewConfig}, From, #state{tid=Tid}=State) ->
- case logger_config:get(Tid,Id) of
- {ok,{_Module,OldConfig}} ->
- Config = maps:merge(OldConfig,NewConfig),
- handle_call({set_config,Id,Config}, From, State);
- {ok,OldConfig} ->
- Config = maps:merge(OldConfig,NewConfig),
- {reply,do_set_config(Tid,Id,Config),State};
- Error ->
- {reply,Error,State}
- end;
-handle_call({set_config,primary,Config0}, _From, #state{tid=Tid}=State) ->
- Config = maps:merge(default_config(primary),Config0),
- {ok,#{handlers:=Handlers}} = logger_config:get(Tid,primary),
- Reply = do_set_config(Tid,primary,Config#{handlers=>Handlers}),
+handle_call({change_config,SetOrUpd,proxy,Config0},_From,#state{tid=Tid}=State) ->
+ Default =
+ case SetOrUpd of
+ set ->
+ logger_proxy:get_default_config();
+ update ->
+ {ok,OldConfig} = logger_config:get(Tid,proxy),
+ OldConfig
+ end,
+ Config = maps:merge(Default,Config0),
+ Reply =
+ case logger_olp:set_opts(logger_proxy,Config) of
+ ok ->
+ logger_config:set(Tid,proxy,Config);
+ Error ->
+ Error
+ end,
+ {reply,Reply,State};
+handle_call({change_config,SetOrUpd,primary,Config0}, _From,
+ #state{tid=Tid}=State) ->
+ {ok,#{handlers:=Handlers}=OldConfig} = logger_config:get(Tid,primary),
+ Default =
+ case SetOrUpd of
+ set -> default_config(primary);
+ update -> OldConfig
+ end,
+ Config = maps:merge(Default,Config0),
+ Reply = logger_config:set(Tid,primary,Config#{handlers=>Handlers}),
+ {reply,Reply,State};
+handle_call({change_config,_SetOrUpd,primary,Key,Value}, _From,
+ #state{tid=Tid}=State) ->
+ {ok,OldConfig} = logger_config:get(Tid,primary),
+ Reply = logger_config:set(Tid,primary,OldConfig#{Key=>Value}),
{reply,Reply,State};
-handle_call({set_config,HandlerId,Config0}, From, #state{tid=Tid}=State) ->
+handle_call({change_config,SetOrUpd,HandlerId,Config0}, From,
+ #state{tid=Tid}=State) ->
case logger_config:get(Tid,HandlerId) of
- {ok,{Module,OldConfig}} ->
- Config = maps:merge(default_config(HandlerId,Module),Config0),
- call_h_async(
- fun() ->
- call_h(Module,changing_config,[OldConfig,Config],
- {ok,Config})
- end,
- fun({ok,Config1}) ->
- do_set_config(Tid,HandlerId,Config1);
- (Error) ->
- Error
- end,From,State);
+ {ok,#{module:=Module}=OldConfig} ->
+ Default =
+ case SetOrUpd of
+ set -> default_config(HandlerId,Module);
+ update -> OldConfig
+ end,
+ Config = maps:merge(Default,Config0),
+ case check_config_change(OldConfig,Config) of
+ ok ->
+ call_h_async(
+ fun() ->
+ call_h(Module,changing_config,
+ [SetOrUpd,OldConfig,Config],
+ {ok,Config})
+ end,
+ fun({ok,Config1}) ->
+ logger_config:set(Tid,HandlerId,Config1);
+ (Error) ->
+ Error
+ end,From,State);
+ Error ->
+ {reply,Error,State}
+ end;
+ _ ->
+ {reply,{error,{not_found,HandlerId}},State}
+ end;
+handle_call({change_config,SetOrUpd,HandlerId,Key,Value}, From,
+ #state{tid=Tid}=State) ->
+ case logger_config:get(Tid,HandlerId) of
+ {ok,#{module:=Module}=OldConfig} ->
+ Config = OldConfig#{Key=>Value},
+ case check_config_change(OldConfig,Config) of
+ ok ->
+ call_h_async(
+ fun() ->
+ call_h(Module,changing_config,
+ [SetOrUpd,OldConfig,Config],
+ {ok,Config})
+ end,
+ fun({ok,Config1}) ->
+ logger_config:set(Tid,HandlerId,Config1);
+ (Error) ->
+ Error
+ end,From,State);
+ Error ->
+ {reply,Error,State}
+ end;
_ ->
{reply,{error,{not_found,HandlerId}},State}
end;
@@ -241,12 +313,12 @@ handle_call({update_formatter_config,HandlerId,NewFConfig},_From,
#state{tid=Tid}=State) ->
Reply =
case logger_config:get(Tid,HandlerId) of
- {ok,{_Mod,#{formatter:={FMod,OldFConfig}}=Config}} ->
+ {ok,#{formatter:={FMod,OldFConfig}}=Config} ->
try
FConfig = maps:merge(OldFConfig,NewFConfig),
check_formatter({FMod,FConfig}),
- do_set_config(Tid,HandlerId,
- Config#{formatter=>{FMod,FConfig}})
+ logger_config:set(Tid,HandlerId,
+ Config#{formatter=>{FMod,FConfig}})
catch throw:Reason -> {error,Reason}
end;
_ ->
@@ -304,38 +376,40 @@ terminate(_Reason, _State) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
-call(Request) ->
+call(Request) when is_tuple(Request) ->
Action = element(1,Request),
case get(?LOGGER_SERVER_TAG) of
true when
Action == add_handler; Action == remove_handler;
- Action == update_config; Action == set_config ->
+ Action == add_filter; Action == remove_filter;
+ Action == change_config ->
{error,{attempting_syncronous_call_to_self,Request}};
_ ->
gen_server:call(?SERVER,Request,?DEFAULT_LOGGER_CALL_TIMEOUT)
end.
+
do_add_filter(Tid,Id,{FId,_} = Filter) ->
- case do_get_config(Tid,Id) of
+ case logger_config:get(Tid,Id) of
{ok,Config} ->
Filters = maps:get(filters,Config,[]),
case lists:keymember(FId,1,Filters) of
true ->
{error,{already_exist,FId}};
false ->
- do_set_config(Tid,Id,Config#{filters=>[Filter|Filters]})
+ logger_config:set(Tid,Id,Config#{filters=>[Filter|Filters]})
end;
Error ->
Error
end.
do_remove_filter(Tid,Id,FilterId) ->
- case do_get_config(Tid,Id) of
+ case logger_config:get(Tid,Id) of
{ok,Config} ->
Filters0 = maps:get(filters,Config,[]),
case lists:keytake(FilterId,1,Filters0) of
{value,_,Filters} ->
- do_set_config(Tid,Id,Config#{filters=>Filters});
+ logger_config:set(Tid,Id,Config#{filters=>Filters});
false ->
{error,{not_found,FilterId}}
end;
@@ -343,20 +417,6 @@ do_remove_filter(Tid,Id,FilterId) ->
Error
end.
-do_get_config(Tid,Id) ->
- case logger_config:get(Tid,Id) of
- {ok,{_,Config}} ->
- {ok,Config};
- {ok,Config} ->
- {ok,Config};
- Error ->
- Error
- end.
-
-do_set_config(Tid,Id,Config) ->
- logger_config:set(Tid,Id,Config),
- ok.
-
default_config(primary) ->
#{level=>notice,
filters=>[],
@@ -373,11 +433,13 @@ default_config(Id,Module) ->
sanity_check(Owner,Key,Value) ->
sanity_check_1(Owner,[{Key,Value}]).
-sanity_check(HandlerId,Config) when is_map(Config) ->
- sanity_check_1(HandlerId,maps:to_list(Config));
+sanity_check(Owner,Config) when is_map(Config) ->
+ sanity_check_1(Owner,maps:to_list(Config));
sanity_check(_,Config) ->
- {error,{invalid_handler_config,Config}}.
+ {error,{invalid_config,Config}}.
+sanity_check_1(proxy,_Config) ->
+ ok; % Details are checked by logger_olp:set_opts/2
sanity_check_1(Owner,Config) when is_list(Config) ->
try
Type = get_type(Owner),
@@ -421,8 +483,6 @@ check_mod(Mod) when is_atom(Mod) ->
check_mod(Mod) ->
throw({invalid_module,Mod}).
-check_level({LevelInt,cached}) when LevelInt>=?EMERGENCY, LevelInt=<?DEBUG ->
- ok;
check_level(Level) ->
case lists:member(Level,?LEVELS) of
true ->
@@ -463,6 +523,15 @@ check_formatter({Mod,Config}) ->
check_formatter(Formatter) ->
throw({invalid_formatter,Formatter}).
+%% When changing configuration for a handler, the id and module fields
+%% can not be changed.
+check_config_change(#{id:=Id,module:=Module},#{id:=Id,module:=Module}) ->
+ ok;
+check_config_change(OldConfig,NewConfig) ->
+ {Old,New} = logger_server:diff_maps(maps:with([id,module],OldConfig),
+ maps:with([id,module],NewConfig)),
+ {error,{illegal_config_change,Old,New}}.
+
call_h(Module, Function, Args, DefRet) ->
%% Not calling code:ensure_loaded + erlang:function_exported here,
%% since in some rare terminal cases, the code_server might not
@@ -471,6 +540,11 @@ call_h(Module, Function, Args, DefRet) ->
catch
C:R:S ->
case {C,R,S} of
+ {error,undef,[{Module,Function=changing_config,Args,_}|_]}
+ when length(Args)=:=3 ->
+ %% Backwards compatible call, if changing_config/3
+ %% did not exist.
+ call_h(Module, Function, tl(Args), DefRet);
{error,undef,[{Module,Function,Args,_}|_]} ->
DefRet;
_ ->
@@ -530,3 +604,14 @@ call_h_reply(Unexpected,State) ->
{process,?SERVER},
{message,Unexpected}]),
{noreply,State}.
+
+%% Return two maps containing only the fields that differ.
+diff_maps(M1,M2) ->
+ diffs(lists:sort(maps:to_list(M1)),lists:sort(maps:to_list(M2)),#{},#{}).
+
+diffs([H|T1],[H|T2],D1,D2) ->
+ diffs(T1,T2,D1,D2);
+diffs([{K,V1}|T1],[{K,V2}|T2],D1,D2) ->
+ diffs(T1,T2,D1#{K=>V1},D2#{K=>V2});
+diffs([],[],D1,D2) ->
+ {D1,D2}.
diff --git a/lib/kernel/src/logger_simple_h.erl b/lib/kernel/src/logger_simple_h.erl
index 8b51dd8569..a0d51dba25 100644
--- a/lib/kernel/src/logger_simple_h.erl
+++ b/lib/kernel/src/logger_simple_h.erl
@@ -50,7 +50,6 @@ removing_handler(#{id:=simple}) ->
ok;
Pid ->
Ref = erlang:monitor(process,Pid),
- unlink(Pid),
Pid ! stop,
receive {'DOWN',Ref,process,Pid,_} ->
ok
@@ -70,7 +69,7 @@ log(#{msg:=_,meta:=#{time:=_}}=Log,_Config) ->
do_log(
#{level=>error,
msg=>{report,{error,simple_handler_process_dead}},
- meta=>#{time=>erlang:system_time(microsecond)}}),
+ meta=>#{time=>logger:timestamp()}}),
do_log(Log);
_ ->
?MODULE ! {log,Log}
@@ -99,7 +98,11 @@ loop(Buffer) ->
replay_buffer(Buffer);
_ ->
ok
- end;
+ end,
+ %% Before stopping, we unlink the logger process to avoid
+ %% an unexpected EXIT message
+ unlink(whereis(logger)),
+ ok;
{log,#{msg:=_,meta:=#{time:=_}}=Log} ->
do_log(Log),
loop(update_buffer(Buffer,Log));
@@ -126,7 +129,7 @@ drop_msg(0) ->
drop_msg(N) ->
[#{level=>info,
msg=>{"Simple handler buffer full, dropped ~w messages",[N]},
- meta=>#{time=>erlang:system_time(microsecond)}}].
+ meta=>#{time=>logger:timestamp()}}].
%%%-----------------------------------------------------------------
%%% Internal
diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl
index 480fafd6d8..c8f1acfca4 100644
--- a/lib/kernel/src/logger_std_h.erl
+++ b/lib/kernel/src/logger_std_h.erl
@@ -19,8 +19,6 @@
%%
-module(logger_std_h).
--behaviour(gen_server).
-
-include("logger.hrl").
-include("logger_internal.hrl").
-include("logger_h_common.hrl").
@@ -28,381 +26,252 @@
-include_lib("kernel/include/file.hrl").
%% API
--export([start_link/3, info/1, filesync/1, reset/1]).
+-export([filesync/1]).
-%% gen_server and proc_lib callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
+%% logger_h_common callbacks
+-export([init/2, check_config/4, config_changed/3, reset_state/2,
+ filesync/3, write/4, handle_info/3, terminate/3]).
%% logger callbacks
--export([log/2, adding_handler/1, removing_handler/1, changing_config/2]).
+-export([log/2, adding_handler/1, removing_handler/1, changing_config/3,
+ filter_config/1]).
-%% handler internal
--export([log_handler_info/4]).
+-define(DEFAULT_CALL_TIMEOUT, 5000).
%%%===================================================================
%%% API
%%%===================================================================
%%%-----------------------------------------------------------------
-%%% Start a standard handler process and link to caller.
-%%% This function is called by the kernel supervisor when this
-%%% handler process gets added
--spec start_link(Name, Config, HandlerState) -> {ok,Pid} | {error,Reason} when
- Name :: atom(),
- Config :: logger:handler_config(),
- HandlerState :: map(),
- Pid :: pid(),
- Reason :: term().
-
-start_link(Name, Config, HandlerState) ->
- proc_lib:start_link(?MODULE,init,[[Name,Config,HandlerState]]).
-
-%%%-----------------------------------------------------------------
%%%
-spec filesync(Name) -> ok | {error,Reason} when
Name :: atom(),
Reason :: handler_busy | {badarg,term()}.
-filesync(Name) when is_atom(Name) ->
- try
- gen_server:call(?name_to_reg_name(?MODULE,Name),
- filesync, ?DEFAULT_CALL_TIMEOUT)
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
filesync(Name) ->
- {error,{badarg,{filesync,[Name]}}}.
-
-%%%-----------------------------------------------------------------
-%%%
--spec info(Name) -> Info | {error,Reason} when
- Name :: atom(),
- Info :: term(),
- Reason :: handler_busy | {badarg,term()}.
-
-info(Name) when is_atom(Name) ->
- try
- gen_server:call(?name_to_reg_name(?MODULE,Name),
- info, ?DEFAULT_CALL_TIMEOUT)
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
-info(Name) ->
- {error,{badarg,{info,[Name]}}}.
-
-%%%-----------------------------------------------------------------
-%%%
--spec reset(Name) -> ok | {error,Reason} when
- Name :: atom(),
- Reason :: handler_busy | {badarg,term()}.
-
-reset(Name) when is_atom(Name) ->
- try
- gen_server:call(?name_to_reg_name(?MODULE,Name),
- reset, ?DEFAULT_CALL_TIMEOUT)
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
-reset(Name) ->
- {error,{badarg,{reset,[Name]}}}.
-
+ logger_h_common:filesync(?MODULE,Name).
%%%===================================================================
-%%% logger callbacks
+%%% logger callbacks - just forward to logger_h_common
%%%===================================================================
%%%-----------------------------------------------------------------
%%% Handler being added
-adding_handler(#{id:=Name}=Config) ->
- case check_config(adding, Config) of
- {ok, Config1} ->
- %% create initial handler state by merging defaults with config
- HConfig = maps:get(config, Config1, #{}),
- HState = maps:merge(get_init_state(), HConfig),
- case logger_h_common:overload_levels_ok(HState) of
- true ->
- start(Name, Config1, HState);
- false ->
- #{sync_mode_qlen := SMQL,
- drop_mode_qlen := DMQL,
- flush_qlen := FQL} = HState,
- {error,{invalid_levels,{SMQL,DMQL,FQL}}}
- end;
- Error ->
- Error
- end.
+-spec adding_handler(Config) -> {ok,Config} | {error,Reason} when
+ Config :: logger:handler_config(),
+ Reason :: term().
+
+adding_handler(Config) ->
+ logger_h_common:adding_handler(Config).
%%%-----------------------------------------------------------------
%%% Updating handler config
-changing_config(OldConfig=#{id:=Name, config:=OldHConfig},
- NewConfig=#{id:=Name}) ->
- #{type:=Type, handler_pid:=HPid, mode_tab:=ModeTab} = OldHConfig,
- NewHConfig = maps:get(config, NewConfig, #{}),
- case maps:get(type, NewHConfig, Type) of
- Type ->
- NewHConfig1 = NewHConfig#{type=>Type,
- handler_pid=>HPid,
- mode_tab=>ModeTab},
- changing_config1(HPid, OldConfig,
- NewConfig#{config=>NewHConfig1});
- _ ->
- {error,{illegal_config_change,OldConfig,NewConfig}}
- end;
-changing_config(OldConfig, NewConfig) ->
- {error,{illegal_config_change,OldConfig,NewConfig}}.
-
-changing_config1(HPid, OldConfig, NewConfig) ->
- case check_config(changing, NewConfig) of
- Result = {ok,NewConfig1} ->
- try gen_server:call(HPid, {change_config,OldConfig,NewConfig1},
- ?DEFAULT_CALL_TIMEOUT) of
- ok -> Result;
- HError -> HError
- catch
- _:{timeout,_} -> {error,handler_busy}
- end;
- Error ->
- Error
- end.
-
-check_config(adding, Config) ->
- %% Merge in defaults on handler level
- HConfig0 = maps:get(config, Config, #{}),
- HConfig = maps:merge(#{type => standard_io},
- HConfig0),
- case check_h_config(maps:to_list(HConfig)) of
- ok ->
- {ok,Config#{config=>HConfig}};
- Error ->
- Error
- end;
-check_config(changing, Config) ->
- HConfig = maps:get(config, Config, #{}),
- case check_h_config(maps:to_list(HConfig)) of
- ok -> {ok,Config};
- Error -> Error
- end.
-
-check_h_config([{type,Type} | Config]) when Type == standard_io;
- Type == standard_error ->
- check_h_config(Config);
-check_h_config([{type,{file,File}} | Config]) when is_list(File) ->
- check_h_config(Config);
-check_h_config([{type,{file,File,Modes}} | Config]) when is_list(File),
- is_list(Modes) ->
- check_h_config(Config);
-check_h_config([Other | Config]) ->
- case logger_h_common:check_common_config(Other) of
- valid ->
- check_h_config(Config);
- invalid ->
- {error,{invalid_config,?MODULE,Other}}
- end;
-check_h_config([]) ->
- ok.
+-spec changing_config(SetOrUpdate, OldConfig, NewConfig) ->
+ {ok,Config} | {error,Reason} when
+ SetOrUpdate :: set | update,
+ OldConfig :: logger:handler_config(),
+ NewConfig :: logger:handler_config(),
+ Config :: logger:handler_config(),
+ Reason :: term().
+changing_config(SetOrUpdate, OldConfig, NewConfig) ->
+ logger_h_common:changing_config(SetOrUpdate, OldConfig, NewConfig).
%%%-----------------------------------------------------------------
%%% Handler being removed
-removing_handler(#{id:=Name}) ->
- stop(Name).
+-spec removing_handler(Config) -> ok when
+ Config :: logger:handler_config().
+
+removing_handler(Config) ->
+ logger_h_common:removing_handler(Config).
%%%-----------------------------------------------------------------
%%% Log a string or report
--spec log(LogEvent, Config) -> ok | dropped when
+-spec log(LogEvent, Config) -> ok when
LogEvent :: logger:log_event(),
Config :: logger:handler_config().
-log(LogEvent, Config = #{id := Name,
- config := #{handler_pid := HPid,
- mode_tab := ModeTab}}) ->
- %% if the handler has crashed, we must drop this event
- %% and hope the handler restarts so we can try again
- true = is_process_alive(HPid),
- Bin = logger_h_common:log_to_binary(LogEvent, Config),
- logger_h_common:call_cast_or_drop(Name, HPid, ModeTab, Bin).
+log(LogEvent, Config) ->
+ logger_h_common:log(LogEvent, Config).
-%%%===================================================================
-%%% gen_server callbacks
-%%%===================================================================
-
-init([Name, Config = #{config := HConfig},
- State0 = #{type := Type, file_ctrl_sync_int := FileCtrlSyncInt}]) ->
- RegName = ?name_to_reg_name(?MODULE,Name),
- register(RegName, self()),
- process_flag(trap_exit, true),
- process_flag(message_queue_data, off_heap),
+%%%-----------------------------------------------------------------
+%%% Remove internal fields from configuration
+-spec filter_config(Config) -> Config when
+ Config :: logger:handler_config().
- ?init_test_hooks(),
- ?start_observation(Name),
-
- case do_init(Name, Type) of
- {ok,InitState} ->
- try ets:new(Name, [public]) of
- ModeTab ->
- ?set_mode(ModeTab, async),
- State = maps:merge(State0, InitState),
- T0 = ?timestamp(),
- State1 =
- ?merge_with_stats(State#{
- mode_tab => ModeTab,
- mode => async,
- file_ctrl_sync => FileCtrlSyncInt,
- last_qlen => 0,
- last_log_ts => T0,
- last_op => sync,
- burst_win_ts => T0,
- burst_msg_count => 0}),
- Config1 =
- Config#{config => HConfig#{handler_pid => self(),
- mode_tab => ModeTab}},
- proc_lib:init_ack({ok,self(),Config1}),
- gen_server:cast(self(), repeated_filesync),
- enter_loop(Config1, State1)
- catch
- _:Error ->
- unregister(RegName),
- logger_h_common:error_notify({init_handler,Name,Error}),
- proc_lib:init_ack(Error)
- end;
- Error ->
- unregister(RegName),
- logger_h_common:error_notify({init_handler,Name,Error}),
- proc_lib:init_ack(Error)
- end.
+filter_config(Config) ->
+ logger_h_common:filter_config(Config).
-do_init(Name, Type) ->
- case open_log_file(Name, Type) of
+%%%===================================================================
+%%% logger_h_common callbacks
+%%%===================================================================
+init(Name, Config) ->
+ MyConfig = maps:with([type,file,modes,file_check,max_no_bytes,
+ max_no_files,compress_on_rotate],Config),
+ case file_ctrl_start(Name, MyConfig) of
{ok,FileCtrlPid} ->
- case logger_h_common:unset_restart_flag(Name, ?MODULE) of
- true ->
- %% inform about restart
- gen_server:cast(self(), {log_handler_info,
- "Handler ~p restarted",
- [Name]});
- false ->
- %% initial start
- ok
- end,
- {ok,#{id=>Name,type=>Type,file_ctrl_pid=>FileCtrlPid}};
+ {ok,MyConfig#{file_ctrl_pid=>FileCtrlPid}};
Error ->
Error
end.
-enter_loop(_Config,State) ->
- gen_server:enter_loop(?MODULE,[],State).
+check_config(Name,set,undefined,NewHConfig) ->
+ check_h_config(merge_default_config(Name,normalize_config(NewHConfig)));
+check_config(Name,SetOrUpdate,OldHConfig,NewHConfig0) ->
+ WriteOnce = maps:with([type,file,modes],OldHConfig),
+ Default =
+ case SetOrUpdate of
+ set ->
+ %% Do not reset write-once fields to defaults
+ merge_default_config(Name,WriteOnce);
+ update ->
+ OldHConfig
+ end,
-%% This is the synchronous log event.
-handle_call({log, Bin}, _From, State) ->
- {Result,State1} = do_log(Bin, call, State),
- %% Result == ok | dropped
- {reply,Result, State1};
+ NewHConfig = maps:merge(Default, normalize_config(NewHConfig0)),
-handle_call(filesync, _From, State = #{type := Type,
- file_ctrl_pid := FileCtrlPid}) ->
- if is_atom(Type) ->
- {reply, ok, State};
- true ->
- {reply, file_ctrl_filesync_sync(FileCtrlPid), State#{last_op=>sync}}
- end;
+ %% Fail if write-once fields are changed
+ case maps:with([type,file,modes],NewHConfig) of
+ WriteOnce ->
+ check_h_config(NewHConfig);
+ Other ->
+ {error,{illegal_config_change,?MODULE,WriteOnce,Other}}
+ end.
-handle_call({change_config,_OldConfig,NewConfig}, _From,
- State = #{filesync_repeat_interval := FSyncInt0}) ->
- HConfig = maps:get(config, NewConfig, #{}),
- State1 = maps:merge(State, HConfig),
- case logger_h_common:overload_levels_ok(State1) of
- true ->
- _ =
- case maps:get(filesync_repeat_interval, HConfig, undefined) of
- undefined ->
- ok;
- no_repeat ->
- _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
- State,
- undefined));
- FSyncInt0 ->
- ok;
- _FSyncInt1 ->
- _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
- State,
- undefined)),
- gen_server:cast(self(), repeated_filesync)
- end,
- {reply, ok, State1};
- false ->
- #{sync_mode_qlen := SMQL,
- drop_mode_qlen := DMQL,
- flush_qlen := FQL} = State1,
- {reply, {error,{invalid_levels,{SMQL,DMQL,FQL}}}, State}
- end;
+check_h_config(HConfig) ->
+ case check_h_config(maps:get(type,HConfig),maps:to_list(HConfig)) of
+ ok ->
+ {ok,fix_file_opts(HConfig)};
+ {error,{Key,Value}} ->
+ {error,{invalid_config,?MODULE,#{Key=>Value}}}
+ end.
-handle_call(info, _From, State) ->
- {reply, State, State};
-
-handle_call(reset, _From, State) ->
- State1 = ?merge_with_stats(State),
- {reply, ok, State1#{last_qlen => 0,
- last_log_ts => ?timestamp()}};
-
-handle_call(stop, _From, State) ->
- {stop, {shutdown,stopped}, ok, State}.
-
-%% This is the asynchronous log event.
-handle_cast({log, Bin}, State) ->
- {_,State1} = do_log(Bin, cast, State),
- {noreply, State1};
-
-handle_cast({log_handler_info, Format, Args}, State = #{id:=Name}) ->
- log_handler_info(Name, Format, Args, State),
- {noreply, State};
-
-%% If FILESYNC_REPEAT_INTERVAL is set to a millisec value, this
-%% clause gets called repeatedly by the handler. In order to
-%% guarantee that a filesync *always* happens after the last log
-%% event, the repeat operation must be active!
-handle_cast(repeated_filesync,
- State = #{type := Type,
- file_ctrl_pid := FileCtrlPid,
- filesync_repeat_interval := FSyncInt,
- last_op := LastOp}) ->
- State1 =
- if not is_atom(Type), is_integer(FSyncInt) ->
- %% only do filesync if something has been
- %% written since last time we checked
- if LastOp == sync ->
- ok;
- true ->
- file_ctrl_filesync_async(FileCtrlPid)
- end,
- {ok,TRef} =
- timer:apply_after(FSyncInt, gen_server,cast,
- [self(),repeated_filesync]),
- State#{rep_sync_tref => TRef, last_op => sync};
- true ->
- State
- end,
- {noreply,State1}.
-
-handle_info({'EXIT',Pid,Why}, State = #{id := Name, type := FileInfo}) ->
- case maps:get(file_ctrl_pid, State, undefined) of
- Pid ->
- %% file error, terminate handler
- logger_h_common:handler_exit(Name,
- {error,{write_failed,FileInfo,Why}});
- _Other ->
- %% ignore EXIT
- ok
- end,
- {noreply, State};
+check_h_config(Type,[{type,Type} | Config]) when Type =:= standard_io;
+ Type =:= standard_error;
+ Type =:= file ->
+ check_h_config(Type,Config);
+check_h_config(file,[{file,File} | Config]) when is_list(File) ->
+ check_h_config(file,Config);
+check_h_config(file,[{modes,Modes} | Config]) when is_list(Modes) ->
+ check_h_config(file,Config);
+check_h_config(file,[{max_no_bytes,Size} | Config])
+ when (is_integer(Size) andalso Size>0) orelse Size=:=infinity ->
+ check_h_config(file,Config);
+check_h_config(file,[{max_no_files,Num} | Config]) when is_integer(Num), Num>=0 ->
+ check_h_config(file,Config);
+check_h_config(file,[{compress_on_rotate,Bool} | Config]) when is_boolean(Bool) ->
+ check_h_config(file,Config);
+check_h_config(file,[{file_check,FileCheck} | Config])
+ when is_integer(FileCheck), FileCheck>=0 ->
+ check_h_config(file,Config);
+check_h_config(_Type,[Other | _]) ->
+ {error,Other};
+check_h_config(_Type,[]) ->
+ ok.
-handle_info(_Info, State) ->
- {noreply, State}.
+normalize_config(#{type:={file,File}}=HConfig) ->
+ HConfig#{type=>file,file=>File};
+normalize_config(#{type:={file,File,Modes}}=HConfig) ->
+ HConfig#{type=>file,file=>File,modes=>Modes};
+normalize_config(HConfig) ->
+ HConfig.
+
+merge_default_config(Name,#{type:=Type}=HConfig) ->
+ merge_default_config(Name,Type,HConfig);
+merge_default_config(Name,#{file:=_}=HConfig) ->
+ merge_default_config(Name,file,HConfig);
+merge_default_config(Name,HConfig) ->
+ merge_default_config(Name,standard_io,HConfig).
+
+merge_default_config(Name,Type,HConfig) ->
+ maps:merge(get_default_config(Name,Type),HConfig).
+
+get_default_config(Name,file) ->
+ #{type => file,
+ file => atom_to_list(Name),
+ modes => [raw,append],
+ file_check => 0,
+ max_no_bytes => infinity,
+ max_no_files => 0,
+ compress_on_rotate => false};
+get_default_config(_Name,Type) ->
+ #{type => Type}.
+
+fix_file_opts(#{modes:=Modes}=HConfig) ->
+ HConfig#{modes=>fix_modes(Modes)};
+fix_file_opts(HConfig) ->
+ HConfig#{filesync_repeat_interval=>no_repeat}.
+
+fix_modes(Modes) ->
+ %% Ensure write|append|exclusive
+ Modes1 =
+ case [M || M <- Modes,
+ lists:member(M,[write,append,exclusive])] of
+ [] -> [append|Modes];
+ _ -> Modes
+ end,
+ %% Ensure raw
+ Modes2 =
+ case lists:member(raw,Modes) of
+ false -> [raw|Modes1];
+ true -> Modes1
+ end,
+ %% Ensure delayed_write
+ case lists:partition(fun(delayed_write) -> true;
+ ({delayed_write,_,_}) -> true;
+ (_) -> false
+ end, Modes2) of
+ {[],_} ->
+ [delayed_write|Modes2];
+ _ ->
+ Modes2
+ end.
-terminate(Reason, State = #{id:=Name, file_ctrl_pid:=FWPid,
- type:=_FileInfo}) ->
- _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref, State,
- undefined)),
+config_changed(_Name,
+ #{file_check:=FileCheck,
+ max_no_bytes:=Size,
+ max_no_files:=Count,
+ compress_on_rotate:=Compress},
+ #{file_check:=FileCheck,
+ max_no_bytes:=Size,
+ max_no_files:=Count,
+ compress_on_rotate:=Compress}=State) ->
+ State;
+config_changed(_Name,
+ #{file_check:=FileCheck,
+ max_no_bytes:=Size,
+ max_no_files:=Count,
+ compress_on_rotate:=Compress},
+ #{file_ctrl_pid := FileCtrlPid} = State) ->
+ FileCtrlPid ! {update_config,#{file_check=>FileCheck,
+ max_no_bytes=>Size,
+ max_no_files=>Count,
+ compress_on_rotate=>Compress}},
+ State#{file_check:=FileCheck,
+ max_no_bytes:=Size,
+ max_no_files:=Count,
+ compress_on_rotate:=Compress};
+config_changed(_Name,_NewHConfig,State) ->
+ State.
+
+filesync(_Name, SyncAsync, #{file_ctrl_pid := FileCtrlPid} = State) ->
+ Result = file_ctrl_filesync(SyncAsync, FileCtrlPid),
+ {Result,State}.
+
+write(_Name, SyncAsync, Bin, #{file_ctrl_pid:=FileCtrlPid} = State) ->
+ Result = file_write(SyncAsync, FileCtrlPid, Bin),
+ {Result,State}.
+
+reset_state(_Name, State) ->
+ State.
+
+handle_info(_Name, {'EXIT',Pid,Why}, #{file_ctrl_pid := Pid}=State) ->
+ %% file_ctrl_pid died, file error, terminate handler
+ exit({error,{write_failed,maps:with([type,file,modes],State),Why}});
+handle_info(_, _, State) ->
+ State.
+
+terminate(_Name, _Reason, #{file_ctrl_pid:=FWPid}) ->
case is_process_alive(FWPid) of
true ->
unlink(FWPid),
@@ -413,16 +282,12 @@ terminate(Reason, State = #{id:=Name, file_ctrl_pid:=FWPid,
ok
after
?DEFAULT_CALL_TIMEOUT ->
- exit(FWPid, kill)
+ exit(FWPid, kill),
+ ok
end;
false ->
ok
- end,
- unregister(?name_to_reg_name(?MODULE, Name)),
- logger_h_common:stop_or_restart(Name, Reason, State).
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
+ end.
%%%===================================================================
%%% Internal functions
@@ -430,213 +295,36 @@ code_change(_OldVsn, State, _Extra) ->
%%%-----------------------------------------------------------------
%%%
-get_init_state() ->
- #{sync_mode_qlen => ?SYNC_MODE_QLEN,
- drop_mode_qlen => ?DROP_MODE_QLEN,
- flush_qlen => ?FLUSH_QLEN,
- burst_limit_enable => ?BURST_LIMIT_ENABLE,
- burst_limit_max_count => ?BURST_LIMIT_MAX_COUNT,
- burst_limit_window_time => ?BURST_LIMIT_WINDOW_TIME,
- overload_kill_enable => ?OVERLOAD_KILL_ENABLE,
- overload_kill_qlen => ?OVERLOAD_KILL_QLEN,
- overload_kill_mem_size => ?OVERLOAD_KILL_MEM_SIZE,
- overload_kill_restart_after => ?OVERLOAD_KILL_RESTART_AFTER,
- file_ctrl_sync_int => ?CONTROLLER_SYNC_INTERVAL,
- filesync_ok_qlen => ?FILESYNC_OK_QLEN,
- filesync_repeat_interval => ?FILESYNC_REPEAT_INTERVAL}.
-
-%%%-----------------------------------------------------------------
-%%% Add a standard handler to the logger.
-%%% This starts a dedicated handler process which should always
-%%% exist if the handler is registered with logger (and should not
-%%% exist if the handler is not registered).
-%%%
-%%% Handler specific config should be provided with a sub map associated
-%%% with a key named 'config', e.g:
-%%%
-%%% Config = #{config => #{sync_mode_qlen => 50}
-%%%
-%%% The standard handler process is linked to logger_sup, which is
-%%% part of the kernel application's supervision tree.
-start(Name, Config, HandlerState) ->
- LoggerStdH =
- #{id => Name,
- start => {?MODULE, start_link, [Name,Config,HandlerState]},
- restart => temporary,
- shutdown => 2000,
- type => worker,
- modules => [?MODULE]},
- case supervisor:start_child(logger_sup, LoggerStdH) of
- {ok,_Pid,Config1} ->
- {ok,Config1};
- Error ->
- Error
- end.
-
-%%%-----------------------------------------------------------------
-%%% Stop and remove the handler.
-stop(Name) ->
- case whereis(?name_to_reg_name(?MODULE,Name)) of
- undefined ->
- ok;
- Pid ->
- %% We don't want to do supervisor:terminate_child here
- %% since we need to distinguish this explicit stop from a
- %% system termination in order to avoid circular attempts
- %% at removing the handler (implying deadlocks and
- %% timeouts).
- _ = gen_server:call(Pid, stop),
- _ = supervisor:delete_child(logger_sup, Name),
- ok
- end.
-
-%%%-----------------------------------------------------------------
-%%% Logging and overload control.
--define(update_file_ctrl_sync(C, Interval),
- if C == 0 -> Interval;
- true -> C-1 end).
-
-%% check for overload between every event (and set Mode to async,
-%% sync or drop accordingly), but never flush the whole mailbox
-%% before LogWindowSize events have been handled
-do_log(Bin, CallOrCast, State = #{id:=Name, mode:=Mode0}) ->
- T1 = ?timestamp(),
-
- %% check if the handler is getting overloaded, or if it's
- %% recovering from overload (the check must be done for each
- %% event to react quickly to large bursts of events and
- %% to ensure that the handler can never end up in drop mode
- %% with an empty mailbox, which would stop operation)
- {Mode1,QLen,Mem,State1} = logger_h_common:check_load(State),
-
- if (Mode1 == drop) andalso (Mode0 =/= drop) ->
- log_handler_info(Name, "Handler ~p switched to drop mode",
- [Name], State);
- (Mode0 == drop) andalso ((Mode1 == async) orelse (Mode1 == sync)) ->
- log_handler_info(Name, "Handler ~p switched to ~w mode",
- [Name,Mode1], State);
- true ->
- ok
- end,
-
- %% kill the handler if it can't keep up with the load
- logger_h_common:kill_if_choked(Name, QLen, Mem, ?MODULE, State),
-
- if Mode1 == flush ->
- flush(Name, QLen, T1, State1);
- true ->
- write(Name, Mode1, T1, Bin, CallOrCast, State1)
- end.
-
-%% this clause is called by do_log/3 after an overload check
-%% has been performed, where QLen > FlushQLen
-flush(Name, _QLen0, T1, State=#{last_log_ts := _T0, mode_tab := ModeTab}) ->
- %% flush messages in the mailbox (a limited number in
- %% order to not cause long delays)
- NewFlushed = logger_h_common:flush_log_events(?FLUSH_MAX_N),
-
- %% write info in log about flushed messages
- log_handler_info(Name, "Handler ~p flushed ~w log events",
- [Name,NewFlushed], State),
-
- %% because of the receive loop when flushing messages, the
- %% handler will be scheduled out often and the mailbox could
- %% grow very large, so we'd better check the queue again here
- {_,_QLen1} = process_info(self(), message_queue_len),
- ?observe(Name,{max_qlen,_QLen1}),
-
- %% Add 1 for the current log event
- ?observe(Name,{flushed,NewFlushed+1}),
-
- State1 = ?update_max_time(?diff_time(T1,_T0),State),
- {dropped,?update_other(flushed,FLUSHED,NewFlushed,
- State1#{mode => ?set_mode(ModeTab,async),
- last_qlen => 0,
- last_log_ts => T1})}.
-
-%% this clause is called to write to file
-write(_Name, Mode, T1, Bin, _CallOrCast,
- State = #{mode_tab := ModeTab,
- file_ctrl_pid := FileCtrlPid,
- file_ctrl_sync := FileCtrlSync,
- last_qlen := LastQLen,
- last_log_ts := T0,
- file_ctrl_sync_int := FileCtrlSyncInt}) ->
- %% check if we need to limit the number of writes
- %% during a burst of log events
- {DoWrite,BurstWinT,BurstMsgCount} = logger_h_common:limit_burst(State),
-
- %% only send a synhrounous event to the file controller process
- %% every FileCtrlSyncInt time, to give the handler time between
- %% file writes so it can keep up with incoming messages
- {Result,LastQLen1} =
- if DoWrite, FileCtrlSync == 0 ->
- ?observe(_Name,{_CallOrCast,1}),
- file_write_sync(FileCtrlPid, Bin, false),
- {ok,element(2, process_info(self(), message_queue_len))};
- DoWrite ->
- ?observe(_Name,{_CallOrCast,1}),
- file_write_async(FileCtrlPid, Bin),
- {ok,LastQLen};
- not DoWrite ->
- ?observe(_Name,{flushed,1}),
- {dropped,LastQLen}
- end,
-
- %% Check if the time since the previous log event is long enough -
- %% and the queue length small enough - to assume the mailbox has
- %% been emptied, and if so, do filesync operation and reset mode to
- %% async. Note that this is the best we can do to detect an idle
- %% handler without setting a timer after each log call/cast. If the
- %% time between two consecutive log events is fast and no new
- %% event comes in after the last one, idle state won't be detected!
- Time = ?diff_time(T1,T0),
- {Mode1,BurstMsgCount1} =
- if (LastQLen1 < ?FILESYNC_OK_QLEN) andalso
- (Time > ?IDLE_DETECT_TIME_USEC) ->
- %% do filesync if necessary
- case maps:get(type, State) of
- Std when is_atom(Std) ->
- ok;
- _File ->
- file_ctrl_filesync_async(FileCtrlPid)
- end,
- {?change_mode(ModeTab, Mode, async),0};
- true ->
- {Mode,BurstMsgCount}
- end,
- State1 =
- ?update_calls_or_casts(_CallOrCast,1,State),
- State2 =
- ?update_max_time(Time,
- State1#{mode => Mode1,
- last_qlen := LastQLen1,
- last_log_ts => T1,
- last_op => write,
- burst_win_ts => BurstWinT,
- burst_msg_count => BurstMsgCount1,
- file_ctrl_sync =>
- ?update_file_ctrl_sync(FileCtrlSync,
- FileCtrlSyncInt)}),
- {Result,State2}.
-
-open_log_file(HandlerName, FileInfo) ->
- case file_ctrl_start(HandlerName, FileInfo) of
- OK = {ok,_FileCtrlPid} -> OK;
- Error -> Error
- end.
-
-do_open_log_file({file,File}) ->
- do_open_log_file({file,File,[raw,append,delayed_write]});
-
-do_open_log_file({file,File,[]}) ->
- do_open_log_file({file,File,[raw,append,delayed_write]});
-
-do_open_log_file({file,File,Modes}) ->
+open_log_file(HandlerName,#{type:=file,
+ file:=FileName,
+ modes:=Modes,
+ file_check:=FileCheck,
+ max_no_bytes:=Size,
+ max_no_files:=Count,
+ compress_on_rotate:=Compress}) ->
try
- case filelib:ensure_dir(File) of
+ case filelib:ensure_dir(FileName) of
ok ->
- file:open(File, Modes);
+ case file:open(FileName, Modes) of
+ {ok, Fd} ->
+ {ok,#file_info{inode=INode}} =
+ file:read_file_info(FileName,[raw]),
+ UpdateModes = [append | Modes--[write,append,exclusive]],
+ State0 = #{handler_name=>HandlerName,
+ file_name=>FileName,
+ modes=>UpdateModes,
+ file_check=>FileCheck,
+ fd=>Fd,
+ inode=>INode,
+ last_check=>timestamp(),
+ synced=>false,
+ write_res=>ok,
+ sync_res=>ok},
+ State = update_rotation({Size,Count,Compress},State0),
+ {ok,State};
+ Error ->
+ Error
+ end;
Error ->
Error
end
@@ -644,34 +332,23 @@ do_open_log_file({file,File,Modes}) ->
_:Reason -> {error,Reason}
end.
-close_log_file(Std) when Std == standard_io; Std == standard_error ->
- ok;
-close_log_file(Fd) ->
+close_log_file(#{fd:=Fd}) ->
_ = file:datasync(Fd),
- _ = file:close(Fd).
+ _ = file:close(Fd),
+ ok;
+close_log_file(_) ->
+ ok.
-log_handler_info(Name, Format, Args, #{file_ctrl_pid := FileCtrlPid}) ->
- Config =
- case logger:get_handler_config(Name) of
- {ok,Conf} -> Conf;
- _ -> #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}
- end,
- Meta = #{time=>erlang:system_time(microsecond)},
- Bin = logger_h_common:log_to_binary(#{level => notice,
- msg => {Format,Args},
- meta => Meta}, Config),
- _ = file_write_async(FileCtrlPid, Bin),
- ok.
%%%-----------------------------------------------------------------
%%% File control process
-file_ctrl_start(HandlerName, FileInfo) ->
+file_ctrl_start(HandlerName, HConfig) ->
Starter = self(),
FileCtrlPid =
spawn_link(fun() ->
- file_ctrl_init(HandlerName, FileInfo, Starter)
+ file_ctrl_init(HandlerName, HConfig, Starter)
end),
receive
{FileCtrlPid,ok} ->
@@ -686,28 +363,21 @@ file_ctrl_start(HandlerName, FileInfo) ->
file_ctrl_stop(Pid) ->
Pid ! stop.
-file_write_async(Pid, Bin) ->
+file_write(async, Pid, Bin) ->
Pid ! {log,Bin},
- ok.
-
-file_write_sync(Pid, Bin, FileSync) ->
- case file_ctrl_call(Pid, {log,self(),Bin,FileSync}) of
- {error,Reason} ->
- {error,{write_failed,Bin,Reason}};
- Result ->
- Result
- end.
+ ok;
+file_write(sync, Pid, Bin) ->
+ file_ctrl_call(Pid, {log,Bin}).
-file_ctrl_filesync_async(Pid) ->
+file_ctrl_filesync(async, Pid) ->
Pid ! filesync,
- ok.
-
-file_ctrl_filesync_sync(Pid) ->
- file_ctrl_call(Pid, {filesync,self()}).
+ ok;
+file_ctrl_filesync(sync, Pid) ->
+ file_ctrl_call(Pid, filesync).
file_ctrl_call(Pid, Msg) ->
MRef = monitor(process, Pid),
- Pid ! {Msg,MRef},
+ Pid ! {Msg,{self(),MRef}},
receive
{MRef,Result} ->
demonitor(MRef, [flush]),
@@ -719,108 +389,255 @@ file_ctrl_call(Pid, Msg) ->
{error,{no_response,Pid}}
end.
-file_ctrl_init(HandlerName, FileInfo, Starter) when is_tuple(FileInfo) ->
+file_ctrl_init(HandlerName,
+ #{type:=file,
+ file:=FileName} = HConfig,
+ Starter) ->
process_flag(message_queue_data, off_heap),
- FileName = element(2, FileInfo),
- case do_open_log_file(FileInfo) of
- {ok,Fd} ->
+ case open_log_file(HandlerName,HConfig) of
+ {ok,State} ->
Starter ! {self(),ok},
- file_ctrl_loop(Fd, file, FileName, false, ok, ok, HandlerName);
+ file_ctrl_loop(State);
{error,Reason} ->
Starter ! {self(),{error,{open_failed,FileName,Reason}}}
end;
-file_ctrl_init(HandlerName, StdDev, Starter) ->
+file_ctrl_init(HandlerName, #{type:=StdDev}, Starter) ->
Starter ! {self(),ok},
- file_ctrl_loop(StdDev, standard_io, StdDev, false, ok, ok, HandlerName).
+ file_ctrl_loop(#{handler_name=>HandlerName,dev=>StdDev}).
-file_ctrl_loop(Fd, Type, DevName, Synced,
- PrevWriteResult, PrevSyncResult, HandlerName) ->
+file_ctrl_loop(State) ->
receive
%% asynchronous event
{log,Bin} ->
- Result = if Type == file ->
- write_to_dev(Fd, Bin, DevName,
- PrevWriteResult, HandlerName);
- true ->
- io:put_chars(Fd, Bin)
- end,
- file_ctrl_loop(Fd, Type, DevName, false,
- Result, PrevSyncResult, HandlerName);
+ State1 = write_to_dev(Bin,State),
+ file_ctrl_loop(State1);
%% synchronous event
- {{log,From,Bin,FileSync},MRef} ->
- if Type == file ->
- %% check that file hasn't been deleted
- CheckFile =
- fun() -> {ok,_} = file:read_file_info(DevName) end,
- spawn_link(CheckFile),
- WResult = write_to_dev(Fd, Bin, DevName,
- PrevWriteResult, HandlerName),
- {Synced1,SResult} =
- if not FileSync ->
- {false,PrevSyncResult};
- true ->
- case sync_dev(Fd, DevName,
- PrevSyncResult, HandlerName) of
- ok -> {true,ok};
- Error -> {false,Error}
- end
- end,
- From ! {MRef,ok},
- file_ctrl_loop(Fd, Type, DevName, Synced1,
- WResult, SResult, HandlerName);
- true ->
- _ = io:put_chars(Fd, Bin),
- From ! {MRef,ok},
- file_ctrl_loop(Fd, Type, DevName, false,
- ok, PrevSyncResult, HandlerName)
- end;
-
- filesync when not Synced ->
- Result = sync_dev(Fd, DevName, PrevSyncResult, HandlerName),
- file_ctrl_loop(Fd, Type, DevName, true,
- PrevWriteResult, Result, HandlerName);
+ {{log,Bin},{From,MRef}} ->
+ State1 = ensure_file(State),
+ State2 = write_to_dev(Bin,State1),
+ From ! {MRef,ok},
+ file_ctrl_loop(State2);
filesync ->
- file_ctrl_loop(Fd, Type, DevName, true,
- PrevWriteResult, PrevSyncResult, HandlerName);
-
- {{filesync,From},MRef} ->
- Result = if not Synced ->
- sync_dev(Fd, DevName, PrevSyncResult, HandlerName);
- true ->
- ok
- end,
+ State1 = sync_dev(State),
+ file_ctrl_loop(State1);
+
+ {filesync,{From,MRef}} ->
+ State1 = ensure_file(State),
+ State2 = sync_dev(State1),
From ! {MRef,ok},
- file_ctrl_loop(Fd, Type, DevName, true,
- PrevWriteResult, Result, HandlerName);
+ file_ctrl_loop(State2);
+
+ {update_config,#{file_check:=FileCheck,
+ max_no_bytes:=Size,
+ max_no_files:=Count,
+ compress_on_rotate:=Compress}} ->
+ State1 = update_rotation({Size,Count,Compress},State),
+ file_ctrl_loop(State1#{file_check=>FileCheck});
stop ->
- _ = close_log_file(Fd),
+ close_log_file(State),
stopped
end.
-write_to_dev(Fd, Bin, FileName, PrevWriteResult, HandlerName) ->
- case ?file_write(Fd, Bin) of
- ok ->
+maybe_ensure_file(#{file_check:=0}=State) ->
+ ensure_file(State);
+maybe_ensure_file(#{last_check:=T0,file_check:=CheckInt}=State)
+ when is_integer(CheckInt) ->
+ T = timestamp(),
+ if T-T0 > CheckInt -> ensure_file(State);
+ true -> State
+ end;
+maybe_ensure_file(State) ->
+ State.
+
+%% In order to play well with tools like logrotate, we need to be able
+%% to re-create the file if it has disappeared (e.g. if rotated by
+%% logrotate)
+ensure_file(#{fd:=Fd0,inode:=INode0,file_name:=FileName,modes:=Modes}=State) ->
+ case file:read_file_info(FileName,[raw]) of
+ {ok,#file_info{inode=INode0}} ->
+ State#{last_check=>timestamp()};
+ _ ->
+ close_log_file(Fd0),
+ case file:open(FileName,Modes) of
+ {ok,Fd} ->
+ {ok,#file_info{inode=INode}} =
+ file:read_file_info(FileName,[raw]),
+ State#{fd=>Fd,inode=>INode,
+ last_check=>timestamp(),
+ synced=>true,sync_res=>ok};
+ Error ->
+ exit({could_not_reopen_file,Error})
+ end
+ end;
+ensure_file(State) ->
+ State.
+
+write_to_dev(Bin,#{dev:=DevName}=State) ->
+ io:put_chars(DevName, Bin),
+ State;
+write_to_dev(Bin, State) ->
+ State1 = #{fd:=Fd} = maybe_ensure_file(State),
+ Result = ?file_write(Fd, Bin),
+ State2 = maybe_rotate_file(Bin,State1),
+ maybe_notify_error(write,Result,State2),
+ State2#{synced=>false,write_res=>Result}.
+
+sync_dev(#{synced:=false}=State) ->
+ State1 = #{fd:=Fd} = maybe_ensure_file(State),
+ Result = ?file_datasync(Fd),
+ maybe_notify_error(filesync,Result,State1),
+ State1#{synced=>true,sync_res=>Result};
+sync_dev(State) ->
+ State.
+
+update_rotation({infinity,_,_},State) ->
+ maybe_remove_archives(0,State),
+ maps:remove(rotation,State);
+update_rotation({Size,Count,Compress},#{file_name:=FileName} = State) ->
+ maybe_remove_archives(Count,State),
+ {ok,#file_info{size=CurrSize}} = file:read_file_info(FileName,[raw]),
+ State1 = State#{rotation=>#{size=>Size,
+ count=>Count,
+ compress=>Compress,
+ curr_size=>CurrSize}},
+ maybe_update_compress(0,State1),
+ maybe_rotate_file(0,State1).
+
+maybe_remove_archives(Count,#{file_name:=FileName}=State) ->
+ Archive = rot_file_name(FileName,Count,false),
+ CompressedArchive = rot_file_name(FileName,Count,true),
+ case {file:read_file_info(Archive,[raw]),
+ file:read_file_info(CompressedArchive,[raw])} of
+ {{error,enoent},{error,enoent}} ->
ok;
- PrevWriteResult ->
- %% don't report same error twice
- PrevWriteResult;
- Error ->
- logger_h_common:error_notify({HandlerName,write,FileName,Error}),
- Error
+ _ ->
+ _ = file:delete(Archive),
+ _ = file:delete(CompressedArchive),
+ maybe_remove_archives(Count+1,State)
end.
-sync_dev(Fd, DevName, PrevSyncResult, HandlerName) ->
- case ?file_datasync(Fd) of
- ok ->
- ok;
- PrevSyncResult ->
- %% don't report same error twice
- PrevSyncResult;
+maybe_update_compress(Count,#{rotation:=#{count:=Count}}) ->
+ ok;
+maybe_update_compress(N,#{file_name:=FileName,
+ rotation:=#{compress:=Compress}}=State) ->
+ Archive = rot_file_name(FileName,N,not Compress),
+ case file:read_file_info(Archive,[raw]) of
+ {ok,_} when Compress ->
+ compress_file(Archive);
+ {ok,_} ->
+ decompress_file(Archive);
+ _ ->
+ ok
+ end,
+ maybe_update_compress(N+1,State).
+
+maybe_rotate_file(Bin,#{rotation:=_}=State) when is_binary(Bin) ->
+ maybe_rotate_file(byte_size(Bin),State);
+maybe_rotate_file(AddSize,#{rotation:=#{size:=RotSize,
+ curr_size:=CurrSize}=Rotation}=State) ->
+ NewSize = CurrSize + AddSize,
+ if NewSize>RotSize ->
+ rotate_file(State#{rotation=>Rotation#{curr_size=>NewSize}});
+ true ->
+ State#{rotation=>Rotation#{curr_size=>NewSize}}
+ end;
+maybe_rotate_file(_Bin,State) ->
+ State.
+
+rotate_file(#{fd:=Fd0,file_name:=FileName,modes:=Modes,rotation:=Rotation}=State) ->
+ State1 = sync_dev(State),
+ _ = file:close(Fd0),
+ _ = file:close(Fd0),
+ rotate_files(FileName,maps:get(count,Rotation),maps:get(compress,Rotation)),
+ case file:open(FileName,Modes) of
+ {ok,Fd} ->
+ {ok,#file_info{inode=INode}} = file:read_file_info(FileName,[raw]),
+ State1#{fd=>Fd,inode=>INode,rotation=>Rotation#{curr_size=>0}};
Error ->
- logger_h_common:error_notify({HandlerName,filesync,DevName,Error}),
- Error
+ exit({could_not_reopen_file,Error})
end.
+rotate_files(FileName,0,_Compress) ->
+ _ = file:delete(FileName),
+ ok;
+rotate_files(FileName,1,Compress) ->
+ FileName0 = FileName++".0",
+ _ = file:rename(FileName,FileName0),
+ if Compress -> compress_file(FileName0);
+ true -> ok
+ end,
+ ok;
+rotate_files(FileName,Count,Compress) ->
+ _ = file:rename(rot_file_name(FileName,Count-2,Compress),
+ rot_file_name(FileName,Count-1,Compress)),
+ rotate_files(FileName,Count-1,Compress).
+
+rot_file_name(FileName,Count,false) ->
+ FileName ++ "." ++ integer_to_list(Count);
+rot_file_name(FileName,Count,true) ->
+ rot_file_name(FileName,Count,false) ++ ".gz".
+
+compress_file(FileName) ->
+ {ok,In} = file:open(FileName,[read,binary]),
+ {ok,Out} = file:open(FileName++".gz",[write]),
+ Z = zlib:open(),
+ zlib:deflateInit(Z, default, deflated, 31, 8, default),
+ compress_data(Z,In,Out),
+ zlib:deflateEnd(Z),
+ zlib:close(Z),
+ _ = file:close(In),
+ _ = file:close(Out),
+ _ = file:delete(FileName),
+ ok.
+
+compress_data(Z,In,Out) ->
+ case file:read(In,100000) of
+ {ok,Data} ->
+ Compressed = zlib:deflate(Z, Data),
+ _ = file:write(Out,Compressed),
+ compress_data(Z,In,Out);
+ eof ->
+ Compressed = zlib:deflate(Z, <<>>, finish),
+ _ = file:write(Out,Compressed),
+ ok
+ end.
+
+decompress_file(FileName) ->
+ {ok,In} = file:open(FileName,[read,binary]),
+ {ok,Out} = file:open(filename:rootname(FileName,".gz"),[write]),
+ Z = zlib:open(),
+ zlib:inflateInit(Z, 31),
+ decompress_data(Z,In,Out),
+ zlib:inflateEnd(Z),
+ zlib:close(Z),
+ _ = file:close(In),
+ _ = file:close(Out),
+ _ = file:delete(FileName),
+ ok.
+
+decompress_data(Z,In,Out) ->
+ case file:read(In,1000) of
+ {ok,Data} ->
+ Decompressed = zlib:inflate(Z, Data),
+ _ = file:write(Out,Decompressed),
+ decompress_data(Z,In,Out);
+ eof ->
+ ok
+ end.
+
+maybe_notify_error(_Op, ok, _State) ->
+ ok;
+maybe_notify_error(Op, Result, #{write_res:=WR,sync_res:=SR})
+ when (Op==write andalso Result==WR) orelse
+ (Op==filesync andalso Result==SR) ->
+ %% don't report same error twice
+ ok;
+maybe_notify_error(Op, Error, #{handler_name:=HandlerName,file_name:=FileName}) ->
+ logger_h_common:error_notify({HandlerName,Op,FileName,Error}),
+ ok.
+
+timestamp() ->
+ erlang:monotonic_time(millisecond).
diff --git a/lib/kernel/src/logger_sup.erl b/lib/kernel/src/logger_sup.erl
index dcdcdad0bd..9ea8558a16 100644
--- a/lib/kernel/src/logger_sup.erl
+++ b/lib/kernel/src/logger_sup.erl
@@ -46,7 +46,13 @@ init([]) ->
intensity => 1,
period => 5},
- {ok, {SupFlags, []}}.
+ Watcher = #{id => logger_handler_watcher,
+ start => {logger_handler_watcher, start_link, []},
+ shutdown => brutal_kill},
+
+ Proxy = logger_proxy:child_spec(),
+
+ {ok, {SupFlags, [Watcher,Proxy]}}.
%%%===================================================================
%%% Internal functions
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index c4e1a0ce1e..a9dc77837e 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -279,24 +279,18 @@ passive_connect_monitor(From, Node) ->
ok = monitor_nodes(true,[{node_type,all}]),
Reply = case lists:member(Node,nodes([connected])) of
true ->
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
true;
_ ->
receive
{nodeup,Node,_} ->
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
true
after connecttime() ->
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
false
end
end,
ok = monitor_nodes(false,[{node_type,all}]),
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
{Pid, Tag} = From,
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
- erlang:send(Pid, {Tag, Reply}),
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]).
+ erlang:send(Pid, {Tag, Reply}).
%% If the net_kernel isn't running we ignore all requests to the
@@ -358,20 +352,34 @@ init({Name, LongOrShortNames, TickT, CleanHalt}) ->
{stop, Error}
end.
-
-do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State) ->
- ConnLookup = ets:lookup(sys_dist, Node),
-
- case ConnLookup of
+do_auto_connect_1(Node, ConnId, From, State) ->
+ case ets:lookup(sys_dist, Node) of
[#barred_connection{}] ->
- case WaitForBarred of
- false ->
- {reply, false, State};
- true ->
+ case ConnId of
+ passive_cnct ->
spawn(?MODULE,passive_connect_monitor,[From,Node]),
- {noreply, State}
+ {noreply, State};
+ _ ->
+ erts_internal:abort_connection(Node, ConnId),
+ {reply, false, State}
end;
+ ConnLookup ->
+ do_auto_connect_2(Node, ConnId, From, State, ConnLookup)
+ end.
+
+do_auto_connect_2(Node, passive_cnct, From, State, ConnLookup) ->
+ try erts_internal:new_connection(Node) of
+ ConnId ->
+ do_auto_connect_2(Node, ConnId, From, State, ConnLookup)
+ catch
+ _:_ ->
+ error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
+ [Node]),
+ {reply, false, State}
+ end;
+do_auto_connect_2(Node, ConnId, From, State, ConnLookup) ->
+ case ConnLookup of
[#connection{conn_id=ConnId, state = up}] ->
{reply, true, State};
[#connection{conn_id=ConnId, waiting=Waiting}=Conn] ->
@@ -385,6 +393,7 @@ do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State) ->
case application:get_env(kernel, dist_auto_connect) of
{ok, never} ->
?connect_failure(Node,{dist_auto_connect,never}),
+ erts_internal:abort_connection(Node, ConnId),
{reply, false, State};
%% This might happen due to connection close
@@ -394,14 +403,16 @@ do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State) ->
(hd(ConnLookup))#connection.state =:= up ->
?connect_failure(Node,{barred_connection,
ets:lookup(sys_dist, Node)}),
+ erts_internal:abort_connection(Node, ConnId),
{reply, false, State};
_ ->
- case setup(ConnLookup, Node,ConnId,Type,From,State) of
+ case setup(Node, ConnId, normal, From, State) of
{ok, SetupPid} ->
Owners = [{SetupPid, Node} | State#state.conn_owners],
{noreply,State#state{conn_owners=Owners}};
_Error ->
?connect_failure(Node, {setup_call, failed, _Error}),
+ erts_internal:abort_connection(Node, ConnId),
{reply, false, State}
end
end
@@ -419,8 +430,8 @@ do_explicit_connect([#connection{conn_id = ConnId}=Conn], _, _, ConnId, From, St
do_explicit_connect([#barred_connection{}], Type, Node, ConnId, From , State) ->
%% Barred connection only affects auto_connect, ignore it.
do_explicit_connect([], Type, Node, ConnId, From , State);
-do_explicit_connect(ConnLookup, Type, Node, ConnId, From , State) ->
- case setup(ConnLookup, Node,ConnId,Type,From,State) of
+do_explicit_connect(_ConnLookup, Type, Node, ConnId, From , State) ->
+ case setup(Node,ConnId,Type,From,State) of
{ok, SetupPid} ->
Owners = [{SetupPid, Node} | State#state.conn_owners],
{noreply,State#state{conn_owners=Owners}};
@@ -429,18 +440,6 @@ do_explicit_connect(ConnLookup, Type, Node, ConnId, From , State) ->
{reply, false, State}
end.
--define(ERTS_DIST_CON_ID_MASK, 16#ffffff). % also in external.h
-
-verify_new_conn_id([], {Nr,_DHandle})
- when (Nr band (bnot ?ERTS_DIST_CON_ID_MASK)) =:= 0 ->
- true;
-verify_new_conn_id([#connection{conn_id = {Old,_}}], {New,_})
- when New =:= ((Old+1) band ?ERTS_DIST_CON_ID_MASK) ->
- true;
-verify_new_conn_id(_, _) ->
- false.
-
-
%% ------------------------------------------------------------
%% handle_call.
@@ -454,34 +453,33 @@ handle_call({passive_cnct, Node}, From, State) when Node =:= node() ->
async_reply({reply, true, State}, From);
handle_call({passive_cnct, Node}, From, State) ->
verbose({passive_cnct, Node}, 1, State),
- Type = normal,
- WaitForBarred = true,
- R = case (catch erts_internal:new_connection(Node)) of
- {Nr,_DHandle}=ConnId when is_integer(Nr) ->
- do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State);
-
- _Error ->
- error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
- [Node]),
- {reply, false, State}
- end,
-
+ R = do_auto_connect_1(Node, passive_cnct, From, State),
return_call(R, From);
%%
%% Explicit connect
%% The response is delayed until the connection is up and running.
%%
-handle_call({connect, _, Node, _, _}, From, State) when Node =:= node() ->
+handle_call({connect, _, Node}, From, State) when Node =:= node() ->
async_reply({reply, true, State}, From);
handle_call({connect, Type, Node}, From, State) ->
verbose({connect, Type, Node}, 1, State),
ConnLookup = ets:lookup(sys_dist, Node),
- R = case (catch erts_internal:new_connection(Node)) of
- {Nr,_DHandle}=ConnId when is_integer(Nr) ->
- do_explicit_connect(ConnLookup, Type, Node, ConnId, From, State);
+ R = try erts_internal:new_connection(Node) of
+ ConnId ->
+ R1 = do_explicit_connect(ConnLookup, Type, Node, ConnId, From, State),
+ case R1 of
+ {reply, true, _S} -> %% already connected
+ ok;
+ {noreply, _S} -> %% connection pending
+ ok;
+ {reply, false, _S} -> %% connection refused
+ erts_internal:abort_connection(Node, ConnId)
+ end,
+ R1
- _Error ->
+ catch
+ _:_ ->
error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
[Node]),
{reply, false, State}
@@ -699,11 +697,11 @@ terminate(_Reason, State) ->
%%
%% Asynchronous auto connect request
%%
-handle_info({auto_connect,Node, Nr, DHandle}, State) ->
- verbose({auto_connect, Node, Nr, DHandle}, 1, State),
- ConnId = {Nr, DHandle},
+handle_info({auto_connect,Node, DHandle}, State) ->
+ verbose({auto_connect, Node, DHandle}, 1, State),
+ ConnId = DHandle,
NewState =
- case do_auto_connect(normal, Node, ConnId, false, noreply, State) of
+ case do_auto_connect_1(Node, ConnId, noreply, State) of
{noreply, S} -> %% Pending connection
S;
@@ -711,7 +709,6 @@ handle_info({auto_connect,Node, Nr, DHandle}, State) ->
S;
{reply, false, S} -> %% Connection refused
- erts_internal:abort_connection(Node, ConnId),
S
end,
{noreply, NewState};
@@ -796,8 +793,8 @@ handle_info({AcceptPid, {accept_pending,MyNode,Node,Address,Type}}, State) ->
AcceptPid ! {self(), {accept_pending, already_pending}},
{noreply, State};
_ ->
- case (catch erts_internal:new_connection(Node)) of
- {Nr,_DHandle}=ConnId when is_integer(Nr) ->
+ try erts_internal:new_connection(Node) of
+ ConnId ->
ets:insert(sys_dist, #connection{node = Node,
conn_id = ConnId,
state = pending,
@@ -806,12 +803,13 @@ handle_info({AcceptPid, {accept_pending,MyNode,Node,Address,Type}}, State) ->
type = Type}),
AcceptPid ! {self(),{accept_pending,ok}},
Owners = [{AcceptPid,Node} | State#state.conn_owners],
- {noreply, State#state{conn_owners = Owners}};
-
- _ ->
+ {noreply, State#state{conn_owners = Owners}}
+ catch
+ _:_ ->
error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
[Node]),
- AcceptPid ! {self(),{accept_pending,nok_pending}}
+ AcceptPid ! {self(),{accept_pending,nok_pending}},
+ {noreply, State}
end
end;
@@ -1275,8 +1273,8 @@ spawn_func(_,{From,Tag},M,F,A,Gleader) ->
%% Set up connection to a new node.
%% -----------------------------------------------------------
-setup(ConnLookup, Node,ConnId,Type,From,State) ->
- case setup_check(ConnLookup, Node, ConnId, State) of
+setup(Node, ConnId, Type, From, State) ->
+ case setup_check(Node, State) of
{ok, L} ->
Mod = L#listen.module,
LAddr = L#listen.address,
@@ -1305,7 +1303,7 @@ setup(ConnLookup, Node,ConnId,Type,From,State) ->
Error
end.
-setup_check(ConnLookup, Node, ConnId, State) ->
+setup_check(Node, State) ->
Allowed = State#state.allowed,
case lists:member(Node, Allowed) of
false when Allowed =/= [] ->
@@ -1313,16 +1311,9 @@ setup_check(ConnLookup, Node, ConnId, State) ->
"disallowed node ~w ** ~n", [Node]),
{error, bad_node};
_ ->
- case verify_new_conn_id(ConnLookup, ConnId) of
- false ->
- error_msg("** Connection attempt to ~w with "
- "bad connection id ~w ** ~n", [Node, ConnId]),
- {error, bad_conn_id};
- true ->
- case select_mod(Node, State#state.listen) of
- {ok, _L}=OK -> OK;
- Error -> Error
- end
+ case select_mod(Node, State#state.listen) of
+ {ok, _L}=OK -> OK;
+ Error -> Error
end
end.
diff --git a/lib/kernel/src/raw_file_io_inflate.erl b/lib/kernel/src/raw_file_io_inflate.erl
index 7e9780310c..d3ed02dd03 100644
--- a/lib/kernel/src/raw_file_io_inflate.erl
+++ b/lib/kernel/src/raw_file_io_inflate.erl
@@ -26,7 +26,7 @@
-include("file_int.hrl").
--define(INFLATE_CHUNK_SIZE, (1 bsl 10)).
+-define(INFLATE_CHUNK_SIZE, (8 bsl 10)).
-define(GZIP_WBITS, (16 + 15)).
callback_mode() -> state_functions.
diff --git a/lib/kernel/src/seq_trace.erl b/lib/kernel/src/seq_trace.erl
index 20185dd319..f0bd1fabe9 100644
--- a/lib/kernel/src/seq_trace.erl
+++ b/lib/kernel/src/seq_trace.erl
@@ -98,7 +98,7 @@ print(Label, Term) ->
-spec reset_trace() -> 'true'.
reset_trace() ->
- erlang:system_flag(1, 0).
+ erlang:system_flag(reset_seq_trace, true).
%% reset_trace(Pid) -> % this might be a useful function too
diff --git a/lib/kernel/src/standard_error.erl b/lib/kernel/src/standard_error.erl
index 5d649e5f94..ef5b532960 100644
--- a/lib/kernel/src/standard_error.erl
+++ b/lib/kernel/src/standard_error.erl
@@ -27,7 +27,8 @@
-define(PROCNAME_SUP, standard_error_sup).
%% Defines for control ops
--define(CTRL_OP_GET_WINSIZE,100).
+-define(ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER, 16#018b0900).
+-define(CTRL_OP_GET_WINSIZE, (100 + ?ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER)).
%%
%% The basic server and start-up.
diff --git a/lib/kernel/src/user.erl b/lib/kernel/src/user.erl
index 872e63ab53..0c9e1ea303 100644
--- a/lib/kernel/src/user.erl
+++ b/lib/kernel/src/user.erl
@@ -28,7 +28,8 @@
-define(NAME, user).
%% Defines for control ops
--define(CTRL_OP_GET_WINSIZE,100).
+-define(ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER, 16#018b0900).
+-define(CTRL_OP_GET_WINSIZE, (100 + ?ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER)).
%%
%% The basic server and start-up.
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index 9f914aa222..08286dd476 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.erl
@@ -32,9 +32,10 @@
-define(OP_BEEP,4).
-define(OP_PUTC_SYNC,5).
% Control op
--define(CTRL_OP_GET_WINSIZE,100).
--define(CTRL_OP_GET_UNICODE_STATE,101).
--define(CTRL_OP_SET_UNICODE_STATE,102).
+-define(ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER, 16#018b0900).
+-define(CTRL_OP_GET_WINSIZE, (100 + ?ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER)).
+-define(CTRL_OP_GET_UNICODE_STATE, (101 + ?ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER)).
+-define(CTRL_OP_SET_UNICODE_STATE, (102 + ?ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER)).
%% start()
%% start(ArgumentList)
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 4a86265a4a..8a6ffe7e72 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -76,8 +76,11 @@ MODULES= \
logger_filters_SUITE \
logger_formatter_SUITE \
logger_legacy_SUITE \
+ logger_olp_SUITE \
+ logger_proxy_SUITE \
logger_simple_h_SUITE \
logger_std_h_SUITE \
+ logger_stress_SUITE \
logger_test_lib \
os_SUITE \
pg2_SUITE \
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index 5c35b82207..94d7c17712 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -31,6 +31,7 @@
otp_3002/1, otp_3184/1, otp_4066/1, otp_4227/1, otp_5363/1,
otp_5606/1,
start_phases/1, get_key/1, get_env/1,
+ set_env/1, set_env_persistent/1, set_env_errors/1,
permit_false_start_local/1, permit_false_start_dist/1, script_start/1,
nodedown_start/1, init2973/0, loop2973/0, loop5606/1]).
@@ -55,6 +56,7 @@ all() ->
load_use_cache, ensure_started, {group, reported_bugs}, start_phases,
script_start, nodedown_start, permit_false_start_local,
permit_false_start_dist, get_key, get_env, ensure_all_started,
+ set_env, set_env_persistent, set_env_errors,
{group, distr_changed}, config_change, shutdown_func, shutdown_timeout,
shutdown_deadlock, config_relative_paths,
persistent_env].
@@ -1944,6 +1946,101 @@ get_appls([_ | T], Res) ->
get_appls([], Res) ->
Res.
+%% Test set_env/1.
+set_env(Conf) when is_list(Conf) ->
+ ok = application:set_env([{appinc, [{own2, persist}, {not_in_app, persist}]},
+ {unknown_app, [{key, persist}]}]),
+
+ %% own_env1 and own2 are set in appinc
+ undefined = application:get_env(appinc, own_env1),
+ {ok, persist} = application:get_env(appinc, own2),
+ {ok, persist} = application:get_env(appinc, not_in_app),
+ {ok, persist} = application:get_env(unknown_app, key),
+
+ ok = application:load(appinc()),
+ {ok, value1} = application:get_env(appinc, own_env1),
+ {ok, val2} = application:get_env(appinc, own2),
+ {ok, persist} = application:get_env(appinc, not_in_app),
+ {ok, persist} = application:get_env(unknown_app, key),
+
+ %% On reload, values are lost
+ ok = application:unload(appinc),
+ ok = application:load(appinc()),
+ {ok, value1} = application:get_env(appinc, own_env1),
+ {ok, val2} = application:get_env(appinc, own2),
+ undefined = application:get_env(appinc, not_in_app),
+
+ %% Clean up
+ ok = application:unload(appinc).
+
+%% Test set_env/2 with persistent true.
+set_env_persistent(Conf) when is_list(Conf) ->
+ Opts = [{persistent, true}],
+ ok = application:set_env([{appinc, [{own2, persist}, {not_in_app, persist}]},
+ {unknown_app, [{key, persist}]}], Opts),
+
+ %% own_env1 and own2 are set in appinc
+ undefined = application:get_env(appinc, own_env1),
+ {ok, persist} = application:get_env(appinc, own2),
+ {ok, persist} = application:get_env(appinc, not_in_app),
+ {ok, persist} = application:get_env(unknown_app, key),
+
+ ok = application:load(appinc()),
+ {ok, value1} = application:get_env(appinc, own_env1),
+ {ok, persist} = application:get_env(appinc, own2),
+ {ok, persist} = application:get_env(appinc, not_in_app),
+ {ok, persist} = application:get_env(unknown_app, key),
+
+ %% On reload, values are not lost
+ ok = application:unload(appinc),
+ ok = application:load(appinc()),
+ {ok, value1} = application:get_env(appinc, own_env1),
+ {ok, persist} = application:get_env(appinc, own2),
+ {ok, persist} = application:get_env(appinc, not_in_app),
+
+ %% Clean up
+ ok = application:unload(appinc).
+
+set_env_errors(Conf) when is_list(Conf) ->
+ "application: 1; application name must be an atom" =
+ badarg_msg(fun() -> application:set_env([{1, []}]) end),
+
+ "application: foo; parameters must be a list" =
+ badarg_msg(fun() -> application:set_env([{foo, bar}]) end),
+
+ "invalid application config: foo_bar" =
+ badarg_msg(fun() -> application:set_env([foo_bar]) end),
+
+ "application: foo; invalid parameter name: 1" =
+ badarg_msg(fun() -> application:set_env([{foo, [{1, 2}]}]) end),
+
+ "application: foo; invalid parameter: config" =
+ badarg_msg(fun() -> application:set_env([{foo, [config]}]) end),
+
+ "application: kernel; erroneous parameter: distributed" =
+ badarg_msg(fun() -> application:set_env([{kernel, [{distributed, config}]}]) end),
+
+ %% This will raise in the future
+ ct:capture_start(),
+ _ = application:set_env([{foo, []}, {foo, []}]),
+ timer:sleep(100),
+ ct:capture_stop(),
+ [_ | _] = string:find(ct:capture_get(), "duplicate application config: foo"),
+
+ ct:capture_start(),
+ _ = application:set_env([{foo, [{bar, baz}, {bar, bat}]}]),
+ timer:sleep(100),
+ ct:capture_stop(),
+ [_ | _] = string:find(ct:capture_get(), "application: foo; duplicate parameter: bar"),
+
+ ok.
+
+badarg_msg(Fun) ->
+ try Fun() of
+ _ -> ct:fail(try_succeeded)
+ catch
+ error:{badarg, Msg} -> Msg
+ end.
%% Test set_env/4 and unset_env/3 with persistent true.
persistent_env(Conf) when is_list(Conf) ->
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index 0709a6e766..9704c3b28c 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1750,7 +1750,7 @@ block_queue(Conf) when is_list(Conf) ->
true = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g},{8,h}] == Terms,
del(File, 2),
Q = qlen(),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
%% OTP-4880. Blocked processes did not get disk_log_stopped message.
@@ -1782,7 +1782,7 @@ block_queue2(Conf) when is_list(Conf) ->
{ok,<<>>} = file:read_file(File ++ ".1"),
del(File, No),
Q = qlen(),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
@@ -2119,7 +2119,7 @@ close_block(Conf) when is_list(Conf) ->
0 = sync_do(Pid2, users),
sync_do(Pid2, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Users terminate (no link...).
Pid3 = spawn_link(?MODULE, lserv, [n]),
@@ -2137,7 +2137,7 @@ close_block(Conf) when is_list(Conf) ->
disk_log:close(n),
disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner terminates.
Pid5 = spawn_link(?MODULE, lserv, [n]),
@@ -2154,7 +2154,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user terminates.
Pid6 = spawn_link(?MODULE, lserv, [n]),
@@ -2174,7 +2174,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner terminates.
Pid7 = spawn_link(?MODULE, lserv, [n]),
@@ -2192,7 +2192,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Two owners, the blocking one terminates.
Pid8 = spawn_link(?MODULE, lserv, [n]),
@@ -2207,7 +2207,7 @@ close_block(Conf) when is_list(Conf) ->
0 = sync_do(Pid9, users),
sync_do(Pid9, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user closes.
Pid10 = spawn_link(?MODULE, lserv, [n]),
@@ -2225,7 +2225,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
sync_do(Pid10, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user unblocks and closes.
Pid11 = spawn_link(?MODULE, lserv, [n]),
@@ -2244,7 +2244,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid11, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner closes.
Pid12 = spawn_link(?MODULE, lserv, [n]),
@@ -2263,7 +2263,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid12, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner unblocks and closes.
Pid13 = spawn_link(?MODULE, lserv, [n]),
@@ -2283,7 +2283,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid13, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No), % cleanup
ok.
@@ -2487,7 +2487,7 @@ error_repair(Conf) when is_list(Conf) ->
P0 = pps(),
{error, {file_error, _, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap}, {size,{40,4}}]),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No),
ok = file:del_dir(Dir),
@@ -2506,7 +2506,7 @@ error_repair(Conf) when is_list(Conf) ->
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {40,No}}]),
ok = disk_log:close(n),
- true = (P1 == pps()),
+ check_pps(P1),
del(File, No),
receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
after 1000 -> ct:fail(failed) end,
@@ -2524,7 +2524,7 @@ error_repair(Conf) when is_list(Conf) ->
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {4000,No}}]),
ok = disk_log:close(n),
- true = (P2 == pps()),
+ check_pps(P2),
del(File, No),
receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
after 1000 -> ct:fail(failed) end,
@@ -2633,7 +2633,7 @@ error_log(Conf) when is_list(Conf) ->
{ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external},{size, {100, No}}]),
{error, {file_error, _, _}} = disk_log:truncate(n),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No),
%% OTP-4880.
@@ -2641,7 +2641,7 @@ error_log(Conf) when is_list(Conf) ->
{ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},{size, 100000}]),
{error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir),
- true = (P0 == pps()),
+ check_pps(P0),
file:delete(File),
B = mk_bytes(60),
@@ -3003,7 +3003,7 @@ error_index(Conf) when is_list(Conf) ->
{error, {invalid_index_file, _}} = disk_log:open(Args),
del(File, No),
- true = (P0 == pps()),
+ check_pps(P0),
true = (Q == qlen()),
ok.
@@ -4436,7 +4436,7 @@ dist_open2(Conf) when is_list(Conf) ->
timer:sleep(500),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
%% This time the first process has a naughty head_func. This test
%% does not add very much. Perhaps it should be removed. However,
@@ -4482,7 +4482,7 @@ dist_open2(Conf) when is_list(Conf) ->
timer:sleep(100),
{error, no_such_log} = disk_log:close(Log),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
No = 2,
Log2 = n2,
@@ -4511,7 +4511,7 @@ dist_open2(Conf) when is_list(Conf) ->
file:delete(File2),
del(File, No),
- true = (P0 == pps()),
+ check_pps(P0),
R.
@@ -4556,7 +4556,7 @@ dist_open2_1(Conf, Delay) ->
{error, no_such_log} = disk_log:info(Log),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
@@ -4613,7 +4613,7 @@ dist_open2_2(Conf, Delay) ->
{[{Node1,{repaired,_,_,_}}],[]}} -> ok
end,
- true = (P0 == pps()),
+ check_pps(P0),
stop_node(Node1),
file:delete(File),
ok.
@@ -4791,10 +4791,59 @@ log(Name, N) ->
format_error(E) ->
lists:flatten(disk_log:format_error(E)).
+check_pps({Ports0,Procs0} = P0) ->
+ case pps() of
+ P0 ->
+ ok;
+ _ ->
+ timer:sleep(500),
+ case pps() of
+ P0 ->
+ ok;
+ {Ports1,Procs1} = P1 ->
+ case {Ports1 -- Ports0, Procs1 -- Procs0} of
+ {[], []} -> ok;
+ {PortsDiff,ProcsDiff} ->
+ io:format("failure, got ~p~n, expected ~p\n", [P1, P0]),
+ show("Old port", Ports0 -- Ports1),
+ show("New port", PortsDiff),
+ show("Old proc", Procs0 -- Procs1),
+ show("New proc", ProcsDiff),
+ ct:fail(failed)
+ end
+ end
+ end.
+
+show(_S, []) ->
+ ok;
+show(S, [{Pid, Name, InitCall}|Pids]) when is_pid(Pid) ->
+ io:format("~s: ~w (~w), ~w: ~p~n",
+ [S, Pid, proc_reg_name(Name), InitCall,
+ erlang:process_info(Pid)]),
+ show(S, Pids);
+show(S, [{Port, _}|Ports]) when is_port(Port)->
+ io:format("~s: ~w: ~p~n", [S, Port, erlang:port_info(Port)]),
+ show(S, Ports).
+
pps() ->
timer:sleep(100),
- {erlang:ports(), lists:filter(fun(P) -> erlang:is_process_alive(P) end,
- processes())}.
+ {port_list(), process_list()}.
+
+port_list() ->
+ [{P,safe_second_element(erlang:port_info(P, name))} ||
+ P <- erlang:ports()].
+
+process_list() ->
+ [{P,process_info(P, registered_name),
+ safe_second_element(process_info(P, initial_call))} ||
+ P <- processes(), erlang:is_process_alive(P)].
+
+proc_reg_name({registered_name, Name}) -> Name;
+proc_reg_name([]) -> no_reg_name.
+
+safe_second_element({_,Info}) -> Info;
+safe_second_element(Other) -> Other.
+
qlen() ->
{_, {_, N}} = lists:keysearch(message_queue_len, 1, process_info(self())),
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 9c6712ad74..5a8bbd56c4 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -25,6 +25,7 @@
init_per_group/2,end_per_group/2]).
-export([tick/1, tick_change/1,
+ connect_node/1,
nodenames/1, hostnames/1,
illegal_nodenames/1, hidden_node/1,
setopts/1,
@@ -70,6 +71,7 @@ suite() ->
all() ->
[tick, tick_change, nodenames, hostnames, illegal_nodenames,
+ connect_node,
hidden_node, setopts,
table_waste, net_setuptime, inet_dist_options_options,
{group, monitor_nodes}].
@@ -87,6 +89,7 @@ init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
+ [slave:stop(N) || N <- nodes()],
ok.
init_per_group(_GroupName, Config) ->
@@ -106,6 +109,12 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
end_per_testcase(_Func, _Config) ->
ok.
+connect_node(Config) when is_list(Config) ->
+ Connected = nodes(connected),
+ true = net_kernel:connect_node(node()),
+ Connected = nodes(connected),
+ ok.
+
tick(Config) when is_list(Config) ->
PaDir = filename:dirname(code:which(erl_distribution_SUITE)),
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 23913ac56a..a51025cba6 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -100,7 +100,7 @@
-export([unicode_mode/1]).
--export([volume_relative_paths/1]).
+-export([volume_relative_paths/1,unc_paths/1]).
-export([tiny_writes/1, tiny_writes_delayed/1,
large_writes/1, large_writes_delayed/1,
@@ -129,7 +129,7 @@ suite() ->
all() ->
[unicode, altname, read_write_file, {group, dirs},
- {group, files}, delete, rename, names, volume_relative_paths,
+ {group, files}, delete, rename, names, volume_relative_paths, unc_paths,
{group, errors}, {group, compression}, {group, links}, copy,
delayed_write, read_ahead, segment_read, segment_write,
ipread, pid2name, interleaved_read_write, otp_5814, otp_10852,
@@ -1367,6 +1367,10 @@ file_info_basic_file(Config) when is_list(Config) ->
io:put_chars(Fd1, "foo bar"),
ok = ?FILE_MODULE:close(Fd1),
+ %% Don't crash the file server when passing incorrect arguments.
+ {error,badarg} = ?FILE_MODULE:read_file_info(Name, [{time, gurka}]),
+ {error,badarg} = ?FILE_MODULE:read_file_info([#{} | gaffel]),
+
%% Test that the file has the expected attributes.
%% The times are tricky, so we will save them to a separate test case.
{ok,FileInfo} = ?FILE_MODULE:read_file_info(Name),
@@ -2178,6 +2182,30 @@ volume_relative_paths(Config) when is_list(Config) ->
{skip, "This test is Windows-specific."}
end.
+unc_paths(Config) when is_list(Config) ->
+ case os:type() of
+ {win32, _} ->
+ %% We assume administrative shares are set up and reachable, and we
+ %% settle for testing presence as some of the returned data is
+ %% different.
+ {ok, _} = file:read_file_info("C:\\Windows\\explorer.exe"),
+ {ok, _} = file:read_file_info("\\\\localhost\\c$\\Windows\\explorer.exe"),
+
+ {ok, Cwd} = file:get_cwd(),
+
+ try
+ ok = file:set_cwd("\\\\localhost\\c$\\Windows\\"),
+ {ok, _} = file:read_file_info("explorer.exe")
+ after
+ file:set_cwd(Cwd)
+ end,
+
+ [] = flush(),
+ ok;
+ _ ->
+ {skip, "This test is Windows-specific."}
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2206,7 +2234,8 @@ e_delete(Config) when is_list(Config) ->
case os:type() of
{win32, _} ->
%% Remove a character device.
- {error, eacces} = ?FILE_MODULE:delete("nul");
+ expect({error, eacces}, {error, einval},
+ ?FILE_MODULE:delete("nul"));
_ ->
?FILE_MODULE:write_file_info(
Base, #file_info {mode=0}),
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 950f5bea6f..52edfaee29 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -41,6 +41,7 @@
busy_send/1, busy_disconnect_passive/1, busy_disconnect_active/1,
fill_sendq/1, partial_recv_and_close/1,
partial_recv_and_close_2/1,partial_recv_and_close_3/1,so_priority/1,
+ recvtos/1, recvttl/1, recvtosttl/1, recvtclass/1,
%% Accept tests
primitive_accept/1,multi_accept_close_listen/1,accept_timeout/1,
accept_timeouts_in_order/1,accept_timeouts_in_order2/1,
@@ -51,7 +52,8 @@
several_accepts_in_one_go/1, accept_system_limit/1,
active_once_closed/1, send_timeout/1, send_timeout_active/1,
otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
- wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1]).
+ wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1,
+ otp_12242/1, delay_send_error/1]).
%% Internal exports.
-export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1,
@@ -83,7 +85,8 @@ all() ->
busy_disconnect_passive, busy_disconnect_active,
fill_sendq, partial_recv_and_close,
partial_recv_and_close_2, partial_recv_and_close_3,
- so_priority, primitive_accept,
+ so_priority, recvtos, recvttl, recvtosttl,
+ recvtclass, primitive_accept,
multi_accept_close_listen, accept_timeout,
accept_timeouts_in_order, accept_timeouts_in_order2,
accept_timeouts_in_order3, accept_timeouts_in_order4,
@@ -93,7 +96,8 @@ all() ->
killing_multi_acceptors2, several_accepts_in_one_go, accept_system_limit,
active_once_closed, send_timeout, send_timeout_active, otp_7731,
wrapping_oct,
- zombie_sockets, otp_7816, otp_8102, otp_9389].
+ zombie_sockets, otp_7816, otp_8102, otp_9389,
+ otp_12242, delay_send_error].
groups() ->
[].
@@ -1914,6 +1918,233 @@ so_priority(Config) when is_list(Config) ->
end
end.
+
+
+%% IP_RECVTOS and IP_RECVTCLASS for IP_PKTOPTIONS
+%% does not seem to be implemented in Linux until kernel 3.1
+%%
+%% It seems pktoptions does not return valid values
+%% for IPv4 connect sockets. On the accept socket
+%% we get valid values, but on the connect socket we get
+%% the default values for TOS and TTL.
+%%
+%% Therefore the argument CheckConnect that enables
+%% checking the returned values for the connect socket.
+%% It is only used for recvtclass that is an IPv6 option
+%% and there we get valid values from both socket ends.
+
+recvtos(_Config) ->
+ test_pktoptions(
+ inet, [{recvtos,tos,96}],
+ fun recvtos_ok/2,
+ false).
+
+recvtosttl(_Config) ->
+ test_pktoptions(
+ inet, [{recvtos,tos,96},{recvttl,ttl,33}],
+ fun (OSType, OSVer) ->
+ recvtos_ok(OSType, OSVer) andalso recvttl_ok(OSType, OSVer)
+ end,
+ false).
+
+recvttl(_Config) ->
+ test_pktoptions(
+ inet, [{recvttl,ttl,33}],
+ fun recvttl_ok/2,
+ false).
+
+recvtclass(_Config) ->
+ {ok,IFs} = inet:getifaddrs(),
+ case
+ [Name ||
+ {Name,Opts} <- IFs,
+ lists:member({addr,{0,0,0,0,0,0,0,1}}, Opts)]
+ of
+ [_] ->
+ test_pktoptions(
+ inet6, [{recvtclass,tclass,224}],
+ fun recvtclass_ok/2,
+ true);
+ [] ->
+ {skip,{ipv6_not_supported,IFs}}
+ end.
+
+%% These version numbers are above the highest noted
+%% in daily tests where the test fails for a plausible reason,
+%% so skip on platforms of lower version, i.e they are future
+%% versions where it is possible that it might not fail.
+%%
+%% When machines with newer versions gets installed,
+%% if the test still fails for a plausible reason these
+%% version numbers simply should be increased.
+%% Or maybe we should change to only test on known good
+%% platforms - change {unix,_} to false?
+
+%% pktoptions is not supported for IPv4
+recvtos_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvtos_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {19,0,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+recvtos_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%% Does not return any value - not implemented for pktoptions
+recvtos_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {3,1,0});
+%%
+recvtos_ok({unix,_}, _) -> true;
+recvtos_ok(_, _) -> false.
+
+%% pktoptions is not supported for IPv4
+recvttl_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvttl_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {19,0,0});
+%% Using the option returns einval, so it is not implemented.
+recvttl_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+recvttl_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%% Does not return any value - not implemented for pktoptions
+recvttl_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {2,7,0});
+%%
+recvttl_ok({unix,_}, _) -> true;
+recvttl_ok(_, _) -> false.
+
+%% pktoptions is not supported for IPv6
+recvtclass_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvtclass_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {19,0,0});
+recvtclass_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%% Using the option returns einval, so it is not implemented.
+recvtclass_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+%% Does not return any value - not implemented for pktoptions
+recvtclass_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {3,1,0});
+%%
+recvtclass_ok({unix,_}, _) -> true;
+recvtclass_ok(_, _) -> false.
+
+semver_lt({X1,Y1,Z1}, {X2,Y2,Z2}) ->
+ if
+ X1 > X2 -> false;
+ X1 < X2 -> true;
+ Y1 > Y2 -> false;
+ Y1 < Y2 -> true;
+ Z1 > Z2 -> false;
+ Z1 < Z2 -> true;
+ true -> false
+ end;
+semver_lt(_, {_,_,_}) -> false.
+
+test_pktoptions(Family, Spec, OSFilter, CheckConnect) ->
+ OSType = os:type(),
+ OSVer = os:version(),
+ case OSFilter(OSType, OSVer) of
+ true ->
+ io:format("Os: ~p, ~p~n", [OSType,OSVer]),
+ test_pktoptions(Family, Spec, CheckConnect, OSType, OSVer);
+ false ->
+ {skip,{not_supported_for_os_version,{OSType,OSVer}}}
+ end.
+%%
+test_pktoptions(Family, Spec, CheckConnect, OSType, OSVer) ->
+ Timeout = 5000,
+ RecvOpts = [RecvOpt || {RecvOpt,_,_} <- Spec],
+ TrueRecvOpts = [{RecvOpt,true} || {RecvOpt,_,_} <- Spec],
+ FalseRecvOpts = [{RecvOpt,false} || {RecvOpt,_,_} <- Spec],
+ Opts = [Opt || {_,Opt,_} <- Spec],
+ OptsVals = [{Opt,Val} || {_,Opt,Val} <- Spec],
+ Address =
+ case Family of
+ inet ->
+ {127,0,0,1};
+ inet6 ->
+ {0,0,0,0,0,0,0,1}
+ end,
+ %%
+ %% Set RecvOpts on listen socket
+ {ok,L} =
+ gen_tcp:listen(
+ 0,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts]),
+ {ok,P} = inet:port(L),
+ {ok,TrueRecvOpts} = inet:getopts(L, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(L, Opts),
+ %%
+ %% Set RecvOpts and Option values on connect socket
+ {ok,S2} =
+ gen_tcp:connect(
+ Address, P,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts ++ OptsVals],
+ Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S2, RecvOpts),
+ {ok,OptsVals} = inet:getopts(S2, Opts),
+ %%
+ %% Accept socket inherits the options from listen socket
+ {ok,S1} = gen_tcp:accept(L, Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S1, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(S1, Opts),
+%%% %%
+%%% %% Handshake
+%%% ok = gen_tcp:send(S1, <<"hello">>),
+%%% {ok,<<"hello">>} = gen_tcp:recv(S2, 5, Timeout),
+%%% ok = gen_tcp:send(S2, <<"hi">>),
+%%% {ok,<<"hi">>} = gen_tcp:recv(S1, 2, Timeout),
+ %%
+ %% Verify returned remote options
+ {ok,[{pktoptions,OptsVals1}]} = inet:getopts(S1, [pktoptions]),
+ {ok,[{pktoptions,OptsVals2}]} = inet:getopts(S2, [pktoptions]),
+ (Result1 = sets_eq(OptsVals1, OptsVals))
+ orelse io:format(
+ "Accept differs: ~p neq ~p~n", [OptsVals1,OptsVals]),
+ (Result2 = sets_eq(OptsVals2, OptsValsDefault))
+ orelse io:format(
+ "Connect differs: ~p neq ~p~n",
+ [OptsVals2,OptsValsDefault]),
+ %%
+ ok = gen_tcp:close(S2),
+ ok = gen_tcp:close(S1),
+ %%
+ %%
+ %% Clear RecvOpts on listen socket and set Option values
+ ok = inet:setopts(L, FalseRecvOpts ++ OptsVals),
+ {ok,FalseRecvOpts} = inet:getopts(L, RecvOpts),
+ {ok,OptsVals} = inet:getopts(L, Opts),
+ %%
+ %% Set RecvOpts on connecting socket
+ %%
+ {ok,S4} =
+ gen_tcp:connect(
+ Address, P,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts],
+ Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S4, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(S4, Opts),
+ %%
+ %% Accept socket inherits the options from listen socket
+ {ok,S3} = gen_tcp:accept(L, Timeout),
+ {ok,FalseRecvOpts} = inet:getopts(S3, RecvOpts),
+ {ok,OptsVals} = inet:getopts(S3, Opts),
+ %%
+ %% Verify returned remote options
+ {ok,[{pktoptions,[]}]} = inet:getopts(S3, [pktoptions]),
+ {ok,[{pktoptions,OptsVals4}]} = inet:getopts(S4, [pktoptions]),
+ (Result3 = sets_eq(OptsVals4, OptsVals))
+ orelse io:format(
+ "Accept2 differs: ~p neq ~p~n", [OptsVals4,OptsVals]),
+ %%
+ ok = gen_tcp:close(S4),
+ ok = gen_tcp:close(S3),
+ ok = gen_tcp:close(L),
+ (Result1 and ((not CheckConnect) or (Result2 and Result3)))
+ orelse
+ exit({failed,
+ [{OptsVals1,OptsVals4,OptsVals},
+ {OptsVals2,OptsValsDefault}],
+ {OSType,OSVer}}),
+%% exit({{OSType,OSVer},success}), % In search for the truth
+ ok.
+
+sets_eq(L1, L2) ->
+ lists:sort(L1) == lists:sort(L2).
+
+
+
%% Accept test utilities (suites are below)
millis() ->
@@ -2205,7 +2436,7 @@ wait_until_accepting(Proc,0) ->
exit({timeout_waiting_for_accepting,Proc});
wait_until_accepting(Proc,N) ->
case process_info(Proc,current_function) of
- {current_function,{prim_inet,accept0,2}} ->
+ {current_function,{prim_inet,accept0,3}} ->
case process_info(Proc,status) of
{status,waiting} ->
ok;
@@ -3056,3 +3287,172 @@ otp_13939(Config) when is_list(Config) ->
exit(Pid, normal),
ct:fail("Server process blocked on send.")
end.
+
+otp_12242(Config) when is_list(Config) ->
+ case os:type() of
+ {win32,_} ->
+ %% Even if we set sndbuf and recbuf to small sizes
+ %% Windows either happily accepts to send GBytes of data
+ %% in no time, so the second send below that is supposed
+ %% to time out just succedes, or the first send that
+ %% is supposed to fill the inet_drv I/O queue and
+ %% start waiting for when more data can be sent
+ %% instead sends all data but suffers a send
+ %% failure that closes the socket
+ {skipped,backpressure_broken_on_win32};
+ _ ->
+ %% Find the IPv4 address of an up and running interface
+ %% that is not loopback nor pointtopoint
+ {ok,IFList} = inet:getifaddrs(),
+ ct:pal("IFList ~p~n", [IFList]),
+ case
+ lists:flatten(
+ [lists:filtermap(
+ fun ({addr,Addr}) when tuple_size(Addr) =:= 4 ->
+ {true,Addr};
+ (_) ->
+ false
+ end, Opts)
+ || {_,Opts} <- IFList,
+ case lists:keyfind(flags, 1, Opts) of
+ {_,Flags} ->
+ lists:member(up, Flags)
+ andalso
+ lists:member(running, Flags)
+ andalso
+ not lists:member(loopback, Flags)
+ andalso
+ not lists:member(pointtopoint, Flags);
+ false ->
+ false
+ end])
+ of
+ [Addr|_] ->
+ otp_12242(Addr);
+ Other ->
+ {skipped,{no_external_address,Other}}
+ end
+ end;
+%%
+otp_12242(Addr) when tuple_size(Addr) =:= 4 ->
+ ct:timetrap(30000),
+ ct:pal("Using address ~p~n", [Addr]),
+ Bufsize = 16 * 1024,
+ Datasize = 128 * 1024 * 1024, % At least 1 s on GBit interface
+ Blob = binary:copy(<<$x>>, Datasize),
+ LOpts =
+ [{backlog,4},{reuseaddr,true},{ip,Addr},
+ binary,{active,false},
+ {recbuf,Bufsize},{sndbuf,Bufsize},{buffer,Bufsize}],
+ COpts =
+ [binary,{active,false},{ip,Addr},
+ {linger,{true,1}}, % 1 s
+ {send_timeout,500},
+ {recbuf,Bufsize},{sndbuf,Bufsize},{buffer,Bufsize}],
+ Dir = filename:dirname(code:which(?MODULE)),
+ {ok,ListenerNode} =
+ test_server:start_node(
+ ?UNIQ_NODE_NAME, slave, [{args,"-pa " ++ Dir}]),
+ Tester = self(),
+ Listener =
+ spawn(
+ ListenerNode,
+ fun () ->
+ {ok,L} = gen_tcp:listen(0, LOpts),
+ {ok,LPort} = inet:port(L),
+ Tester ! {self(),port,LPort},
+ {ok,A} = gen_tcp:accept(L),
+ ok = gen_tcp:close(L),
+ receive
+ {Tester,stop} ->
+ ok = gen_tcp:close(A)
+ end
+ end),
+ ListenerMref = monitor(process, Listener),
+ LPort = receive {Listener,port,P} -> P end,
+ {ok,C} = gen_tcp:connect(Addr, LPort, COpts, infinity),
+ {ok,ReadCOpts} = inet:getopts(C, [recbuf,sndbuf,buffer]),
+ ct:pal("ReadCOpts ~p~n", [ReadCOpts]),
+ %%
+ %% Fill the buffers
+ ct:pal("Sending ~p bytes~n", [Datasize]),
+ ok = gen_tcp:send(C, Blob),
+ ct:pal("Sent ~p bytes~n", [Datasize]),
+ %% Spawn the Closer,
+ %% try to ensure that the close call is in progress
+ %% before the owner proceeds with sending
+ Owner = self(),
+ {_Closer,CloserMref} =
+ spawn_opt(
+ fun () ->
+ Owner ! {tref, erlang:start_timer(50, Owner, closing)},
+ ct:pal("Calling gen_tcp:close(C)~n"),
+ try gen_tcp:close(C) of
+ Result ->
+ ct:pal("gen_tcp:close(C) -> ~p~n", [Result]),
+ ok = Result
+ catch
+ Class:Reason:Stacktrace ->
+ ct:pal(
+ "gen_tcp:close(C) >< ~p:~p~n ~p~n",
+ [Class,Reason,Stacktrace]),
+ erlang:raise(Class, Reason, Stacktrace)
+ end
+ end, [link,monitor]),
+ receive
+ {tref,Tref} ->
+ receive {timeout,Tref,_} -> ok end,
+ ct:pal("Sending ~p bytes again~n", [Datasize]),
+ %% Now should the close be in progress...
+ %% All buffers are full, remote end is not reading,
+ %% and the send timeout is 1 s so this will timeout:
+ {error,timeout} = gen_tcp:send(C, Blob),
+ ct:pal("Sending ~p bytes again timed out~n", [Datasize]),
+ ok = inet:setopts(C, [{send_timeout,10000}]),
+ %% There is a hidden timeout here. Port close is sampled
+ %% every 5 s by prim_inet:send_recv_reply.
+ %% Linger is 3 s so the Closer will finish this send:
+ ct:pal("Sending ~p bytes with 10 s timeout~n", [Datasize]),
+ {error,closed} = gen_tcp:send(C, Blob),
+ ct:pal("Sending ~p bytes with 10 s timeout was closed~n",
+ [Datasize]),
+ normal = wait(CloserMref),
+ ct:pal("The Closer has exited~n"),
+ Listener ! {Tester,stop},
+ receive {'DOWN',ListenerMref,_,_,_} -> ok end,
+ ct:pal("The Listener has exited~n"),
+ test_server:stop_node(ListenerNode),
+ ok
+ end.
+
+wait(Mref) ->
+ receive {'DOWN',Mref,_,_,Reason} -> Reason end.
+
+%% OTP-15536
+%% Test that send error works correctly for delay_send
+delay_send_error(Config) ->
+ {ok, LS} = gen_tcp:listen(0, [{reuseaddr, true}, {packet, 1}, {active, false}]),
+ {ok,{{0,0,0,0},PortNum}}=inet:sockname(LS),
+ P = spawn_link(
+ fun() ->
+ {ok, S} = gen_tcp:accept(LS),
+ receive die -> gen_tcp:close(S) end
+ end),
+ erlang:monitor(process, P),
+ {ok, S} = gen_tcp:connect("localhost", PortNum,
+ [{packet, 1}, {active, false}, {delay_send, true}]),
+
+ %% Do a couple of sends first to see that it works
+ ok = gen_tcp:send(S, "hello"),
+ ok = gen_tcp:send(S, "hello"),
+ ok = gen_tcp:send(S, "hello"),
+
+ %% Make the receiver close
+ P ! die,
+ receive _Down -> ok end,
+
+ ok = gen_tcp:send(S, "hello"),
+ timer:sleep(500), %% Sleep in order for delay_send to have time to trigger
+
+ %% This used to result in a double free
+ {error, closed} = gen_tcp:send(S, "hello").
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index b39399b18a..af9985de45 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -34,8 +34,9 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-export([send_to_closed/1, active_n/1,
- buffer_size/1, binary_passive_recv/1, bad_address/1,
+ buffer_size/1, binary_passive_recv/1, max_buffer_size/1, bad_address/1,
read_packets/1, open_fd/1, connect/1, implicit_inet6/1,
+ recvtos/1, recvtosttl/1, recvttl/1, recvtclass/1,
local_basic/1, local_unbound/1,
local_fdopen/1, local_fdopen_unbound/1, local_abstract/1]).
@@ -44,9 +45,10 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [send_to_closed, buffer_size, binary_passive_recv,
+ [send_to_closed, buffer_size, binary_passive_recv, max_buffer_size,
bad_address, read_packets, open_fd, connect,
implicit_inet6, active_n,
+ recvtos, recvtosttl, recvttl, recvtclass,
{group, local}].
groups() ->
@@ -237,6 +239,14 @@ buffer_size_server_recv(Socket, IP, Port, Cnt) ->
end.
+%%-------------------------------------------------------------
+%% OTP-15206: Keep buffer small for udp
+%%-------------------------------------------------------------
+max_buffer_size(Config) when is_list(Config) ->
+ {ok, Socket} = gen_udp:open(0, [binary]),
+ ok = inet:setopts(Socket,[{recbuf, 1 bsl 20}]),
+ {ok, [{buffer, 65536}]} = inet:getopts(Socket,[buffer]),
+ gen_udp:close(Socket).
%%-------------------------------------------------------------
%% OTP-3823 gen_udp:recv does not return address in binary mode
@@ -564,6 +574,168 @@ active_n(Config) when is_list(Config) ->
ok.
+
+recvtos(_Config) ->
+ test_recv_opts(
+ inet, [{recvtos,tos,96}],
+ fun recvtos_ok/2).
+
+recvtosttl(_Config) ->
+ test_recv_opts(
+ inet, [{recvtos,tos,96},{recvttl,ttl,33}],
+ fun (OSType, OSVer) ->
+ recvtos_ok(OSType, OSVer) andalso recvttl_ok(OSType, OSVer)
+ end).
+
+recvttl(_Config) ->
+ test_recv_opts(
+ inet, [{recvttl,ttl,33}],
+ fun recvttl_ok/2).
+
+recvtclass(_Config) ->
+ {ok,IFs} = inet:getifaddrs(),
+ case
+ [Name ||
+ {Name,Opts} <- IFs,
+ lists:member({addr,{0,0,0,0,0,0,0,1}}, Opts)]
+ of
+ [_] ->
+ test_recv_opts(
+ inet6, [{recvtclass,tclass,224}],
+ fun recvtclass_ok/2);
+ [] ->
+ {skip,ipv6_not_supported,IFs}
+ end.
+
+%% These version numbers are just above the highest noted in daily tests
+%% where the test fails for a plausible reason, that is the lowest
+%% where we can expect that the test mighe succeed, so
+%% skip on platforms lower than this.
+%%
+%% On newer versions it might be fixed, but we'll see about that
+%% when machines with newer versions gets installed...
+%% If the test still fails for a plausible reason these
+%% version numbers simply should be increased.
+%% Or maybe we should change to only test on known good platforms?
+
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%%
+recvtos_ok({unix,_}, _) -> true;
+recvtos_ok(_, _) -> false.
+
+recvttl_ok({unix,_}, _) -> true;
+recvttl_ok(_, _) -> false.
+
+%% Using the option returns einval, so it is not implemented.
+recvtclass_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {9,9,0});
+recvtclass_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {2,6,11});
+%%
+recvtclass_ok({unix,_}, _) -> true;
+recvtclass_ok(_, _) -> false.
+
+semver_lt({X1,Y1,Z1}, {X2,Y2,Z2}) ->
+ if
+ X1 > X2 -> false;
+ X1 < X2 -> true;
+ Y1 > Y2 -> false;
+ Y1 < Y2 -> true;
+ Z1 > Z2 -> false;
+ Z1 < Z2 -> true;
+ true -> false
+ end;
+semver_lt(_, {_,_,_}) -> false.
+
+test_recv_opts(Family, Spec, OSFilter) ->
+ OSType = os:type(),
+ OSVer = os:version(),
+ case OSFilter(OSType, OSVer) of
+ true ->
+ io:format("Os: ~p, ~p~n", [OSType,OSVer]),
+ test_recv_opts(Family, Spec, OSType, OSVer);
+ false ->
+ {skip,{not_supported_for_os_version,{OSType,OSVer}}}
+ end.
+%%
+test_recv_opts(Family, Spec, _OSType, _OSVer) ->
+ Timeout = 5000,
+ RecvOpts = [RecvOpt || {RecvOpt,_,_} <- Spec],
+ TrueRecvOpts = [{RecvOpt,true} || {RecvOpt,_,_} <- Spec],
+ FalseRecvOpts = [{RecvOpt,false} || {RecvOpt,_,_} <- Spec],
+ Opts = [Opt || {_,Opt,_} <- Spec],
+ OptsVals = [{Opt,Val} || {_,Opt,Val} <- Spec],
+ TrueRecvOpts_OptsVals = TrueRecvOpts ++ OptsVals,
+ Addr =
+ case Family of
+ inet ->
+ {127,0,0,1};
+ inet6 ->
+ {0,0,0,0,0,0,0,1}
+ end,
+ %%
+ {ok,S1} =
+ gen_udp:open(0, [Family,binary,{active,false}|TrueRecvOpts]),
+ {ok,P1} = inet:port(S1),
+ {ok,TrueRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S1, FalseRecvOpts),
+ {ok,FalseRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S1, TrueRecvOpts_OptsVals),
+ {ok,TrueRecvOpts_OptsVals} = inet:getopts(S1, RecvOpts ++ Opts),
+ %%
+ {ok,S2} =
+ gen_udp:open(0, [Family,binary,{active,true}|FalseRecvOpts]),
+ {ok,P2} = inet:port(S2),
+ {ok,FalseRecvOpts_OptsVals2} = inet:getopts(S2, RecvOpts ++ Opts),
+ OptsVals2 = FalseRecvOpts_OptsVals2 -- FalseRecvOpts,
+ %%
+ ok = gen_udp:send(S2, Addr, P1, <<"abcde">>),
+ ok = gen_udp:send(S1, Addr, P2, <<"fghij">>),
+ {ok,{_,P2,OptsVals3,<<"abcde">>}} = gen_udp:recv(S1, 0, Timeout),
+ verify_sets_eq(OptsVals3, OptsVals2),
+ receive
+ {udp,S2,_,P1,<<"fghij">>} ->
+ ok;
+ Other1 ->
+ exit({unexpected,Other1})
+ after Timeout ->
+ exit(timeout)
+ end,
+ %%
+ ok = inet:setopts(S1, FalseRecvOpts),
+ {ok,FalseRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S2, TrueRecvOpts),
+ {ok,TrueRecvOpts} = inet:getopts(S2, RecvOpts),
+ %%
+ ok = gen_udp:send(S2, Addr, P1, <<"klmno">>),
+ ok = gen_udp:send(S1, Addr, P2, <<"pqrst">>),
+ {ok,{_,P2,<<"klmno">>}} = gen_udp:recv(S1, 0, Timeout),
+ receive
+ {udp,S2,_,P1,OptsVals4,<<"pqrst">>} ->
+ verify_sets_eq(OptsVals4, OptsVals);
+ Other2 ->
+ exit({unexpected,Other2})
+ after Timeout ->
+ exit(timeout)
+ end,
+ ok = gen_udp:close(S1),
+ ok = gen_udp:close(S2),
+%% exit({{OSType,OSVer},success}), % In search for the truth
+ ok.
+
+verify_sets_eq(L1, L2) ->
+ L = lists:sort(L1),
+ case lists:sort(L2) of
+ L ->
+ ok;
+ _ ->
+ exit({sets_neq,L1,L2})
+ end.
+
+
local_basic(_Config) ->
SFile = local_filename(server),
SAddr = {local,bin_filename(SFile)},
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 0e7b7adc47..8eab36e308 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -1383,7 +1383,7 @@ ring(Config) when is_list(Config) ->
rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1466,7 +1466,7 @@ simple_ring(Config) when is_list(Config) ->
rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1542,7 +1542,7 @@ line(Config) when is_list(Config) ->
rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
%% Sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1626,7 +1626,7 @@ simple_line(Config) when is_list(Config) ->
rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -3555,7 +3555,7 @@ single_node(Time, Node, Config) ->
lists:foreach(fun(N) -> _ = erlang:disconnect_node(N) end, nodes()),
?UNTIL(get_known(node()) =:= [node()]),
spawn(?MODULE, init_2, []),
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
net_adm:ping(Node).
init_2() ->
@@ -4009,13 +4009,6 @@ collect_nodes(N, Max) ->
[Node | collect_nodes(N+1, Max)]
end.
-only_element(_E, []) ->
- true;
-only_element(E, [E|R]) ->
- only_element(E, R);
-only_element(_E, _) ->
- false.
-
exit_p(Pid) ->
Ref = erlang:monitor(process, Pid),
Pid ! die,
@@ -4038,6 +4031,11 @@ wait_for_exit_fast(Pid) ->
ok
end.
+sleep(Time) when Time > 0 ->
+ ct:sleep(Time);
+sleep(_Time) ->
+ ok.
+
check_everywhere(Nodes, Name, Config) ->
?UNTIL(begin
case rpc:multicall(Nodes, global, whereis_name, [Name]) of
@@ -4162,10 +4160,10 @@ rpc_cast(Node, Module, Function, Args, File) ->
%% The emulator now ensures that the node has been removed from
%% nodes().
-rpc_disconnect_node(Node, DisconnectedNode, _Config) ->
- True = rpc:call(Node, erlang, disconnect_node, [DisconnectedNode]),
- False = lists:member(DisconnectedNode, rpc:call(Node, erlang, nodes, [])),
- {true, false} = {True, False}.
+rpc_disconnect_node(Node, DisconnectedNode, Config) ->
+ true = rpc:call(Node, erlang, disconnect_node, [DisconnectedNode]),
+ ?UNTIL
+ (not lists:member(DisconnectedNode, rpc:call(Node, erlang, nodes, []))).
%%%
%%% Utility
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 2e5f8c7d2c..5a2d809aa4 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -21,6 +21,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
+-include_lib("kernel/src/inet_res.hrl").
-include_lib("kernel/src/inet_dns.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -34,7 +35,7 @@
ipv4_to_ipv6/0, ipv4_to_ipv6/1,
host_and_addr/0, host_and_addr/1,
t_gethostnative/1,
- gethostnative_parallell/1, cname_loop/1,
+ gethostnative_parallell/1, cname_loop/1, missing_hosts_reload/1,
gethostnative_soft_restart/0, gethostnative_soft_restart/1,
gethostnative_debug_level/0, gethostnative_debug_level/1,
lookup_bad_search_option/1,
@@ -56,7 +57,7 @@ all() ->
[t_gethostbyaddr, t_gethostbyname, t_getaddr,
t_gethostbyaddr_v6, t_gethostbyname_v6, t_getaddr_v6,
ipv4_to_ipv6, host_and_addr, {group, parse},
- t_gethostnative, gethostnative_parallell, cname_loop,
+ t_gethostnative, gethostnative_parallell, cname_loop, missing_hosts_reload,
gethostnative_debug_level, gethostnative_soft_restart,
lookup_bad_search_option,
getif, getif_ifr_name_overflow, getservbyname_overflow,
@@ -840,6 +841,32 @@ cname_loop(Config) when is_list(Config) ->
ok.
+%% Test that hosts file gets reloaded correctly in case when it
+% was missing during initial startup
+missing_hosts_reload(Config) when is_list(Config) ->
+ RootDir = proplists:get_value(priv_dir,Config),
+ HostsFile = filename:join(RootDir, atom_to_list(?MODULE) ++ ".hosts"),
+ InetRc = filename:join(RootDir, "inetrc"),
+ ok = file:write_file(InetRc, "{hosts_file, \"" ++ HostsFile ++ "\"}.\n"),
+ {error, enoent} = file:read_file_info(HostsFile),
+ % start a node
+ Pa = filename:dirname(code:which(?MODULE)),
+ {ok, TestNode} = test_server:start_node(?MODULE, slave,
+ [{args, "-pa " ++ Pa ++ " -kernel inetrc '\"" ++ InetRc ++ "\"'"}]),
+ % ensure it has our RC
+ Rc = rpc:call(TestNode, inet_db, get_rc, []),
+ {hosts_file, HostsFile} = lists:keyfind(hosts_file, 1, Rc),
+ % ensure it does not resolve
+ {error, nxdomain} = rpc:call(TestNode, inet_hosts, gethostbyname, ["somehost"]),
+ % write hosts file
+ ok = file:write_file(HostsFile, "1.2.3.4 somehost"),
+ % wait for cached timestamp to expire
+ timer:sleep(?RES_FILE_UPDATE_TM * 1000 + 100),
+ % ensure it DOES resolve
+ {ok,{hostent,"somehost",[],inet,4,[{1,2,3,4}]}} =
+ rpc:call(TestNode, inet_hosts, gethostbyname, ["somehost"]),
+ % cleanup
+ true = test_server:stop_node(TestNode).
%% These must be run in the whole suite since they need
%% the host list and require inet_gethost_native to be started.
@@ -1060,28 +1087,26 @@ getservbyname_overflow(Config) when is_list(Config) ->
getifaddrs(Config) when is_list (Config) ->
{ok,IfAddrs} = inet:getifaddrs(),
io:format("IfAddrs = ~p.~n", [IfAddrs]),
- case
- {os:type(),
- [If ||
- {If,Opts} <- IfAddrs,
- lists:keymember(hwaddr, 1, Opts)]} of
- {{unix,sunos},[]} -> ok;
- {OT,[]} ->
- ct:fail({should_have_hwaddr,OT});
- _ -> ok
+ case [If || {If,Opts} <- IfAddrs, lists:keymember(hwaddr, 1, Opts)] of
+ [] ->
+ case os:type() of
+ {unix,sunos} -> ok;
+ OT ->
+ ct:fail({should_have_hwaddr,OT})
+ end;
+ [_|_] -> ok
end,
- Addrs =
- [element(1, A) || A <- ifaddrs(IfAddrs)],
+ Addrs = ifaddrs(IfAddrs),
io:format("Addrs = ~p.~n", [Addrs]),
[check_addr(Addr) || Addr <- Addrs],
ok.
-check_addr({addr,Addr})
+check_addr(Addr)
when tuple_size(Addr) =:= 8,
element(1, Addr) band 16#FFC0 =:= 16#FE80 ->
io:format("Addr: ~p link local; SKIPPED!~n", [Addr]),
ok;
-check_addr({addr,Addr}) ->
+check_addr(Addr) ->
io:format("Addr: ~p.~n", [Addr]),
Ping = "ping",
Pong = "pong",
@@ -1097,78 +1122,86 @@ check_addr({addr,Addr}) ->
ok = gen_tcp:close(S2),
ok = gen_tcp:close(L).
--record(ifopts, {name,flags,addrs=[],hwaddr}).
-
-ifaddrs([]) -> [];
-ifaddrs([{If,Opts}|IOs]) ->
- #ifopts{flags=F} = Ifopts = check_ifopts(Opts, #ifopts{name=If}),
- case F of
- {flags,Flags} ->
- case lists:member(running, Flags) of
- true -> Ifopts#ifopts.addrs;
- false -> []
- end ++ ifaddrs(IOs);
- undefined ->
- ifaddrs(IOs)
+ifaddrs(IfOpts) ->
+ IfMap = collect_ifopts(IfOpts),
+ ChkFun =
+ fun Self({{_,Flags} = Key, Opts}, ok) ->
+ Broadcast = lists:member(broadcast, Flags),
+ P2P = lists:member(pointtopoint, Flags),
+ case Opts of
+ [{addr,_},{netmask,_},{broadaddr,_}|Os]
+ when Broadcast ->
+ Self({Key, Os}, ok);
+ [{addr,_},{netmask,_},{dstaddr,_}|Os]
+ when P2P ->
+ Self({Key, Os}, ok);
+ [{addr,_},{netmask,_}|Os] ->
+ Self({Key, Os}, ok);
+ [{hwaddr,_}|Os] ->
+ Self({Key, Os}, ok);
+ [] ->
+ ok
+ end
+ end,
+ fold_ifopts(ChkFun, ok, IfMap),
+ AddrsFun =
+ fun ({{_,Flags}, Opts}, Acc) ->
+ case
+ lists:member(running, Flags)
+ andalso (not lists:member(pointtopoint, Flags))
+ of
+ true ->
+ lists:reverse(
+ [Addr || {addr,Addr} <- Opts],
+ Acc);
+ false ->
+ Acc
+ end
+ end,
+ fold_ifopts(AddrsFun, [], IfMap).
+
+collect_ifopts(IfOpts) ->
+ collect_ifopts(IfOpts, #{}).
+%%
+collect_ifopts(IfOpts, IfMap) ->
+ case IfOpts of
+ [{If,[{flags,Flags}|Opts]}|IfOs] ->
+ Key = {If,Flags},
+ case maps:is_key(Key, IfMap) of
+ true ->
+ ct:fail({unexpected_ifopts,IfOpts,IfMap});
+ false ->
+ collect_ifopts(IfOs, IfMap, Opts, Key, [])
+ end;
+ [] ->
+ IfMap;
+ _ ->
+ ct:fail({unexpected_ifopts,IfOpts,IfMap})
+ end.
+%%
+collect_ifopts(IfOpts, IfMap, Opts, Key, R) ->
+ case Opts of
+ [{flags,_}|_] ->
+ {If,_} = Key,
+ collect_ifopts(
+ [{If,Opts}|IfOpts], maps:put(Key, lists:reverse(R), IfMap));
+ [OptVal|Os] ->
+ collect_ifopts(IfOpts, IfMap, Os, Key, [OptVal|R]);
+ [] ->
+ collect_ifopts(IfOpts, maps:put(Key, lists:reverse(R), IfMap))
end.
-check_ifopts([], #ifopts{flags=F,addrs=Raddrs}=Ifopts) ->
- Addrs = lists:reverse(Raddrs),
- R = Ifopts#ifopts{addrs=Addrs},
- io:format("~p.~n", [R]),
- %% See how we did...
- {flags,Flags} = F,
- case lists:member(broadcast, Flags) of
- true ->
- [case A of
- {{addr,_},{netmask,_},{broadaddr,_}} ->
- A;
- {{addr,T},{netmask,_}} when tuple_size(T) =:= 8 ->
- A
- end || A <- Addrs];
- false ->
- case lists:member(pointtopoint, Flags) of
- true ->
- [case A of
- {{addr,_},{netmask,_},{dstaddr,_}} ->
- A
- end || A <- Addrs];
- false ->
- [case A of
- {{addr,_},{netmask,_}} ->
- A
- end || A <- Addrs]
- end
- end,
- R;
-check_ifopts([{flags,_}=F|Opts], #ifopts{flags=undefined}=Ifopts) ->
- check_ifopts(Opts, Ifopts#ifopts{flags=F});
-check_ifopts([{flags,_}=F|Opts], #ifopts{flags=Flags}=Ifopts) ->
- case F of
- Flags ->
- check_ifopts(Opts, Ifopts);
- _ ->
- ct:fail({multiple_flags,F,Ifopts})
- end;
-check_ifopts(
- [{addr,_}=A,{netmask,_}=N,{dstaddr,_}=D|Opts],
- #ifopts{addrs=Addrs}=Ifopts) ->
- check_ifopts(Opts, Ifopts#ifopts{addrs=[{A,N,D}|Addrs]});
-check_ifopts(
- [{addr,_}=A,{netmask,_}=N,{broadaddr,_}=B|Opts],
- #ifopts{addrs=Addrs}=Ifopts) ->
- check_ifopts(Opts, Ifopts#ifopts{addrs=[{A,N,B}|Addrs]});
-check_ifopts(
- [{addr,_}=A,{netmask,_}=N|Opts],
- #ifopts{addrs=Addrs}=Ifopts) ->
- check_ifopts(Opts, Ifopts#ifopts{addrs=[{A,N}|Addrs]});
-check_ifopts([{addr,_}=A|Opts], #ifopts{addrs=Addrs}=Ifopts) ->
- check_ifopts(Opts, Ifopts#ifopts{addrs=[{A}|Addrs]});
-check_ifopts([{hwaddr,Hwaddr}=H|Opts], #ifopts{hwaddr=undefined}=Ifopts)
- when is_list(Hwaddr) ->
- check_ifopts(Opts, Ifopts#ifopts{hwaddr=H});
-check_ifopts([{hwaddr,_}=H|_], #ifopts{}=Ifopts) ->
- ct:fail({multiple_hwaddrs,H,Ifopts}).
+fold_ifopts(Fun, Acc, IfMap) ->
+ fold_ifopts(Fun, Acc, IfMap, maps:keys(IfMap)).
+%%
+fold_ifopts(Fun, Acc, IfMap, Keys) ->
+ case Keys of
+ [Key|Ks] ->
+ Opts = maps:get(Key, IfMap),
+ fold_ifopts(Fun, Fun({Key,Opts}, Acc), IfMap, Ks);
+ [] ->
+ Acc
+ end.
%% Works just like lists:member/2, except that any {127,_,_,_} tuple
%% matches any other {127,_,_,_}. We do this to handle Linux systems
diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl
index ada9c2689c..27ff74e309 100644
--- a/lib/kernel/test/inet_sockopt_SUITE.erl
+++ b/lib/kernel/test/inet_sockopt_SUITE.erl
@@ -110,9 +110,14 @@ simple(Config) when is_list(Config) ->
{S1,S2} = create_socketpair(Opt, Opt),
{ok,Opt} = inet:getopts(S1,OptTags),
{ok,Opt} = inet:getopts(S2,OptTags),
- COpt = [{X,case X of nodelay -> false;_ -> Y end} || {X,Y} <- Opt],
+ NoPushOpt = case os:type() of
+ {unix, Osname} when Osname =:= linux; Osname =:= freebsd -> {nopush, true};
+ {_,_} -> {nopush, false}
+ end,
+ COpt = [{X,case X of nodelay -> false;_ -> Y end} || {X,Y} <- [NoPushOpt|Opt]],
+ COptTags = [X || {X,_} <- COpt],
inet:setopts(S1,COpt),
- {ok,COpt} = inet:getopts(S1,OptTags),
+ {ok,COpt} = inet:getopts(S1,COptTags),
{ok,Opt} = inet:getopts(S2,OptTags),
gen_tcp:close(S1),
gen_tcp:close(S2),
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index 6a006cdc01..4f90260f98 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -295,7 +295,7 @@ is_real_system(KernelVsn, StdlibVsn) ->
%% before restart.
%% ------------------------------------------------
many_restarts() ->
- [{timetrap,{minutes,8}}].
+ [{timetrap,{minutes,16}}].
many_restarts(Config) when is_list(Config) ->
{ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC),
@@ -315,7 +315,7 @@ loop_restart(N,Node,EHPid) ->
loose_node:stop(Node),
ct:fail(not_stopping)
end,
- ok = wait_for(30, Node, EHPid),
+ ok = wait_for(60, Node, EHPid),
loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[logger])).
wait_for(0,Node,_) ->
@@ -367,7 +367,8 @@ restart(Config) when is_list(Config) ->
SysProcs0 = rpc:call(Node, ?MODULE, find_system_processes, []),
io:format("SysProcs0=~p~n", [SysProcs0]),
[InitPid, PurgerPid, LitCollectorPid,
- DirtySigNPid, DirtySigHPid, DirtySigMPid] = SysProcs0,
+ DirtySigNPid, DirtySigHPid, DirtySigMPid,
+ PrimFilePid] = SysProcs0,
InitPid = rpc:call(Node, erlang, whereis, [init]),
PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]),
Procs = rpc:call(Node, erlang, processes, []),
@@ -385,7 +386,8 @@ restart(Config) when is_list(Config) ->
SysProcs1 = rpc:call(Node, ?MODULE, find_system_processes, []),
io:format("SysProcs1=~p~n", [SysProcs1]),
[InitPid1, PurgerPid1, LitCollectorPid1,
- DirtySigNPid1, DirtySigHPid1, DirtySigMPid1] = SysProcs1,
+ DirtySigNPid1, DirtySigHPid1, DirtySigMPid1,
+ PrimFilePid1] = SysProcs1,
%% Still the same init process!
InitPid1 = rpc:call(Node, erlang, whereis, [init]),
@@ -411,6 +413,10 @@ restart(Config) when is_list(Config) ->
DirtySigMP = pid_to_list(DirtySigMPid),
DirtySigMP = pid_to_list(DirtySigMPid1),
+ %% and same prim_file helper process!
+ PrimFileP = pid_to_list(PrimFilePid),
+ PrimFileP = pid_to_list(PrimFilePid1),
+
NewProcs0 = rpc:call(Node, erlang, processes, []),
NewProcs = NewProcs0 -- SysProcs1,
case check_processes(NewProcs, MaxPid) of
@@ -437,7 +443,8 @@ restart(Config) when is_list(Config) ->
literal_collector,
dirty_sig_handler_normal,
dirty_sig_handler_high,
- dirty_sig_handler_max}).
+ dirty_sig_handler_max,
+ prim_file}).
find_system_processes() ->
find_system_procs(processes(), #sys_procs{}).
@@ -448,7 +455,8 @@ find_system_procs([], SysProcs) ->
SysProcs#sys_procs.literal_collector,
SysProcs#sys_procs.dirty_sig_handler_normal,
SysProcs#sys_procs.dirty_sig_handler_high,
- SysProcs#sys_procs.dirty_sig_handler_max];
+ SysProcs#sys_procs.dirty_sig_handler_max,
+ SysProcs#sys_procs.prim_file];
find_system_procs([P|Ps], SysProcs) ->
case process_info(P, [initial_call, priority]) of
[{initial_call,{otp_ring0,start,2}},_] ->
@@ -472,6 +480,9 @@ find_system_procs([P|Ps], SysProcs) ->
{priority,max}] ->
undefined = SysProcs#sys_procs.dirty_sig_handler_max,
find_system_procs(Ps, SysProcs#sys_procs{dirty_sig_handler_max = P});
+ [{initial_call,{prim_file,start,0}},_] ->
+ undefined = SysProcs#sys_procs.prim_file,
+ find_system_procs(Ps, SysProcs#sys_procs{prim_file = P});
_ ->
find_system_procs(Ps, SysProcs)
end.
diff --git a/lib/kernel/test/kernel.spec b/lib/kernel/test/kernel.spec
index 62afc9f97b..eaa17f3a59 100644
--- a/lib/kernel/test/kernel.spec
+++ b/lib/kernel/test/kernel.spec
@@ -2,3 +2,4 @@
{config, "../test_server/ts.unix.config"}.
{suites,"../kernel_test", all}.
+{skip_suites,"../kernel_test",[logger_stress_SUITE],"Benchmarks only"}.
diff --git a/lib/kernel/test/kernel_bench.spec b/lib/kernel/test/kernel_bench.spec
index 4de133f21b..898ceb59e0 100644
--- a/lib/kernel/test/kernel_bench.spec
+++ b/lib/kernel/test/kernel_bench.spec
@@ -1,2 +1,3 @@
{groups,"../kernel_test",zlib_SUITE,[bench]}.
{groups,"../kernel_test",file_SUITE,[bench]}.
+{suites,"../kernel_test",[logger_stress_SUITE]}.
diff --git a/lib/kernel/test/logger.cover b/lib/kernel/test/logger.cover
index 960bc0abff..9691aa295e 100644
--- a/lib/kernel/test/logger.cover
+++ b/lib/kernel/test/logger.cover
@@ -4,9 +4,12 @@
logger_backend,
logger_config,
logger_disk_log_h,
- logger_h_common,
logger_filters,
logger_formatter,
+ logger_handler_watcher,
+ logger_h_common,
+ logger_olp,
+ logger_proxy,
logger_server,
logger_simple_h,
logger_std_h,
diff --git a/lib/kernel/test/logger.spec b/lib/kernel/test/logger.spec
index 1ab90b3e93..3aec37951d 100644
--- a/lib/kernel/test/logger.spec
+++ b/lib/kernel/test/logger.spec
@@ -7,5 +7,7 @@
logger_filters_SUITE,
logger_formatter_SUITE,
logger_legacy_SUITE,
+ logger_olp_SUITE,
+ logger_proxy_SUITE,
logger_simple_h_SUITE,
logger_std_h_SUITE]}.
diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl
index b367b4dd54..035e5d8974 100644
--- a/lib/kernel/test/logger_SUITE.erl
+++ b/lib/kernel/test/logger_SUITE.erl
@@ -37,7 +37,8 @@
suite() ->
- [{timetrap,{seconds,30}}].
+ [{timetrap,{seconds,30}},
+ {ct_hooks,[logger_test_lib]}].
init_per_suite(Config) ->
case logger:get_handler_config(?STANDARD_HANDLER) of
@@ -87,6 +88,7 @@ all() ->
macros,
set_level,
set_module_level,
+ set_application_level,
cache_module_level,
format_report,
filter_failed,
@@ -97,7 +99,10 @@ all() ->
via_logger_process,
other_node,
compare_levels,
- process_metadata].
+ process_metadata,
+ app_config,
+ kernel_config,
+ pretty_print].
start_stop(_Config) ->
S = whereis(logger),
@@ -210,6 +215,7 @@ add_remove_filter(cleanup,_Config) ->
change_config(_Config) ->
%% Overwrite handler config - check that defaults are added
+ {error,{not_found,h1}} = logger:set_handler_config(h1,#{}),
ok = logger:add_handler(h1,?MODULE,#{level=>notice,custom=>custom}),
{ok,#{module:=?MODULE,level:=notice,filter_default:=log,custom:=custom}} =
logger:get_handler_config(h1),
@@ -241,6 +247,18 @@ change_config(_Config) ->
{ok,C4} = logger:get_handler_config(h1),
C4 = C3#{custom:=new_custom},
+ %% Change handler config: Id and module can not be changed
+ {error,{illegal_config_change,Old,New}} =
+ logger:set_handler_config(h1,id,newid),
+ %% Check that only the faulty field is included in return
+ [{id,h1}] = maps:to_list(Old),
+ [{id,newid}] = maps:to_list(New),
+ %% Check that both fields are included when both are changed
+ {error,{illegal_config_change,
+ #{id:=h1,module:=?MODULE},
+ #{id:=newid,module:=newmodule}}} =
+ logger:set_handler_config(h1,#{id=>newid,module=>newmodule}),
+
%% Change primary config: Single key
PConfig0 = logger:get_primary_config(),
ok = logger:set_primary_config(level,warning),
@@ -258,7 +276,7 @@ change_config(_Config) ->
logger:get_primary_config(),
3 = maps:size(PC1),
%% Check that internal 'handlers' field has not been changed
- MS = [{{{?HANDLER_KEY,'$1'},'_','_','_'},[],['$1']}],
+ MS = [{{{?HANDLER_KEY,'$1'},'_','_'},[],['$1']}],
HIds1 = lists:sort(ets:select(?LOGGER_TABLE,MS)), % dirty, internal data
HIds2 = lists:sort(logger:get_handler_ids()),
HIds1 = HIds2,
@@ -355,6 +373,7 @@ log_all_levels_api(cleanup,_Config) ->
macros(_Config) ->
ok = logger:add_handler(h1,?MODULE,#{level=>all,filter_default=>log}),
test_macros(emergency),
+ test_log_macro(alert),
ok.
macros(cleanup,_Config) ->
@@ -387,6 +406,8 @@ set_module_level(_Config) ->
{error,{invalid_level,bad}} = logger:set_module_level(?MODULE,bad),
{error,{not_a_list_of_modules,{bad}}} =
logger:set_module_level({bad},warning),
+ {error,{not_a_list_of_modules,[{bad}]}} =
+ logger:set_module_level([{bad}],warning),
ok = logger:set_module_level(?MODULE,warning),
[{?MODULE,warning}] = logger:get_module_level([?MODULE,other]),
[{?MODULE,warning}] = logger:get_module_level(?MODULE),
@@ -403,6 +424,7 @@ set_module_level(_Config) ->
ok = check_logged(notice,M2,?MY_LOC(1)),
{error,{not_a_list_of_modules,{bad}}} = logger:unset_module_level({bad}),
+ {error,{not_a_list_of_modules,[{bad}]}} = logger:unset_module_level([{bad}]),
ok = logger:unset_module_level(?MODULE),
[] = logger:get_module_level([?MODULE,other]),
[] = logger:get_module_level(?MODULE),
@@ -422,6 +444,39 @@ set_module_level(cleanup,_Config) ->
logger:unset_module_level(?MODULE),
ok.
+set_application_level(_Config) ->
+
+ {error,{not_loaded,mnesia}} = logger:set_application_level(mnesia, warning),
+ {error,{not_loaded,mnesia}} = logger:unset_application_level(mnesia),
+
+ case application:load(mnesia) of
+ ok ->
+ {ok, Modules} = application:get_key(mnesia, modules),
+ [] = logger:get_module_level(Modules),
+
+ {error,{invalid_level,warn}} =
+ logger:set_application_level(mnesia, warn),
+
+ ok = logger:set_application_level(mnesia, debug),
+ DebugModules = lists:sort([{M,debug} || M <- Modules]),
+ DebugModules = lists:sort(logger:get_module_level(Modules)),
+
+ ok = logger:set_application_level(mnesia, warning),
+
+ WarnModules = lists:sort([{M,warning} || M <- Modules]),
+ WarnModules = lists:sort(logger:get_module_level(Modules)),
+
+ ok = logger:unset_application_level(mnesia),
+ [] = logger:get_module_level(Modules);
+ {error,{"no such file or directory","mnesia.app"}} ->
+ {skip, "Cannot load mnesia, does not exist"}
+ end.
+
+set_application_level(cleanup,_Config) ->
+ _ = logger:unset_application_level(mnesia),
+ _ = application:unload(mnesia),
+ ok.
+
cache_module_level(_Config) ->
ok = logger:unset_module_level(?MODULE),
[] = ets:lookup(?LOGGER_TABLE,?MODULE), %dirty - add API in logger_config?
@@ -469,7 +524,11 @@ filter_failed(_Config) ->
%% Logger filters
{error,{invalid_filter,_}} =
logger:add_primary_filter(lf,{fun(_) -> ok end,args}),
- ok = logger:add_primary_filter(lf,{fun(_,_) -> a=b end,args}),
+ ok = logger:add_primary_filter(lf,
+ {fun(_,_) ->
+ erlang:error({badmatch,b})
+ end,
+ args}),
#{filters:=[_]} = logger:get_primary_config(),
ok = logger:notice(M1=?map_rep),
ok = check_logged(notice,M1,#{}),
@@ -487,7 +546,11 @@ filter_failed(_Config) ->
{error,{not_found,h0}} = logger:remove_handler_filter(h0,hf),
{error,{invalid_filter,_}} =
logger:add_handler_filter(h1,hf,{fun(_) -> ok end,args}),
- ok = logger:add_handler_filter(h1,hf,{fun(_,_) -> a=b end,args}),
+ ok = logger:add_handler_filter(h1,hf,
+ {fun(_,_) ->
+ erlang:error({badmatch,b})
+ end,
+ args}),
{ok,#{filters:=[_]}} = logger:get_handler_config(h1),
ok = logger:notice(M3=?map_rep),
ok = check_logged(notice,M3,#{}),
@@ -509,7 +572,7 @@ handler_failed(_Config) ->
register(callback_receiver,self()),
{error,{invalid_id,1}} = logger:add_handler(1,?MODULE,#{}),
{error,{invalid_module,"nomodule"}} = logger:add_handler(h1,"nomodule",#{}),
- {error,{invalid_handler_config,bad}} = logger:add_handler(h1,?MODULE,bad),
+ {error,{invalid_config,bad}} = logger:add_handler(h1,?MODULE,bad),
{error,{invalid_filters,false}} =
logger:add_handler(h1,?MODULE,#{filters=>false}),
{error,{invalid_filter_default,true}} =
@@ -523,7 +586,11 @@ handler_failed(_Config) ->
false = lists:search(fun(#{id:=h1}) -> true; (_) -> false end,H1),
{error,{not_found,h1}} = logger:remove_handler(h1),
- ok = logger:add_handler(h2,?MODULE,#{filter_default=>log,log_call=>fun() -> a = b end}),
+ ok = logger:add_handler(h2,?MODULE,
+ #{filter_default => log,
+ log_call => fun() ->
+ erlang:error({badmatch,b})
+ end}),
{error,{already_exist,h2}} = logger:add_handler(h2,othermodule,#{}),
[add] = test_server:messages_get(),
@@ -534,7 +601,7 @@ handler_failed(_Config) ->
{error,{not_found,h2}} = logger:remove_handler(h2),
CallAddHandler = fun() -> logger:add_handler(h2,?MODULE,#{}) end,
- CrashHandler = fun() -> a = b end,
+ CrashHandler = fun() -> erlang:error({badmatch,b}) end,
KillHandler = fun() -> exit(self(), die) end,
{error,{handler_not_added,{attempting_syncronous_call_to_self,_}}} =
@@ -580,7 +647,8 @@ handler_failed(cleanup,_Config) ->
ok.
config_sanity_check(_Config) ->
- %% Logger config
+ %% Primary config
+ {error,{invalid_config,bad}} = logger:set_primary_config(bad),
{error,{invalid_filter_default,bad}} =
logger:set_primary_config(filter_default,bad),
{error,{invalid_level,bad}} = logger:set_primary_config(level,bad),
@@ -831,14 +899,14 @@ process_metadata(_Config) ->
undefined = logger:get_process_metadata(),
{error,badarg} = ?TRY(logger:set_process_metadata(bad)),
ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
- Time = erlang:system_time(microsecond),
+ Time = logger:timestamp(),
ProcMeta = #{time=>Time,line=>0,custom=>proc},
ok = logger:set_process_metadata(ProcMeta),
S1 = ?str,
?LOG_NOTICE(S1,#{custom=>macro}),
check_logged(notice,S1,#{time=>Time,line=>0,custom=>macro}),
- Time2 = erlang:system_time(microsecond),
+ Time2 = logger:timestamp(),
S2 = ?str,
?LOG_NOTICE(S2,#{time=>Time2,line=>1,custom=>macro}),
check_logged(notice,S2,#{time=>Time2,line=>1,custom=>macro}),
@@ -853,12 +921,286 @@ process_metadata(_Config) ->
ok = logger:unset_process_metadata(),
undefined = logger:get_process_metadata(),
+ ok = logger:update_process_metadata(#{custom=>added_again}),
+ {error,badarg} = ?TRY(logger:update_process_metadata(bad)),
+ #{custom:=added_again} = logger:get_process_metadata(),
+
ok.
process_metadata(cleanup,_Config) ->
logger:remove_handler(h1),
ok.
+app_config(Config) ->
+ %% Start a node with default configuration
+ {ok,_,Node} = logger_test_lib:setup(Config,[]),
+
+ App1Name = app1,
+ App1 = {application, App1Name,
+ [{description, "Test of app with logger config"},
+ {applications, [kernel]}]},
+ ok = rpc:call(Node,application,load,[App1]),
+ ok = rpc:call(Node,application,set_env,
+ [App1Name,logger,[{handler,default,logger_std_h,#{}}]]),
+
+ %% Try to add an own default handler
+ {error,{bad_config,{handler,{app1,{already_exist,default}}}}} =
+ rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ %% Add a different handler
+ ok = rpc:call(Node,application,set_env,[App1Name,logger,
+ [{handler,myh,logger_std_h,#{}}]]),
+ ok = rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ {ok,#{filters:=DF}} = rpc:call(Node,logger,get_handler_config,[default]),
+ {ok,#{filters:=[]}} = rpc:call(Node,logger,get_handler_config,[myh]),
+
+ true = test_server:stop_node(Node),
+
+ %% Start a node with no default handler, then add an own default handler
+ {ok,#{handlers:=[#{id:=simple}]},Node} =
+ logger_test_lib:setup(Config,[{logger,[{handler,default,undefined}]}]),
+
+ ok = rpc:call(Node,application,load,[App1]),
+ ok = rpc:call(Node,application,set_env,
+ [App1Name,logger,[{handler,default,logger_std_h,#{}}]]),
+ ok = rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ #{handlers:=[#{id:=default,filters:=DF}]} =
+ rpc:call(Node,logger,get_config,[]),
+
+ true = test_server:stop_node(Node),
+
+ %% Start a silent node, then add an own default handler
+ {ok,#{handlers:=[]},Node} =
+ logger_test_lib:setup(Config,[{error_logger,silent}]),
+
+ {error,{bad_config,{handler,[{some,bad,config}]}}} =
+ rpc:call(Node,logger,add_handlers,[[{some,bad,config}]]),
+ ok = rpc:call(Node,logger,add_handlers,
+ [[{handler,default,logger_std_h,#{}}]]),
+
+ #{handlers:=[#{id:=default,filters:=DF}]} =
+ rpc:call(Node,logger,get_config,[]),
+
+ ok.
+
+%% This test case is maintly to see code coverage. Note that
+%% logger_env_var_SUITE tests a lot of the same, and checks the
+%% functionality more thoroughly, but since it all happens at node
+%% start, it is not possible to see code coverage in that test.
+kernel_config(Config) ->
+ %% Start a node with simple handler only, then simulate kernel
+ %% start by calling internally exported
+ %% internal_init_logger(). This is to test all variants of kernel
+ %% config, including bad config, and see the code coverage.
+ {ok,#{handlers:=[#{id:=simple,filters:=DF}]}=LC,Node} =
+ logger_test_lib:setup(Config,[{error_logger,false}]),
+
+ %% Same once more, to get coverage
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ LC = rpc:call(Node,logger,get_config,[]),
+
+ %% This shall mean the same as above, but using 'logger' parameter
+ %% instead of 'error_logger'
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{handler,default,undefined}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ LC = rpc:call(Node,logger,get_config,[]),
+
+ %% Silent
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,silent]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Default
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% error_logger=tty (same as default)
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,tty]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% error_logger={file,File}
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ F = filename:join(?config(priv_dir,Config),
+ atom_to_list(?FUNCTION_NAME)++".log"),
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,{file,F}]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,
+ config:=#{type:=file,file:=F,modes:=Modes}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+ [append,delayed_write,raw] = lists:sort(Modes),
+
+
+ %% Same, but using 'logger' parameter instead of 'error_logger'
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_std_h,
+ #{config=>#{type=>{file,F}}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,
+ config:=#{type:=file,file:=F,modes:=Modes}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but with type={file,File,Modes}
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ M = [raw,write],
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_std_h,
+ #{config=>#{type=>{file,F,M}}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,
+ config:=#{type:=file,file:=F,modes:=[delayed_write|M]}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but with disk_log handler
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_disk_log_h,
+ #{config=>#{file=>F}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{file:=F}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Set primary filters and module level. No default handler.
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{handler,default,undefined},
+ {filters,stop,[{f1,{fun(_,_) -> log end,ok}}]},
+ {module_level,debug,[?MODULE]}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=stop,filters:=[_]},
+ handlers:=[],
+ module_levels:=[{?MODULE,debug}]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Bad config
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,bad]),
+ {error,{bad_config,{kernel,{error_logger,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,logger_level,bad]),
+ {error,{bad_config,{kernel,{logger_level,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,unset_env,[kernel,logger_level]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[bad]}]]),
+ {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[bad]}]]),
+ {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[{f1,bad}]}]]),
+ {error,{bad_config,{kernel,{invalid_filter,{f1,bad}}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,MF=[{filters,stop,[]},{filters,log,[]}]]),
+ {error,{bad_config,{kernel,{multiple_filters,MF}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{module_level,bad,[?MODULE]}]]),
+ {error,{bad_config,{kernel,{invalid_level,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok.
+
+pretty_print(Config) ->
+ ok = logger:add_handler(?FUNCTION_NAME,logger_std_h,#{}),
+ ok = logger:set_module_level([module1,module2],debug),
+
+ ct:capture_start(),
+ logger:i(),
+ ct:capture_stop(),
+ I0 = ct:capture_get(),
+
+ ct:capture_start(),
+ logger:i(primary),
+ ct:capture_stop(),
+ IPrim = ct:capture_get(),
+
+ ct:capture_start(),
+ logger:i(handlers),
+ ct:capture_stop(),
+ IHs = ct:capture_get(),
+
+ ct:capture_start(),
+ logger:i(proxy),
+ ct:capture_stop(),
+ IProxy = ct:capture_get(),
+
+ ct:capture_start(),
+ logger:i(modules),
+ ct:capture_stop(),
+ IMs = ct:capture_get(),
+
+ I02 = lists:append([IPrim,IHs,IProxy,IMs]),
+ %% ct:log("~p~n",[I0]),
+ %% ct:log("~p~n",[I02]),
+ I0 = I02,
+
+ ct:capture_start(),
+ logger:i(handlers),
+ ct:capture_stop(),
+ IHs = ct:capture_get(),
+
+ Ids = logger:get_handler_ids(),
+ IHs2 =
+ lists:append(
+ [begin
+ ct:capture_start(),
+ logger:i(Id),
+ ct:capture_stop(),
+ [_|IH] = ct:capture_get(),
+ IH
+ end || Id <- Ids]),
+
+ %% ct:log("~p~n",[IHs]),
+ %% ct:log("~p~n",[["Handler configuration: \n"|IHs2]]),
+ IHs = ["Handler configuration: \n"|IHs2],
+ ok.
+
%%%-----------------------------------------------------------------
%%% Internal
check_logged(Level,Format,Args,Meta) ->
@@ -1009,6 +1351,34 @@ test_macros(emergency=Level) ->
[{F2,x},{error,fun_that_crashes}],#{}),
ok.
+test_log_macro(Level) ->
+ ?LOG(Level,#{Level=>rep}),
+ ok = check_logged(Level,#{Level=>rep},?MY_LOC(1)),
+ ?LOG(Level,#{Level=>rep},#{my=>meta}),
+ ok = check_logged(Level,#{Level=>rep},(?MY_LOC(1))#{my=>meta}),
+ ?LOG(Level,"~w: ~w",[Level,fa]),
+ ok = check_logged(Level,"~w: ~w",[Level,fa],?MY_LOC(1)),
+ ?LOG(Level,"~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fa,meta],(?MY_LOC(1))#{my=>meta}),
+ ?LOG(Level,fun(x) -> {"~w: ~w ~w",[Level,fun_to_fa,meta]} end,
+ x, #{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],
+ (?MY_LOC(3))#{my=>meta}),
+ ?LOG(Level,fun(x) -> #{Level=>fun_to_r,meta=>true} end, x, #{my=>meta}),
+ ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},
+ (?MY_LOC(2))#{my=>meta}),
+ ?LOG(Level,fun(x) -> <<"fun_to_s">> end,x,#{}),
+ ok = check_logged(Level,<<"fun_to_s">>,?MY_LOC(1)),
+ F1=fun(x) -> {fun_to_bad} end,
+ ?LOG(Level,F1,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN ERROR: ~tp; Returned: ~tp",
+ [{F1,x},{fun_to_bad}],#{}),
+ F2=fun(x) -> erlang:error(fun_that_crashes) end,
+ ?LOG(Level,F2,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN CRASH: ~tp; Reason: ~tp",
+ [{F2,x},{error,fun_that_crashes}],#{}),
+ ok.
+
%%%-----------------------------------------------------------------
%%% Called by macro ?TRY(X)
my_try(Fun) ->
diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl
index 7e5b574869..9bbec42de8 100644
--- a/lib/kernel/test/logger_disk_log_h_SUITE.erl
+++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl
@@ -24,6 +24,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/logger.hrl").
-include_lib("kernel/src/logger_internal.hrl").
+-include_lib("kernel/src/logger_olp.hrl").
-include_lib("kernel/src/logger_h_common.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-include_lib("kernel/include/file.hrl").
@@ -92,11 +93,11 @@ all() ->
disk_log_opts,
default_formatter,
logging,
+ filter_config,
errors,
formatter_fail,
config_fail,
bad_input,
- info_and_reset,
reconfig,
sync,
disk_log_full,
@@ -302,6 +303,20 @@ logging(cleanup, _Config) ->
Name = list_to_atom(lists:concat([?FUNCTION_NAME,"_1"])),
remove_and_stop(Name).
+filter_config(_Config) ->
+ ok = logger:add_handler(?MODULE,logger_disk_log_h,#{}),
+ {ok,#{config:=HConfig}=Config} = logger:get_handler_config(?MODULE),
+ HConfig = maps:without([olp],HConfig),
+
+ FakeFullHConfig = HConfig#{olp=>{regname,self(),erlang:make_ref()}},
+ #{config:=HConfig} =
+ logger_disk_log_h:filter_config(Config#{config=>FakeFullHConfig}),
+ ok.
+
+filter_config(cleanup,_Config) ->
+ logger:remove_handler(?MODULE),
+ ok.
+
errors(Config) ->
PrivDir = ?config(priv_dir,Config),
Name1 = list_to_atom(lists:concat([?FUNCTION_NAME,"_1"])),
@@ -316,13 +331,29 @@ errors(Config) ->
%%! TODO:
%%! Check how bad log_opts are handled!
- {error,{illegal_config_change,_,_}} =
- logger:set_handler_config(Name1,
- config,
- #{file=>LogFile1,
- type=>halt}),
- {error,{illegal_config_change,_,_}} =
- logger:set_handler_config(Name1,id,new),
+ {error,{illegal_config_change,
+ logger_disk_log_h,
+ #{type:=wrap},
+ #{type:=halt}}} =
+ logger:update_handler_config(Name1,
+ config,
+ #{type=>halt,
+ file=>LogFile1}),
+
+ {error,{illegal_config_change,
+ logger_disk_log_h,
+ #{file:=LogFile1},
+ #{file:="newfilename"}}} =
+ logger:update_handler_config(Name1,
+ config,
+ #{file=>"newfilename"}),
+
+ %% Read-only fields may (accidentially) be included in the change,
+ %% but it won't take effect
+ {ok,C} = logger:get_handler_config(Name1),
+ ok = logger:set_handler_config(Name1,config,#{olp=>dummyvalue}),
+ {ok,C} = logger:get_handler_config(Name1),
+
ok = logger:remove_handler(Name1),
{error,{not_found,Name1}} = logger:remove_handler(Name1),
@@ -367,7 +398,7 @@ formatter_fail(Config) ->
ok = logger:set_handler_config(Name,formatter,{?MODULE,bad_return}),
logger:notice(?msg,?domain),
try_match_file(?log_no(LogFile,1),
- escape(Got3)++"FORMATTER ERROR: bad_return_value",
+ escape(Got3)++"FORMATTER ERROR: bad return value",
5000),
%% Check that handler is still alive and was never dead
@@ -380,20 +411,22 @@ formatter_fail(cleanup,_Config) ->
ok.
config_fail(_Config) ->
- {error,{handler_not_added,{invalid_config,logger_disk_log_h,{bad,bad}}}} =
+ {error,{handler_not_added,{invalid_config,logger_disk_log_h,#{bad:=bad}}}} =
logger:add_handler(?MODULE,logger_disk_log_h,
#{config => #{bad => bad},
filter_default=>log,
formatter=>{?MODULE,self()}}),
- {error,{handler_not_added,{invalid_levels,{_,1,_}}}} =
+ {error,{handler_not_added,{invalid_olp_levels,#{drop_mode_qlen:=1}}}} =
logger:add_handler(?MODULE,logger_disk_log_h,
#{config => #{drop_mode_qlen=>1}}),
- {error,{handler_not_added,{invalid_levels,{43,42,_}}}} =
+ {error,{handler_not_added,{invalid_olp_levels,#{sync_mode_qlen:=43,
+ drop_mode_qlen:=42}}}} =
logger:add_handler(?MODULE,logger_disk_log_h,
#{config => #{sync_mode_qlen=>43,
drop_mode_qlen=>42}}),
- {error,{handler_not_added,{invalid_levels,{_,43,42}}}} =
+ {error,{handler_not_added,{invalid_olp_levels,#{drop_mode_qlen:=43,
+ flush_qlen:=42}}}} =
logger:add_handler(?MODULE,logger_disk_log_h,
#{config => #{drop_mode_qlen=>43,
flush_qlen=>42}}),
@@ -402,40 +435,26 @@ config_fail(_Config) ->
#{filter_default=>log,
formatter=>{?MODULE,self()}}),
%% can't change the disk log options for a log already in use
- {error,{illegal_config_change,_,_}} =
- logger:set_handler_config(?MODULE,config,
- #{max_no_files=>2}),
- %% can't change name of an existing handler
- {error,{illegal_config_change,_,_}} =
- logger:set_handler_config(?MODULE,id,bad),
+ {error,{illegal_config_change,logger_disk_log_h,_,_}} =
+ logger:update_handler_config(?MODULE,config,
+ #{max_no_files=>2}),
%% incorrect values of OP params
{ok,#{config := HConfig}} = logger:get_handler_config(?MODULE),
- {error,{invalid_levels,_}} =
- logger:set_handler_config(?MODULE,config,
- HConfig#{sync_mode_qlen=>100,
- flush_qlen=>99}),
+ {error,{invalid_olp_levels,_}} =
+ logger:update_handler_config(?MODULE,config,
+ HConfig#{sync_mode_qlen=>100,
+ flush_qlen=>99}),
%% invalid name of config parameter
- {error,{invalid_config,logger_disk_log_h,{filesync_rep_int,2000}}} =
- logger:set_handler_config(?MODULE, config,
- HConfig#{filesync_rep_int => 2000}),
+ {error,{invalid_config,logger_disk_log_h,#{filesync_rep_int:=2000}}} =
+ logger:update_handler_config(?MODULE, config,
+ HConfig#{filesync_rep_int => 2000}),
ok.
config_fail(cleanup,_Config) ->
logger:remove_handler(?MODULE).
bad_input(_Config) ->
{error,{badarg,{filesync,["BadType"]}}} =
- logger_disk_log_h:filesync("BadType"),
- {error,{badarg,{info,["BadType"]}}} = logger_disk_log_h:info("BadType"),
- {error,{badarg,{reset,["BadType"]}}} = logger_disk_log_h:reset("BadType").
-
-info_and_reset(_Config) ->
- ok = logger:add_handler(?MODULE,logger_disk_log_h,
- #{filter_default=>log,
- formatter=>{?MODULE,self()}}),
- #{id := ?MODULE} = logger_disk_log_h:info(?MODULE),
- ok = logger_disk_log_h:reset(?MODULE).
-info_and_reset(cleanup,_Config) ->
- logger:remove_handler(?MODULE).
+ logger_disk_log_h:filesync("BadType").
reconfig(Config) ->
Dir = ?config(priv_dir,Config),
@@ -444,7 +463,7 @@ reconfig(Config) ->
#{filter_default=>log,
filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
formatter=>{?MODULE,self()}}),
- #{id := ?MODULE,
+ #{%id := ?MODULE,
sync_mode_qlen := ?SYNC_MODE_QLEN,
drop_mode_qlen := ?DROP_MODE_QLEN,
flush_qlen := ?FLUSH_QLEN,
@@ -455,14 +474,32 @@ reconfig(Config) ->
overload_kill_qlen := ?OVERLOAD_KILL_QLEN,
overload_kill_mem_size := ?OVERLOAD_KILL_MEM_SIZE,
overload_kill_restart_after := ?OVERLOAD_KILL_RESTART_AFTER,
- filesync_repeat_interval := ?FILESYNC_REPEAT_INTERVAL,
- log_opts := #{type := ?DISK_LOG_TYPE,
- max_no_files := ?DISK_LOG_MAX_NO_FILES,
- max_no_bytes := ?DISK_LOG_MAX_NO_BYTES,
- file := _DiskLogFile}} =
- logger_disk_log_h:info(?MODULE),
-
- {ok,#{config := HConfig0}} = logger:get_handler_config(?MODULE),
+ cb_state :=
+ #{handler_state :=
+ #{log_opts := #{type := ?DISK_LOG_TYPE,
+ max_no_files := ?DISK_LOG_MAX_NO_FILES,
+ max_no_bytes := ?DISK_LOG_MAX_NO_BYTES,
+ file := DiskLogFile}},
+ filesync_repeat_interval := ?FILESYNC_REPEAT_INTERVAL}} =
+ logger_olp:info(h_proc_name()),
+ {ok,#{config :=
+ #{sync_mode_qlen := ?SYNC_MODE_QLEN,
+ drop_mode_qlen := ?DROP_MODE_QLEN,
+ flush_qlen := ?FLUSH_QLEN,
+ burst_limit_enable := ?BURST_LIMIT_ENABLE,
+ burst_limit_max_count := ?BURST_LIMIT_MAX_COUNT,
+ burst_limit_window_time := ?BURST_LIMIT_WINDOW_TIME,
+ overload_kill_enable := ?OVERLOAD_KILL_ENABLE,
+ overload_kill_qlen := ?OVERLOAD_KILL_QLEN,
+ overload_kill_mem_size := ?OVERLOAD_KILL_MEM_SIZE,
+ overload_kill_restart_after := ?OVERLOAD_KILL_RESTART_AFTER,
+ filesync_repeat_interval := ?FILESYNC_REPEAT_INTERVAL,
+ file := DiskLogFile,
+ max_no_files := ?DISK_LOG_MAX_NO_FILES,
+ max_no_bytes := ?DISK_LOG_MAX_NO_BYTES,
+ type := wrap} = HConfig0}} =
+ logger:get_handler_config(?MODULE),
+
HConfig1 = HConfig0#{sync_mode_qlen => 1,
drop_mode_qlen => 2,
flush_qlen => 3,
@@ -475,7 +512,7 @@ reconfig(Config) ->
overload_kill_restart_after => infinity,
filesync_repeat_interval => no_repeat},
ok = logger:set_handler_config(?MODULE, config, HConfig1),
- #{id := ?MODULE,
+ #{%id := ?MODULE,
sync_mode_qlen := 1,
drop_mode_qlen := 2,
flush_qlen := 3,
@@ -486,8 +523,31 @@ reconfig(Config) ->
overload_kill_qlen := 100000,
overload_kill_mem_size := 10000000,
overload_kill_restart_after := infinity,
- filesync_repeat_interval := no_repeat} =
- logger_disk_log_h:info(?MODULE),
+ cb_state := #{filesync_repeat_interval := no_repeat}} =
+ logger_olp:info(h_proc_name()),
+ {ok,#{config:=HConfig1}} = logger:get_handler_config(?MODULE),
+
+ ok = logger:update_handler_config(?MODULE, config,
+ #{flush_qlen => ?FLUSH_QLEN}),
+ {ok,#{config:=C1}} = logger:get_handler_config(?MODULE),
+ ct:log("C1: ~p",[C1]),
+ C1 = HConfig1#{flush_qlen => ?FLUSH_QLEN},
+
+ ok = logger:set_handler_config(?MODULE, config, #{sync_mode_qlen => 1}),
+ {ok,#{config:=C2}} = logger:get_handler_config(?MODULE),
+ ct:log("C2: ~p",[C2]),
+ C2 = HConfig0#{sync_mode_qlen => 1},
+
+ ok = logger:set_handler_config(?MODULE, config, #{drop_mode_qlen => 100}),
+ {ok,#{config:=C3}} = logger:get_handler_config(?MODULE),
+ ct:log("C3: ~p",[C3]),
+ C3 = HConfig0#{drop_mode_qlen => 100},
+
+ ok = logger:update_handler_config(?MODULE, config, #{sync_mode_qlen => 1}),
+ {ok,#{config:=C4}} = logger:get_handler_config(?MODULE),
+ ct:log("C4: ~p",[C4]),
+ C4 = HConfig0#{sync_mode_qlen => 1,
+ drop_mode_qlen => 100},
ok = logger:remove_handler(?MODULE),
@@ -502,11 +562,50 @@ reconfig(Config) ->
max_no_files => 1,
max_no_bytes => 1024,
file => File}}),
- #{log_opts := #{type := halt,
- max_no_files := 1,
- max_no_bytes := 1024,
- file := File}} =
- logger_disk_log_h:info(?MODULE),
+ #{cb_state :=
+ #{handler_state :=
+ #{log_opts := #{type := halt,
+ max_no_files := 1,
+ max_no_bytes := 1024,
+ file := File}}}} =
+ logger_olp:info(h_proc_name()),
+ {ok,#{config :=
+ #{type := halt,
+ max_no_files := 1,
+ max_no_bytes := 1024,
+ file := File}=HaltHConfig} = Config2} =
+ logger:get_handler_config(?MODULE),
+
+ ok = logger:update_handler_config(?MODULE, level, notice),
+ {ok,C5} = logger:get_handler_config(?MODULE),
+ ct:log("C5: ~p",[C5]),
+ C5 = Config2#{level => notice},
+
+ ok = logger:set_handler_config(?MODULE, level, info),
+ {ok,C6} = logger:get_handler_config(?MODULE),
+ ct:log("C6: ~p",[C6]),
+ C6 = Config2#{level => info},
+
+ %% You are not allowed to actively set the write once fields
+ %% (type, max_no_files, max_no_bytes, file) in runtime.
+ {error, {illegal_config_change,_,_,_}} =
+ logger:set_handler_config(?MODULE,config,#{type=>wrap}),
+ {error, {illegal_config_change,_,_,_}} =
+ logger:set_handler_config(?MODULE,config,#{max_no_files=>2}),
+ {error, {illegal_config_change,_,_,_}} =
+ logger:set_handler_config(?MODULE,config,#{max_no_bytes=>2048}),
+ {error, {illegal_config_change,_,_,_}} =
+ logger:set_handler_config(?MODULE,config,#{file=>"otherfile.log"}),
+ {ok,C7} = logger:get_handler_config(?MODULE),
+ ct:log("C7: ~p",[C7]),
+ C7 = C6,
+
+ %% ... but if you don't specify the write once fields, then
+ %% set_handler_config shall NOT reset them to their default value
+ ok = logger:set_handler_config(?MODULE,config,#{sync_mode_qlen=>1}),
+ {ok,#{config:=C8}} = logger:get_handler_config(?MODULE),
+ ct:log("C8: ~p",[C8]),
+ C8 = HaltHConfig#{sync_mode_qlen=>1},
ok.
reconfig(cleanup, _Config) ->
@@ -523,67 +622,55 @@ sync(Config) ->
filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
formatter=>{?MODULE,nl}}),
- start_tracer([{disk_log,blog,2},
+ start_tracer([{logger_disk_log_h,disk_log_write,3},
{disk_log,sync,1}],
- [{disk_log,blog,<<"first\n">>},
+ [{logger_disk_log_h,disk_log_write,<<"first\n">>},
{disk_log,sync}]),
logger:notice("first", ?domain),
%% wait for automatic disk_log_sync
check_tracer(?FILESYNC_REPEAT_INTERVAL*2),
- start_tracer([{disk_log,blog,2},
- {disk_log,sync,1}],
- [{disk_log,blog,<<"second\n">>},
- {disk_log,blog,<<"third\n">>},
- {disk_log,sync}]),
- %% two log requests in fast succession will make the handler skip
- %% an automatic disk log sync
- logger:notice("second", ?domain),
- logger:notice("third", ?domain),
- %% do explicit sync
- logger_disk_log_h:filesync(?MODULE),
- check_tracer(100),
-
- %% check that if there's no repeated disk_log_sync active,
+ %% check that if there's no repeated filesync active,
%% a disk_log_sync is still performed when handler goes idle
{ok,#{config := HConfig}} = logger:get_handler_config(?MODULE),
HConfig1 = HConfig#{filesync_repeat_interval => no_repeat},
- ok = logger:set_handler_config(?MODULE, config, HConfig1),
-
+ ok = logger:update_handler_config(?MODULE, config, HConfig1),
no_repeat = maps:get(filesync_repeat_interval,
- logger_disk_log_h:info(?MODULE)),
+ maps:get(cb_state,logger_olp:info(h_proc_name()))),
- start_tracer([{disk_log,blog,2},
+ start_tracer([{logger_disk_log_h,disk_log_write,3},
{disk_log,sync,1}],
- [{disk_log,blog,<<"fourth\n">>},
- {disk_log,blog,<<"fifth\n">>},
+ [{logger_disk_log_h,disk_log_write,<<"second\n">>},
+ {disk_log,sync},
+ {logger_disk_log_h,disk_log_write,<<"third\n">>},
{disk_log,sync}]),
- logger:notice("fourth", ?domain),
- timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
- logger:notice("fifth", ?domain),
+ logger:notice("second", ?domain),
+ timer:sleep(?IDLE_DETECT_TIME*2),
+ logger:notice("third", ?domain),
%% wait for automatic disk_log_sync
- check_tracer(?IDLE_DETECT_TIME_MSEC*2),
+ check_tracer(?IDLE_DETECT_TIME*2),
- try_read_file(Log, {ok,<<"first\nsecond\nthird\nfourth\nfifth\n">>}, 1000),
+ try_read_file(Log, {ok,<<"first\nsecond\nthird\n">>}, 1000),
- %% switch repeated disk_log_sync on and verify that the looping works
+ %% switch repeated filesync on and verify that the looping works
SyncInt = 1000,
WaitT = 4500,
- OneSync = {logger_disk_log_h,handle_cast,repeated_disk_log_sync},
- %% receive 1 initial repeated_disk_log_sync, then 1 per sec
- start_tracer([{logger_disk_log_h,handle_cast,2}],
- [OneSync || _ <- lists:seq(1, 1 + trunc(WaitT/SyncInt))]),
+ OneSync = {logger_h_common,handle_cast,repeated_filesync},
+ %% receive 1 repeated_filesync per sec
+ start_tracer([{{logger_h_common,handle_cast,2},
+ [{[repeated_filesync,'_'],[],[{message,{caller}}]}]}],
+ [OneSync || _ <- lists:seq(1, trunc(WaitT/SyncInt))]),
HConfig2 = HConfig#{filesync_repeat_interval => SyncInt},
- ok = logger:set_handler_config(?MODULE, config, HConfig2),
+ ok = logger:update_handler_config(?MODULE, config, HConfig2),
SyncInt = maps:get(filesync_repeat_interval,
- logger_disk_log_h:info(?MODULE)),
+ maps:get(cb_state,logger_olp:info(h_proc_name()))),
timer:sleep(WaitT),
HConfig3 = HConfig#{filesync_repeat_interval => no_repeat},
- ok = logger:set_handler_config(?MODULE, config, HConfig3),
+ ok = logger:update_handler_config(?MODULE, config, HConfig3),
check_tracer(100),
ok.
sync(cleanup,_Config) ->
@@ -617,7 +704,7 @@ disk_log_wrap(Config) ->
end,
{ok,_} = dbg:tracer(process, {TraceFun, Tester}),
{ok,_} = dbg:p(whereis(h_proc_name()), [c]),
- {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 2, []),
+ {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 3, []),
Text = [34 + rand:uniform(126-34) || _ <- lists:seq(1,MaxBytes)],
ct:pal("String = ~p (~w)", [Text, erts_debug:size(Text)]),
@@ -635,7 +722,7 @@ disk_log_wrap(Config) ->
timer:sleep(1000),
dbg:stop_clear(),
Received = lists:flatmap(fun({trace,_M,handle_info,
- [{disk_log,_Node,_Name,What},_]}) ->
+ [_,{disk_log,_Node,_Name,What},_]}) ->
[{trace,What}];
({log,_}) ->
[]
@@ -671,7 +758,7 @@ disk_log_full(Config) ->
end,
{ok,_} = dbg:tracer(process, {TraceFun, Tester}),
{ok,_} = dbg:p(whereis(h_proc_name()), [c]),
- {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 2, []),
+ {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 3, []),
NoOfChars = 5,
Text = [34 + rand:uniform(126-34) || _ <- lists:seq(1,NoOfChars)],
@@ -681,20 +768,24 @@ disk_log_full(Config) ->
timer:sleep(2000),
dbg:stop_clear(),
Received = lists:flatmap(fun({trace,_M,handle_info,
- [{disk_log,_Node,_Name,What},_]}) ->
+ [_,{disk_log,_Node,_Name,What},_]}) ->
[{trace,What}];
({log,_}) ->
[]
end, test_server:messages_get()),
ct:pal("Trace =~n~p", [Received]),
- [{trace,full},
- {trace,{error_status,{error,{full,_}}}}] = Received,
+
+ %% The tail here could be an error_status notification, if the
+ %% last write was synchronous, but in most cases it will not be
+ [{trace,full}|_] = Received,
+ %% [{trace,full},
+ %% {trace,{error_status,{error,{full,_}}}}] = Received,
ok.
disk_log_full(cleanup, _Config) ->
dbg:stop_clear(),
logger:remove_handler(?MODULE).
-disk_log_events(Config) ->
+disk_log_events(_Config) ->
Node = node(),
Log = ?MODULE,
ok = logger:add_handler(?MODULE,
@@ -720,14 +811,14 @@ disk_log_events(Config) ->
end,
{ok,_} = dbg:tracer(process, {TraceFun, Tester}),
{ok,_} = dbg:p(whereis(h_proc_name()), [c]),
- {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 2, []),
+ {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 3, []),
[whereis(h_proc_name()) ! E || E <- Events],
%% wait for trace messages
timer:sleep(2000),
dbg:stop_clear(),
Received = lists:map(fun({trace,_M,handle_info,
- [Got,_]}) -> Got
+ [_,Got,_]}) -> Got
end, test_server:messages_get()),
ct:pal("Trace =~n~p", [Received]),
NoOfEvents = length(Events),
@@ -750,13 +841,17 @@ write_failure(Config) ->
false = (undefined == rpc:call(Node, ets, whereis, [?TEST_HOOKS_TAB])),
rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
- rpc:call(Node, ?MODULE, set_result, [disk_log_blog,ok]),
- HState = rpc:call(Node, logger_disk_log_h, info, [?STANDARD_HANDLER]),
- ct:pal("LogOpts = ~p", [LogOpts = maps:get(log_opts, HState)]),
-
+ rpc:call(Node, ?MODULE, set_result, [disk_log_write,ok]),
+ HState = rpc:call(Node, logger_olp, info, [h_proc_name(?STANDARD_HANDLER)]),
+ LogOpts = maps:get(log_opts,
+ maps:get(handler_state,
+ maps:get(cb_state,HState))),
+ ct:pal("LogOpts = ~p", [LogOpts]),
+
+ %% ?check and ?check_no_log in this test only check for internal log events
ok = log_on_remote_node(Node, "Logged1"),
rpc:call(Node, logger_disk_log_h, filesync, [?STANDARD_HANDLER]),
- ?check_no_log,
+ ?check_no_log, % no internal log when write ok
SyncRepInt = case (fun() -> is_atom(?FILESYNC_REPEAT_INTERVAL) end)() of
true -> 5500;
@@ -765,24 +860,26 @@ write_failure(Config) ->
try_read_file(Log, {ok,<<"Logged1\n">>}, SyncRepInt),
- rpc:call(Node, ?MODULE, set_result, [disk_log_blog,{error,no_such_log}]),
+ rpc:call(Node, ?MODULE, set_result, [disk_log_write,{error,no_such_log}]),
ok = log_on_remote_node(Node, "Cause simple error printout"),
+ %% this should have caused an internal log
?check({error,{?STANDARD_HANDLER,log,LogOpts,{error,no_such_log}}}),
-
+
ok = log_on_remote_node(Node, "No second error printout"),
- ?check_no_log,
+ ?check_no_log, % but don't log same error twice
- rpc:call(Node, ?MODULE, set_result, [disk_log_blog,
+ rpc:call(Node, ?MODULE, set_result, [disk_log_write,
{error,{full,?STANDARD_HANDLER}}]),
ok = log_on_remote_node(Node, "Cause simple error printout"),
+ %% this was a different error, so it should be logged
?check({error,{?STANDARD_HANDLER,log,LogOpts,
{error,{full,?STANDARD_HANDLER}}}}),
- rpc:call(Node, ?MODULE, set_result, [disk_log_blog,ok]),
+ rpc:call(Node, ?MODULE, set_result, [disk_log_write,ok]),
ok = log_on_remote_node(Node, "Logged2"),
rpc:call(Node, logger_disk_log_h, filesync, [?STANDARD_HANDLER]),
- ?check_no_log,
+ ?check_no_log, % no internal log when write ok
try_read_file(Log, {ok,<<"Logged1\nLogged2\n">>}, SyncRepInt),
ok.
write_failure(cleanup, _Config) ->
@@ -801,15 +898,16 @@ sync_failure(Config) ->
rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
rpc:call(Node, ?MODULE, set_result, [disk_log_sync,ok]),
- HState = rpc:call(Node, logger_disk_log_h, info, [?STANDARD_HANDLER]),
- LogOpts = maps:get(log_opts, HState),
+ HState = rpc:call(Node, logger_olp, info, [h_proc_name(?STANDARD_HANDLER)]),
+ LogOpts = maps:get(log_opts, maps:get(handler_state,
+ maps:get(cb_state,HState))),
SyncInt = 500,
- ok = rpc:call(Node, logger, set_handler_config,
+ ok = rpc:call(Node, logger, update_handler_config,
[?STANDARD_HANDLER, config,
#{filesync_repeat_interval => SyncInt}]),
- Info = rpc:call(Node, logger_disk_log_h, info, [?STANDARD_HANDLER]),
- SyncInt = maps:get(filesync_repeat_interval, Info),
+ Info = rpc:call(Node, logger_olp, info, [h_proc_name(?STANDARD_HANDLER)]),
+ SyncInt = maps:get(filesync_repeat_interval, maps:get(cb_state, Info)),
ok = log_on_remote_node(Node, "Logged1"),
?check_no_log,
@@ -880,7 +978,7 @@ op_switch_to_sync(Config) ->
drop_mode_qlen => NumOfReqs+1,
flush_qlen => 2*NumOfReqs,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Lines = count_lines(Log),
NumOfReqs = Lines,
@@ -905,7 +1003,7 @@ op_switch_to_drop(Config) ->
drop_mode_qlen => 2,
flush_qlen => Procs*NumOfReqs*Bursts,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
%% It sometimes happens that the handler either gets
%% the requests in a slow enough pace so that dropping
%% never occurs. Therefore, lets generate a number of
@@ -951,7 +1049,7 @@ op_switch_to_flush(Config) ->
drop_mode_qlen => 300,
flush_qlen => 300,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 1500,
Procs = 10,
Bursts = 10,
@@ -993,7 +1091,7 @@ limit_burst_disabled(Config) ->
burst_limit_window_time => 2000,
drop_mode_qlen => 200,
flush_qlen => 300}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 100,
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Logged = count_lines(Log),
@@ -1013,7 +1111,7 @@ limit_burst_enabled_one(Config) ->
burst_limit_window_time => 2000,
drop_mode_qlen => 200,
flush_qlen => 300}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 100,
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Logged = count_lines(Log),
@@ -1034,7 +1132,7 @@ limit_burst_enabled_period(Config) ->
burst_limit_window_time => BurstTWin,
drop_mode_qlen => 20000,
flush_qlen => 20001}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
Windows = 3,
Sent = send_burst({t,BurstTWin*Windows}, seq, {chars,79}, notice),
@@ -1054,7 +1152,7 @@ kill_disabled(Config) ->
HConfig#{config=>DLHConfig#{overload_kill_enable=>false,
overload_kill_qlen=>10,
overload_kill_mem_size=>100}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 100,
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Logged = count_lines(Log),
@@ -1076,7 +1174,7 @@ qlen_kill_new(Config) ->
overload_kill_qlen=>10,
overload_kill_mem_size=>Mem0+50000,
overload_kill_restart_after=>RestartAfter}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
MRef = erlang:monitor(process, Pid0),
NumOfReqs = 100,
Procs = 4,
@@ -1085,7 +1183,7 @@ qlen_kill_new(Config) ->
receive
{'DOWN', MRef, _, _, Info} ->
case Info of
- {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ {shutdown,{overloaded,QLen,Mem}} ->
ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
killed ->
ct:pal("Slow shutdown, handler process was killed!", [])
@@ -1095,7 +1193,7 @@ qlen_kill_new(Config) ->
ok
after
5000 ->
- Info = logger_disk_log_h:info(?MODULE),
+ Info = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info]),
ct:fail("Handler not dead! It should not have survived this!")
end.
@@ -1113,7 +1211,7 @@ mem_kill_new(Config) ->
overload_kill_qlen=>50000,
overload_kill_mem_size=>Mem0+500,
overload_kill_restart_after=>RestartAfter}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
MRef = erlang:monitor(process, Pid0),
NumOfReqs = 100,
Procs = 4,
@@ -1122,7 +1220,7 @@ mem_kill_new(Config) ->
receive
{'DOWN', MRef, _, _, Info} ->
case Info of
- {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ {shutdown,{overloaded,QLen,Mem}} ->
ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
killed ->
ct:pal("Slow shutdown, handler process was killed!", [])
@@ -1132,7 +1230,7 @@ mem_kill_new(Config) ->
ok
after
5000 ->
- Info = logger_disk_log_h:info(?MODULE),
+ Info = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info]),
ct:fail("Handler not dead! It should not have survived this!")
end.
@@ -1147,7 +1245,7 @@ restart_after(Config) ->
HConfig#{config=>DLHConfig#{overload_kill_enable=>true,
overload_kill_qlen=>10,
overload_kill_restart_after=>infinity}},
- ok = logger:set_handler_config(?MODULE, NewHConfig1),
+ ok = logger:update_handler_config(?MODULE, NewHConfig1),
MRef1 = erlang:monitor(process, whereis(h_proc_name())),
%% kill handler
send_burst({n,100}, {spawn,4,0}, {chars,79}, notice),
@@ -1158,7 +1256,7 @@ restart_after(Config) ->
ok
after
5000 ->
- Info1 = logger_std_h:info(?MODULE),
+ Info1 = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info1]),
ct:fail("Handler not dead! It should not have survived this!")
end,
@@ -1169,7 +1267,7 @@ restart_after(Config) ->
HConfig#{config=>DLHConfig#{overload_kill_enable=>true,
overload_kill_qlen=>10,
overload_kill_restart_after=>RestartAfter}},
- ok = logger:set_handler_config(?MODULE, NewHConfig2),
+ ok = logger:update_handler_config(?MODULE, NewHConfig2),
Pid0 = whereis(h_proc_name()),
MRef2 = erlang:monitor(process, Pid0),
%% kill handler
@@ -1182,7 +1280,7 @@ restart_after(Config) ->
ok
after
5000 ->
- Info2 = logger_std_h:info(?MODULE),
+ Info2 = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info2]),
ct:fail("Handler not dead! It should not have survived this!")
end,
@@ -1194,7 +1292,7 @@ restart_after(cleanup, _Config) ->
%% during high load to verify that sync, dropping and flushing is
%% handled correctly.
handler_requests_under_load() ->
- [{timetrap,{minutes,3}}].
+ [{timetrap,{minutes,5}}].
handler_requests_under_load(Config) ->
{Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
NewHConfig =
@@ -1202,12 +1300,16 @@ handler_requests_under_load(Config) ->
drop_mode_qlen => 1000,
flush_qlen => 2000,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
- Pid = spawn_link(fun() -> send_requests(?MODULE, 1, [{filesync,[]},
- {info,[]},
- {reset,[]},
- {change_config,[]}])
- end),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
+ Pid = spawn_link(
+ fun() -> send_requests(1,[{logger_disk_log_h,filesync,[?MODULE],[]},
+ {logger_olp,info,[h_proc_name()],[]},
+ {logger_olp,reset,[h_proc_name()],[]},
+ {logger,update_handler_config,
+ [?MODULE, config,
+ #{overload_kill_enable => false}],
+ []}])
+ end),
Procs = 100,
Sent = Procs * send_burst({n,5000}, {spawn,Procs,10}, {chars,79}, notice),
Pid ! {self(),finish},
@@ -1219,29 +1321,22 @@ handler_requests_under_load(Config) ->
[E || E <- Res,
is_tuple(E) andalso (element(1,E) == error)]
end,
- Errors = [{Req,FindError(Res)} || {Req,Res} <- ReqResult],
- NoOfReqs = lists:foldl(fun({_,Res}, N) -> N + length(Res) end, 0, ReqResult),
+ Errors = [{Func,FindError(Res)} || {_,Func,_,Res} <- ReqResult],
+ NoOfReqs = lists:foldl(fun({_,_,_,Res}, N) -> N + length(Res) end,
+ 0, ReqResult),
ct:pal("~w requests made. Errors: ~n~p", [NoOfReqs,Errors]),
ok = file_delete(Log).
handler_requests_under_load(cleanup, _Config) ->
ok = stop_handler(?MODULE).
-send_requests(HName, TO, Reqs = [{Req,Res}|Rs]) ->
+send_requests(TO, Reqs = [{Mod,Func,Args,Res}|Rs]) ->
receive
{From,finish} ->
From ! {self(),Reqs}
after
TO ->
- Result =
- case Req of
- change_config ->
- logger:set_handler_config(HName, logger_disk_log_h,
- #{overload_kill_enable =>
- false});
- Func ->
- logger_disk_log_h:Func(HName)
- end,
- send_requests(HName, TO, Rs ++ [{Req,[Result|Res]}])
+ Result = apply(Mod,Func,Args),
+ send_requests(TO, Rs ++ [{Mod,Func,Args,[Result|Res]}])
end.
%%%-----------------------------------------------------------------
@@ -1359,15 +1454,6 @@ format(Msg,Tag) ->
erlang:display(Error),
exit(Error).
-remove(Handler, LogName) ->
- logger_disk_log_h:remove(Handler, LogName),
- HState = #{log_names := Logs} = logger_disk_log_h:info(),
- false = maps:is_key(LogName, HState),
- false = lists:member(LogName, Logs),
- false = logger_config:exist(?LOGGER_TABLE, LogName),
- {error,no_such_log} = disk_log:info(LogName),
- ok.
-
start_and_add(Name, Config, LogOpts) ->
HConfig = maps:get(config, Config, #{}),
HConfig1 = maps:merge(HConfig, LogOpts),
@@ -1494,7 +1580,9 @@ start_tracer(Trace,Expected) ->
ok.
tpl([{M,F,A}|Trace]) ->
- {ok,Match} = dbg:tpl(M,F,A,[]),
+ tpl([{{M,F,A},c}|Trace]);
+tpl([{{M,F,A},MS}|Trace]) ->
+ {ok,Match} = dbg:tpl(M,F,A,MS),
case lists:keyfind(matched,1,Match) of
{_,_,1} ->
ok;
@@ -1507,23 +1595,23 @@ tpl([{M,F,A}|Trace]) ->
tpl([]) ->
ok.
-tracer({trace,_,call,{logger_disk_log_h,handle_cast,[Op|_]}},
+tracer({trace,_,call,{logger_h_common,handle_cast,[Op|_]},Caller},
{Pid,[{Mod,Func,Op}|Expected]}) ->
- maybe_tracer_done(Pid,Expected,{Mod,Func,Op});
-tracer({trace,_,call,{Mod=disk_log,Func=blog,[_,Data]}}, {Pid,[{Mod,Func,Data}|Expected]}) ->
- maybe_tracer_done(Pid,Expected,{Mod,Func,Data});
-tracer({trace,_,call,{Mod,Func,_}}, {Pid,[{Mod,Func}|Expected]}) ->
- maybe_tracer_done(Pid,Expected,{Mod,Func});
-tracer({trace,_,call,Call}, {Pid,Expected}) ->
- ct:log("Tracer got unexpected: ~p~nExpected: ~p~n",[Call,Expected]),
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Op},Caller);
+tracer({trace,_,call,{Mod=logger_disk_log_h,Func=disk_log_write,[_,_,Data]},Caller}, {Pid,[{Mod,Func,Data}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Data},Caller);
+tracer({trace,_,call,{Mod,Func,_},Caller}, {Pid,[{Mod,Func}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func},Caller);
+tracer({trace,_,call,Call,Caller}, {Pid,Expected}) ->
+ ct:log("Tracer got unexpected: ~p~nCaller: ~p~nExpected: ~p~n",[Call,Caller,Expected]),
Pid ! {tracer_got_unexpected,Call,Expected},
{Pid,Expected}.
-maybe_tracer_done(Pid,[],Got) ->
- ct:log("Tracer got: ~p~n",[Got]),
+maybe_tracer_done(Pid,[],Got,Caller) ->
+ ct:log("Tracer got: ~p~nCaller: ~p~n",[Got,Caller]),
Pid ! tracer_done;
-maybe_tracer_done(Pid,Expected,Got) ->
- ct:log("Tracer got: ~p~n",[Got]),
+maybe_tracer_done(Pid,Expected,Got,Caller) ->
+ ct:log("Tracer got: ~p~nCaller: ~p~n",[Got,Caller]),
{Pid,Expected}.
check_tracer(T) ->
@@ -1551,25 +1639,30 @@ h_proc_name() ->
h_proc_name(Name) ->
list_to_atom(lists:concat([logger_disk_log_h,"_",Name])).
-file_delete(Log) ->
- file:delete(Log).
-
wait_for_process_up(T) ->
- wait_for_process_up(h_proc_name(),T).
+ wait_for_process_up(?MODULE, h_proc_name(), T).
-wait_for_process_up(Name,T) ->
+wait_for_process_up(Name, RegName, T) ->
N = (T div 500) + 1,
- wait_for_process_up1(Name,N).
+ wait_for_process_up1(Name, RegName, N).
-wait_for_process_up1(Name,0) ->
+wait_for_process_up1(_Name, _RegName, 0) ->
error;
-wait_for_process_up1(Name,N) ->
+wait_for_process_up1(Name, RegName, N) ->
timer:sleep(500),
- case whereis(Name) of
+ case whereis(RegName) of
Pid when is_pid(Pid) ->
- %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
- {ok,Pid};
+ case logger:get_handler_config(Name) of
+ {ok,_} ->
+ %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
+ {ok,Pid};
+ _ ->
+ wait_for_process_up1(Name, RegName, N-1)
+ end;
undefined ->
%% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]),
- wait_for_process_up1(Name,N-1)
+ wait_for_process_up1(Name, RegName, N-1)
end.
+
+file_delete(Log) ->
+ file:delete(Log).
diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl
index 04a4364947..9d2ad11be8 100644
--- a/lib/kernel/test/logger_env_var_SUITE.erl
+++ b/lib/kernel/test/logger_env_var_SUITE.erl
@@ -59,7 +59,8 @@ groups() ->
logger_undefined,
logger_many_handlers_default_first,
logger_many_handlers_default_last,
- logger_many_handlers_default_last_broken_filter
+ logger_many_handlers_default_last_broken_filter,
+ logger_proxy
]},
{bad,[],[bad_error_logger,
bad_level,
@@ -71,6 +72,7 @@ all() ->
sasl_compatible_false,
sasl_compatible_false_no_progress,
sasl_compatible,
+ all_logger_level,
{group,bad},
{group,error_logger},
{group,logger}
@@ -540,6 +542,19 @@ logger_many_handlers(Config, Env, LogErr, LogInfo, NumProgress) ->
ok.
+logger_proxy(Config) ->
+ %% assume current node runs with default settings
+ DefOpts = logger_olp:get_opts(logger_proxy),
+ {ok,_,Node} = setup(Config,
+ [{logger,[{proxy,#{sync_mode_qlen=>0,
+ drop_mode_qlen=>2}}]}]),
+ Expected = DefOpts#{sync_mode_qlen:=0,
+ drop_mode_qlen:=2},
+ Expected = rpc:call(Node,logger_olp,get_opts,[logger_proxy]),
+ Expected = rpc:call(Node,logger,get_proxy_config,[]),
+
+ ok.
+
sasl_compatible_false(Config) ->
Log = file(Config,?FUNCTION_NAME),
{ok,_,Node} = setup(Config,
@@ -572,6 +587,24 @@ sasl_compatible(Config) ->
0),% progress in std logger
ok.
+all_logger_level(Config) ->
+ [all_logger_level(Config,Level) || Level <- [none,
+ emergency,
+ alert,
+ critical,
+ error,
+ warning,
+ notice,
+ info,
+ debug,
+ all]],
+ ok.
+
+all_logger_level(Config,Level) ->
+ {ok,#{primary:=#{level:=Level}},Node} = setup(Config,[{logger_level,Level}]),
+ true = test_server:stop_node(Node),
+ ok.
+
bad_error_logger(Config) ->
error = setup(Config,[{error_logger,baddest}]).
diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl
index 8fe8d5199b..83e3e6c40a 100644
--- a/lib/kernel/test/logger_formatter_SUITE.erl
+++ b/lib/kernel/test/logger_formatter_SUITE.erl
@@ -166,6 +166,56 @@ single_line(_Config) ->
" info:\nterm\n" = string:prefix(String2,ExpectedTimestamp),
String2 = format(info,{"~p",[term]},#{time=>Time},#{single_line=>bad}),
+
+
+ %% Test that no extra commas/spaces are added when removing
+ %% newlines, especially not after "=>" in a map association (as
+ %% was the case in OTP-21.0, when the only single_line adjustment
+ %% was done by regexp replacement of "\n" by ", ").
+ Prefix =
+ "Some characters to fill the line ------------------------------------- ",
+ String3 = format(info,{"~s~p~n~s~p~n",[Prefix,
+ lists:seq(1,10),
+ Prefix,
+ #{a=>map,with=>a,few=>accociations}]},
+ #{time=>Time},
+ #{single_line=>true}),
+ ct:log(String3),
+ match = re:run(String3,"\\[1,2,3,4,5,6,7,8,9,10\\]",[{capture,none}]),
+ match = re:run(String3,
+ "#{a => map,few => accociations,with => a}",
+ [{capture,none}]),
+
+ %% This part is added to make sure that the previous test made
+ %% sense, i.e. that there would actually be newlines inside the
+ %% list and map.
+ String4 = format(info,{"~s~p~n~s~p~n",[Prefix,
+ lists:seq(1,10),
+ Prefix,
+ #{a=>map,with=>a,few=>accociations}]},
+ #{time=>Time},
+ #{single_line=>false}),
+ ct:log(String4),
+ match = re:run(String4,"\\[1,2,3,\n",[global,{capture,none}]),
+ {match,Match4} = re:run(String4,"=>\n",[global,{capture,all}]),
+ 3 = length(Match4),
+
+ %% Test that big metadata fields do not get line breaks
+ String5 = format(info,"",
+ #{mymeta=>lists:seq(1,100)},
+ #{single_line=>true,template=>[mymeta,"\n"]}),
+ ct:log(String5),
+ [_] = string:lexemes(String5,"\n"),
+
+ %% Ensure that the previous test made sense, i.e. that the
+ %% metadata field does produce multiple lines if
+ %% single_line==false.
+ String6 = format(info,"",
+ #{mymeta=>lists:seq(1,100)},
+ #{single_line=>false,template=>[mymeta,"\n"]}),
+ ct:log(String6),
+ [_,_|_] = string:lexemes(String6,"\n"),
+
ok.
template(_Config) ->
@@ -312,30 +362,48 @@ format_msg(_Config) ->
#{report_cb=>fun(_)-> faulty_return end},
#{template=>Template}),
ct:log(String5),
- "REPORT_CB ERROR: term; Returned: faulty_return" = String5,
+ "REPORT_CB/1 ERROR: term; Returned: faulty_return" = String5,
String6 = format(info,{report,term},
#{report_cb=>fun(_)-> erlang:error(fun_crashed) end},
#{template=>Template}),
ct:log(String6),
- "REPORT_CB CRASH: term; Reason: {error,fun_crashed}" = String6,
+ "REPORT_CB/1 CRASH: term; Reason: {error,fun_crashed,"++_ = String6,
+
+ String7 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> ['not',a,string] end},
+ #{template=>Template}),
+ ct:log(String7),
+ "REPORT_CB/2 ERROR: term; Returned: ['not',a,string]" = String7,
+
+ String8 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> faulty_return end},
+ #{template=>Template}),
+ ct:log(String8),
+ "REPORT_CB/2 ERROR: term; Returned: faulty_return" = String8,
+
+ String9 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> erlang:error(fun_crashed) end},
+ #{template=>Template}),
+ ct:log(String9),
+ "REPORT_CB/2 CRASH: term; Reason: {error,fun_crashed,"++_ = String9,
%% strings are not formatted
- String7 = format(info,{string,"string"},
+ String10 = format(info,{string,"string"},
#{report_cb=>fun(_)-> {"formatted",[]} end},
#{template=>Template}),
- ct:log(String7),
- "string" = String7,
+ ct:log(String10),
+ "string" = String10,
- String8 = format(info,{string,['not',printable,list]},
+ String11 = format(info,{string,['not',printable,list]},
#{report_cb=>fun(_)-> {"formatted",[]} end},
#{template=>Template}),
- ct:log("~ts",[String8]), % avoiding ct_log crash
- "FORMAT ERROR: \"~ts\" - [['not',printable,list]]" = String8,
+ ct:log("~ts",[String11]), % avoiding ct_log crash
+ "FORMAT ERROR: \"~ts\" - [['not',printable,list]]" = String11,
- String9 = format(info,{string,"string"},#{},#{template=>Template}),
- ct:log(String9),
- "string" = String9,
+ String12 = format(info,{string,"string"},#{},#{template=>Template}),
+ ct:log(String12),
+ "string" = String12,
ok.
@@ -639,8 +707,10 @@ check_config(_Config) ->
?cfgerr({max_size,bad}) =
logger_formatter:check_config(#{max_size => bad}),
+ ok =
+ logger_formatter:check_config(#{report_cb => fun(_,_) -> "" end}),
?cfgerr({report_cb,F}) =
- logger_formatter:check_config(#{report_cb => F=fun(_,_) -> {"",[]} end}),
+ logger_formatter:check_config(#{report_cb => F=fun(_,_,_) -> {"",[]} end}),
?cfgerr({report_cb,bad}) =
logger_formatter:check_config(#{report_cb => bad}),
@@ -695,6 +765,8 @@ check_config(_Config) ->
%% Test that formatter config can be changed, and that the default
%% template is updated accordingly
update_config(_Config) ->
+ {error,{not_found,?MODULE}} = logger:update_formatter_config(?MODULE,#{}),
+
logger:add_handler_filter(default,silence,{fun(_,_) -> stop end,ok}),
ok = logger:add_handler(?MODULE,?MODULE,#{}),
D = lists:seq(1,1000),
@@ -747,6 +819,11 @@ update_config(_Config) ->
ct:log("~p",[C6]),
["=NOTICE REPORT==== "++_,_D6] = Lines6,
+ {error,{invalid_formatter_config,bad}} =
+ logger:update_formatter_config(?MODULE,bad),
+ {error,{invalid_formatter_config,logger_formatter,{depth,bad}}} =
+ logger:update_formatter_config(?MODULE,depth,bad),
+
ok.
update_config(cleanup,_Config) ->
@@ -790,7 +867,7 @@ my_try(Fun) ->
try Fun() catch C:R:S -> {C,R,hd(S)} end.
timestamp() ->
- erlang:system_time(microsecond).
+ logger:timestamp().
%% necessary?
add_time(#{time:=_}=Meta) ->
diff --git a/lib/kernel/test/logger_olp_SUITE.erl b/lib/kernel/test/logger_olp_SUITE.erl
new file mode 100644
index 0000000000..ea3eec89f5
--- /dev/null
+++ b/lib/kernel/test/logger_olp_SUITE.erl
@@ -0,0 +1,90 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_olp_SUITE).
+
+-compile(export_all).
+
+-include_lib("kernel/src/logger_olp.hrl").
+
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [idle_timer].
+
+%%%-----------------------------------------------------------------
+%%% Test cases
+idle_timer(_Config) ->
+ {ok,_Pid,Olp} = logger_olp:start_link(?MODULE,?MODULE,self(),#{}),
+ [logger_olp:load(Olp,{msg,N}) || N<-lists:seq(1,3)],
+ timer:sleep(?IDLE_DETECT_TIME*2),
+ [{load,{msg,1}},
+ {load,{msg,2}},
+ {load,{msg,3}},
+ {notify,idle}] = test_server:messages_get(),
+ logger_olp:cast(Olp,hello),
+ timer:sleep(?IDLE_DETECT_TIME*2),
+ [{cast,hello}] = test_server:messages_get(),
+ ok.
+idle_timer(cleanup,_Config) ->
+ unlink(whereis(?MODULE)),
+ logger_olp:stop(?MODULE),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Olp callbacks
+init(P) ->
+ {ok,P}.
+
+handle_load(M,P) ->
+ P ! {load,M},
+ P.
+
+handle_cast(M,P) ->
+ P ! {cast,M},
+ {noreply,P}.
+
+notify(N,P) ->
+ P ! {notify,N},
+ P.
diff --git a/lib/kernel/test/logger_proxy_SUITE.erl b/lib/kernel/test/logger_proxy_SUITE.erl
new file mode 100644
index 0000000000..777531e4ed
--- /dev/null
+++ b/lib/kernel/test/logger_proxy_SUITE.erl
@@ -0,0 +1,274 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_proxy_SUITE).
+
+-compile(export_all).
+
+%% -include_lib("common_test/include/ct.hrl").
+%% -include_lib("kernel/include/logger.hrl").
+%% -include_lib("kernel/src/logger_internal.hrl").
+
+%% -define(str,"Log from "++atom_to_list(?FUNCTION_NAME)++
+%% ":"++integer_to_list(?LINE)).
+%% -define(map_rep,#{function=>?FUNCTION_NAME, line=>?LINE}).
+%% -define(keyval_rep,[{function,?FUNCTION_NAME}, {line,?LINE}]).
+
+%% -define(MY_LOC(N),#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},
+%% file=>?FILE, line=>?LINE-N}).
+
+%% -define(TRY(X), my_try(fun() -> X end)).
+
+
+-define(HNAME,list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME]))).
+-define(LOC,#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},line=>?LINE}).
+-define(ENSURE_TIME,5000).
+
+suite() ->
+ [{timetrap,{seconds,30}},
+ {ct_hooks,[logger_test_lib]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [basic,
+ emulator,
+ remote,
+ remote_emulator,
+ config,
+ restart_after,
+ terminate].
+
+%%%-----------------------------------------------------------------
+%%% Test cases
+basic(_Config) ->
+ ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
+ logger_proxy ! {log,notice,"Log from: ~p; ~p",[?FUNCTION_NAME,?LINE],L1=?LOC},
+ ok = ensure(L1),
+ logger_proxy ! {log,notice,[{test_case,?FUNCTION_NAME},{line,?LINE}],L2=?LOC},
+ ok = ensure(L2),
+ logger_proxy:log({remote,node(),{log,notice,
+ "Log from: ~p; ~p",
+ [?FUNCTION_NAME,?LINE],
+ L3=?LOC}}),
+ ok = ensure(L3),
+ logger_proxy:log({remote,node(),{log,notice,
+ [{test_case,?FUNCTION_NAME},
+ {line,?LINE}],
+ L4=?LOC}}),
+ ok = ensure(L4),
+ ok.
+basic(cleanup,_Config) ->
+ ok = logger:remove_handler(?HNAME).
+
+emulator(_Config) ->
+ ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
+ Pid = spawn(fun() -> erlang:error(some_reason) end),
+ ok = ensure(#{pid=>Pid}),
+ ok.
+emulator(cleanup,_Config) ->
+ ok = logger:remove_handler(?HNAME).
+
+remote(Config) ->
+ {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
+ ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
+ L1 = ?LOC, spawn(Node,fun() -> logger:notice("Log from ~p; ~p",[?FUNCTION_NAME,?LINE],L1) end),
+ ok = ensure(L1),
+ L2 = ?LOC, spawn(Node,fun() -> logger:notice([{test_case,?FUNCTION_NAME},{line,?LINE}],L2) end),
+ ok = ensure(L2),
+ ok.
+remote(cleanup,_Config) ->
+ ok = logger:remove_handler(?HNAME).
+
+remote_emulator(Config) ->
+ {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
+ ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
+ Pid = spawn(Node,fun() -> erlang:error(some_reason) end),
+ ok = ensure(#{pid=>Pid}),
+ ok.
+remote_emulator(cleanup,_Config) ->
+ ok = logger:remove_handler(?HNAME).
+
+config(_Config) ->
+ C1 = #{sync_mode_qlen:=SQ,
+ drop_mode_qlen:=DQ} = logger:get_proxy_config(),
+ C1 = logger_olp:get_opts(logger_proxy),
+
+ %% Update the existing config with these two values
+ SQ1 = SQ+1,
+ DQ1 = DQ+1,
+ ok = logger:update_proxy_config(#{sync_mode_qlen=>SQ1,
+ drop_mode_qlen=>DQ1}),
+ C2 = logger:get_proxy_config(), % reads from ets table
+ C2 = logger_olp:get_opts(logger_proxy), % ensure consistency with process opts
+ C2 = C1#{sync_mode_qlen:=SQ1,
+ drop_mode_qlen:=DQ1},
+
+ %% Update the existing again with only one value
+ SQ2 = SQ+2,
+ ok = logger:update_proxy_config(#{sync_mode_qlen=>SQ2}),
+ C3 = logger:get_proxy_config(),
+ C3 = logger_olp:get_opts(logger_proxy),
+ C3 = C2#{sync_mode_qlen:=SQ2},
+
+ %% Set the config, i.e. merge with defaults
+ ok = logger:set_proxy_config(#{sync_mode_qlen=>SQ1}),
+ C4 = logger:get_proxy_config(),
+ C4 = logger_olp:get_opts(logger_proxy),
+ C4 = C1#{sync_mode_qlen:=SQ1},
+
+ %% Reset to default
+ ok = logger:set_proxy_config(#{}),
+ C5 = logger:get_proxy_config(),
+ C5 = logger_olp:get_opts(logger_proxy),
+ C5 = logger_proxy:get_default_config(),
+
+ %% Errors
+ {error,{invalid_olp_config,_}} =
+ logger:set_proxy_config(#{faulty_key=>1}),
+ {error,{invalid_olp_config,_}} =
+ logger:set_proxy_config(#{sync_mode_qlen=>infinity}),
+ {error,{invalid_config,[]}} = logger:set_proxy_config([]),
+
+ {error,{invalid_olp_config,_}} =
+ logger:update_proxy_config(#{faulty_key=>1}),
+ {error,{invalid_olp_config,_}} =
+ logger:update_proxy_config(#{sync_mode_qlen=>infinity}),
+ {error,{invalid_config,[]}} = logger:update_proxy_config([]),
+
+ C5 = logger:get_proxy_config(),
+ C5 = logger_olp:get_opts(logger_proxy),
+
+ ok.
+config(cleanup,_Config) ->
+ _ = logger:set_logger_proxy(logger_proxy:get_default_config()),
+ ok.
+
+restart_after(_Config) ->
+ Restart = 3000,
+ ok = logger:update_proxy_config(#{overload_kill_enable => true,
+ overload_kill_qlen => 10,
+ overload_kill_restart_after => Restart}),
+ Proxy = whereis(logger_proxy),
+ Proxy = erlang:system_info(system_logger),
+ ProxyConfig = logger:get_proxy_config(),
+ ProxyConfig = logger_olp:get_opts(logger_proxy),
+
+ Ref = erlang:monitor(process,Proxy),
+ spawn(fun() ->
+ [logger_proxy ! {log,debug,
+ [{test_case,?FUNCTION_NAME},
+ {line,?LINE}],
+ ?LOC} || _ <- lists:seq(1,100)]
+ end),
+ receive
+ {'DOWN',Ref,_,_,_Reason} ->
+ undefined = erlang:system_info(system_logger),
+ timer:sleep(Restart),
+ poll_restarted(10)
+ after 5000 ->
+ ct:fail(proxy_not_terminated)
+ end,
+
+ Proxy1 = whereis(logger_proxy),
+ Proxy1 = erlang:system_info(system_logger),
+ ProxyConfig = logger:get_proxy_config(),
+ ProxyConfig = logger_olp:get_opts(logger_proxy),
+
+ ok.
+restart_after(cleanup,_Config) ->
+ _ = logger:set_logger_proxy(logger_proxy:get_default_config()),
+ ok.
+
+%% Test that system_logger flag is set to logger process if
+%% logger_proxy terminates for other reason than overloaded.
+terminate(_Config) ->
+ Logger = whereis(logger),
+ Proxy = whereis(logger_proxy),
+ Proxy = erlang:system_info(system_logger),
+ ProxyConfig = logger:get_proxy_config(),
+ ProxyConfig = logger_olp:get_opts(logger_proxy),
+
+ Ref = erlang:monitor(process,Proxy),
+ ok = logger_olp:stop(Proxy),
+ receive
+ {'DOWN',Ref,_,_,_Reason} ->
+ Logger = erlang:system_info(system_logger),
+ logger_proxy:restart(),
+ poll_restarted(10)
+ after 5000 ->
+ ct:fail(proxy_not_terminated)
+ end,
+
+ Proxy1 = whereis(logger_proxy),
+ Proxy1 = erlang:system_info(system_logger),
+ ProxyConfig = logger:get_proxy_config(),
+ ProxyConfig = logger_olp:get_opts(logger_proxy),
+
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+
+poll_restarted(0) ->
+ ct:fail(proxy_not_restarted);
+poll_restarted(N) ->
+ timer:sleep(1000),
+ case whereis(logger_proxy) of
+ undefined ->
+ poll_restarted(N-1);
+ _Pid ->
+ ok
+ end.
+
+%% Logger handler callback
+log(#{meta:=Meta},#{config:=Pid}) ->
+ Pid ! {logged,Meta}.
+
+%% Check that the log from the logger callback function log/2 is received
+ensure(Match) ->
+ receive {logged,Meta} ->
+ case maps:with(maps:keys(Match),Meta) of
+ Match -> ok;
+ _NoMatch -> {error,Match,Meta,test_server:messages_get()}
+ end
+ after ?ENSURE_TIME -> {error,Match,test_server:messages_get()}
+ end.
diff --git a/lib/kernel/test/logger_simple_h_SUITE.erl b/lib/kernel/test/logger_simple_h_SUITE.erl
index 79e5c057ad..e0ad792bdb 100644
--- a/lib/kernel/test/logger_simple_h_SUITE.erl
+++ b/lib/kernel/test/logger_simple_h_SUITE.erl
@@ -117,8 +117,7 @@ replace_default(Config) ->
log(Node, critical, [?str,[?keyval_rep]]),
log(Node, notice, [["fake",string,"line:",?LINE]]),
- Env = rpc:call(Node, application, get_env, [kernel, logger, []]),
- ok = rpc:call(Node, logger, add_handlers, [Env]),
+ ok = rpc:call(Node, logger, add_handlers, [kernel]),
ok.
diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl
index ca54458ac1..0c5516f82b 100644
--- a/lib/kernel/test/logger_std_h_SUITE.erl
+++ b/lib/kernel/test/logger_std_h_SUITE.erl
@@ -25,10 +25,15 @@
-include_lib("kernel/include/logger.hrl").
-include_lib("kernel/src/logger_internal.hrl").
-include_lib("kernel/src/logger_h_common.hrl").
+-include_lib("kernel/src/logger_olp.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-include_lib("kernel/include/file.hrl").
--define(check_no_log, [] = test_server:messages_get()).
+-define(check_no_log,
+ begin
+ timer:sleep(?IDLE_DETECT_TIME*2),
+ [] = test_server:messages_get()
+ end).
-define(check(Expected),
receive
{log,Expected} ->
@@ -107,14 +112,16 @@ all() ->
add_remove_instance_standard_error,
add_remove_instance_file1,
add_remove_instance_file2,
+ add_remove_instance_file3,
+ add_remove_instance_file4,
default_formatter,
+ filter_config,
errors,
formatter_fail,
config_fail,
crash_std_h_to_file,
crash_std_h_to_disk_log,
bad_input,
- info_and_reset,
reconfig,
file_opts,
sync,
@@ -135,11 +142,18 @@ all() ->
mem_kill_new,
mem_kill_std,
restart_after,
- handler_requests_under_load
+ handler_requests_under_load,
+ recreate_deleted_log,
+ reopen_changed_log,
+ rotate_size,
+ rotate_size_compressed,
+ rotate_size_reopen,
+ rotation_opts,
+ rotation_opts_restart_handler
].
add_remove_instance_tty(_Config) ->
- {error,{handler_not_added,{invalid_config,logger_std_h,{type,tty}}}} =
+ {error,{handler_not_added,{invalid_config,logger_std_h,#{type:=tty}}}} =
logger:add_handler(?MODULE,logger_std_h,
#{config => #{type => tty},
filter_default=>log,
@@ -172,10 +186,27 @@ add_remove_instance_file2(Config) ->
add_remove_instance_file2(cleanup,_Config) ->
logger_std_h_remove().
-add_remove_instance_file(Log, Type) ->
+add_remove_instance_file3(_Config) ->
+ Log = atom_to_list(?MODULE),
+ StdHConfig = #{type=>file},
+ add_remove_instance_file(Log, StdHConfig).
+add_remove_instance_file3(cleanup,_Config) ->
+ logger_std_h_remove().
+
+add_remove_instance_file4(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir,"stdlog4.txt"),
+ StdHConfig = #{file=>Log,modes=>[]},
+ add_remove_instance_file(Log, StdHConfig).
+add_remove_instance_file4(cleanup,_Config) ->
+ logger_std_h_remove().
+
+add_remove_instance_file(Log, Type) when not is_map(Type) ->
+ add_remove_instance_file(Log,#{type=>Type});
+add_remove_instance_file(Log, StdHConfig) when is_map(StdHConfig) ->
ok = logger:add_handler(?MODULE,
logger_std_h,
- #{config => #{type => Type},
+ #{config => StdHConfig,
filter_default=>stop,
filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
formatter=>{?MODULE,self()}}),
@@ -204,6 +235,20 @@ default_formatter(_Config) ->
match = re:run(Msg,"=NOTICE REPORT====.*\n"++M1,[{capture,none}]),
ok.
+filter_config(_Config) ->
+ ok = logger:add_handler(?MODULE,logger_std_h,#{}),
+ {ok,#{config:=HConfig}=Config} = logger:get_handler_config(?MODULE),
+ HConfig = maps:without([olp],HConfig),
+
+ FakeFullHConfig = HConfig#{olp=>{regname,self(),erlang:make_ref()}},
+ #{config:=HConfig} =
+ logger_std_h:filter_config(Config#{config=>FakeFullHConfig}),
+ ok.
+
+filter_config(cleanup,_Config) ->
+ logger:remove_handler(?MODULE),
+ ok.
+
errors(Config) ->
Dir = ?config(priv_dir,Config),
Log = filename:join(Dir,?FUNCTION_NAME),
@@ -219,7 +264,7 @@ errors(Config) ->
{error,
{handler_not_added,
- {invalid_config,logger_std_h,{type,faulty_type}}}} =
+ {invalid_config,logger_std_h,#{type:=faulty_type}}}} =
logger:add_handler(?MODULE,logger_std_h,
#{config => #{type => faulty_type}}),
@@ -230,15 +275,16 @@ errors(Config) ->
_ ->
NoDir = lists:concat(["/",?MODULE,"_dir"]),
{error,
- {handler_not_added,{{open_failed,NoDir,eacces},_}}} =
+ {handler_not_added,{open_failed,NoDir,eacces}}} =
logger:add_handler(myh2,logger_std_h,
#{config=>#{type=>{file,NoDir}}})
end,
{error,
- {handler_not_added,{{open_failed,Log,_},_}}} =
+ {handler_not_added,
+ {invalid_config,logger_std_h,#{modes:=bad_file_opt}}}} =
logger:add_handler(myh3,logger_std_h,
- #{config=>#{type=>{file,Log,[bad_file_opt]}}}),
+ #{config=>#{type=>{file,Log,bad_file_opt}}}),
ok = logger:notice(?msg).
@@ -280,7 +326,7 @@ formatter_fail(Config) ->
ok = logger:set_handler_config(?MODULE,formatter,{?MODULE,bad_return}),
logger:notice(?msg,?domain),
try_match_file(Log,
- escape(Got3)++"FORMATTER ERROR: bad_return_value",
+ escape(Got3)++"FORMATTER ERROR: bad return value",
5000),
%% Check that handler is still alive and was never dead
@@ -293,25 +339,27 @@ formatter_fail(cleanup,_Config) ->
logger:remove_handler(?MODULE).
config_fail(_Config) ->
- {error,{handler_not_added,{invalid_config,logger_std_h,{bad,bad}}}} =
+ {error,{handler_not_added,{invalid_config,logger_std_h,#{bad:=bad}}}} =
logger:add_handler(?MODULE,logger_std_h,
#{config => #{bad => bad},
filter_default=>log,
formatter=>{?MODULE,self()}}),
{error,{handler_not_added,{invalid_config,logger_std_h,
- {restart_type,bad}}}} =
+ #{restart_type:=bad}}}} =
logger:add_handler(?MODULE,logger_std_h,
#{config => #{restart_type => bad},
filter_default=>log,
formatter=>{?MODULE,self()}}),
- {error,{handler_not_added,{invalid_levels,{_,1,_}}}} =
+ {error,{handler_not_added,{invalid_olp_levels,#{drop_mode_qlen:=1}}}} =
logger:add_handler(?MODULE,logger_std_h,
#{config => #{drop_mode_qlen=>1}}),
- {error,{handler_not_added,{invalid_levels,{43,42,_}}}} =
+ {error,{handler_not_added,{invalid_olp_levels,#{sync_mode_qlen:=43,
+ drop_mode_qlen:=42}}}} =
logger:add_handler(?MODULE,logger_std_h,
#{config => #{sync_mode_qlen=>43,
drop_mode_qlen=>42}}),
- {error,{handler_not_added,{invalid_levels,{_,43,42}}}} =
+ {error,{handler_not_added,{invalid_olp_levels,#{drop_mode_qlen:=43,
+ flush_qlen:=42}}}} =
logger:add_handler(?MODULE,logger_std_h,
#{config => #{drop_mode_qlen=>43,
flush_qlen=>42}}),
@@ -319,18 +367,24 @@ config_fail(_Config) ->
ok = logger:add_handler(?MODULE,logger_std_h,
#{filter_default=>log,
formatter=>{?MODULE,self()}}),
- {error,{illegal_config_change,_,_}} =
+ {error,{illegal_config_change,logger_std_h,#{type:=_},#{type:=_}}} =
logger:set_handler_config(?MODULE,config,
#{type=>{file,"file"}}),
- {error,{illegal_config_change,_,_}} =
- logger:set_handler_config(?MODULE,id,bad),
- {error,{invalid_levels,_}} =
+
+ {error,{invalid_olp_levels,_}} =
logger:set_handler_config(?MODULE,config,
#{sync_mode_qlen=>100,
flush_qlen=>99}),
- {error,{invalid_config,logger_std_h,{filesync_rep_int,2000}}} =
+ {error,{invalid_config,logger_std_h,#{filesync_rep_int:=2000}}} =
logger:set_handler_config(?MODULE, config,
#{filesync_rep_int => 2000}),
+
+ %% Read-only fields may (accidentially) be included in the change,
+ %% but it won't take effect
+ {ok,C} = logger:get_handler_config(?MODULE),
+ ok = logger:set_handler_config(?MODULE,config,#{olp=>dummyvalue}),
+ {ok,C} = logger:get_handler_config(?MODULE),
+
ok.
config_fail(cleanup,_Config) ->
@@ -396,10 +450,13 @@ crash_std_h(Config,Func,Var,Type,Log) ->
%% logger would send the log event to the logger process here instead
%% of logging it itself.
log_on_remote_node(Node,Msg) ->
+ Pid = self(),
_ = spawn_link(Node,
fun() -> erlang:group_leader(whereis(user),self()),
- logger:notice(Msg)
+ logger:notice(Msg),
+ Pid ! done
end),
+ receive done -> ok end,
ok.
@@ -427,14 +484,7 @@ sync_and_read(Node,file,Log) ->
end.
bad_input(_Config) ->
- {error,{badarg,{filesync,["BadType"]}}} = logger_std_h:filesync("BadType"),
- {error,{badarg,{info,["BadType"]}}} = logger_std_h:info("BadType"),
- {error,{badarg,{reset,["BadType"]}}} = logger_std_h:reset("BadType").
-
-
-info_and_reset(_Config) ->
- #{id := ?STANDARD_HANDLER} = logger_std_h:info(?STANDARD_HANDLER),
- ok = logger_std_h:reset(?STANDARD_HANDLER).
+ {error,{badarg,{filesync,["BadType"]}}} = logger_std_h:filesync("BadType").
reconfig(Config) ->
Dir = ?config(priv_dir,Config),
@@ -444,9 +494,10 @@ reconfig(Config) ->
filter_default=>log,
filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
formatter=>{?MODULE,self()}}),
- #{id := ?MODULE,
- type := standard_io,
- file_ctrl_pid := FileCtrlPid,
+ #{%id := ?MODULE,
+ cb_state:=#{handler_state := #{type := standard_io,
+ file_ctrl_pid := FileCtrlPid},
+ filesync_repeat_interval := no_repeat},
sync_mode_qlen := ?SYNC_MODE_QLEN,
drop_mode_qlen := ?DROP_MODE_QLEN,
flush_qlen := ?FLUSH_QLEN,
@@ -456,9 +507,25 @@ reconfig(Config) ->
overload_kill_enable := ?OVERLOAD_KILL_ENABLE,
overload_kill_qlen := ?OVERLOAD_KILL_QLEN,
overload_kill_mem_size := ?OVERLOAD_KILL_MEM_SIZE,
- overload_kill_restart_after := ?OVERLOAD_KILL_RESTART_AFTER,
- filesync_repeat_interval := ?FILESYNC_REPEAT_INTERVAL} =
- logger_std_h:info(?MODULE),
+ overload_kill_restart_after := ?OVERLOAD_KILL_RESTART_AFTER} =
+ logger_olp:info(h_proc_name()),
+
+ {ok,
+ #{config:=
+ #{type := standard_io,
+ sync_mode_qlen := ?SYNC_MODE_QLEN,
+ drop_mode_qlen := ?DROP_MODE_QLEN,
+ flush_qlen := ?FLUSH_QLEN,
+ burst_limit_enable := ?BURST_LIMIT_ENABLE,
+ burst_limit_max_count := ?BURST_LIMIT_MAX_COUNT,
+ burst_limit_window_time := ?BURST_LIMIT_WINDOW_TIME,
+ overload_kill_enable := ?OVERLOAD_KILL_ENABLE,
+ overload_kill_qlen := ?OVERLOAD_KILL_QLEN,
+ overload_kill_mem_size := ?OVERLOAD_KILL_MEM_SIZE,
+ overload_kill_restart_after := ?OVERLOAD_KILL_RESTART_AFTER,
+ filesync_repeat_interval := no_repeat} =
+ DefaultHConf}}
+ = logger:get_handler_config(?MODULE),
ok = logger:set_handler_config(?MODULE, config,
#{sync_mode_qlen => 1,
@@ -471,10 +538,11 @@ reconfig(Config) ->
overload_kill_qlen => 100000,
overload_kill_mem_size => 10000000,
overload_kill_restart_after => infinity,
- filesync_repeat_interval => no_repeat}),
- #{id := ?MODULE,
- type := standard_io,
- file_ctrl_pid := FileCtrlPid,
+ filesync_repeat_interval => 5000}),
+ #{%id := ?MODULE,
+ cb_state := #{handler_state := #{type := standard_io,
+ file_ctrl_pid := FileCtrlPid},
+ filesync_repeat_interval := no_repeat},
sync_mode_qlen := 1,
drop_mode_qlen := 2,
flush_qlen := 3,
@@ -484,8 +552,77 @@ reconfig(Config) ->
overload_kill_enable := true,
overload_kill_qlen := 100000,
overload_kill_mem_size := 10000000,
- overload_kill_restart_after := infinity,
- filesync_repeat_interval := no_repeat} = logger_std_h:info(?MODULE),
+ overload_kill_restart_after := infinity} = logger_olp:info(h_proc_name()),
+
+ {ok,#{config :=
+ #{type := standard_io,
+ sync_mode_qlen := 1,
+ drop_mode_qlen := 2,
+ flush_qlen := 3,
+ burst_limit_enable := false,
+ burst_limit_max_count := 10,
+ burst_limit_window_time := 10,
+ overload_kill_enable := true,
+ overload_kill_qlen := 100000,
+ overload_kill_mem_size := 10000000,
+ overload_kill_restart_after := infinity,
+ filesync_repeat_interval := no_repeat} = HConf}} =
+ logger:get_handler_config(?MODULE),
+
+ ok = logger:update_handler_config(?MODULE, config,
+ #{flush_qlen => ?FLUSH_QLEN}),
+ {ok,#{config:=C1}} = logger:get_handler_config(?MODULE),
+ ct:log("C1: ~p",[C1]),
+ C1 = HConf#{flush_qlen => ?FLUSH_QLEN},
+
+ ok = logger:set_handler_config(?MODULE, config, #{sync_mode_qlen => 1}),
+ {ok,#{config:=C2}} = logger:get_handler_config(?MODULE),
+ ct:log("C2: ~p",[C2]),
+ C2 = DefaultHConf#{sync_mode_qlen => 1},
+
+ ok = logger:set_handler_config(?MODULE, config, #{drop_mode_qlen => 100}),
+ {ok,#{config:=C3}} = logger:get_handler_config(?MODULE),
+ ct:log("C3: ~p",[C3]),
+ C3 = DefaultHConf#{drop_mode_qlen => 100},
+
+ ok = logger:update_handler_config(?MODULE, config, #{sync_mode_qlen => 1}),
+ {ok,#{config:=C4}} = logger:get_handler_config(?MODULE),
+ ct:log("C4: ~p",[C4]),
+ C4 = DefaultHConf#{sync_mode_qlen => 1,
+ drop_mode_qlen => 100},
+
+ ok = logger:remove_handler(?MODULE),
+
+ File = filename:join(Dir,lists:concat([?FUNCTION_NAME,".log"])),
+ ok = logger:add_handler(?MODULE,
+ logger_std_h,
+ #{config => #{type => {file,File}},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+
+ {ok,#{config:=#{filesync_repeat_interval:=FSI}=FileHConfig}} =
+ logger:get_handler_config(?MODULE),
+ ok = logger:update_handler_config(?MODULE,config,
+ #{filesync_repeat_interval=>FSI+2000}),
+ {ok,#{config:=C5}} = logger:get_handler_config(?MODULE),
+ ct:log("C5: ~p",[C5]),
+ C5 = FileHConfig#{filesync_repeat_interval=>FSI+2000},
+
+ %% You are not allowed to actively set 'type' in runtime, since
+ %% this is a write once field.
+ {error, {illegal_config_change,logger_std_h,_,_}} =
+ logger:set_handler_config(?MODULE,config,#{type=>standard_io}),
+ {ok,#{config:=C6}} = logger:get_handler_config(?MODULE),
+ ct:log("C6: ~p",[C6]),
+ C6 = C5,
+
+ %% ... but if you don't specify 'type', then set_handler_config shall
+ %% NOT reset it to its default value
+ ok = logger:set_handler_config(?MODULE,config,#{sync_mode_qlen=>1}),
+ {ok,#{config:=C7}} = logger:get_handler_config(?MODULE),
+ ct:log("C7: ~p",[C7]),
+ C7 = FileHConfig#{sync_mode_qlen=>1},
ok.
reconfig(cleanup, _Config) ->
@@ -495,22 +632,51 @@ reconfig(cleanup, _Config) ->
file_opts(Config) ->
Dir = ?config(priv_dir,Config),
Log = filename:join(Dir, lists:concat([?FUNCTION_NAME,".log"])),
- BadFileOpts = [raw],
- BadType = {file,Log,BadFileOpts},
- {error,{handler_not_added,{{open_failed,Log,enoent},_}}} =
- logger:add_handler(?MODULE, logger_std_h,
- #{config => #{type => BadType}}),
+ MissingOpts = [raw],
+ Type1 = {file,Log,MissingOpts},
+ ok = logger:add_handler(?MODULE, logger_std_h,
+ #{config => #{type => Type1}}),
+ {ok,#{config:=#{type:=file,file:=Log,modes:=Modes1}}} =
+ logger:get_handler_config(?MODULE),
+ [append,delayed_write,raw] = lists:sort(Modes1),
+ ok = logger:remove_handler(?MODULE),
OkFileOpts = [raw,append],
OkType = {file,Log,OkFileOpts},
ok = logger:add_handler(?MODULE,
logger_std_h,
- #{config => #{type => OkType},
+ #{config => #{type => OkType}, % old format
filter_default=>log,
filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
formatter=>{?MODULE,self()}}),
- #{type := OkType} = logger_std_h:info(?MODULE),
+ ModOpts = [delayed_write|OkFileOpts],
+ #{cb_state := #{handler_state := #{type:=file,
+ file:=Log,
+ modes:=ModOpts}}} =
+ logger_olp:info(h_proc_name()),
+ {ok,#{config := #{type:=file,
+ file:=Log,
+ modes:=ModOpts}}} = logger:get_handler_config(?MODULE),
+ ok = logger:remove_handler(?MODULE),
+
+ ok = logger:add_handler(?MODULE,
+ logger_std_h,
+ #{config => #{type => file,
+ file => Log,
+ modes => OkFileOpts}, % new format
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+
+ #{cb_state := #{handler_state := #{type:=file,
+ file:=Log,
+ modes:=ModOpts}}} =
+ logger_olp:info(h_proc_name()),
+ {ok,#{config := #{type:=file,
+ file:=Log,
+ modes:=ModOpts}}} =
+ logger:get_handler_config(?MODULE),
logger:notice(M1=?msg,?domain),
?check(M1),
B1 = ?bin(M1),
@@ -526,17 +692,16 @@ sync(Config) ->
Type = {file,Log},
ok = logger:add_handler(?MODULE,
logger_std_h,
- #{config => #{type => Type},
+ #{config => #{type => Type,
+ file_check => 10000},
filter_default=>log,
filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
formatter=>{?MODULE,nl}}),
%% check repeated filesync happens
- start_tracer([{logger_std_h, write_to_dev, 5},
- {logger_std_h, sync_dev, 4},
+ start_tracer([{logger_std_h, write_to_dev, 2},
{file, datasync, 1}],
[{logger_std_h, write_to_dev, <<"first\n">>},
- {logger_std_h, sync_dev},
{file,datasync}]),
logger:notice("first", ?domain),
@@ -544,11 +709,9 @@ sync(Config) ->
check_tracer(filesync_rep_int()*2),
%% check that explicit filesync is only done once
- start_tracer([{logger_std_h, write_to_dev, 5},
- {logger_std_h, sync_dev, 4},
+ start_tracer([{logger_std_h, write_to_dev, 2},
{file, datasync, 1}],
[{logger_std_h, write_to_dev, <<"second\n">>},
- {logger_std_h, sync_dev},
{file,datasync},
{no_more,500}
]),
@@ -561,43 +724,39 @@ sync(Config) ->
%% check that if there's no repeated filesync active,
%% a filesync is still performed when handler goes idle
- logger:set_handler_config(?MODULE, config,
- #{filesync_repeat_interval => no_repeat}),
- no_repeat = maps:get(filesync_repeat_interval, logger_std_h:info(?MODULE)),
- %% The following timer is to make sure the time from last log
- %% ("second") to next ("third") is long enough, so the a flush is
- %% triggered by the idle timeout between "thrid" and "fourth".
- timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
- start_tracer([{logger_std_h, write_to_dev, 5},
- {logger_std_h, sync_dev, 4},
+ ok = logger:update_handler_config(?MODULE, config,
+ #{filesync_repeat_interval => no_repeat}),
+ no_repeat = maps:get(filesync_repeat_interval,
+ maps:get(cb_state, logger_olp:info(h_proc_name()))),
+ start_tracer([{logger_std_h, write_to_dev, 2},
{file, datasync, 1}],
[{logger_std_h, write_to_dev, <<"third\n">>},
- {logger_std_h, sync_dev},
{file,datasync},
{logger_std_h, write_to_dev, <<"fourth\n">>},
- {logger_std_h, sync_dev},
{file,datasync}]),
logger:notice("third", ?domain),
%% wait for automatic filesync
- timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
+ timer:sleep(?IDLE_DETECT_TIME*2),
logger:notice("fourth", ?domain),
%% wait for automatic filesync
- check_tracer(?IDLE_DETECT_TIME_MSEC*2),
+ check_tracer(?IDLE_DETECT_TIME*2),
%% switch repeated filesync on and verify that the looping works
SyncInt = 1000,
WaitT = 4500,
- OneSync = {logger_std_h,handle_cast,repeated_filesync},
- %% receive 1 initial repeated_filesync, then 1 per sec
- start_tracer([{logger_std_h,handle_cast,2}],
- [OneSync || _ <- lists:seq(1, 1 + trunc(WaitT/SyncInt))]),
-
- logger:set_handler_config(?MODULE, config,
- #{filesync_repeat_interval => SyncInt}),
- SyncInt = maps:get(filesync_repeat_interval, logger_std_h:info(?MODULE)),
+ OneSync = {logger_h_common,handle_cast,repeated_filesync},
+ %% receive 1 repeated_filesync per sec
+ start_tracer([{{logger_h_common,handle_cast,2},
+ [{[repeated_filesync,'_'],[],[]}]}],
+ [OneSync || _ <- lists:seq(1, trunc(WaitT/SyncInt))]),
+
+ ok = logger:update_handler_config(?MODULE, config,
+ #{filesync_repeat_interval => SyncInt}),
+ SyncInt = maps:get(filesync_repeat_interval,
+ maps:get(cb_state,logger_olp:info(h_proc_name()))),
timer:sleep(WaitT),
- logger:set_handler_config(?MODULE, config,
- #{filesync_repeat_interval => no_repeat}),
+ ok = logger:update_handler_config(?MODULE, config,
+ #{filesync_repeat_interval => no_repeat}),
check_tracer(100),
ok.
sync(cleanup, _Config) ->
@@ -652,11 +811,9 @@ sync_failure(Config) ->
rpc:call(Node, ?MODULE, set_result, [file_datasync,ok]),
SyncInt = 500,
- ok = rpc:call(Node, logger, set_handler_config,
+ ok = rpc:call(Node, logger, update_handler_config,
[?STANDARD_HANDLER, config,
#{filesync_repeat_interval => SyncInt}]),
- Info = rpc:call(Node, logger_std_h, info, [?STANDARD_HANDLER]),
- SyncInt = maps:get(filesync_repeat_interval, Info),
ok = log_on_remote_node(Node, "Logged1"),
?check_no_log,
@@ -718,7 +875,7 @@ op_switch_to_sync_file(Config) ->
drop_mode_qlen => NumOfReqs+1,
flush_qlen => 2*NumOfReqs,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
%% TRecvPid = start_op_trace(),
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Lines = count_lines(Log),
@@ -747,7 +904,7 @@ op_switch_to_sync_tty(Config) ->
drop_mode_qlen => NumOfReqs+1,
flush_qlen => 2*NumOfReqs,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
ok.
op_switch_to_sync_tty(cleanup, _Config) ->
@@ -770,7 +927,7 @@ op_switch_to_drop_file(Config) ->
flush_qlen =>
Procs*NumOfReqs*Bursts,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
%% It sometimes happens that the handler gets the
%% requests in a slow enough pace so that dropping
%% never occurs. Therefore, lets generate a number of
@@ -807,7 +964,7 @@ op_switch_to_drop_tty(Config) ->
flush_qlen =>
Procs*NumOfReqs+1,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
ok.
op_switch_to_drop_tty(cleanup, _Config) ->
@@ -832,7 +989,7 @@ op_switch_to_flush_file(Config) ->
drop_mode_qlen => 300,
flush_qlen => 300,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 1500,
Procs = 10,
Bursts = 10,
@@ -879,7 +1036,7 @@ op_switch_to_flush_tty(Config) ->
drop_mode_qlen => 100,
flush_qlen => 100,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 1000,
Procs = 100,
send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
@@ -895,7 +1052,7 @@ limit_burst_disabled(Config) ->
burst_limit_window_time => 2000,
drop_mode_qlen => 200,
flush_qlen => 300}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 100,
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Logged = count_lines(Log),
@@ -915,7 +1072,7 @@ limit_burst_enabled_one(Config) ->
burst_limit_window_time => 2000,
drop_mode_qlen => 200,
flush_qlen => 300}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 100,
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Logged = count_lines(Log),
@@ -936,7 +1093,7 @@ limit_burst_enabled_period(Config) ->
burst_limit_window_time => BurstTWin,
drop_mode_qlen => 20000,
flush_qlen => 20001}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
Windows = 3,
Sent = send_burst({t,BurstTWin*Windows}, seq, {chars,79}, notice),
@@ -956,7 +1113,7 @@ kill_disabled(Config) ->
HConfig#{config=>StdHConfig#{overload_kill_enable=>false,
overload_kill_qlen=>10,
overload_kill_mem_size=>100}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
NumOfReqs = 100,
send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
Logged = count_lines(Log),
@@ -977,7 +1134,7 @@ qlen_kill_new(Config) ->
overload_kill_qlen=>10,
overload_kill_mem_size=>Mem0+50000,
overload_kill_restart_after=>RestartAfter}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
MRef = erlang:monitor(process, Pid0),
NumOfReqs = 100,
Procs = 4,
@@ -986,7 +1143,7 @@ qlen_kill_new(Config) ->
receive
{'DOWN', MRef, _, _, Info} ->
case Info of
- {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ {shutdown,{overloaded,QLen,Mem}} ->
ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
killed ->
ct:pal("Slow shutdown, handler process was killed!", [])
@@ -996,7 +1153,7 @@ qlen_kill_new(Config) ->
ok
after
5000 ->
- Info = logger_std_h:info(?MODULE),
+ Info = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info]),
ct:fail("Handler not dead! It should not have survived this!")
end.
@@ -1011,7 +1168,7 @@ qlen_kill_std(_Config) ->
%% File = lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"]),
%% Log = filename:join(Dir, File),
%% Node = start_std_h_on_new_node(Config, ?FUNCTION_NAME, Log),
- %% ok = rpc:call(Node, logger, set_handler_config,
+ %% ok = rpc:call(Node, logger, update_handler_config,
%% [?STANDARD_HANDLER, config,
%% #{overload_kill_enable=>true,
%% overload_kill_qlen=>10,
@@ -1028,7 +1185,7 @@ mem_kill_new(Config) ->
overload_kill_qlen=>50000,
overload_kill_mem_size=>Mem0+500,
overload_kill_restart_after=>RestartAfter}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
MRef = erlang:monitor(process, Pid0),
NumOfReqs = 100,
Procs = 4,
@@ -1037,7 +1194,7 @@ mem_kill_new(Config) ->
receive
{'DOWN', MRef, _, _, Info} ->
case Info of
- {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ {shutdown,{overloaded,QLen,Mem}} ->
ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
killed ->
ct:pal("Slow shutdown, handler process was killed!", [])
@@ -1047,7 +1204,7 @@ mem_kill_new(Config) ->
ok
after
5000 ->
- Info = logger_std_h:info(?MODULE),
+ Info = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info]),
ct:fail("Handler not dead! It should not have survived this!")
end.
@@ -1067,7 +1224,7 @@ restart_after(Config) ->
HConfig#{config=>StdHConfig#{overload_kill_enable=>true,
overload_kill_qlen=>10,
overload_kill_restart_after=>infinity}},
- ok = logger:set_handler_config(?MODULE, NewHConfig1),
+ ok = logger:update_handler_config(?MODULE, NewHConfig1),
MRef1 = erlang:monitor(process, whereis(h_proc_name())),
%% kill handler
send_burst({n,100}, {spawn,4,0}, {chars,79}, notice),
@@ -1078,18 +1235,19 @@ restart_after(Config) ->
ok
after
5000 ->
- Info1 = logger_std_h:info(?MODULE),
+ Info1 = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info1]),
ct:fail("Handler not dead! It should not have survived this!")
end,
-
+
{Log,_,_} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER,
+
NewHConfig2 =
HConfig#{config=>StdHConfig#{overload_kill_enable=>true,
overload_kill_qlen=>10,
overload_kill_restart_after=>RestartAfter}},
- ok = logger:set_handler_config(?MODULE, NewHConfig2),
+ ok = logger:update_handler_config(?MODULE, NewHConfig2),
Pid0 = whereis(h_proc_name()),
MRef2 = erlang:monitor(process, Pid0),
%% kill handler
@@ -1102,7 +1260,7 @@ restart_after(Config) ->
ok
after
5000 ->
- Info2 = logger_std_h:info(?MODULE),
+ Info2 = logger_olp:info(h_proc_name()),
ct:pal("Handler state = ~p", [Info2]),
ct:fail("Handler not dead! It should not have survived this!")
end,
@@ -1123,12 +1281,16 @@ handler_requests_under_load(Config) ->
drop_mode_qlen => 1000,
flush_qlen => 2000,
burst_limit_enable => false}},
- ok = logger:set_handler_config(?MODULE, NewHConfig),
- Pid = spawn_link(fun() -> send_requests(?MODULE, 1, [{filesync,[]},
- {info,[]},
- {reset,[]},
- {change_config,[]}])
- end),
+ ok = logger:update_handler_config(?MODULE, NewHConfig),
+ Pid = spawn_link(
+ fun() -> send_requests(1,[{logger_std_h,filesync,[?MODULE],[]},
+ {logger_olp,info,[h_proc_name()],[]},
+ {logger_olp,reset,[h_proc_name()],[]},
+ {logger,update_handler_config,
+ [?MODULE, config,
+ #{overload_kill_enable => false}],
+ []}])
+ end),
Sent = send_burst({t,10000}, seq, {chars,79}, notice),
Pid ! {self(),finish},
ReqResult = receive {Pid,Result} -> Result end,
@@ -1139,41 +1301,390 @@ handler_requests_under_load(Config) ->
[E || E <- Res,
is_tuple(E) andalso (element(1,E) == error)]
end,
- Errors = [{Req,FindError(Res)} || {Req,Res} <- ReqResult],
- NoOfReqs = lists:foldl(fun({_,Res}, N) -> N + length(Res) end, 0, ReqResult),
+ Errors = [{Func,FindError(Res)} || {_,Func,_,Res} <- ReqResult],
+ NoOfReqs = lists:foldl(fun({_,_,_,Res}, N) -> N + length(Res) end,
+ 0, ReqResult),
ct:pal("~w requests made. Errors: ~n~p", [NoOfReqs,Errors]),
ok = file_delete(Log).
handler_requests_under_load(cleanup, _Config) ->
ok = stop_handler(?MODULE).
-send_requests(HName, TO, Reqs = [{Req,Res}|Rs]) ->
+recreate_deleted_log(Config) ->
+ {Log,_HConfig,_StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ logger:notice("first",?domain),
+ logger_std_h:filesync(?MODULE),
+ ok = file:rename(Log,Log++".old"),
+ logger:notice("second",?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,<<"first\n">>} = file:read_file(Log++".old"),
+ {ok,<<"second\n">>} = file:read_file(Log),
+ ok.
+recreate_deleted_log(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+reopen_changed_log(Config) ->
+ {Log,_HConfig,_StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ logger:notice("first",?domain),
+ logger_std_h:filesync(?MODULE),
+ ok = file:rename(Log,Log++".old"),
+ ok = file:write_file(Log,""),
+ logger:notice("second",?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,<<"first\n">>} = file:read_file(Log++".old"),
+ {ok,<<"second\n">>} = file:read_file(Log),
+ ok.
+reopen_changed_log(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+rotate_size(Config) ->
+ {Log,_HConfig,_StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ok = logger:update_handler_config(?MODULE,#{config=>#{max_no_bytes=>1000,
+ max_no_files=>2}}),
+
+ Str = lists:duplicate(19,$a),
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,50)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=1000}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+
+ logger:notice(Str,?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=1020}} = file:read_file_info(Log++".0"),
+ {error,enoent} = file:read_file_info(Log++".1"),
+
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,51)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=1020}} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=1020}} = file:read_file_info(Log++".1"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,50)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=1000}} = file:read_file_info(Log),
+ {ok,#file_info{size=1020}} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=1020}} = file:read_file_info(Log++".1"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+
+ logger:notice("bbbb",?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=1005}} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=1020}} = file:read_file_info(Log++".1"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+
+ ok.
+rotate_size(cleanup,_Config) ->
+ ok = stop_handler(?MODULE).
+
+rotate_size_compressed(Config) ->
+ {Log,_HConfig,_StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ok = logger:update_handler_config(?MODULE,
+ #{config=>#{max_no_bytes=>1000,
+ max_no_files=>2,
+ compress_on_rotate=>true}}),
+ Str = lists:duplicate(19,$a),
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,50)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=1000}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+ {error,enoent} = file:read_file_info(Log++".0.gz"),
+
+ logger:notice(Str,?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=35}} = file:read_file_info(Log++".0.gz"),
+ {error,enoent} = file:read_file_info(Log++".1"),
+ {error,enoent} = file:read_file_info(Log++".1.gz"),
+
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,51)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=35}} = file:read_file_info(Log++".0.gz"),
+ {error,enoent} = file:read_file_info(Log++".1"),
+ {ok,#file_info{size=35}} = file:read_file_info(Log++".1.gz"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+ {error,enoent} = file:read_file_info(Log++".2.gz"),
+
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,50)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=1000}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=35}} = file:read_file_info(Log++".0.gz"),
+ {error,enoent} = file:read_file_info(Log++".1"),
+ {ok,#file_info{size=35}} = file:read_file_info(Log++".1.gz"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+ {error,enoent} = file:read_file_info(Log++".2.gz"),
+
+ logger:notice("bbbb",?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=38}} = file:read_file_info(Log++".0.gz"),
+ {error,enoent} = file:read_file_info(Log++".1"),
+ {ok,#file_info{size=35}} = file:read_file_info(Log++".1.gz"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+ {error,enoent} = file:read_file_info(Log++".2.gz"),
+
+ ok.
+rotate_size_compressed(cleanup,_Config) ->
+ ok = stop_handler(?MODULE).
+
+rotate_size_reopen(Config) ->
+ {Log,_HConfig,_StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ok = logger:update_handler_config(?MODULE,#{config=>#{max_no_bytes=>1000,
+ max_no_files=>2}}),
+
+ Str = lists:duplicate(19,$a),
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,40)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=800}} = file:read_file_info(Log),
+
+ {ok,HConfig} = logger:get_handler_config(?MODULE),
+ ok = logger:remove_handler(?MODULE),
+ ok = logger:add_handler(?MODULE,maps:get(module,HConfig),HConfig),
+ {ok,#file_info{size=800}} = file:read_file_info(Log),
+
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,40)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=580}} = file:read_file_info(Log),
+ {ok,#file_info{size=1020}} = file:read_file_info(Log++".0"),
+ ok.
+rotate_size_reopen(cleanup,_Config) ->
+ ok = stop_handler(?MODULE).
+
+rotation_opts(Config) ->
+ {Log,_HConfig,StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ #{max_no_bytes:=infinity,
+ max_no_files:=0,
+ compress_on_rotate:=false} = StdHConfig,
+
+ %% Test bad rotation config
+ {error,{invalid_config,_,_}} =
+ logger:update_handler_config(?MODULE,config,#{max_no_bytes=>0}),
+ {error,{invalid_config,_,_}} =
+ logger:update_handler_config(?MODULE,config,#{max_no_files=>infinity}),
+ {error,{invalid_config,_,_}} =
+ logger:update_handler_config(?MODULE,config,
+ #{compress_on_rotate=>undefined}),
+
+
+ %% Test good rotation config - start with no rotation
+ Str = lists:duplicate(19,$a),
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,10)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=200}} = file:read_file_info(Log),
+ [] = filelib:wildcard(Log++".*"),
+
+ %% Turn on rotation, check that existing file is rotated since its
+ %% size exceeds max_no_bytes
+ ok = logger:update_handler_config(?MODULE,
+ config,
+ #{max_no_bytes=>100,
+ max_no_files=>2}),
+ timer:sleep(100), % give some time to execute config_changed
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ Log0 = Log++".0",
+ {ok,#file_info{size=200}} = file:read_file_info(Log0),
+ [Log0] = filelib:wildcard(Log++".*"),
+
+ %% Fill all logs
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,13)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=20}} = file:read_file_info(Log),
+ {ok,#file_info{size=120}} = file:read_file_info(Log0),
+ {ok,#file_info{size=120}} = file:read_file_info(Log++".1"),
+ [_,_] = filelib:wildcard(Log++".*"),
+
+ %% Extend size and count and check that nothing changes with existing files
+ ok = logger:update_handler_config(?MODULE,
+ config,
+ #{max_no_bytes=>200,
+ max_no_files=>3}),
+ timer:sleep(100), % give some time to execute config_changed
+ {ok,#file_info{size=20}} = file:read_file_info(Log),
+ {ok,#file_info{size=120}} = file:read_file_info(Log0),
+ {ok,#file_info{size=120}} = file:read_file_info(Log++".1"),
+ [_,_] = filelib:wildcard(Log++".*"),
+
+ %% Add more log events and see that extended size and count works
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,10)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=220}} = file:read_file_info(Log0),
+ {ok,#file_info{size=120}} = file:read_file_info(Log++".1"),
+ {ok,#file_info{size=120}} = file:read_file_info(Log++".2"),
+ [_,_,_] = filelib:wildcard(Log++".*"),
+
+ %% Reduce count and check that archive files that exceed the new
+ %% count are moved
+ ok = logger:update_handler_config(?MODULE,
+ config,
+ #{max_no_files=>1}),
+ timer:sleep(100), % give some time to execute config_changed
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=220}} = file:read_file_info(Log0),
+ [Log0] = filelib:wildcard(Log++".*"),
+
+ %% Extend size and count again, and turn on compression. Check
+ %% that archives are compressed
+ ok = logger:update_handler_config(?MODULE,
+ config,
+ #{max_no_bytes=>100,
+ max_no_files=>2,
+ compress_on_rotate=>true}),
+ timer:sleep(100), % give some time to execute config_changed
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ Log0gz = Log0++".gz",
+ {ok,#file_info{size=29}} = file:read_file_info(Log0gz),
+ [Log0gz] = filelib:wildcard(Log++".*"),
+
+ %% Fill all logs
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,13)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=20}} = file:read_file_info(Log),
+ {ok,#file_info{size=29}} = file:read_file_info(Log0gz),
+ {ok,#file_info{size=29}} = file:read_file_info(Log++".1.gz"),
+ [_,_] = filelib:wildcard(Log++".*"),
+
+ %% Reduce count and turn off compression. Check that archives that
+ %% exceeds the new count are removed, and the rest are
+ %% uncompressed.
+ ok = logger:update_handler_config(?MODULE,
+ config,
+ #{max_no_files=>1,
+ compress_on_rotate=>false}),
+ timer:sleep(100), % give some time to execute config_changed
+ {ok,#file_info{size=20}} = file:read_file_info(Log),
+ {ok,#file_info{size=120}} = file:read_file_info(Log0),
+ [Log0] = filelib:wildcard(Log++".*"),
+
+ %% Check that config and handler state agree on the current rotation settings
+ {ok,#{config:=#{max_no_bytes:=100,
+ max_no_files:=1,
+ compress_on_rotate:=false}}} =
+ logger:get_handler_config(?MODULE),
+ #{cb_state:=#{handler_state:=#{max_no_bytes:=100,
+ max_no_files:=1,
+ compress_on_rotate:=false}}} =
+ logger_olp:info(h_proc_name()),
+ ok.
+rotation_opts(cleanup,_Config) ->
+ ok = stop_handler(?MODULE).
+
+rotation_opts_restart_handler(Config) ->
+ {Log,_HConfig,_StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ok = logger:update_handler_config(?MODULE,
+ config,
+ #{max_no_bytes=>100,
+ max_no_files=>2}),
+
+ %% Fill all logs
+ Str = lists:duplicate(19,$a),
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,15)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=60}} = file:read_file_info(Log),
+ {ok,#file_info{size=120}} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=120}} = file:read_file_info(Log++".1"),
+ [_,_] = filelib:wildcard(Log++".*"),
+
+ %% Stop/start handler and turn off rotation. Check that archives are removed.
+ {ok,#{config:=StdHConfig1}=HConfig1} = logger:get_handler_config(?MODULE),
+ ok = logger:remove_handler(?MODULE),
+ ok = logger:add_handler(
+ ?MODULE,logger_std_h,
+ HConfig1#{config=>StdHConfig1#{max_no_bytes=>infinity}}),
+ timer:sleep(100),
+ {ok,#file_info{size=60}} = file:read_file_info(Log),
+ [] = filelib:wildcard(Log++".*"),
+
+ %% Add some log events and check that file is no longer rotated.
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,10)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=260}} = file:read_file_info(Log),
+ [] = filelib:wildcard(Log++".*"),
+
+ %% Stop/start handler and trun on rotation. Check that file is rotated.
+ {ok,#{config:=StdHConfig2}=HConfig2} = logger:get_handler_config(?MODULE),
+ ok = logger:remove_handler(?MODULE),
+ ok = logger:add_handler(
+ ?MODULE,logger_std_h,
+ HConfig2#{config=>StdHConfig2#{max_no_bytes=>100,
+ max_no_files=>2}}),
+ timer:sleep(100),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=260}} = file:read_file_info(Log++".0"),
+ [_] = filelib:wildcard(Log++".*"),
+
+ %% Fill all logs
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,10)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=80}} = file:read_file_info(Log),
+ {ok,#file_info{size=120}} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=260}} = file:read_file_info(Log++".1"),
+
+ %% Stop/start handler, reduce count and turn on compression. Check
+ %% that excess archives are removed, and the rest compressed.
+ {ok,#{config:=StdHConfig3}=HConfig3} = logger:get_handler_config(?MODULE),
+ ok = logger:remove_handler(?MODULE),
+ ok = logger:add_handler(
+ ?MODULE,logger_std_h,
+ HConfig3#{config=>StdHConfig3#{max_no_bytes=>75,
+ max_no_files=>1,
+ compress_on_rotate=>true}}),
+ timer:sleep(100),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=29}} = file:read_file_info(Log++".0.gz"),
+ [_] = filelib:wildcard(Log++".*"),
+
+ %% Stop/start handler and turn off compression. Check that achives
+ %% are decompressed.
+ {ok,#{config:=StdHConfig4}=HConfig4} = logger:get_handler_config(?MODULE),
+ ok = logger:remove_handler(?MODULE),
+ ok = logger:add_handler(
+ ?MODULE,logger_std_h,
+ HConfig4#{config=>StdHConfig4#{compress_on_rotate=>false}}),
+ timer:sleep(100),
+ {ok,#file_info{size=0}} = file:read_file_info(Log),
+ {ok,#file_info{size=80}} = file:read_file_info(Log++".0"),
+ [_] = filelib:wildcard(Log++".*"),
+
+ ok.
+rotation_opts_restart_handler(cleanup,_Config) ->
+ ok = stop_handler(?MODULE).
+
+%%%-----------------------------------------------------------------
+%%%
+send_requests(TO, Reqs = [{Mod,Func,Args,Res}|Rs]) ->
receive
{From,finish} ->
From ! {self(),Reqs}
after
TO ->
- Result =
- case Req of
- change_config ->
- logger:set_handler_config(HName, config,
- #{overload_kill_enable =>
- false});
- Func ->
- logger_std_h:Func(HName)
- end,
- send_requests(HName, TO, Rs ++ [{Req,[Result|Res]}])
+ Result = apply(Mod,Func,Args),
+ send_requests(TO, Rs ++ [{Mod,Func,Args,[Result|Res]}])
end.
%%%-----------------------------------------------------------------
%%%
-start_handler(Name, TTY, Config) when TTY == standard_io;
- TTY == standard_error->
+start_handler(Name, TTY, _Config) when TTY == standard_io;
+ TTY == standard_error->
ok = logger:add_handler(Name,
logger_std_h,
#{config => #{type => TTY},
- filter_default=>log,
- filters=>?DEFAULT_HANDLER_FILTERS([Name]),
+ filter_default=>stop,
+ filters=>filter_only_this_domain(Name),
formatter=>{?MODULE,op}}),
{ok,HConfig = #{config := StdHConfig}} = logger:get_handler_config(Name),
{HConfig,StdHConfig};
@@ -1187,12 +1698,17 @@ start_handler(Name, FuncName, Config) ->
ok = logger:add_handler(Name,
logger_std_h,
#{config => #{type => Type},
- filter_default=>log,
- filters=>?DEFAULT_HANDLER_FILTERS([Name]),
+ filter_default=>stop,
+ filters=>filter_only_this_domain(Name),
formatter=>{?MODULE,op}}),
{ok,HConfig = #{config := StdHConfig}} = logger:get_handler_config(Name),
{Log,HConfig,StdHConfig}.
+
+filter_only_this_domain(Name) ->
+ [{remote_gl,{fun logger_filters:remote_gl/2,stop}},
+ {domain,{fun logger_filters:domain/2,{log,super,[Name]}}}].
+
stop_handler(Name) ->
R = logger:remove_handler(Name),
ct:pal("Handler ~p stopped! Result: ~p", [Name,R]),
@@ -1422,7 +1938,7 @@ start_op_trace() ->
{ok,_} = dbg:p(self(), [c]),
MS1 = dbg:fun2ms(fun([_]) -> return_trace() end),
- {ok,_} = dbg:tp(logger_h_common, check_load, 1, MS1),
+ {ok,_} = dbg:tpl(logger_h_common, check_load, 1, MS1),
{ok,_} = dbg:tpl(logger_h_common, flush_log_requests, 2, []),
@@ -1496,7 +2012,10 @@ analyse(Msgs) ->
start_tracer(Trace,Expected) ->
Pid = self(),
- FileCtrlPid = maps:get(file_ctrl_pid, logger_std_h:info(?MODULE)),
+ FileCtrlPid = maps:get(file_ctrl_pid,
+ maps:get(handler_state,
+ maps:get(cb_state,
+ logger_olp:info(h_proc_name())))),
dbg:tracer(process,{fun tracer/2,{Pid,Expected}}),
dbg:p(whereis(h_proc_name()),[c]),
dbg:p(FileCtrlPid,[c]),
@@ -1504,7 +2023,9 @@ start_tracer(Trace,Expected) ->
ok.
tpl([{M,F,A}|Trace]) ->
- {ok,Match} = dbg:tpl(M,F,A,[]),
+ tpl([{{M,F,A},[]}|Trace]);
+tpl([{{M,F,A},MS}|Trace]) ->
+ {ok,Match} = dbg:tpl(M,F,A,MS),
case lists:keyfind(matched,1,Match) of
{_,_,1} ->
ok;
@@ -1517,10 +2038,10 @@ tpl([{M,F,A}|Trace]) ->
tpl([]) ->
ok.
-tracer({trace,_,call,{logger_std_h,handle_cast,[Op|_]}},
+tracer({trace,_,call,{logger_h_common,handle_cast,[Op|_]}},
{Pid,[{Mod,Func,Op}|Expected]}) ->
maybe_tracer_done(Pid,Expected,{Mod,Func,Op});
-tracer({trace,_,call,{Mod=logger_std_h,Func=write_to_dev,[_,Data,_,_,_]}},
+tracer({trace,_,call,{Mod=logger_std_h,Func=write_to_dev,[Data,_]}},
{Pid,[{Mod,Func,Data}|Expected]}) ->
maybe_tracer_done(Pid,Expected,{Mod,Func,Data});
tracer({trace,_,call,{Mod,Func,_}}, {Pid,[{Mod,Func}|Expected]}) ->
@@ -1570,27 +2091,29 @@ h_proc_name() ->
h_proc_name(Name) ->
?name_to_reg_name(logger_std_h,Name).
-file_delete(Log) ->
- file:delete(Log).
-
wait_for_process_up(T) ->
- wait_for_process_up(h_proc_name(),T).
+ wait_for_process_up(?MODULE, h_proc_name(), T).
-wait_for_process_up(Name,T) ->
+wait_for_process_up(Name, RegName, T) ->
N = (T div 500) + 1,
- wait_for_process_up1(Name,N).
+ wait_for_process_up1(Name, RegName, N).
-wait_for_process_up1(_Name,0) ->
+wait_for_process_up1(_Name, _RegName, 0) ->
error;
-wait_for_process_up1(Name,N) ->
+wait_for_process_up1(Name, RegName, N) ->
timer:sleep(500),
- case whereis(Name) of
+ case whereis(RegName) of
Pid when is_pid(Pid) ->
- %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
- {ok,Pid};
+ case logger:get_handler_config(Name) of
+ {ok,_} ->
+ %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
+ {ok,Pid};
+ _ ->
+ wait_for_process_up1(Name, RegName, N-1)
+ end;
undefined ->
%% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]),
- wait_for_process_up1(Name,N-1)
+ wait_for_process_up1(Name, RegName, N-1)
end.
filesync_rep_int() ->
@@ -1598,3 +2121,7 @@ filesync_rep_int() ->
true -> 5500;
false -> ?FILESYNC_REPEAT_INTERVAL + 500
end.
+
+
+file_delete(Log) ->
+ file:delete(Log).
diff --git a/lib/kernel/test/logger_stress_SUITE.erl b/lib/kernel/test/logger_stress_SUITE.erl
new file mode 100644
index 0000000000..1a278fb1b2
--- /dev/null
+++ b/lib/kernel/test/logger_stress_SUITE.erl
@@ -0,0 +1,550 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_stress_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct_event.hrl").
+-include_lib("kernel/include/logger.hrl").
+-include_lib("kernel/src/logger_h_common.hrl").
+
+-ifdef(SAVE_STATS).
+ -define(COLLECT_STATS(_All_,_Procs_),
+ ct:pal("~p",[stats(_All_,_Procs_)])).
+-else.
+ -define(COLLECT_STATS(_All_,_Procs__), ok).
+-endif.
+
+-define(TEST_DURATION,120). % seconds
+
+suite() ->
+ [{timetrap,{minutes,3}},
+ {ct_hooks,[logger_test_lib]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [allow_events,
+ reject_events,
+ std_handler,
+ disk_log_handler,
+ std_handler_time,
+ std_handler_time_big,
+ disk_log_handler_time,
+ disk_log_handler_time_big,
+ emulator_events,
+ remote_events,
+ remote_to_disk_log,
+ remote_emulator_events,
+ remote_emulator_to_disk_log].
+
+%%%-----------------------------------------------------------------
+%%% Test cases
+%%%-----------------------------------------------------------------
+%% Time from log macro call to handler callback
+allow_events(Config) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(Config,
+ [{logger,
+ [{handler,default,?MODULE,#{}}]},
+ {logger_level,notice}]),
+ N = 100000,
+ {T,_} = timer:tc(fun() -> rpc:call(Node,?MODULE,nlogs,[N]) end),
+ IOPS = N * 1000/T, % log events allowed per millisecond
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{value,IOPS}]}),
+ {comment,io_lib:format("~.2f accepted events pr millisecond",
+ [IOPS])}.
+
+%% Time from log macro call to reject (log level)
+reject_events(Config) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(Config,
+ [{logger,
+ [{handler,default,?MODULE,#{}}]},
+ {logger_level,error}]),
+ N = 1000000,
+ {T,_} = timer:tc(fun() -> rpc:call(Node,?MODULE,nlogs,[N]) end),
+ IOPS = N * 1000/T, % log events rejected per millisecond
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{value,IOPS}]}),
+ {comment,io_lib:format("~.2f rejected events pr millisecond",
+ [IOPS])}.
+
+%% Cascading failure that produce gen_server and proc_lib reports -
+%% how many of the produced log events are actually written to a log
+%% with logger_std_h file handler.
+std_handler(Config) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(Config,
+ [{logger,
+ [{handler,default,logger_std_h,
+ #{config=>#{type=>{file,"default.log"}}}}]}]),
+
+ cascade({Node,{logger_backend,log_allowed,2},[]},
+ {Node,{logger_std_h,write,4},[{default,logger_std_h_default}]},
+ fun otp_cascading/0).
+std_handler(cleanup,_Config) ->
+ _ = file:delete("default.log"),
+ ok.
+
+%% Disable overload protection and just print a lot - measure time.
+%% The IOPS reported is the number of log events written per millisecond.
+std_handler_time(Config) ->
+ measure_handler_time(logger_std_h,#{type=>{file,"default.log"}},Config).
+std_handler_time(cleanup,_Config) ->
+ _ = file:delete("default.log"),
+ ok.
+
+std_handler_time_big(Config) ->
+ measure_handler_time_big(logger_std_h,#{type=>{file,"default.log"}},Config).
+std_handler_time_big(cleanup,_Config) ->
+ _ = file:delete("default.log"),
+ ok.
+
+%% Cascading failure that produce gen_server and proc_lib reports -
+%% how many of the produced log events are actually written to a log
+%% with logger_disk_log_h wrap file handler.
+disk_log_handler(Config) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(Config,
+ [{logger,
+ [{handler,default,logger_disk_log_h,#{}}]}]),
+ cascade({Node,{logger_backend,log_allowed,2},[]},
+ {Node,{logger_disk_log_h,write,4},
+ [{default,logger_disk_log_h_default}]},
+ fun otp_cascading/0).
+disk_log_handler(cleanup,_Config) ->
+ Files = filelib:wildcard("default.log.*"),
+ [_ = file:delete(F) || F <- Files],
+ ok.
+
+%% Disable overload protection and just print a lot - measure time.
+%% The IOPS reported is the number of log events written per millisecond.
+disk_log_handler_time(Config) ->
+ measure_handler_time(logger_disk_log_h,#{type=>halt},Config).
+disk_log_handler_time(cleanup,_Config) ->
+ _ = file:delete("default"),
+ ok.
+
+disk_log_handler_time_big(Config) ->
+ measure_handler_time_big(logger_disk_log_h,#{type=>halt},Config).
+disk_log_handler_time_big(cleanup,_Config) ->
+ _ = file:delete("default"),
+ ok.
+
+%% Cascading failure that produce log events from the emulator - how
+%% many of the produced log events pass through the proxy.
+emulator_events(Config) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(Config,
+ [{logger,
+ [{handler,default,?MODULE,#{}}]}]),
+ cascade({Node,{?MODULE,producer,0},[]},
+ {Node,{?MODULE,log,2},[{proxy,logger_proxy}]},
+ fun em_cascading/0).
+
+%% Cascading failure that produce gen_server and proc_lib reports on
+%% remote node - how many of the produced log events pass through the
+%% proxy.
+remote_events(Config) ->
+ {ok,_,Node1} =
+ logger_test_lib:setup([{postfix,1}|Config],
+ [{logger,
+ [{handler,default,?MODULE,#{}}]}]),
+ {ok,_,Node2} =
+ logger_test_lib:setup([{postfix,2}|Config],[]),
+ cascade({Node2,{logger_backend,log_allowed,2},[{remote_proxy,logger_proxy}]},
+ {Node1,{?MODULE,log,2},[{local_proxy,logger_proxy}]},
+ fun otp_cascading/0).
+
+%% Cascading failure that produce gen_server and proc_lib reports on
+%% remote node - how many of the produced log events are actually
+%% written to a log with logger_disk_log_h wrap file handler.
+remote_to_disk_log(Config) ->
+ {ok,_,Node1} =
+ logger_test_lib:setup([{postfix,1}|Config],
+ [{logger,
+ [{handler,default,logger_disk_log_h,#{}}]}]),
+ {ok,_,Node2} =
+ logger_test_lib:setup([{postfix,2}|Config],[]),
+ cascade({Node2,{logger_backend,log_allowed,2},[{remote_proxy,logger_proxy}]},
+ {Node1,{logger_disk_log_h,write,4},
+ [{local_proxy,logger_proxy},
+ {local_default,logger_disk_log_h_default}]},
+ fun otp_cascading/0).
+remote_to_disk_log(cleanup,_Config) ->
+ Files = filelib:wildcard("default.log.*"),
+ [_ = file:delete(F) || F <- Files],
+ ok.
+
+%% Cascading failure that produce log events from the emulator on
+%% remote node - how many of the produced log events pass through the
+%% proxy.
+remote_emulator_events(Config) ->
+ {ok,_,Node1} =
+ logger_test_lib:setup([{postfix,1}|Config],
+ [{logger,
+ [{handler,default,?MODULE,#{}}]}]),
+ {ok,_,Node2} =
+ logger_test_lib:setup([{postfix,2}|Config],[]),
+ cascade({Node2,{?MODULE,producer,0},[{remote_proxy,logger_proxy}]},
+ {Node1,{?MODULE,log,2},[{local_proxy,logger_proxy}]},
+ fun em_cascading/0).
+
+%% Cascading failure that produce log events from the emulator on
+%% remote node - how many of the produced log events are actually
+%% written to a log with logger_disk_log_h wrap file handler.
+remote_emulator_to_disk_log(Config) ->
+ {ok,_,Node1} =
+ logger_test_lib:setup([{postfix,1}|Config],
+ [{logger,
+ [{handler,default,logger_disk_log_h,#{}}]}]),
+ {ok,_,Node2} =
+ logger_test_lib:setup([{postfix,2}|Config],[]),
+ cascade({Node2,{?MODULE,producer,0},[{remote_proxy,logger_proxy}]},
+ {Node1,{logger_disk_log_h,write,4},
+ [{local_proxy,logger_proxy},
+ {local_default,logger_disk_log_h_default}]},
+ fun em_cascading/0).
+remote_emulator_to_disk_log(cleanup,_Config) ->
+ Files = filelib:wildcard("default.log.*"),
+ [_ = file:delete(F) || F <- Files],
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+measure_handler_time(Module,HCfg,Config) ->
+ measure_handler_time(Module,100000,small_fa(),millisecond,HCfg,#{},Config).
+
+measure_handler_time_big(Module,HCfg,Config) ->
+ FCfg = #{chars_limit=>4096, max_size=>1024},
+ measure_handler_time(Module,100,big_fa(),second,HCfg,FCfg,Config).
+
+measure_handler_time(Module,N,FA,Unit,HCfg,FCfg,Config) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(
+ Config,
+ [{logger,
+ [{handler,default,Module,
+ #{formatter => {logger_formatter,
+ maps:merge(#{legacy_header=>false,
+ single_line=>true},FCfg)},
+ config=>maps:merge(#{sync_mode_qlen => N+1,
+ drop_mode_qlen => N+1,
+ flush_qlen => N+1,
+ burst_limit_enable => false,
+ filesync_repeat_interval => no_repeat},
+ HCfg)}}]}]),
+ %% HPid = rpc:call(Node,erlang,whereis,[?name_to_reg_name(Module,default)]),
+ %% {links,[_,FCPid]} = rpc:call(Node,erlang,process_info,[HPid,links]),
+ T0 = erlang:monotonic_time(millisecond),
+ ok = rpc:call(Node,?MODULE,nlogs_wait,[N,FA,Module]),
+ %% ok = rpc:call(Node,fprof,apply,[fun ?MODULE:nlogs_wait/2,[N div 10,FA,Module],[{procs,[HPid,FCPid]}]]),
+ T1 = erlang:monotonic_time(millisecond),
+ T = T1-T0,
+ M = case Unit of
+ millisecond -> 1;
+ second -> 1000
+ end,
+ IOPS = M*N/T,
+ ct:pal("N: ~p~nT: ~p~nIOPS: ~.2f events pr ~w",[N,T,IOPS,Unit]),
+ %% Stats = rpc:call(Node,logger_olp,info,[?name_to_reg_name(Module,default)]),
+ %% ct:pal("Stats: ~p",[Stats]),
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{value,IOPS}]}),
+ {comment,io_lib:format("~.2f events written pr ~w",[IOPS,Unit])}.
+
+nlogs_wait(N,{F,A},Module) ->
+ group_leader(whereis(user),self()),
+ [?LOG_NOTICE(F,A) || _ <- lists:seq(1,N)],
+ wait(Module).
+
+wait(Module) ->
+ case Module:filesync(default) of
+ {error,handler_busy} ->
+ wait(Module);
+ ok ->
+ ok
+ end.
+
+small_fa() ->
+ Str = "\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "[\\]^_`abcdefghijklmnopqr",
+ {"~ts",[Str]}.
+
+big_fa() ->
+ {"~p",[lists:duplicate(1048576,"a")]}.
+
+nlogs(N) ->
+ group_leader(whereis(user),self()),
+ Str = "\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "[\\]^_`abcdefghijklmnopqr",
+ [?LOG_NOTICE(Str) || _ <- lists:seq(1,N)],
+ ok.
+
+%% cascade(ProducerInfo,ConsumerInfo,TestFun)
+cascade({PNode,PMFA,_PStatProcs},{CNode,CMFA,_CStatProcs},TestFun) ->
+ Tab = ets:new(counter,[set,public]),
+ ets:insert(Tab,{producer,0}),
+ ets:insert(Tab,{consumer,0}),
+ dbg:tracer(process,{fun tracer/2,{Tab,PNode,CNode}}),
+ dbg:n(PNode),
+ dbg:n(CNode),
+ dbg:cn(node()),
+ dbg:p(all,[call,arity]),
+ dbg:tpl(PMFA,[]),
+ dbg:tpl(CMFA,[]),
+
+ Pid = rpc:call(CNode,?MODULE,wrap_test,[PNode,TestFun]),
+ MRef = erlang:monitor(process,Pid),
+ TO = ?TEST_DURATION*1000,
+ receive {'DOWN',MRef,_,_,Reason} ->
+ ct:fail({remote_pid_down,Reason})
+ after TO ->
+ All = ets:lookup_element(Tab,producer,2),
+ Written = ets:lookup_element(Tab,consumer,2),
+ dbg:stop_clear(),
+ ?COLLECT_STATS(All,
+ [{PNode,P,Id} || {Id,P} <- _PStatProcs] ++
+ [{CNode,P,Id} || {Id,P} <- _CStatProcs]),
+ Ratio = Written/All * 100,
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{value,Ratio}]}),
+ {comment,io_lib:format("~p % (~p written, ~p produced)",
+ [round(Ratio),Written,All])}
+ end.
+
+wrap_test(Fun) ->
+ wrap_test(node(),Fun).
+wrap_test(Node,Fun) ->
+ reset(),
+ group_leader(whereis(user),self()),
+ rpc:call(Node,?MODULE,do_fun,[Fun]).
+
+do_fun(Fun) ->
+ reset(),
+ Fun().
+
+reset() ->
+ reset([logger_std_h_default, logger_disk_log_h_default, logger_proxy]).
+reset([P|Ps]) ->
+ is_pid(whereis(P)) andalso logger_olp:reset(P),
+ reset(Ps);
+reset([]) ->
+ ok.
+
+
+tracer({trace,_,call,{?MODULE,producer,_}},{Tab,_PNode,_CNode}=S) ->
+ ets:update_counter(Tab,producer,1),
+ S;
+tracer({trace,Pid,call,{logger_backend,log_allowed,_}},{Tab,PNode,_CNode}=S) when node(Pid)=:=PNode ->
+ ets:update_counter(Tab,producer,1),
+ S;
+tracer({trace,_,call,{?MODULE,log,_}},{Tab,_PNode,_CNode}=S) ->
+ ets:update_counter(Tab,consumer,1),
+ S;
+tracer({trace,_,call,{_,write,_}},{Tab,_PNode,_CNode}=S) ->
+ ets:update_counter(Tab,consumer,1),
+ S;
+tracer(_,S) ->
+ S.
+
+
+%%%-----------------------------------------------------------------
+%%% Collect statistics
+-define(STAT_KEYS,
+ [burst_drops,
+ calls,
+ casts,
+ drops,
+ flushed,
+ flushes,
+ freq,
+ last_qlen,
+ max_qlen,
+ time,
+ writes]).
+-define(EVENT_KEYS,
+ [calls,casts,flushed]).
+
+stats(All,Procs) ->
+ NI = [{Id,rpc:call(N,logger_olp,info,[P])} || {N,P,Id}<-Procs],
+ [{all,All}|[stats(Id,I,All) || {Id,I} <- NI]].
+
+stats(Id,Info,All) ->
+ S = maps:with(?STAT_KEYS,Info),
+ AllOnProc = lists:sum(maps:values(maps:with(?EVENT_KEYS,S))),
+ if All>0 ->
+ Writes = maps:get(writes,S),
+ {_,ActiveTime} = maps:get(time,S),
+ Rate = round(100*Writes/All),
+ RateOnProc =
+ if AllOnProc>0 ->
+ round(100*Writes/AllOnProc);
+ true ->
+ 0
+ end,
+ AvFreq =
+ if ActiveTime>0 ->
+ round(Writes/ActiveTime);
+ true ->
+ 0
+ end,
+ {Id,
+ {stats,S},
+ {rate,Rate},
+ {rate_on_proc,RateOnProc},
+ {av_freq,AvFreq}};
+ true ->
+ {Id,none}
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Spawn a lot of processes that crash repeatedly, causing a lot of
+%%% error reports from the emulator.
+em_cascading() ->
+ spawn(fun() -> super() end).
+
+super() ->
+ process_flag(trap_exit,true),
+ spawn_link(fun server/0),
+ [spawn_link(fun client/0) || _<-lists:seq(1,10000)],
+ super_loop().
+
+super_loop() ->
+ receive
+ {'EXIT',_,server} ->
+ spawn_link(fun server/0),
+ super_loop();
+ {'EXIT',_,_} ->
+ _L = lists:sum(lists:seq(1,10000)),
+ spawn_link(fun client/0),
+ super_loop()
+ end.
+
+client() ->
+ receive
+ after 1 ->
+ case whereis(server) of
+ Pid when is_pid(Pid) ->
+ ok;
+ undefined ->
+ producer(),
+ erlang:error(some_exception)
+ end
+ end,
+ client().
+
+server() ->
+ register(server,self()),
+ receive
+ after 3000 ->
+ exit(server)
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% Create a supervisor tree with processes that crash repeatedly,
+%%% causing a lot of supervisor reports and crashreports
+otp_cascading() ->
+ {ok,Pid} = supervisor:start_link({local,otp_super}, ?MODULE, [otp_super]),
+ unlink(Pid),
+ Pid.
+
+otp_server_sup() ->
+ supervisor:start_link({local,otp_server_sup},?MODULE,[otp_server_sup]).
+
+otp_client_sup(N) ->
+ supervisor:start_link({local,otp_client_sup},?MODULE,[otp_client_sup,N]).
+
+otp_server() ->
+ gen_server:start_link({local,otp_server},?MODULE,[otp_server],[]).
+
+otp_client() ->
+ gen_server:start_link(?MODULE,[otp_client],[]).
+
+init([otp_super]) ->
+ {ok, {{one_for_one, 200, 10},
+ [{client_sup,
+ {?MODULE, otp_client_sup, [10000]},
+ permanent, 1000, supervisor, [?MODULE]},
+ {server_sup,
+ {?MODULE, otp_server_sup, []},
+ permanent, 1000, supervisor, [?MODULE]}
+ ]}};
+init([otp_server_sup]) ->
+ {ok, {{one_for_one, 2, 10},
+ [{server,
+ {?MODULE, otp_server, []},
+ permanent, 1000, worker, [?MODULE]}
+ ]}};
+init([otp_client_sup,N]) ->
+ spawn(fun() ->
+ [supervisor:start_child(otp_client_sup,[])
+ || _ <- lists:seq(1,N)]
+ end),
+ {ok, {{simple_one_for_one, N*10, 1},
+ [{client,
+ {?MODULE, otp_client, []},
+ permanent, 1000, worker, [?MODULE]}
+ ]}};
+init([otp_server]) ->
+ {ok, server, 10000};
+init([otp_client]) ->
+ {ok, client,1}.
+
+handle_info(timeout, client) ->
+ true = is_pid(whereis(otp_server)),
+ {noreply,client,1};
+handle_info(timeout, server) ->
+ exit(self(), some_error).
+
+%%%-----------------------------------------------------------------
+%%% Logger callbacks
+log(_LogEvent,_Config) ->
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Function to trace on for counting produced emulator messages
+producer() ->
+ ok.
diff --git a/lib/kernel/test/logger_test_lib.erl b/lib/kernel/test/logger_test_lib.erl
index 81eb9ce5eb..be4bc427fb 100644
--- a/lib/kernel/test/logger_test_lib.erl
+++ b/lib/kernel/test/logger_test_lib.erl
@@ -28,11 +28,17 @@
post_end_per_testcase/5, post_end_per_suite/3]).
setup(Config,Vars) ->
+ Postfix = case proplists:get_value(postfix, Config) of
+ undefined -> "";
+ P -> ["_",P]
+ end,
FuncStr = lists:concat([proplists:get_value(suite, Config), "_",
- proplists:get_value(tc, Config)]),
+ proplists:get_value(tc, Config)|
+ Postfix]),
ConfigFileName = filename:join(proplists:get_value(priv_dir, Config), FuncStr),
file:write_file(ConfigFileName ++ ".config", io_lib:format("[{kernel, ~p}].",[Vars])),
- case test_server:start_node(proplists:get_value(tc, Config), slave,
+ Sname = lists:concat([proplists:get_value(tc,Config)|Postfix]),
+ case test_server:start_node(Sname, slave,
[{args, ["-pa ",filename:dirname(code:which(?MODULE)),
" -boot start_sasl -kernel start_timer true "
"-config ",ConfigFileName]}]) of
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index a02b5f87d1..2f465a15bc 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -1300,7 +1300,8 @@ e_delete(Config) when is_list(Config) ->
case os:type() of
{win32, _} ->
%% Remove a character device.
- {error, eacces} = ?PRIM_FILE:delete("nul");
+ expect({error, eacces}, {error, einval},
+ ?PRIM_FILE:delete("nul"));
_ ->
?PRIM_FILE:write_file_info(
Base, #file_info {mode=0}),
diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl
index 0c0b1cbcb6..ad060aa05c 100644
--- a/lib/kernel/test/sendfile_SUITE.erl
+++ b/lib/kernel/test/sendfile_SUITE.erl
@@ -341,7 +341,21 @@ t_sendfile_closeduring(Config) ->
-1
end,
- ok = sendfile_send({127,0,0,1}, Send, 0).
+ ok = sendfile_send({127,0,0,1}, Send, 0, [{active,false}]),
+ [] = flush(),
+ ok = sendfile_send({127,0,0,1}, Send, 0, [{active,true}]),
+ [] = flush(),
+ ok.
+
+flush() ->
+ lists:reverse(flush([])).
+
+flush(Acc) ->
+ receive M ->
+ flush([M | Acc])
+ after 0 ->
+ Acc
+ end.
t_sendfile_crashduring(Config) ->
Filename = proplists:get_value(big_file, Config),
@@ -409,12 +423,16 @@ sendfile_send(Send) ->
sendfile_send(Host, Send) ->
sendfile_send(Host, Send, []).
sendfile_send(Host, Send, Orig) ->
+ sendfile_send(Host, Send, Orig, [{active,false}]).
+
+sendfile_send(Host, Send, Orig, SockOpts) ->
+
SFServer = spawn_link(?MODULE, sendfile_server, [self(), Orig]),
receive
{server, Port} ->
- {ok, Sock} = gen_tcp:connect(Host, Port,
- [binary,{packet,0},
- {active,false}]),
+ Opts = [binary,{packet,0}|SockOpts],
+ io:format("connect with opts = ~p\n", [Opts]),
+ {ok, Sock} = gen_tcp:connect(Host, Port, Opts),
Data = case proplists:get_value(arity,erlang:fun_info(Send)) of
1 ->
Send(Sock);
diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl
index 9d97254dc0..07a46ac51e 100644
--- a/lib/kernel/test/seq_trace_SUITE.erl
+++ b/lib/kernel/test/seq_trace_SUITE.erl
@@ -26,7 +26,8 @@
old_heap_token/1,
send/1, distributed_send/1, recv/1, distributed_recv/1,
trace_exit/1, distributed_exit/1, call/1, port/1,
- match_set_seq_token/1, gc_seq_token/1, label_capability_mismatch/1]).
+ match_set_seq_token/1, gc_seq_token/1, label_capability_mismatch/1,
+ send_literal/1]).
%% internal exports
-export([simple_tracer/2, one_time_receiver/0, one_time_receiver/1,
@@ -45,7 +46,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [token_set_get, tracer_set_get, print, send,
+ [token_set_get, tracer_set_get, print, send, send_literal,
distributed_send, recv, distributed_recv, trace_exit,
old_heap_token,
distributed_exit, call, port, match_set_seq_token,
@@ -162,23 +163,51 @@ do_print(TsType, Label) ->
{Label,{print,_,_,[],print3}, Ts1}] = stop_tracer(2),
check_ts(TsType, Ts0),
check_ts(TsType, Ts1).
-
+
send(Config) when is_list(Config) ->
lists:foreach(fun do_send/1, ?TIMESTAMP_MODES).
do_send(TsType) ->
+ do_send(TsType, send).
+
+do_send(TsType, Msg) ->
seq_trace:reset_trace(),
start_tracer(),
Receiver = spawn(?MODULE,one_time_receiver,[]),
Label = make_ref(),
seq_trace:set_token(label,Label),
set_token_flags([send, TsType]),
- Receiver ! send,
+ Receiver ! Msg,
Self = self(),
seq_trace:reset_trace(),
- [{Label,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
+ [{Label,{send,_,Self,Receiver,Msg}, Ts}] = stop_tracer(1),
check_ts(TsType, Ts).
+%% This testcase tests that we do not segfault when we have a
+%% literal as the message and the message is copied onto the
+%% heap during a GC.
+send_literal(Config) when is_list(Config) ->
+ lists:foreach(fun do_send_literal/1,
+ [atom, make_ref(), ets:new(hej,[]), 1 bsl 64,
+ "gurka", {tuple,test,with,#{}}, #{}]).
+
+do_send_literal(Msg) ->
+ N = 10000,
+ seq_trace:reset_trace(),
+ start_tracer(),
+ Label = make_ref(),
+ seq_trace:set_token(label,Label),
+ set_token_flags([send, 'receive', no_timestamp]),
+ Receiver = spawn_link(fun() -> receive ok -> ok end end),
+ [Receiver ! Msg || _ <- lists:seq(1, N)],
+ erlang:garbage_collect(Receiver),
+ [Receiver ! Msg || _ <- lists:seq(1, N)],
+ erlang:garbage_collect(Receiver),
+ Self = self(),
+ seq_trace:reset_trace(),
+ [{Label,{send,_,Self,Receiver,Msg}, Ts} | _] = stop_tracer(N),
+ check_ts(no_timestamp, Ts).
+
distributed_send(Config) when is_list(Config) ->
lists:foreach(fun do_distributed_send/1, ?TIMESTAMP_MODES).
@@ -805,6 +834,24 @@ do_shrink(N) ->
erlang:garbage_collect(),
do_shrink(N-1).
+%% Test that messages from a port does not clear the token
+port_clean_token(Config) when is_list(Config) ->
+ seq_trace:reset_trace(),
+ Label = make_ref(),
+ seq_trace:set_token(label, Label),
+ {label,Label} = seq_trace:get_token(label),
+
+ %% Create a port and get messages from it
+ %% We use os:cmd as a convenience as it does
+ %% open_port, port_command, port_close and receives replies.
+ %% Maybe it is not ideal to rely on the internal implementation
+ %% of os:cmd but it will have to do.
+ os:cmd("ls"),
+
+ %% Make sure that the seq_trace token is still there
+ {label,Label} = seq_trace:get_token(label),
+
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index aa8e4dc119..b1ae513223 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 6.0
+KERNEL_VSN = 6.3.1
diff --git a/lib/megaco/doc/src/Makefile b/lib/megaco/doc/src/Makefile
index 43704cddf4..5e085b60b0 100644
--- a/lib/megaco/doc/src/Makefile
+++ b/lib/megaco/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2017. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -114,6 +114,7 @@ clean_man:
clean_html:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
imgs: $(IMG_FILES:%=$(HTMLDIR)/%)
diff --git a/lib/megaco/doc/src/book.xml b/lib/megaco/doc/src/book.xml
index 9c304d6cae..06ff315de7 100644
--- a/lib/megaco/doc/src/book.xml
+++ b/lib/megaco/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>2000</year><year>2016</year>
+ <year>2000</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/megaco/doc/src/megaco.xml b/lib/megaco/doc/src/megaco.xml
index d4a7451bfc..c7bcdfcd6f 100644
--- a/lib/megaco/doc/src/megaco.xml
+++ b/lib/megaco/doc/src/megaco.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco.xml</file>
</header>
- <module>megaco</module>
+ <module since="">megaco</module>
<modulesummary>Main API of the Megaco application</modulesummary>
<description>
<p>Interface module for the Megaco application</p>
@@ -135,7 +135,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
<funcs>
<func>
- <name>start() -> ok | {error, Reason}</name>
+ <name since="">start() -> ok | {error, Reason}</name>
<fsummary>Starts the Megaco application</fsummary>
<type>
<v>Reason = term()</v>
@@ -153,7 +153,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>stop() -> ok | {error, Reason}</name>
+ <name since="">stop() -> ok | {error, Reason}</name>
<fsummary>Stops the Megaco application</fsummary>
<type>
<v>Reason = term()</v>
@@ -166,7 +166,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>start_user(UserMid, Config) -> ok | {error, Reason}</name>
+ <name since="">start_user(UserMid, Config) -> ok | {error, Reason}</name>
<fsummary>Initial configuration of a user</fsummary>
<type>
<v>UserMid = megaco_mid()</v>
@@ -188,7 +188,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>stop_user(UserMid) -> ok | {error, Reason}</name>
+ <name since="">stop_user(UserMid) -> ok | {error, Reason}</name>
<fsummary>Delete the configuration of a user</fsummary>
<type>
<v>UserMid = megaco_mid()</v>
@@ -203,8 +203,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>user_info(UserMid) -> [{Item, Value}]</name>
- <name>user_info(UserMid, Item) -> Value | exit(Reason)</name>
+ <name since="">user_info(UserMid) -> [{Item, Value}]</name>
+ <name since="">user_info(UserMid, Item) -> Value | exit(Reason)</name>
<fsummary>Lookup user information</fsummary>
<type>
<v>Handle = user_info_handle()</v>
@@ -703,7 +703,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>update_user_info(UserMid, Item, Value) -> ok | {error, Reason}</name>
+ <name since="">update_user_info(UserMid, Item, Value) -> ok | {error, Reason}</name>
<fsummary>Update information about a user</fsummary>
<type>
<v>UserMid = megaco_mid() </v>
@@ -721,8 +721,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>conn_info(ConnHandle) -> [{Item, Value}]</name>
- <name>conn_info(ConnHandle, Item) -> Value | exit(Reason)</name>
+ <name since="">conn_info(ConnHandle) -> [{Item, Value}]</name>
+ <name since="">conn_info(ConnHandle, Item) -> Value | exit(Reason)</name>
<fsummary>Lookup information about an active connection</fsummary>
<type>
<v>ConnHandle = #megaco_conn_handle{}</v>
@@ -1222,7 +1222,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>update_conn_info(ConnHandle, Item, Value) -> ok | {error, Reason}</name>
+ <name since="">update_conn_info(ConnHandle, Item, Value) -> ok | {error, Reason}</name>
<fsummary>Update information about an active connection</fsummary>
<type>
<v>ConnHandle = #megaco_conn_handle{}</v>
@@ -1241,8 +1241,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>system_info() -> [{Item, Value}] | exit(Reason)</name>
- <name>system_info(Item) -> Value | exit(Reason)</name>
+ <name since="">system_info() -> [{Item, Value}] | exit(Reason)</name>
+ <name since="">system_info(Item) -> Value | exit(Reason)</name>
<fsummary>Lookup system information</fsummary>
<type>
<v>Item = system_info_item()</v>
@@ -1289,7 +1289,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>info() -> Info</name>
+ <name since="">info() -> Info</name>
<fsummary>All the information of the application</fsummary>
<type>
<v>Info = [{Key, Value}]</v>
@@ -1311,8 +1311,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>connect(ReceiveHandle, RemoteMid, SendHandle, ControlPid) -> {ok, ConnHandle} | {error, Reason}</name>
- <name>connect(ReceiveHandle, RemoteMid, SendHandle, ControlPid, Extra) -> {ok, ConnHandle} | {error, Reason}</name>
+ <name since="">connect(ReceiveHandle, RemoteMid, SendHandle, ControlPid) -> {ok, ConnHandle} | {error, Reason}</name>
+ <name since="">connect(ReceiveHandle, RemoteMid, SendHandle, ControlPid, Extra) -> {ok, ConnHandle} | {error, Reason}</name>
<fsummary>Establish a "virtual" connection</fsummary>
<type>
<v>ReceiveHandle = #megaco_receive_handle{}</v>
@@ -1436,7 +1436,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>disconnect(ConnHandle, DiscoReason) -> ok | {error, ErrReason}</name>
+ <name since="">disconnect(ConnHandle, DiscoReason) -> ok | {error, ErrReason}</name>
<fsummary>Tear down a "virtual" connection</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -1454,7 +1454,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>call(ConnHandle, Actions, Options) -> {ProtocolVersion, UserReply}</name>
+ <name since="">call(ConnHandle, Actions, Options) -> {ProtocolVersion, UserReply}</name>
<fsummary>Sends one or more transaction request(s) and waits for the reply</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -1545,7 +1545,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>cast(ConnHandle, Actions, Options) -> ok | {error, Reason}</name>
+ <name since="">cast(ConnHandle, Actions, Options) -> ok | {error, Reason}</name>
<fsummary>Sends one or more transaction request(s) but does NOT wait for a reply</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -1582,7 +1582,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>encode_actions(ConnHandle, Actions, Options) -> {ok, BinOrBins} | {error, Reason}</name>
+ <name since="">encode_actions(ConnHandle, Actions, Options) -> {ok, BinOrBins} | {error, Reason}</name>
<fsummary>Encode action requests for one or more transaction request(s)</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -1607,9 +1607,9 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>token_tag2string(Tag) -> Result</name>
- <name>token_tag2string(Tag, EncoderMod) -> Result</name>
- <name>token_tag2string(Tag, EncoderMod, Version) -> Result</name>
+ <name since="">token_tag2string(Tag) -> Result</name>
+ <name since="">token_tag2string(Tag, EncoderMod) -> Result</name>
+ <name since="">token_tag2string(Tag, EncoderMod, Version) -> Result</name>
<fsummary>Convert a token tag to a string</fsummary>
<type>
<v>Tag = atom()</v>
@@ -1635,7 +1635,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>cancel(ConnHandle, CancelReason) -> ok | {error, ErrReason}</name>
+ <name since="">cancel(ConnHandle, CancelReason) -> ok | {error, ErrReason}</name>
<fsummary>Cancel all outstanding messages for this connection</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -1655,8 +1655,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) -> ok</name>
- <name>process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg, Extra) -> ok</name>
+ <name since="">process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) -> ok</name>
+ <name since="">process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg, Extra) -> ok</name>
<fsummary>Process a received message</fsummary>
<type>
<v>ReceiveHandle = #megaco_receive_handle{}</v>
@@ -1755,8 +1755,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) -> ok</name>
- <name>receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg, Extra) -> ok</name>
+ <name since="">receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) -> ok</name>
+ <name since="">receive_message(ReceiveHandle, ControlPid, SendHandle, BinMsg, Extra) -> ok</name>
<fsummary>Process a received message</fsummary>
<type>
<v>ReceiveHandle = #megaco_receive_handle{}</v>
@@ -1783,7 +1783,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>parse_digit_map(DigitMapBody) -> {ok, ParsedDigitMap} | {error, Reason}</name>
+ <name since="">parse_digit_map(DigitMapBody) -> {ok, ParsedDigitMap} | {error, Reason}</name>
<fsummary>Parses a digit map body</fsummary>
<type>
<v>DigitMapBody = string()</v>
@@ -1802,8 +1802,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>eval_digit_map(DigitMap) -> {ok, MatchResult} | {error, Reason}</name>
- <name>eval_digit_map(DigitMap, Timers) -> {ok, MatchResult} | {error, Reason}</name>
+ <name since="">eval_digit_map(DigitMap) -> {ok, MatchResult} | {error, Reason}</name>
+ <name since="">eval_digit_map(DigitMap, Timers) -> {ok, MatchResult} | {error, Reason}</name>
<fsummary>Collect digit map letters according to the digit map</fsummary>
<type>
<v>DigitMap = #'DigitMapValue'{} | parsed_digit_map()</v>
@@ -1839,7 +1839,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>report_digit_event(DigitMapEvalPid, Events) -> ok | {error, Reason}</name>
+ <name since="">report_digit_event(DigitMapEvalPid, Events) -> ok | {error, Reason}</name>
<fsummary>Send one or more events to the event collector process</fsummary>
<type>
<v>DigitMapEvalPid = pid()</v>
@@ -1866,7 +1866,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>test_digit_event(DigitMap, Events) -> {ok, Kind, Letters} | {error, Reason}</name>
+ <name since="">test_digit_event(DigitMap, Events) -> {ok, Kind, Letters} | {error, Reason}</name>
<fsummary>Feed digit map collector with events and return the result</fsummary>
<type>
<v>DigitMap = #'DigitMapValue'{} | parsed_digit_map()</v>
@@ -1900,7 +1900,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>encode_sdp(SDP) -> {ok, PP} | {error, Reason}</name>
+ <name since="">encode_sdp(SDP) -> {ok, PP} | {error, Reason}</name>
<fsummary>Encode an SDP construct</fsummary>
<type>
<v>SDP = sdp_property_parm() | sdp_property_group() | sdp_property_groups() | asn1_NOVALUE</v>
@@ -1929,7 +1929,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>decode_sdp(PP) -> {ok, SDP} | {error, Reason}</name>
+ <name since="">decode_sdp(PP) -> {ok, SDP} | {error, Reason}</name>
<fsummary>Decode an property parameter construct</fsummary>
<type>
<v>PP = property_parm() | property_group() | property_groups() | asn1_NOVALUE</v>
@@ -1969,7 +1969,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>get_sdp_record_from_PropertGroup(Type, PG) -> [sdp()]</name>
+ <name since="">get_sdp_record_from_PropertGroup(Type, PG) -> [sdp()]</name>
<fsummary>Get all sdp records of a certain type from a property group</fsummary>
<type>
<v>Type = v | c | m | o | a | b | t | r | z | k | s | i | u | e | p</v>
@@ -1986,8 +1986,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>versions1() -> {ok, VersionInfo} | {error, Reason}</name>
- <name>versions2() -> {ok, Info} | {error, Reason}</name>
+ <name since="">versions1() -> {ok, VersionInfo} | {error, Reason}</name>
+ <name since="">versions2() -> {ok, Info} | {error, Reason}</name>
<fsummary>Retreive various system and application info</fsummary>
<type>
<v>VersionInfo = [version_info()]</v>
@@ -2007,8 +2007,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>print_version_info() -> void()</name>
- <name>print_version_info(VersionInfo) -> void()</name>
+ <name since="">print_version_info() -> void()</name>
+ <name since="">print_version_info(VersionInfo) -> void()</name>
<fsummary>Formated print of result of the versions functions</fsummary>
<type>
<v>VersionInfo = [version_info()]</v>
@@ -2029,7 +2029,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>enable_trace(Level, Destination) -> void()</name>
+ <name since="">enable_trace(Level, Destination) -> void()</name>
<fsummary>Start megaco tracing</fsummary>
<type>
<v>Level = max | min | 0 &lt;= integer() &lt;= 100</v>
@@ -2057,7 +2057,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>disable_trace() -> void()</name>
+ <name since="">disable_trace() -> void()</name>
<fsummary>Stop megaco tracing</fsummary>
<desc>
<p>This function is used to stop megaco tracing.</p>
@@ -2065,7 +2065,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</desc>
</func>
<func>
- <name>set_trace(Level) -> void()</name>
+ <name since="">set_trace(Level) -> void()</name>
<fsummary>Change megaco trace level</fsummary>
<type>
<v>Level = max | min | 0 &lt;= integer() &lt;= 100</v>
@@ -2081,10 +2081,10 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>get_stats() -> {ok, TotalStats} | {error, Reason}</name>
- <name>get_stats(GlobalCounter) -> {ok, CounterStats} | {error, Reason}</name>
- <name>get_stats(ConnHandle) -> {ok, ConnHandleStats} | {error, Reason}</name>
- <name>get_stats(ConnHandle, Counter) -> {ok, integer()} | {error, Reason}</name>
+ <name since="">get_stats() -> {ok, TotalStats} | {error, Reason}</name>
+ <name since="">get_stats(GlobalCounter) -> {ok, CounterStats} | {error, Reason}</name>
+ <name since="">get_stats(ConnHandle) -> {ok, ConnHandleStats} | {error, Reason}</name>
+ <name since="">get_stats(ConnHandle, Counter) -> {ok, integer()} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>TotalStats = [total_stats()]</v>
@@ -2110,8 +2110,8 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>reset_stats() -> void()</name>
- <name>reset_stats(ConnHandle) -> void()</name>
+ <name since="">reset_stats() -> void()</name>
+ <name since="">reset_stats(ConnHandle) -> void()</name>
<fsummary></fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -2123,7 +2123,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>test_request(ConnHandle, Version, EncodingMod, EncodingConfig, Actions) -> {MegaMsg, EncodeRes}</name>
+ <name since="">test_request(ConnHandle, Version, EncodingMod, EncodingConfig, Actions) -> {MegaMsg, EncodeRes}</name>
<fsummary>Tests if the Actions argument is correct</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -2150,7 +2150,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
</func>
<func>
- <name>test_reply(ConnHandle, Version, EncodingMod, EncodingConfig, Reply) -> {MegaMsg, EncodeRes}</name>
+ <name since="">test_reply(ConnHandle, Version, EncodingMod, EncodingConfig, Reply) -> {MegaMsg, EncodeRes}</name>
<fsummary>Tests if the Reply argument is correct</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
diff --git a/lib/megaco/doc/src/megaco_codec_meas.xml b/lib/megaco/doc/src/megaco_codec_meas.xml
index 13cc3eb834..5184fe392e 100644
--- a/lib/megaco/doc/src/megaco_codec_meas.xml
+++ b/lib/megaco/doc/src/megaco_codec_meas.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_codec_meas.xml</file>
</header>
- <module>megaco_codec_meas</module>
+ <module since="">megaco_codec_meas</module>
<modulesummary>This module implements a simple megaco codec measurement tool.</modulesummary>
<description>
<p>This module implements a simple megaco codec measurement tool.</p>
@@ -43,8 +43,8 @@
<funcs>
<func>
- <name>start() -> void()</name>
- <name>start(MessagePackage) -> void()</name>
+ <name since="">start() -> void()</name>
+ <name since="">start(MessagePackage) -> void()</name>
<fsummary></fsummary>
<type>
<v>MessagePackageRaw = message_package()</v>
diff --git a/lib/megaco/doc/src/megaco_codec_mstone1.xml b/lib/megaco/doc/src/megaco_codec_mstone1.xml
index 2ff959a648..507a790c71 100644
--- a/lib/megaco/doc/src/megaco_codec_mstone1.xml
+++ b/lib/megaco/doc/src/megaco_codec_mstone1.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_codec_mstone1.xml</file>
</header>
- <module>megaco_codec_mstone1</module>
+ <module since="">megaco_codec_mstone1</module>
<modulesummary>This module implements a simple megaco codec-based performance tool.</modulesummary>
<description>
<p>This module implements the <em>mstone1</em> tool,
@@ -44,9 +44,9 @@
<funcs>
<func>
- <name>start() -> void()</name>
- <name>start(MessagePackage) -> void()</name>
- <name>start(MessagePackage, Factor) -> void()</name>
+ <name since="">start() -> void()</name>
+ <name since="">start(MessagePackage) -> void()</name>
+ <name since="">start(MessagePackage, Factor) -> void()</name>
<fsummary></fsummary>
<type>
<v>MessagePackage = message_package()</v>
@@ -63,9 +63,9 @@
</func>
<func>
- <name>start_flex() -> void()</name>
- <name>start_flex(MessagePackage) -> void()</name>
- <name>start_flex(MessagePackage, Factor) -> void()</name>
+ <name since="">start_flex() -> void()</name>
+ <name since="">start_flex(MessagePackage) -> void()</name>
+ <name since="">start_flex(MessagePackage, Factor) -> void()</name>
<fsummary></fsummary>
<type>
<v>MessagePackage = message_package()</v>
@@ -83,9 +83,9 @@
</func>
<func>
- <name>start_only_drv() -> void()</name>
- <name>start_only_drv(MessagePackage) -> void()</name>
- <name>start_only_drv(MessagePackage, Factor) -> void()</name>
+ <name since="">start_only_drv() -> void()</name>
+ <name since="">start_only_drv(MessagePackage) -> void()</name>
+ <name since="">start_only_drv(MessagePackage, Factor) -> void()</name>
<fsummary></fsummary>
<type>
<v>MessagePackage = message_package()</v>
@@ -105,9 +105,9 @@
</func>
<func>
- <name>start_no_drv() -> void()</name>
- <name>start_no_drv(MessagePackage) -> void()</name>
- <name>start_no_drv(MessagePackage, Factor) -> void()</name>
+ <name since="">start_no_drv() -> void()</name>
+ <name since="">start_no_drv(MessagePackage) -> void()</name>
+ <name since="">start_no_drv(MessagePackage, Factor) -> void()</name>
<fsummary></fsummary>
<type>
<v>MessagePackage = message_package()</v>
diff --git a/lib/megaco/doc/src/megaco_codec_mstone2.xml b/lib/megaco/doc/src/megaco_codec_mstone2.xml
index 3da30d4f99..03990f5c3d 100644
--- a/lib/megaco/doc/src/megaco_codec_mstone2.xml
+++ b/lib/megaco/doc/src/megaco_codec_mstone2.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_codec_mstone2.xml</file>
</header>
- <module>megaco_codec_mstone2</module>
+ <module since="">megaco_codec_mstone2</module>
<modulesummary>This module implements a simple megaco codec-based performance tool.</modulesummary>
<description>
<p>This module implements the <em>mstone2</em> tool,
@@ -44,8 +44,8 @@
<funcs>
<func>
- <name>start() -> void()</name>
- <name>start(MessagePackage) -> void()</name>
+ <name since="">start() -> void()</name>
+ <name since="">start(MessagePackage) -> void()</name>
<fsummary></fsummary>
<type>
<v>MessagePackage = message_package()</v>
diff --git a/lib/megaco/doc/src/megaco_codec_transform.xml b/lib/megaco/doc/src/megaco_codec_transform.xml
index 26b83c3799..392868fdfa 100644
--- a/lib/megaco/doc/src/megaco_codec_transform.xml
+++ b/lib/megaco/doc/src/megaco_codec_transform.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_codec_transform.xml</file>
</header>
- <module>megaco_codec_transform</module>
+ <module since="">megaco_codec_transform</module>
<modulesummary>Megaco message transformation utility.</modulesummary>
<description>
@@ -45,8 +45,8 @@
<funcs>
<func>
- <name>export_messages() -> void()</name>
- <name>export_messages(MessagePackage) -> void()</name>
+ <name since="">export_messages() -> void()</name>
+ <name since="">export_messages(MessagePackage) -> void()</name>
<fsummary></fsummary>
<type>
<v>MessagePackage = atom()</v>
diff --git a/lib/megaco/doc/src/megaco_edist_compress.xml b/lib/megaco/doc/src/megaco_edist_compress.xml
index d5c7c7224d..16443e469c 100644
--- a/lib/megaco/doc/src/megaco_edist_compress.xml
+++ b/lib/megaco/doc/src/megaco_edist_compress.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_edist_compress.xml</file>
</header>
- <module>megaco_edist_compress</module>
+ <module since="">megaco_edist_compress</module>
<modulesummary>Megaco erlang dist compress behaviour.</modulesummary>
<description>
<p>The following functions should be exported from a
@@ -40,7 +40,7 @@
</description>
<funcs>
<func>
- <name>Module:encode(R, Version) -> T</name>
+ <name since="">Module:encode(R, Version) -> T</name>
<fsummary>Encode (compress) a megaco component.</fsummary>
<type>
<v>R = megaco_message() | transaction() | action_reply() | action_request() | command_request()</v>
@@ -53,7 +53,7 @@
</desc>
</func>
<func>
- <name>Module:decode(T, Version) -> R</name>
+ <name since="">Module:decode(T, Version) -> R</name>
<fsummary>Decode (decompress) a megaco component.</fsummary>
<type>
<v>T = term()</v>
diff --git a/lib/megaco/doc/src/megaco_encoder.xml b/lib/megaco/doc/src/megaco_encoder.xml
index 13c6ed324b..cc8270440b 100644
--- a/lib/megaco/doc/src/megaco_encoder.xml
+++ b/lib/megaco/doc/src/megaco_encoder.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_encoder.xml</file>
</header>
- <module>megaco_encoder</module>
+ <module since="">megaco_encoder</module>
<modulesummary>Megaco encoder behaviour.</modulesummary>
<description>
<p>The following functions should be exported from a
@@ -64,7 +64,7 @@ action_reply() = #'ActionReply'{}
<funcs>
<func>
- <name>Module:encode_message(EncodingConfig, Version, Message) -> {ok, Bin} | Error</name>
+ <name since="">Module:encode_message(EncodingConfig, Version, Message) -> {ok, Bin} | Error</name>
<fsummary>Encode a megaco message.</fsummary>
<type>
<v>EncodingConfig = list()</v>
@@ -81,7 +81,7 @@ action_reply() = #'ActionReply'{}
</func>
<func>
- <name>Module:decode_message(EncodingConfig, Version, Bin) -> {ok, Message} | Error</name>
+ <name since="">Module:decode_message(EncodingConfig, Version, Bin) -> {ok, Message} | Error</name>
<fsummary>Decode a megaco message.</fsummary>
<type>
<v>EncodingConfig = list()</v>
@@ -104,7 +104,7 @@ action_reply() = #'ActionReply'{}
</func>
<func>
- <name>Module:decode_mini_message(EncodingConfig, Version, Bin) -> {ok, Message} | Error</name>
+ <name since="">Module:decode_mini_message(EncodingConfig, Version, Bin) -> {ok, Message} | Error</name>
<fsummary>Perform a minimal decode of a megaco message.</fsummary>
<type>
<v>EncodingConfig = list()</v>
@@ -129,7 +129,7 @@ action_reply() = #'ActionReply'{}
</func>
<func>
- <name>Module:encode_transaction(EncodingConfig, Version, Transaction) -> OK | Error</name>
+ <name since="">Module:encode_transaction(EncodingConfig, Version, Transaction) -> OK | Error</name>
<fsummary>Encode a megaco transaction.</fsummary>
<type>
<v>EncodingConfig = list()</v>
@@ -155,7 +155,7 @@ action_reply() = #'ActionReply'{}
</func>
<func>
- <name>Module:encode_action_requests(EncodingConfig, Version, ARs) -> OK | Error</name>
+ <name since="">Module:encode_action_requests(EncodingConfig, Version, ARs) -> OK | Error</name>
<fsummary>Encode megaco action requests.</fsummary>
<type>
<v>EncodingConfig = list()</v>
@@ -181,7 +181,7 @@ action_reply() = #'ActionReply'{}
</func>
<func>
- <name>Module:encode_action_reply(EncodingConfig, Version, AR) -> OK | Error</name>
+ <name since="">Module:encode_action_reply(EncodingConfig, Version, AR) -> OK | Error</name>
<fsummary>Encode a megaco action reply.</fsummary>
<type>
<v>EncodingConfig = list()</v>
diff --git a/lib/megaco/doc/src/megaco_flex_scanner.xml b/lib/megaco/doc/src/megaco_flex_scanner.xml
index 0856f3f429..121a7fbcff 100644
--- a/lib/megaco/doc/src/megaco_flex_scanner.xml
+++ b/lib/megaco/doc/src/megaco_flex_scanner.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_flex_scanner.xml</file>
</header>
- <module>megaco_flex_scanner</module>
+ <module since="">megaco_flex_scanner</module>
<modulesummary>Interface module to the flex scanner linked in driver.</modulesummary>
<description>
<p>This module contains the public interface to the flex scanner
@@ -72,7 +72,7 @@ megaco_version() = integer() >= 1
<funcs>
<func>
- <name>start() -> {ok, PortOrPorts} | {error, Reason}</name>
+ <name since="">start() -> {ok, PortOrPorts} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>PortOrPorts = megaco_ports()</v>
@@ -94,7 +94,7 @@ megaco_version() = integer() >= 1
</func>
<func>
- <name>stop(PortOrPorts) -> stopped</name>
+ <name since="">stop(PortOrPorts) -> stopped</name>
<fsummary></fsummary>
<type>
<v>PortOrPorts = megaco_ports()</v>
@@ -108,7 +108,7 @@ megaco_version() = integer() >= 1
</func>
<func>
- <name>is_reentrant_enabled() -> Boolean</name>
+ <name since="">is_reentrant_enabled() -> Boolean</name>
<fsummary></fsummary>
<type>
<v>Boolean = boolean()</v>
@@ -121,7 +121,7 @@ megaco_version() = integer() >= 1
</func>
<func>
- <name>is_scanner_port(Port, PortOrPorts) -> Boolean</name>
+ <name since="">is_scanner_port(Port, PortOrPorts) -> Boolean</name>
<fsummary></fsummary>
<type>
<v>Port = port()</v>
@@ -137,7 +137,7 @@ megaco_version() = integer() >= 1
</func>
<func>
- <name>scan(Binary, PortOrPorts) -> {ok, Tokens, Version, LatestLine} | {error, Reason, LatestLine} </name>
+ <name since="">scan(Binary, PortOrPorts) -> {ok, Tokens, Version, LatestLine} | {error, Reason, LatestLine} </name>
<fsummary></fsummary>
<type>
<v>Binary = binary()</v>
diff --git a/lib/megaco/doc/src/megaco_tcp.xml b/lib/megaco/doc/src/megaco_tcp.xml
index 77aee32f6c..63713b2c56 100644
--- a/lib/megaco/doc/src/megaco_tcp.xml
+++ b/lib/megaco/doc/src/megaco_tcp.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_tcp.xml</file>
</header>
- <module>megaco_tcp</module>
+ <module since="">megaco_tcp</module>
<modulesummary>Interface module to TPKT transport protocol for Megaco/H.248.</modulesummary>
<description>
<p>This module contains the public interface to the TPKT (TCP/IP) version
@@ -40,7 +40,7 @@
</description>
<funcs>
<func>
- <name>start_transport() -> {ok, TransportRef}</name>
+ <name since="">start_transport() -> {ok, TransportRef}</name>
<fsummary></fsummary>
<type>
<v>TransportRef = pid()</v>
@@ -51,7 +51,7 @@
</desc>
</func>
<func>
- <name>listen(TransportRef, ListenPortSpecList) -> ok</name>
+ <name since="">listen(TransportRef, ListenPortSpecList) -> ok</name>
<fsummary></fsummary>
<type>
<v>TransportRef = pid() | regname()</v>
@@ -65,7 +65,7 @@
</desc>
</func>
<func>
- <name>connect(TransportRef, OptionList) -> {ok, Handle, ControlPid} | {error, Reason}</name>
+ <name since="">connect(TransportRef, OptionList) -> {ok, Handle, ControlPid} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>TransportRef = pid() | regname()</v>
@@ -86,7 +86,7 @@
</desc>
</func>
<func>
- <name>close(Handle) -> ok</name>
+ <name since="">close(Handle) -> ok</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -96,7 +96,7 @@
</desc>
</func>
<func>
- <name>socket(Handle) -> Socket</name>
+ <name since="">socket(Handle) -> Socket</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -109,7 +109,7 @@
</desc>
</func>
<func>
- <name>send_message(Handle, Message) -> ok</name>
+ <name since="">send_message(Handle, Message) -> ok</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -120,7 +120,7 @@
</desc>
</func>
<func>
- <name>block(Handle) -> ok</name>
+ <name since="">block(Handle) -> ok</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -130,7 +130,7 @@
</desc>
</func>
<func>
- <name>unblock(Handle) -> ok</name>
+ <name since="">unblock(Handle) -> ok</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -141,7 +141,7 @@
</desc>
</func>
<func>
- <name>upgrade_receive_handle(ControlPid) -> ok</name>
+ <name since="">upgrade_receive_handle(ControlPid) -> ok</name>
<fsummary></fsummary>
<type>
<v>ControlPid = pid()</v>
@@ -153,9 +153,9 @@
</desc>
</func>
<func>
- <name>get_stats() -> {ok, TotalStats} | {error, Reason}</name>
- <name>get_stats(SendHandle) -> {ok, SendHandleStats} | {error, Reason}</name>
- <name>get_stats(SendHandle, Counter) -> {ok, CounterStats} | {error, Reason}</name>
+ <name since="">get_stats() -> {ok, TotalStats} | {error, Reason}</name>
+ <name since="">get_stats(SendHandle) -> {ok, SendHandleStats} | {error, Reason}</name>
+ <name since="">get_stats(SendHandle, Counter) -> {ok, CounterStats} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>TotalStats = [send_handle_stats()]</v>
@@ -173,8 +173,8 @@
</desc>
</func>
<func>
- <name>reset_stats() -> void()</name>
- <name>reset_stats(SendHandle) -> void()</name>
+ <name since="">reset_stats() -> void()</name>
+ <name since="">reset_stats(SendHandle) -> void()</name>
<fsummary></fsummary>
<type>
<v>SendHandle = send_handle()</v>
diff --git a/lib/megaco/doc/src/megaco_transport.xml b/lib/megaco/doc/src/megaco_transport.xml
index 3002e9b74e..ba8c794750 100644
--- a/lib/megaco/doc/src/megaco_transport.xml
+++ b/lib/megaco/doc/src/megaco_transport.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_transport.xml</file>
</header>
- <module>megaco_transport</module>
+ <module since="">megaco_transport</module>
<modulesummary>Megaco transport behaviour.</modulesummary>
<description>
<p>The following functions should be exported from a
@@ -54,8 +54,8 @@
</description>
<funcs>
<func>
- <name>Module:send_message(Handle, Msg) -> ok | {cancel, Reason} | Error</name>
- <name>Module:send_message(Handle, Msg, Resend) -> ok | {cancel, Reason} | Error</name>
+ <name since="">Module:send_message(Handle, Msg) -> ok | {cancel, Reason} | Error</name>
+ <name since="">Module:send_message(Handle, Msg, Resend) -> ok | {cancel, Reason} | Error</name>
<fsummary>Send a megaco message.</fsummary>
<type>
<v>Handle = term()</v>
@@ -99,7 +99,7 @@
</func>
<func>
- <name>Module:resend_message(Handle, Msg) -> ok | {cancel, Reason} | Error</name>
+ <name since="">Module:resend_message(Handle, Msg) -> ok | {cancel, Reason} | Error</name>
<fsummary>Re-send a megaco message.</fsummary>
<type>
<v>Handle = term()</v>
diff --git a/lib/megaco/doc/src/megaco_udp.xml b/lib/megaco/doc/src/megaco_udp.xml
index b2559c77d5..3d776c19b6 100644
--- a/lib/megaco/doc/src/megaco_udp.xml
+++ b/lib/megaco/doc/src/megaco_udp.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_udp.xml</file>
</header>
- <module>megaco_udp</module>
+ <module since="">megaco_udp</module>
<modulesummary>Interface module to UDP transport protocol for Megaco/H.248.</modulesummary>
<description>
<p>This module contains the public interface to the UDP/IP version
@@ -40,7 +40,7 @@
</description>
<funcs>
<func>
- <name>start_transport() -> {ok, TransportRef}</name>
+ <name since="">start_transport() -> {ok, TransportRef}</name>
<fsummary></fsummary>
<type>
<v>TransportRef = pid()</v>
@@ -51,7 +51,7 @@
</desc>
</func>
<func>
- <name>open(TransportRef, OptionList) -> {ok, Handle, ControlPid} | {error, Reason}</name>
+ <name since="">open(TransportRef, OptionList) -> {ok, Handle, ControlPid} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>TransportRef = pid() | regname()</v>
@@ -73,7 +73,7 @@
</desc>
</func>
<func>
- <name>close(Handle, Msg) -> ok</name>
+ <name since="">close(Handle, Msg) -> ok</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -84,7 +84,7 @@
</desc>
</func>
<func>
- <name>socket(Handle) -> Socket</name>
+ <name since="">socket(Handle) -> Socket</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -97,7 +97,7 @@
</desc>
</func>
<func>
- <name>create_send_handle(Handle, Host, Port) -> send_handle()</name>
+ <name since="">create_send_handle(Handle, Host, Port) -> send_handle()</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -110,7 +110,7 @@
</desc>
</func>
<func>
- <name>send_message(SendHandle, Msg) -> ok</name>
+ <name since="">send_message(SendHandle, Msg) -> ok</name>
<fsummary></fsummary>
<type>
<v>SendHandle = send_handle()</v>
@@ -125,7 +125,7 @@
</desc>
</func>
<func>
- <name>block(Handle) -> ok</name>
+ <name since="">block(Handle) -> ok</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -135,7 +135,7 @@
</desc>
</func>
<func>
- <name>unblock(Handle) -> ok</name>
+ <name since="">unblock(Handle) -> ok</name>
<fsummary></fsummary>
<type>
<v>Handle = socket_handle()</v>
@@ -146,7 +146,7 @@
</desc>
</func>
<func>
- <name>upgrade_receive_handle(ControlPid, NewHandle) -> ok</name>
+ <name since="">upgrade_receive_handle(ControlPid, NewHandle) -> ok</name>
<fsummary></fsummary>
<type>
<v>ControlPid = pid()</v>
@@ -160,9 +160,9 @@
</desc>
</func>
<func>
- <name>get_stats() -> {ok, TotalStats} | {error, Reason}</name>
- <name>get_stats(SendHandle) -> {ok, SendHandleStats} | {error, Reason}</name>
- <name>get_stats(SendHandle, Counter) -> {ok, CounterStats} | {error, Reason}</name>
+ <name since="">get_stats() -> {ok, TotalStats} | {error, Reason}</name>
+ <name since="">get_stats(SendHandle) -> {ok, SendHandleStats} | {error, Reason}</name>
+ <name since="">get_stats(SendHandle, Counter) -> {ok, CounterStats} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>TotalStats = [total_stats()]</v>
@@ -180,8 +180,8 @@
</desc>
</func>
<func>
- <name>reset_stats() -> void()</name>
- <name>reset_stats(SendHandle) -> void()</name>
+ <name since="">reset_stats() -> void()</name>
+ <name since="">reset_stats(SendHandle) -> void()</name>
<fsummary></fsummary>
<type>
<v>SendHandle = send_handle()</v>
diff --git a/lib/megaco/doc/src/megaco_user.xml b/lib/megaco/doc/src/megaco_user.xml
index 067be15fe0..198f2aa24c 100644
--- a/lib/megaco/doc/src/megaco_user.xml
+++ b/lib/megaco/doc/src/megaco_user.xml
@@ -32,7 +32,7 @@
<rev>%VSN%</rev>
<file>megaco_user.xml</file>
</header>
- <module>megaco_user</module>
+ <module since="">megaco_user</module>
<modulesummary>Callback module for users of the Megaco application</modulesummary>
<description>
<p>This module defines the callback behaviour of Megaco users. A
@@ -164,8 +164,8 @@ protocol_version() = integer() ]]></code>
<funcs>
<func>
- <name>handle_connect(ConnHandle, ProtocolVersion) -> ok | error | {error,ErrorDescr}</name>
- <name>handle_connect(ConnHandle, ProtocolVersion, Extra]) -> ok | error | {error,ErrorDescr}</name>
+ <name since="">handle_connect(ConnHandle, ProtocolVersion) -> ok | error | {error,ErrorDescr}</name>
+ <name since="">handle_connect(ConnHandle, ProtocolVersion, Extra]) -> ok | error | {error,ErrorDescr}</name>
<fsummary>Invoked when a new connection is established</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -202,7 +202,7 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_disconnect(ConnHandle, ProtocolVersion, Reason) -> ok</name>
+ <name since="">handle_disconnect(ConnHandle, ProtocolVersion, Reason) -> ok</name>
<fsummary>Invoked when a connection is teared down</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -220,8 +220,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_syntax_error(ReceiveHandle, ProtocolVersion, DefaultED) -> reply | {reply, ED} | no_reply | {no_reply, ED} </name>
- <name>handle_syntax_error(ReceiveHandle, ProtocolVersion, DefaultED, Extra) -> reply | {reply, ED} | no_reply | {no_reply, ED} </name>
+ <name since="">handle_syntax_error(ReceiveHandle, ProtocolVersion, DefaultED) -> reply | {reply, ED} | no_reply | {no_reply, ED} </name>
+ <name since="">handle_syntax_error(ReceiveHandle, ProtocolVersion, DefaultED, Extra) -> reply | {reply, ED} | no_reply | {no_reply, ED} </name>
<fsummary>Invoked when a received message had syntax errors</fsummary>
<type>
<v>ReceiveHandle = receive_handle()</v>
@@ -258,8 +258,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_message_error(ConnHandle, ProtocolVersion, ErrorDescr) -> ok</name>
- <name>handle_message_error(ConnHandle, ProtocolVersion, ErrorDescr, Extra) -> ok</name>
+ <name since="">handle_message_error(ConnHandle, ProtocolVersion, ErrorDescr) -> ok</name>
+ <name since="">handle_message_error(ConnHandle, ProtocolVersion, ErrorDescr, Extra) -> ok</name>
<fsummary>Invoked when a received message just contains an error</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -291,8 +291,8 @@ protocol_version() = integer() ]]></code>
<!--
<func>
- <name>handle_segment_error(ConnHandle, ProtocolVersion, TransId, SegmentError) -> ok</name>
- <name>handle_segment_error(ConnHandle, ProtocolVersion, TransId, SegmentError, Extra) -> ok</name>
+ <name since="">handle_segment_error(ConnHandle, ProtocolVersion, TransId, SegmentError) -> ok</name>
+ <name since="">handle_segment_error(ConnHandle, ProtocolVersion, TransId, SegmentError, Extra) -> ok</name>
<fsummary>Invoked when a segment error has been detected</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -316,8 +316,8 @@ protocol_version() = integer() ]]></code>
-->
<func>
- <name>handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) -> pending() | reply() | ignore_trans_request</name>
- <name>handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests, Extra) -> pending() | reply() | ignore_trans_request</name>
+ <name since="">handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) -> pending() | reply() | ignore_trans_request</name>
+ <name since="">handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests, Extra) -> pending() | reply() | ignore_trans_request</name>
<fsummary>Invoked for each transaction request</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -420,8 +420,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData) -> reply()</name>
- <name>handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData, Extra) -> reply()</name>
+ <name since="">handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData) -> reply()</name>
+ <name since="">handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData, Extra) -> reply()</name>
<fsummary>Optionally invoked for a time consuming transaction request</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -460,8 +460,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, ReplyData) -> ok</name>
- <name>handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, ReplyData, Extra) -> ok</name>
+ <name since="">handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, ReplyData) -> ok</name>
+ <name since="">handle_trans_reply(ConnHandle, ProtocolVersion, UserReply, ReplyData, Extra) -> ok</name>
<fsummary>Optionally invoked for a transaction reply</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -593,8 +593,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) -> ok</name>
- <name>handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Extra) -> ok</name>
+ <name since="">handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) -> ok</name>
+ <name since="">handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData, Extra) -> ok</name>
<fsummary>Optionally invoked for a transaction acknowledgement</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -658,8 +658,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) -> ok</name>
- <name>handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans, Extra) -> ok</name>
+ <name since="">handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) -> ok</name>
+ <name since="">handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans, Extra) -> ok</name>
<fsummary>Invoked when an unexpected message is received</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -685,8 +685,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_trans_request_abort(ConnHandle, ProtocolVersion, TransNo, Pid) -> ok</name>
- <name>handle_trans_request_abort(ConnHandle, ProtocolVersion, TransNo, Pid, Extra) -> ok</name>
+ <name since="">handle_trans_request_abort(ConnHandle, ProtocolVersion, TransNo, Pid) -> ok</name>
+ <name since="">handle_trans_request_abort(ConnHandle, ProtocolVersion, TransNo, Pid, Extra) -> ok</name>
<fsummary>Invoked when an transaction request has been aborted</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
@@ -710,8 +710,8 @@ protocol_version() = integer() ]]></code>
</func>
<func>
- <name>handle_segment_reply(ConnHandle, ProtocolVersion, TransNo, SegNo, SegCompl) -> ok</name>
- <name>handle_segment_reply(ConnHandle, ProtocolVersion, TransNo, SegNo, SegCompl, Extra) -> ok</name>
+ <name since="">handle_segment_reply(ConnHandle, ProtocolVersion, TransNo, SegNo, SegCompl) -> ok</name>
+ <name since="">handle_segment_reply(ConnHandle, ProtocolVersion, TransNo, SegNo, SegCompl, Extra) -> ok</name>
<fsummary>Segment Reply Indication</fsummary>
<type>
<v>ConnHandle = conn_handle()</v>
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index 54e048a172..b697c3f631 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -37,7 +37,22 @@
section is the version number of Megaco.</p>
- <section><title>Megaco 3.18.3</title>
+ <section><title>Megaco 3.18.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 3.18.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index a4f7de7f07..f4c82c537a 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.18.3
+MEGACO_VSN = 3.18.4
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/Makefile b/lib/mnesia/doc/src/Makefile
index da52c69f00..d9647fc081 100644
--- a/lib/mnesia/doc/src/Makefile
+++ b/lib/mnesia/doc/src/Makefile
@@ -118,6 +118,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/mnesia/doc/src/mnesia.xml b/lib/mnesia/doc/src/mnesia.xml
index 621b6047ee..11b0b8e987 100644
--- a/lib/mnesia/doc/src/mnesia.xml
+++ b/lib/mnesia/doc/src/mnesia.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file></file>
</header>
- <module>mnesia</module>
+ <module since="">mnesia</module>
<modulesummary>A distributed telecommunications DBMS</modulesummary>
<description>
@@ -183,7 +183,7 @@
<funcs>
<func>
- <name>abort(Reason) -> transaction abort</name>
+ <name since="">abort(Reason) -> transaction abort</name>
<fsummary>Terminates the current transaction.</fsummary>
<desc>
<p>Makes the transaction silently
@@ -195,7 +195,7 @@
</desc>
</func>
<func>
- <name>activate_checkpoint(Args) -> {ok,Name,Nodes} | {error,Reason}</name>
+ <name since="">activate_checkpoint(Args) -> {ok,Name,Nodes} | {error,Reason}</name>
<fsummary>Activates a checkpoint.</fsummary>
<desc>
<marker id="activate_checkpoint"></marker>
@@ -259,7 +259,7 @@
</desc>
</func>
<func>
- <name>activity(AccessContext, Fun [, Args]) -> ResultOfFun | exit(Reason)</name>
+ <name since="">activity(AccessContext, Fun [, Args]) -> ResultOfFun | exit(Reason)</name>
<fsummary>Executes <c>Fun</c> in <c>AccessContext</c>.</fsummary>
<desc>
<marker id="activity_2_3"></marker>
@@ -271,7 +271,7 @@
</desc>
</func>
<func>
- <name>activity(AccessContext, Fun, Args, AccessMod) -> ResultOfFun | exit(Reason)</name>
+ <name since="">activity(AccessContext, Fun, Args, AccessMod) -> ResultOfFun | exit(Reason)</name>
<fsummary>Executes <c>Fun</c> in <c>AccessContext</c>.</fsummary>
<desc>
<marker id="activity_4"></marker>
@@ -403,7 +403,7 @@
</desc>
</func>
<func>
- <name>add_table_copy(Tab, Node, Type) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">add_table_copy(Tab, Node, Type) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Copies a table to a remote node.</fsummary>
<desc>
<marker id="add_table_copy"></marker>
@@ -420,7 +420,7 @@ mnesia:add_table_copy(person, Node, disc_copies)</code>
</desc>
</func>
<func>
- <name>add_table_index(Tab, AttrName) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">add_table_index(Tab, AttrName) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Creates an index for a table.</fsummary>
<desc>
<marker id="add_table_index"></marker>
@@ -441,7 +441,7 @@ mnesia:add_table_index(person, age)</code>
</desc>
</func>
<func>
- <name>all_keys(Tab) -> KeyList | transaction abort</name>
+ <name since="">all_keys(Tab) -> KeyList | transaction abort</name>
<fsummary>Returns all keys in a table.</fsummary>
<desc>
<marker id="all_keys"></marker>
@@ -453,7 +453,7 @@ mnesia:add_table_index(person, age)</code>
</desc>
</func>
<func>
- <name>async_dirty(Fun, [, Args]) -> ResultOfFun | exit(Reason)</name>
+ <name since="">async_dirty(Fun, [, Args]) -> ResultOfFun | exit(Reason)</name>
<fsummary>Calls the <c>Fun</c> in a context that is not protected by a transaction.</fsummary>
<desc>
<marker id="async_dirty"></marker>
@@ -493,7 +493,7 @@ mnesia:add_table_index(person, age)</code>
</desc>
</func>
<func>
- <name>backup(Opaque [, BackupMod]) -> ok | {error,Reason}</name>
+ <name since="">backup(Opaque [, BackupMod]) -> ok | {error,Reason}</name>
<fsummary>Backs up all tables in the database.</fsummary>
<desc>
<marker id="backup"></marker>
@@ -505,7 +505,7 @@ mnesia:add_table_index(person, age)</code>
</desc>
</func>
<func>
- <name>backup_checkpoint(Name, Opaque [, BackupMod]) -> ok | {error,Reason}</name>
+ <name since="">backup_checkpoint(Name, Opaque [, BackupMod]) -> ok | {error,Reason}</name>
<fsummary>Backs up all tables in a checkpoint.</fsummary>
<desc>
<marker id="backup_checkpoint"></marker>
@@ -520,7 +520,7 @@ mnesia:add_table_index(person, age)</code>
</desc>
</func>
<func>
- <name>change_config(Config, Value) -> {error, Reason} | {ok, ReturnValue}</name>
+ <name since="">change_config(Config, Value) -> {error, Reason} | {ok, ReturnValue}</name>
<fsummary>Changes a configuration parameter.</fsummary>
<desc>
<marker id="change_config"></marker>
@@ -554,7 +554,7 @@ mnesia:add_table_index(person, age)</code>
</desc>
</func>
<func>
- <name>change_table_access_mode(Tab, AccessMode) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">change_table_access_mode(Tab, AccessMode) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Changes the access mode for the table.</fsummary>
<desc>
<marker id="change_table_access_mode"></marker>
@@ -568,7 +568,7 @@ mnesia:add_table_index(person, age)</code>
</desc>
</func>
<func>
- <name>change_table_copy_type(Tab, Node, To) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">change_table_copy_type(Tab, Node, To) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Changes the storage type of a table.</fsummary>
<desc>
<marker id="change_table_copy_type"></marker>
@@ -585,7 +585,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
</desc>
</func>
<func>
- <name>change_table_load_order(Tab, LoadOrder) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">change_table_load_order(Tab, LoadOrder) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Changes the load order priority for the table.</fsummary>
<desc>
<marker id="change_table_load_order"></marker>
@@ -595,7 +595,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
</desc>
</func>
<func>
- <name>change_table_majority(Tab, Majority) -> {aborted, R} | {atomic, ok}</name>
+ <name since="OTP R14B03">change_table_majority(Tab, Majority) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Changes the majority check setting for the table.</fsummary>
<desc>
<p><c>Majority</c> must be a boolean. Default is <c>false</c>.
@@ -607,7 +607,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
</desc>
</func>
<func>
- <name>clear_table(Tab) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">clear_table(Tab) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Deletes all entries in a table.</fsummary>
<desc>
<marker id="clear_table"></marker>
@@ -615,7 +615,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
</desc>
</func>
<func>
- <name>create_schema(DiscNodes) -> ok | {error,Reason}</name>
+ <name since="">create_schema(DiscNodes) -> ok | {error,Reason}</name>
<fsummary>Creates a new schema on the specified nodes.</fsummary>
<desc>
<marker id="create_schema"></marker>
@@ -637,7 +637,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
</desc>
</func>
<func>
- <name>create_table(Name, TabDef) -> {atomic, ok} | {aborted, Reason}</name>
+ <name since="">create_table(Name, TabDef) -> {atomic, ok} | {aborted, Reason}</name>
<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>
@@ -799,7 +799,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>deactivate_checkpoint(Name) -> ok | {error, Reason}</name>
+ <name since="">deactivate_checkpoint(Name) -> ok | {error, Reason}</name>
<fsummary>Deactivates a checkpoint.</fsummary>
<desc>
<marker id="deactivate_checkpoint"></marker>
@@ -811,7 +811,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>del_table_copy(Tab, Node) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">del_table_copy(Tab, Node) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Deletes the replica of table <c>Tab</c> at node <c>Node</c>.</fsummary>
<desc>
<marker id="del_table_copy"></marker>
@@ -825,7 +825,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>del_table_index(Tab, AttrName) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">del_table_index(Tab, AttrName) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Deletes an index in a table.</fsummary>
<desc>
<marker id="del_table_index"></marker>
@@ -834,7 +834,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>delete({Tab, Key}) -> transaction abort | ok</name>
+ <name since="">delete({Tab, Key}) -> transaction abort | ok</name>
<fsummary>Deletes all records in table <c>Tab</c> with the key <c>Key</c>.</fsummary>
<desc>
<marker id="delete_2"></marker>
@@ -842,7 +842,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>delete(Tab, Key, LockKind) -> transaction abort | ok</name>
+ <name since="">delete(Tab, Key, LockKind) -> transaction abort | ok</name>
<fsummary>Deletes all records in table <c>Tab</c>with the key <c>Key</c>.</fsummary>
<desc>
<marker id="delete_3"></marker>
@@ -857,7 +857,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>delete_object(Record) -> transaction abort | ok</name>
+ <name since="">delete_object(Record) -> transaction abort | ok</name>
<fsummary>Delete a record.</fsummary>
<desc>
<marker id="delete_object_1"></marker>
@@ -866,7 +866,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>delete_object(Tab, Record, LockKind) -> transaction abort | ok</name>
+ <name since="">delete_object(Tab, Record, LockKind) -> transaction abort | ok</name>
<fsummary>Deletes a record.</fsummary>
<desc>
<marker id="delete_object_3"></marker>
@@ -883,7 +883,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>delete_schema(DiscNodes) -> ok | {error,Reason}</name>
+ <name since="">delete_schema(DiscNodes) -> ok | {error,Reason}</name>
<fsummary>Deletes the schema on the given nodes.</fsummary>
<desc>
<marker id="delete_schema"></marker>
@@ -904,7 +904,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>delete_table(Tab) -> {aborted, Reason} | {atomic, ok}</name>
+ <name since="">delete_table(Tab) -> {aborted, Reason} | {atomic, ok}</name>
<fsummary>Deletes permanently all replicas of table <c>Tab</c>.</fsummary>
<desc>
<marker id="delete_table"></marker>
@@ -912,7 +912,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_all_keys(Tab) -> KeyList | exit({aborted, Reason})</name>
+ <name since="">dirty_all_keys(Tab) -> KeyList | exit({aborted, Reason})</name>
<fsummary>Dirty search for all record keys in table.</fsummary>
<desc>
<marker id="delete_all_keys"></marker>
@@ -920,7 +920,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_delete({Tab, Key}) -> ok | exit({aborted, Reason})</name>
+ <name since="">dirty_delete({Tab, Key}) -> ok | exit({aborted, Reason})</name>
<fsummary>Dirty delete of a record.</fsummary>
<desc>
<marker id="dirty_delete"></marker>
@@ -928,14 +928,14 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_delete(Tab, Key) -> ok | exit({aborted, Reason})</name>
+ <name since="">dirty_delete(Tab, Key) -> ok | exit({aborted, Reason})</name>
<fsummary>Dirty delete of a record.</fsummary>
<desc>
<p>Dirty equivalent of the function <c>mnesia:delete/3</c>.</p>
</desc>
</func>
<func>
- <name>dirty_delete_object(Record)</name>
+ <name since="">dirty_delete_object(Record)</name>
<fsummary>Dirty delete of a record.</fsummary>
<desc>
<marker id="dirty_delete_object_1"></marker>
@@ -944,14 +944,14 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_delete_object(Tab, Record)</name>
+ <name since="">dirty_delete_object(Tab, Record)</name>
<fsummary>Dirty delete of a record.</fsummary>
<desc>
<p>Dirty equivalent of the function <c>mnesia:delete_object/3</c>.</p>
</desc>
</func>
<func>
- <name>dirty_first(Tab) -> Key | exit({aborted, Reason})</name>
+ <name since="">dirty_first(Tab) -> Key | exit({aborted, Reason})</name>
<fsummary>Returns the key for the first record in a table.</fsummary>
<desc>
<marker id="dirty_first"></marker>
@@ -967,7 +967,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_index_match_object(Pattern, Pos)</name>
+ <name since="">dirty_index_match_object(Pattern, Pos)</name>
<fsummary>Dirty pattern match using index.</fsummary>
<desc>
<marker id="dirty_index_match_object_2"></marker>
@@ -977,7 +977,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_index_match_object(Tab, Pattern, Pos)</name>
+ <name since="">dirty_index_match_object(Tab, Pattern, Pos)</name>
<fsummary>Dirty pattern match using index.</fsummary>
<desc>
<p>Dirty equivalent of the function
@@ -985,7 +985,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_index_read(Tab, SecondaryKey, Pos)</name>
+ <name since="">dirty_index_read(Tab, SecondaryKey, Pos)</name>
<fsummary>Dirty read using index.</fsummary>
<desc>
<marker id="dirty_index_read"></marker>
@@ -994,7 +994,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_last(Tab) -> Key | exit({aborted, Reason})</name>
+ <name since="">dirty_last(Tab) -> Key | exit({aborted, Reason})</name>
<fsummary>Returns the key for the last record in a table.</fsummary>
<desc>
<marker id="dirty_last"></marker>
@@ -1006,7 +1006,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_match_object(Pattern) -> RecordList | exit({aborted, Reason})</name>
+ <name since="">dirty_match_object(Pattern) -> RecordList | exit({aborted, Reason})</name>
<fsummary>Dirty pattern match pattern.</fsummary>
<desc>
<marker id="dirty_match_object_1"></marker>
@@ -1015,7 +1015,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_match_object(Tab, Pattern) -> RecordList | exit({aborted, Reason})</name>
+ <name since="">dirty_match_object(Tab, Pattern) -> RecordList | exit({aborted, Reason})</name>
<fsummary>Dirty pattern match pattern.</fsummary>
<desc>
<p>Dirty equivalent of the function
@@ -1023,7 +1023,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_next(Tab, Key) -> Key | exit({aborted, Reason})</name>
+ <name since="">dirty_next(Tab, Key) -> Key | exit({aborted, Reason})</name>
<fsummary>Return the next key in a table.</fsummary>
<desc>
<marker id="dirty_next"></marker>
@@ -1038,7 +1038,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_prev(Tab, Key) -> Key | exit({aborted, Reason})</name>
+ <name since="">dirty_prev(Tab, Key) -> Key | exit({aborted, Reason})</name>
<fsummary>Returns the previous key in a table.</fsummary>
<desc>
<marker id="dirty_prev"></marker>
@@ -1050,7 +1050,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_read({Tab, Key}) -> ValueList | exit({aborted, Reason}</name>
+ <name since="">dirty_read({Tab, Key}) -> ValueList | exit({aborted, Reason}</name>
<fsummary>Dirty read of records.</fsummary>
<desc>
<marker id="dirty_read"></marker>
@@ -1058,14 +1058,14 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_read(Tab, Key) -> ValueList | exit({aborted, Reason}</name>
+ <name since="">dirty_read(Tab, Key) -> ValueList | exit({aborted, Reason}</name>
<fsummary>Dirty read of records.</fsummary>
<desc>
<p>Dirty equivalent of the function <c>mnesia:read/3</c>.</p>
</desc>
</func>
<func>
- <name>dirty_select(Tab, MatchSpec) -> ValueList | exit({aborted, Reason}</name>
+ <name since="">dirty_select(Tab, MatchSpec) -> ValueList | exit({aborted, Reason}</name>
<fsummary>Dirty matches the objects in <c>Tab</c> against <c>MatchSpec</c>.</fsummary>
<desc>
<marker id="dirty_select"></marker>
@@ -1073,7 +1073,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_slot(Tab, Slot) -> RecordList | exit({aborted, Reason})</name>
+ <name since="">dirty_slot(Tab, Slot) -> RecordList | exit({aborted, Reason})</name>
<fsummary>Returns the list of records that are associated with <c>Slot</c> in a table.</fsummary>
<desc>
<marker id="dirty_slot"></marker>
@@ -1089,7 +1089,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_update_counter({Tab, Key}, Incr) -> NewVal | exit({aborted, Reason})</name>
+ <name since="">dirty_update_counter({Tab, Key}, Incr) -> NewVal | exit({aborted, Reason})</name>
<fsummary>Dirty update of a counter record.</fsummary>
<desc>
<marker id="dirty_update_counter"></marker>
@@ -1097,7 +1097,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_update_counter(Tab, Key, Incr) -> NewVal | exit({aborted, Reason})</name>
+ <name since="">dirty_update_counter(Tab, Key, Incr) -> NewVal | exit({aborted, Reason})</name>
<fsummary>Dirty update of a counter record.</fsummary>
<desc>
<p>Mnesia has no special counter records. However,
@@ -1126,7 +1126,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_write(Record) -> ok | exit({aborted, Reason})</name>
+ <name since="">dirty_write(Record) -> ok | exit({aborted, Reason})</name>
<fsummary>Dirty write of a record.</fsummary>
<desc>
<marker id="dirty_write_1"></marker>
@@ -1135,14 +1135,14 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dirty_write(Tab, Record) -> ok | exit({aborted, Reason})</name>
+ <name since="">dirty_write(Tab, Record) -> ok | exit({aborted, Reason})</name>
<fsummary>Dirty write of a record.</fsummary>
<desc>
<p>Dirty equivalent of the function <c>mnesia:write/3</c>.</p>
</desc>
</func>
<func>
- <name>dump_log() -> dumped</name>
+ <name since="">dump_log() -> dumped</name>
<fsummary>Performs a user-initiated dump of the local log file.</fsummary>
<desc>
<marker id="dump_log"></marker>
@@ -1156,7 +1156,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dump_tables(TabList) -> {atomic, ok} | {aborted, Reason}</name>
+ <name since="">dump_tables(TabList) -> {atomic, ok} | {aborted, Reason}</name>
<fsummary>Dumps all RAM tables to disc.</fsummary>
<desc>
<marker id="dump_tables"></marker>
@@ -1168,7 +1168,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>dump_to_textfile(Filename)</name>
+ <name since="">dump_to_textfile(Filename)</name>
<fsummary>Dumps local tables into a text file.</fsummary>
<desc>
<marker id="dump_to_textfile"></marker>
@@ -1181,7 +1181,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>error_description(Error) -> String</name>
+ <name since="">error_description(Error) -> String</name>
<fsummary>Returns a string describing a particular Mnesia error.</fsummary>
<desc>
<marker id="error_description"></marker>
@@ -1259,7 +1259,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>ets(Fun, [, Args]) -> ResultOfFun | exit(Reason)</name>
+ <name since="">ets(Fun, [, Args]) -> ResultOfFun | exit(Reason)</name>
<fsummary>Calls the <c>Fun</c> in a raw context that is not protected by a transaction.</fsummary>
<desc>
<marker id="ets"></marker>
@@ -1278,7 +1278,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>first(Tab) -> Key | transaction abort</name>
+ <name since="">first(Tab) -> Key | transaction abort</name>
<fsummary>Returns the key for the first record in a table.</fsummary>
<desc>
<marker id="first"></marker>
@@ -1293,7 +1293,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>foldl(Function, Acc, Table) -> NewAcc | transaction abort</name>
+ <name since="">foldl(Function, Acc, Table) -> NewAcc | transaction abort</name>
<fsummary>Calls <c>Function</c> for each record in <c>Table</c>.</fsummary>
<desc>
<marker id="foldl"></marker>
@@ -1306,7 +1306,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>foldr(Function, Acc, Table) -> NewAcc | transaction abort</name>
+ <name since="">foldr(Function, Acc, Table) -> NewAcc | transaction abort</name>
<fsummary>Calls <c>Function</c> for each record in <c>Table</c>.</fsummary>
<desc>
<marker id="foldr"></marker>
@@ -1317,7 +1317,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>force_load_table(Tab) -> yes | ErrorDescription</name>
+ <name since="">force_load_table(Tab) -> yes | ErrorDescription</name>
<fsummary>Forces a table to be loaded into the system.</fsummary>
<desc>
<marker id="force_load_table"></marker>
@@ -1335,7 +1335,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>index_match_object(Pattern, Pos) -> transaction abort | ObjList</name>
+ <name since="">index_match_object(Pattern, Pos) -> transaction abort | ObjList</name>
<fsummary>Matches records and uses index information.</fsummary>
<desc>
<marker id="index_match_object_2"></marker>
@@ -1345,7 +1345,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>index_match_object(Tab, Pattern, Pos, LockKind) -> transaction abort | ObjList</name>
+ <name since="">index_match_object(Tab, Pattern, Pos, LockKind) -> transaction abort | ObjList</name>
<fsummary>Matches records and uses index information.</fsummary>
<desc>
<marker id="index_match_object_4"></marker>
@@ -1377,7 +1377,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>index_read(Tab, SecondaryKey, Pos) -> transaction abort | RecordList</name>
+ <name since="">index_read(Tab, SecondaryKey, Pos) -> transaction abort | RecordList</name>
<fsummary>Reads records through index table.</fsummary>
<desc>
<marker id="index_read"></marker>
@@ -1397,7 +1397,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>info() -> ok</name>
+ <name since="">info() -> ok</name>
<fsummary>Prints system information on the terminal.</fsummary>
<desc>
<marker id="info"></marker>
@@ -1408,7 +1408,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>install_fallback(Opaque) -> ok | {error,Reason}</name>
+ <name since="">install_fallback(Opaque) -> ok | {error,Reason}</name>
<fsummary>Installs a backup as fallback.</fsummary>
<desc>
<marker id="install_fallback_1"></marker>
@@ -1417,7 +1417,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>install_fallback(Opaque), BackupMod) -> ok | {error,Reason}</name>
+ <name since="">install_fallback(Opaque), BackupMod) -> ok | {error,Reason}</name>
<fsummary>Installs a backup as fallback.</fsummary>
<desc>
<p>Calls <c>mnesia:install_fallback(Opaque, Args)</c>, where
@@ -1425,7 +1425,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>install_fallback(Opaque, Args) -> ok | {error,Reason}</name>
+ <name since="">install_fallback(Opaque, Args) -> ok | {error,Reason}</name>
<fsummary>Installs a backup as fallback.</fsummary>
<desc>
<p>Installs a backup as fallback. The fallback is used to
@@ -1483,7 +1483,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>is_transaction() -> boolean</name>
+ <name since="">is_transaction() -> boolean</name>
<fsummary>Checks if code is running in a transaction.</fsummary>
<desc>
<marker id="is_transaction"></marker>
@@ -1492,7 +1492,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>last(Tab) -> Key | transaction abort</name>
+ <name since="">last(Tab) -> Key | transaction abort</name>
<fsummary>Returns the key for the last record in a table.</fsummary>
<desc>
<p>Works exactly like
@@ -1503,7 +1503,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>load_textfile(Filename)</name>
+ <name since="">load_textfile(Filename)</name>
<fsummary>Loads tables from a text file.</fsummary>
<desc>
<marker id="load_textfile"></marker>
@@ -1516,7 +1516,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>lock(LockItem, LockKind) -> Nodes | ok | transaction abort</name>
+ <name since="">lock(LockItem, LockKind) -> Nodes | ok | transaction abort</name>
<fsummary>Explicit grab lock.</fsummary>
<desc>
<marker id="lock"></marker>
@@ -1605,7 +1605,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>match_object(Pattern) -> transaction abort | RecList</name>
+ <name since="">match_object(Pattern) -> transaction abort | RecList</name>
<fsummary>Matches <c>Pattern</c> for records.</fsummary>
<desc>
<marker id="match_object_1"></marker>
@@ -1614,7 +1614,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>match_object(Tab, Pattern, LockKind) -> transaction abort | RecList</name>
+ <name since="">match_object(Tab, Pattern, LockKind) -> transaction abort | RecList</name>
<fsummary>Matches <c>Pattern</c> for records.</fsummary>
<desc>
<marker id="match_object_3"></marker>
@@ -1639,7 +1639,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>move_table_copy(Tab, From, To) -> {aborted, Reason} | {atomic, ok}</name>
+ <name since="">move_table_copy(Tab, From, To) -> {aborted, Reason} | {atomic, ok}</name>
<fsummary>Moves the copy of table <c>Tab</c> from node <c>From</c> to node <c>To</c>.</fsummary>
<desc>
<marker id="move_table_copy"></marker>
@@ -1653,7 +1653,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>next(Tab, Key) -> Key | transaction abort</name>
+ <name since="">next(Tab, Key) -> Key | transaction abort</name>
<fsummary>Returns the next key in a table.</fsummary>
<desc>
<marker id="next"></marker>
@@ -1665,7 +1665,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>prev(Tab, Key) -> Key | transaction abort</name>
+ <name since="">prev(Tab, Key) -> Key | transaction abort</name>
<fsummary>Returns the previous key in a table.</fsummary>
<desc>
<p>Works exactly like
@@ -1676,7 +1676,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>read({Tab, Key}) -> transaction abort | RecordList</name>
+ <name since="">read({Tab, Key}) -> transaction abort | RecordList</name>
<fsummary>Reads records(s) with a given key.</fsummary>
<desc>
<marker id="read_2"></marker>
@@ -1684,14 +1684,14 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>read(Tab, Key) -> transaction abort | RecordList</name>
+ <name since="">read(Tab, Key) -> transaction abort | RecordList</name>
<fsummary>Reads records(s) with a given key.</fsummary>
<desc>
<p>Calls function <c>mnesia:read(Tab, Key, read)</c>.</p>
</desc>
</func>
<func>
- <name>read(Tab, Key, LockKind) -> transaction abort | RecordList</name>
+ <name since="">read(Tab, Key, LockKind) -> transaction abort | RecordList</name>
<fsummary>Reads records(s) with a given key.</fsummary>
<desc>
<marker id="read_3"></marker>
@@ -1716,7 +1716,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>read_lock_table(Tab) -> ok | transaction abort</name>
+ <name since="">read_lock_table(Tab) -> ok | transaction abort</name>
<fsummary>Sets a read lock on an entire table.</fsummary>
<desc>
<marker id="read_lock_table"></marker>
@@ -1725,7 +1725,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>report_event(Event) -> ok</name>
+ <name since="">report_event(Event) -> ok</name>
<fsummary>Reports a user event to the Mnesia event handler.</fsummary>
<desc>
<marker id="report_event"></marker>
@@ -1743,7 +1743,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>restore(Opaque, Args) -> {atomic, RestoredTabs} |{aborted, Reason}</name>
+ <name since="">restore(Opaque, Args) -> {atomic, RestoredTabs} |{aborted, Reason}</name>
<fsummary>Online restore of backup.</fsummary>
<desc>
<marker id="restore"></marker>
@@ -1803,7 +1803,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>s_delete({Tab, Key}) -> ok | transaction abort</name>
+ <name since="">s_delete({Tab, Key}) -> ok | transaction abort</name>
<fsummary>Sets sticky lock and delete records.</fsummary>
<desc>
<marker id="s_delete"></marker>
@@ -1812,7 +1812,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>s_delete_object(Record) -> ok | transaction abort</name>
+ <name since="">s_delete_object(Record) -> ok | transaction abort</name>
<fsummary>Sets sticky lock and delete record.</fsummary>
<desc>
<marker id="s_delete_object"></marker>
@@ -1822,7 +1822,7 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>s_write(Record) -> ok | transaction abort</name>
+ <name since="">s_write(Record) -> ok | transaction abort</name>
<fsummary>Writes <c>Record</c> and sets sticky lock.</fsummary>
<desc>
<marker id="s_write"></marker>
@@ -1832,21 +1832,21 @@ mnesia:create_table(person,
</desc>
</func>
<func>
- <name>schema() -> ok</name>
+ <name since="">schema() -> ok</name>
<fsummary>Prints information about all table definitions on the terminal.</fsummary>
<desc>
<p>Prints information about all table definitions on the terminal.</p>
</desc>
</func>
<func>
- <name>schema(Tab) -> ok</name>
+ <name since="">schema(Tab) -> ok</name>
<fsummary>Prints information about one table definition on the terminal.</fsummary>
<desc>
<p>Prints information about one table definition on the terminal.</p>
</desc>
</func>
<func>
- <name>select(Tab, MatchSpec [, Lock]) -> transaction abort | [Object]</name>
+ <name since="">select(Tab, MatchSpec [, Lock]) -> transaction abort | [Object]</name>
<fsummary>Matches the objects in <c>Tab</c> against <c>MatchSpec</c>.</fsummary>
<desc>
<marker id="select_2_3"></marker>
@@ -1884,7 +1884,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>select(Tab, MatchSpec, NObjects, Lock) -> transaction abort | {[Object],Cont} | '$end_of_table'</name>
+ <name since="">select(Tab, MatchSpec, NObjects, Lock) -> transaction abort | {[Object],Cont} | '$end_of_table'</name>
<fsummary>Matches the objects in <c>Tab</c> against <c>MatchSpec</c>.</fsummary>
<desc>
<marker id="select_4"></marker>
@@ -1907,7 +1907,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>select(Cont) -> transaction abort | {[Object],Cont} | '$end_of_table'</name>
+ <name since="">select(Cont) -> transaction abort | {[Object],Cont} | '$end_of_table'</name>
<fsummary>Continues selecting objects.</fsummary>
<desc>
<p>Selects more objects with the match specification initiated
@@ -1919,7 +1919,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>set_debug_level(Level) -> OldLevel</name>
+ <name since="">set_debug_level(Level) -> OldLevel</name>
<fsummary>Changes the internal debug level of Mnesia.</fsummary>
<desc>
<marker id="set_debug_level"></marker>
@@ -1930,7 +1930,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>set_master_nodes(MasterNodes) -> ok | {error, Reason}</name>
+ <name since="">set_master_nodes(MasterNodes) -> ok | {error, Reason}</name>
<fsummary>Sets the master nodes for all tables.</fsummary>
<desc>
<marker id="set_master_nodes_1"></marker>
@@ -1943,7 +1943,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>set_master_nodes(Tab, MasterNodes) -> ok | {error, Reason}</name>
+ <name since="">set_master_nodes(Tab, MasterNodes) -> ok | {error, Reason}</name>
<fsummary>Sets the master nodes for a table.</fsummary>
<desc>
<marker id="set_master_nodes_2"></marker>
@@ -1968,14 +1968,14 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>snmp_close_table(Tab) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">snmp_close_table(Tab) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Removes the possibility for SNMP to manipulate the table.</fsummary>
<desc>
<p>Removes the possibility for SNMP to manipulate the table.</p>
</desc>
</func>
<func>
- <name>snmp_get_mnesia_key(Tab, RowIndex) -> {ok, Key} | undefined</name>
+ <name since="">snmp_get_mnesia_key(Tab, RowIndex) -> {ok, Key} | undefined</name>
<fsummary>Gets the corresponding Mnesia key from an SNMP index.</fsummary>
<type>
<v>Tab ::= atom()</v>
@@ -1990,7 +1990,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>snmp_get_next_index(Tab, RowIndex) -> {ok, NextIndex} | endOfTable</name>
+ <name since="">snmp_get_next_index(Tab, RowIndex) -> {ok, NextIndex} | endOfTable</name>
<fsummary>Gets the index of the next lexicographical row.</fsummary>
<type>
<v>Tab ::= atom()</v>
@@ -2006,7 +2006,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>snmp_get_row(Tab, RowIndex) -> {ok, Row} | undefined</name>
+ <name since="">snmp_get_row(Tab, RowIndex) -> {ok, Row} | undefined</name>
<fsummary>Retrieves a row indexed by an SNMP index.</fsummary>
<type>
<v>Tab ::= atom()</v>
@@ -2019,7 +2019,7 @@ mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),</code>
</desc>
</func>
<func>
- <name>snmp_open_table(Tab, SnmpStruct) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">snmp_open_table(Tab, SnmpStruct) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Organizes a Mnesia table as an SNMP table.</fsummary>
<type>
<v>Tab ::= atom()</v>
@@ -2073,10 +2073,17 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>start() -> ok | {error, Reason}</name>
+ <name since="">start() -> ok | {error, Reason}</name>
<fsummary>Starts a local Mnesia system.</fsummary>
<desc>
<marker id="start"></marker>
+ <p>Mnesia startup is asynchronous. The function call
+ <c>mnesia:start()</c> returns the atom <c>ok</c> and then
+ starts to initialize the different tables. Depending on the
+ size of the database, this can take some time, and the
+ application programmer must wait for the tables that the
+ application needs before they can be used. This is achieved
+ by using the function <c>mnesia:wait_for_tables/2</c>.</p>
<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
@@ -2108,7 +2115,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>stop() -> stopped</name>
+ <name since="">stop() -> stopped</name>
<fsummary>Stops Mnesia locally.</fsummary>
<desc>
<marker id="stop"></marker>
@@ -2117,7 +2124,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>subscribe(EventCategory) -> {ok, Node} | {error, Reason}</name>
+ <name since="">subscribe(EventCategory) -> {ok, Node} | {error, Reason}</name>
<fsummary>Subscribes to events of type <c>EventCategory</c>.</fsummary>
<desc>
<marker id="subscribe"></marker>
@@ -2127,7 +2134,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>sync_dirty(Fun, [, Args]) -> ResultOfFun | exit(Reason)</name>
+ <name since="">sync_dirty(Fun, [, Args]) -> ResultOfFun | exit(Reason)</name>
<fsummary>Calls the <c>Fun</c> in a context that is not protected by a transaction.</fsummary>
<desc>
<marker id="sync_dirty"></marker>
@@ -2143,7 +2150,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>sync_log() -> ok | {error, Reason}</name>
+ <name since="OTP 17.0">sync_log() -> ok | {error, Reason}</name>
<fsummary>Performs a file sync of the local log file.</fsummary>
<desc>
<p>Ensures that the local transaction log file is synced to disk.
@@ -2153,7 +2160,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>sync_transaction(Fun, [[, Args], Retries]) -> {aborted, Reason} | {atomic, ResultOfFun}</name>
+ <name since="">sync_transaction(Fun, [[, Args], Retries]) -> {aborted, Reason} | {atomic, ResultOfFun}</name>
<fsummary>Synchronously executes a transaction.</fsummary>
<desc>
<marker id="sync_transaction"></marker>
@@ -2166,7 +2173,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>system_info(InfoKey) -> Info | exit({aborted, Reason})</name>
+ <name since="">system_info(InfoKey) -> Info | exit({aborted, Reason})</name>
<fsummary>Returns information about the Mnesia system.</fsummary>
<desc>
<marker id="system_info"></marker>
@@ -2353,7 +2360,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>table(Tab [,[Option]]) -> QueryHandle</name>
+ <name since="">table(Tab [,[Option]]) -> QueryHandle</name>
<fsummary>Return a QLC query handle.</fsummary>
<desc>
<marker id="table"></marker>
@@ -2408,7 +2415,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>table_info(Tab, InfoKey) -> Info | exit({aborted, Reason})</name>
+ <name since="">table_info(Tab, InfoKey) -> Info | exit({aborted, Reason})</name>
<fsummary>Returns local information about table.</fsummary>
<desc>
<marker id="table_info"></marker>
@@ -2560,7 +2567,7 @@ mnesia:create_table(employee,
</desc>
</func>
<func>
- <name>transaction(Fun [[, Args], Retries]) -> {aborted, Reason} | {atomic, ResultOfFun}</name>
+ <name since="">transaction(Fun [[, Args], Retries]) -> {aborted, Reason} | {atomic, ResultOfFun}</name>
<fsummary>Executes a transaction.</fsummary>
<desc>
<marker id="transaction"></marker>
@@ -2628,7 +2635,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>transform_table(Tab, Fun, NewAttributeList, NewRecordName) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">transform_table(Tab, Fun, NewAttributeList, NewRecordName) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Changes format on all records in table <c>Tab</c>.</fsummary>
<desc>
<marker id="transform_table_4"></marker>
@@ -2649,7 +2656,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>transform_table(Tab, Fun, NewAttributeList) -> {aborted, R} | {atomic, ok}</name>
+ <name since="">transform_table(Tab, Fun, NewAttributeList) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Changes format on all records in table <c>Tab</c>.</fsummary>
<desc>
<p>Calls <c>mnesia:transform_table(Tab, Fun,
@@ -2658,7 +2665,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>traverse_backup(Source, [SourceMod,] Target, [TargetMod,] Fun, Acc) -> {ok, LastAcc} | {error, Reason}</name>
+ <name since="">traverse_backup(Source, [SourceMod,] Target, [TargetMod,] Fun, Acc) -> {ok, LastAcc} | {error, Reason}</name>
<fsummary>Traversal of a backup.</fsummary>
<desc>
<marker id="traverse_backup"></marker>
@@ -2689,7 +2696,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>uninstall_fallback() -> ok | {error,Reason}</name>
+ <name since="">uninstall_fallback() -> ok | {error,Reason}</name>
<fsummary>Uninstalls a fallback.</fsummary>
<desc>
<marker id="uninstall_fallback_0"></marker>
@@ -2698,7 +2705,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>uninstall_fallback(Args) -> ok | {error,Reason}</name>
+ <name since="">uninstall_fallback(Args) -> ok | {error,Reason}</name>
<fsummary>Uninstalls a fallback.</fsummary>
<desc>
<p>Deinstalls a fallback before it
@@ -2725,7 +2732,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>unsubscribe(EventCategory) -> {ok, Node} | {error, Reason}</name>
+ <name since="">unsubscribe(EventCategory) -> {ok, Node} | {error, Reason}</name>
<fsummary>Subscribes to events of type <c>EventCategory</c>.</fsummary>
<desc>
<marker id="unsubscribe"></marker>
@@ -2735,7 +2742,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>wait_for_tables(TabList, Timeout) -> ok | {timeout, BadTabList} | {error, Reason}</name>
+ <name since="">wait_for_tables(TabList, Timeout) -> ok | {timeout, BadTabList} | {error, Reason}</name>
<fsummary>Waits for tables to be accessible.</fsummary>
<desc>
<marker id="wait_for_tables"></marker>
@@ -2746,7 +2753,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>wread({Tab, Key}) -> transaction abort | RecordList</name>
+ <name since="">wread({Tab, Key}) -> transaction abort | RecordList</name>
<fsummary>Reads records with given key.</fsummary>
<desc>
<marker id="wread"></marker>
@@ -2754,7 +2761,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>write(Record) -> transaction abort | ok</name>
+ <name since="">write(Record) -> transaction abort | ok</name>
<fsummary>Writes a record into the database.</fsummary>
<desc>
<marker id="write_1"></marker>
@@ -2763,7 +2770,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>write(Tab, Record, LockKind) -> transaction abort | ok</name>
+ <name since="">write(Tab, Record, LockKind) -> transaction abort | ok</name>
<fsummary>Writes a record into the database.</fsummary>
<desc>
<marker id="write_3"></marker>
@@ -2779,7 +2786,7 @@ raise(Name, Amount) ->
</desc>
</func>
<func>
- <name>write_lock_table(Tab) -> ok | transaction abort</name>
+ <name since="">write_lock_table(Tab) -> ok | transaction abort</name>
<fsummary>Sets write lock on an entire table.</fsummary>
<desc>
<marker id="write_lock_table"></marker>
diff --git a/lib/mnesia/doc/src/mnesia_frag_hash.xml b/lib/mnesia/doc/src/mnesia_frag_hash.xml
index 51b32129b6..ccaba412d0 100644
--- a/lib/mnesia/doc/src/mnesia_frag_hash.xml
+++ b/lib/mnesia/doc/src/mnesia_frag_hash.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2002</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -34,7 +34,7 @@
<rev>A</rev>
<file>mnesia_frag_hash.sgml</file>
</header>
- <module>mnesia_frag_hash</module>
+ <module since="">mnesia_frag_hash</module>
<modulesummary>Defines mnesia_frag_hash callback behavior</modulesummary>
<description>
<p>This module defines a callback behavior for user-defined hash
@@ -50,7 +50,7 @@
<funcs>
<func>
- <name>init_state(Tab, State) -> NewState | abort(Reason)</name>
+ <name since="">init_state(Tab, State) -> NewState | abort(Reason)</name>
<fsummary>Initiates the hash state for a new table.</fsummary>
<type>
<v>Tab = atom()</v>
@@ -72,7 +72,7 @@
</desc>
</func>
<func>
- <name>add_frag(State) -> {NewState, IterFrags, AdditionalLockFrags} | abort(Reason)</name>
+ <name since="">add_frag(State) -> {NewState, IterFrags, AdditionalLockFrags} | abort(Reason)</name>
<fsummary>Starts when a new fragment is added to a fragmented table.</fsummary>
<type>
<v>State = term()</v>
@@ -100,7 +100,7 @@
</desc>
</func>
<func>
- <name>del_frag(State) -> {NewState, IterFrags, AdditionalLockFrags} | abort(Reason)</name>
+ <name since="">del_frag(State) -> {NewState, IterFrags, AdditionalLockFrags} | abort(Reason)</name>
<fsummary>Starts when a fragment is deleted from a fragmented table.</fsummary>
<type>
<v>State = term()</v>
@@ -127,10 +127,10 @@
</desc>
</func>
<func>
- <name>key_to_frag_number(State, Key) -> FragNum | abort(Reason)</name>
+ <name since="">key_to_frag_number(State, Key) -> FragNum | abort(Reason)</name>
<fsummary>Resolves the key of a record into a fragment number.</fsummary>
<type>
- <v>FragNum = integer()()</v>
+ <v>FragNum = integer()</v>
<v>Reason = term()</v>
</type>
<desc>
@@ -140,7 +140,7 @@
</desc>
</func>
<func>
- <name>match_spec_to_frag_numbers(State, MatchSpec) -> FragNums | abort(Reason)</name>
+ <name since="">match_spec_to_frag_numbers(State, MatchSpec) -> FragNums | abort(Reason)</name>
<fsummary>Resolves a <c>MatchSpec</c> into a list of fragment numbers.</fsummary>
<type>
<v>MatcSpec = ets_select_match_spec()</v>
diff --git a/lib/mnesia/doc/src/mnesia_registry.xml b/lib/mnesia/doc/src/mnesia_registry.xml
index a76f716981..18ddc4ab9e 100644
--- a/lib/mnesia/doc/src/mnesia_registry.xml
+++ b/lib/mnesia/doc/src/mnesia_registry.xml
@@ -34,7 +34,7 @@
<rev>A</rev>
<file>mnesia_registry.sgml</file>
</header>
- <module>mnesia_registry</module>
+ <module since="">mnesia_registry</module>
<modulesummary>Dump support for registries in erl_interface.</modulesummary>
<description>
<p>This module is usually part of the <c>erl_interface</c>
@@ -57,7 +57,7 @@
<funcs>
<func>
- <name>create_table(Tab) -> ok | exit(Reason)</name>
+ <name since="">create_table(Tab) -> ok | exit(Reason)</name>
<fsummary>Creates a registry table in Mnesia.</fsummary>
<desc>
<p>A wrapper function for <c>mnesia:create_table/2</c>,
@@ -73,7 +73,7 @@
</desc>
</func>
<func>
- <name>create_table(Tab, TabDef) -> ok | exit(Reason)</name>
+ <name since="">create_table(Tab, TabDef) -> ok | exit(Reason)</name>
<fsummary>Creates a customized registry table in Mnesia.</fsummary>
<desc>
<p>A wrapper function for <c>mnesia:create_table/2</c>,
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 7134e3d1e4..22fb5e8c48 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -39,7 +39,70 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.15.4</title>
+ <section><title>Mnesia 4.15.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Avoid overload warnings caused by a race condition.</p>
+ <p>
+ Own Id: OTP-15619 Aux Id: ERIERL-310 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed type spec for <c>mnesia:change_config/2</c>.</p>
+ <p>
+ Own Id: OTP-15201 Aux Id: PR-1881 </p>
+ </item>
+ <item>
+ <p>
+ When master node is set do not force a load from
+ ram_copies replica when there are no available
+ disc_copies, since that would load an empty table. Wait
+ until a disk replica is available or until user
+ explicitly force_loads the table.</p>
+ <p>
+ Own Id: OTP-15221 Aux Id: ERIERL-217 </p>
+ </item>
+ <item>
+ <p>
+ Allow to add replicas even if all other replicas are down
+ when the other replicas are not stored on disk.</p>
+ <p>
+ Own Id: OTP-15226 Aux Id: ERIERL-221 </p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>mnesia:delete_object/1</c> bug, where
+ delete_object was deleting the record if it was written
+ in the same transaction even if it was written to a
+ different value.</p>
+ <p>
+ Own Id: OTP-15231 Aux Id: PR-1858 </p>
+ </item>
+ <item>
+ <p>
+ Fixed a bug where the bag table index data was not
+ deleted when objects were deleted.</p>
+ <p>
+ Own Id: OTP-15243</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.4</title>
<section><title>Improvements and New Features</title>
<list>
@@ -54,6 +117,32 @@
</section>
+<section><title>Mnesia 4.15.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When master node is set do not force a load from
+ ram_copies replica when there are no available
+ disc_copies, since that would load an empty table. Wait
+ until a disk replica is available or until user
+ explicitly force_loads the table.</p>
+ <p>
+ Own Id: OTP-15221 Aux Id: ERIERL-217 </p>
+ </item>
+ <item>
+ <p>
+ Allow to add replicas even if all other replicas are down
+ when the other replicase are not stored on disk.</p>
+ <p>
+ Own Id: OTP-15226 Aux Id: ERIERL-221 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Mnesia 4.15.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index e298904e2a..223dba3f90 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -168,6 +168,9 @@
-type snmp_struct() :: [{atom(), snmp_type() | tuple_of(snmp_type())}].
-type snmp_type() :: 'fix_string' | 'string' | 'integer'.
-type tuple_of(_T) :: tuple().
+-type config_key() :: extra_db_nodes | dc_dump_limit.
+-type config_value() :: [node()] | number().
+-type config_result() :: {ok, config_value()} | {error, term()}.
-define(DEFAULT_ACCESS, ?MODULE).
@@ -278,7 +281,8 @@ stop() ->
Other -> Other
end.
--spec change_config(Config::atom(), Value::_) -> ok | {error, term()}.
+-spec change_config(Config::config_key(), Value::config_value()) ->
+ config_result().
change_config(extra_db_nodes, Ns) when is_list(Ns) ->
mnesia_controller:connect_nodes(Ns);
change_config(dc_dump_limit, N) when is_number(N), N > 0 ->
@@ -779,12 +783,16 @@ do_delete_object(Tid, Ts, Tab, Val, LockKind) ->
?ets_insert(Store, {Oid, Val, delete_object});
_ ->
case ?ets_match_object(Store, {Oid, '_', write}) of
- [] ->
- ?ets_match_delete(Store, {Oid, Val, '_'}),
- ?ets_insert(Store, {Oid, Val, delete_object});
- _ ->
- ?ets_delete(Store, Oid),
- ?ets_insert(Store, {Oid, Oid, delete})
+ [] ->
+ ?ets_match_delete(Store, {Oid, Val, '_'}),
+ ?ets_insert(Store, {Oid, Val, delete_object});
+ Ops ->
+ case lists:member({Oid, Val, write}, Ops) of
+ true ->
+ ?ets_delete(Store, Oid),
+ ?ets_insert(Store, {Oid, Oid, delete});
+ false -> ok
+ end
end
end,
ok;
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index f81ba783f2..882de0d613 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -772,22 +772,6 @@ handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
end;
-handle_call({net_load, Tab, Cs}, From, State) ->
- State2 =
- case State#state.schema_is_merged of
- true ->
- Worker = #net_load{table = Tab,
- opt_reply_to = From,
- reason = {dumper,{add_table_copy, unknown}},
- cstruct = Cs
- },
- add_worker(Worker, State);
- false ->
- reply(From, {not_loaded, schema_not_merged}),
- State
- end,
- noreply(State2);
-
handle_call(Msg, From, State) when State#state.schema_is_merged /= true ->
%% Buffer early messages
Msgs = State#state.early_msgs,
@@ -1457,7 +1441,8 @@ orphan_tables([Tab | Tabs], Node, Ns, Local, Remote) ->
L = [Tab | Local],
orphan_tables(Tabs, Node, Ns, L, Remote);
Masters ->
- R = [{Tab, Masters} | Remote],
+ %% Do not disc_load table from RamCopyHolders
+ R = [{Tab, Masters -- RamCopyHolders} | Remote],
orphan_tables(Tabs, Node, Ns, Local, R)
end;
_ ->
@@ -2162,6 +2147,15 @@ load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=Repl
{dumper,{add_table_copy,_}} -> true;
_ -> false
end,
+
+ OnlyRamCopies = case Cs of
+ #cstruct{disc_copies = DC,
+ disc_only_copies = DOC,
+ external_copies = Ext} ->
+ [] =:= (DC ++ (DOC ++ Ext)) -- [node()];
+ _ ->
+ false
+ end,
if
ReadNode == node() ->
%% Already loaded locally
@@ -2173,6 +2167,8 @@ load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=Repl
end;
AccessMode == read_only, not AddTableCopy ->
fun() -> disc_load_table(Tab, Reason, ReplyTo) end;
+ Active =:= [], AddTableCopy, OnlyRamCopies ->
+ fun() -> disc_load_table(Tab, Reason, ReplyTo) end;
true ->
fun() ->
%% Either we cannot read the table yet
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index a2880d6cf4..cb2ee504f9 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -67,10 +67,10 @@ get_log_writes() ->
incr_log_writes() ->
Left = mnesia_lib:incr_counter(trans_log_writes_left, -1),
if
- Left > 0 ->
- ignore;
+ Left =:= 0 ->
+ adjust_log_writes(true);
true ->
- adjust_log_writes(true)
+ ignore
end.
adjust_log_writes(DoCast) ->
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index 917ada65df..098265d5fc 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -155,7 +155,7 @@ del_object_bag_([IxK|IxKs], Found, Type, Tab, Key, Obj, Ixt) ->
bag ->
db_match_erase(Ixt, {IxK, Key});
ordered ->
- db_erase(Ixt, {{IxK, Key}})
+ db_erase(Ixt, {IxK, Key})
end;
_ ->
ok
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index ebe924a86e..2cdae0c906 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -67,7 +67,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
EtsOpts = proplists:get_value(ets, StorageProps, []),
Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
- {dumper, _} -> %% Resources already allocated
+ {dumper, DR} when is_atom(DR) -> %% Resources already allocated
ignore;
_ ->
mnesia_monitor:mktab(Tab, Args),
@@ -91,8 +91,8 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
EtsOpts = proplists:get_value(ets, StorageProps, []),
Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
- {dumper, _} -> %% Resources allready allocated
- ignore;
+ {dumper, DR} when is_atom(DR) ->
+ ignore; %% Resources already allocated
_ ->
mnesia_monitor:mktab(Tab, Args),
Fname = mnesia_lib:tab2dcd(Tab),
@@ -131,7 +131,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies -
{repair, mnesia_monitor:get_env(auto_repair)}
| DetsOpts],
case Reason of
- {dumper, _} ->
+ {dumper, DR} when is_atom(DR) ->
mnesia_index:init_index(Tab, Storage),
snmpify(Tab, Storage),
set({Tab, load_node}, node()),
diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl
index 62199d8b9a..ccbfdc9738 100644
--- a/lib/mnesia/test/mnesia_durability_test.erl
+++ b/lib/mnesia/test/mnesia_durability_test.erl
@@ -46,6 +46,7 @@
master_nodes/1, starting_master_nodes/1,
master_on_non_local_tables/1,
remote_force_load_with_local_master_node/1,
+ master_node_with_ram_copy_2/1, master_node_with_ram_copy_3/1,
dump_ram_copies/1, dump_disc_copies/1, dump_disc_only/1]).
-include("mnesia_test_lib.hrl").
@@ -91,7 +92,8 @@ groups() ->
{load_tables_with_master_tables, [],
[master_nodes, starting_master_nodes,
master_on_non_local_tables,
- remote_force_load_with_local_master_node]},
+ remote_force_load_with_local_master_node,
+ master_node_with_ram_copy_2, master_node_with_ram_copy_3]},
{durability_of_dump_tables, [],
[dump_ram_copies, dump_disc_copies, dump_disc_only]}].
@@ -1165,6 +1167,107 @@ remote_force_load_with_local_master_node(Config) when is_list(Config) ->
?verify_mnesia(Nodes, []).
+master_node_with_ram_copy_2(Config) when is_list(Config) ->
+ [A, B] = Nodes = ?acquire_nodes(2, Config),
+ Tab = ?FUNCTION_NAME,
+ ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A]}, {ram_copies, [B]}])),
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+
+ %% Test that we don't load from ram_copies
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node require force_load
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+
+ ?match(yes, rpc:call(A, mnesia, force_load_table, [Tab])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+
+ ?verify_mnesia(Nodes, []).
+
+
+master_node_with_ram_copy_3(Config) when is_list(Config) ->
+ [A, B, C] = Nodes = ?acquire_nodes(3, Config),
+ Tab = ?FUNCTION_NAME,
+ ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A,C]}, {ram_copies, [B]}])),
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+
+ %% Test that we don't load from ram_copies
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node will wait until loaded
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node requires force load
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(ok, rpc:call(C, mnesia, set_master_nodes, [[B]])),
+
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(yes, rpc:call(C, mnesia, force_load_table, [Tab])),
+
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(C, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ ?verify_mnesia(Nodes, []).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1415,7 +1518,7 @@ do_disc_durability(Config,CopyType) ->
[{Tab_bag, 22, a_2222}], [{Tab_bag, 33, a_3333}],
[{Tab_set, counter, 10}]]),
- timer:sleep(1000), %% Debugging strange msgs..
+ timer:sleep(500), %% Debugging strange msgs..
?log("Flushed ~p ~n", [mnesia_test_lib:flush()]),
?verify_mnesia(Nodes, []).
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index eb1f987cf0..a451c8d0c8 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -31,10 +31,11 @@
db_node_lifecycle/1, evil_delete_db_node/1, start_and_stop/1,
checkpoint/1, table_lifecycle/1, storage_options/1,
add_copy_conflict/1, add_copy_when_going_down/1,
+ add_copy_with_down/1,
replica_management/1, clear_table_during_load/1,
schema_availability/1, local_content/1,
replica_location/1, user_properties/1, unsupp_user_props/1,
- sorted_ets/1,
+ sorted_ets/1, index_cleanup/1,
change_table_access_mode/1, change_table_load_order/1,
set_master_nodes/1, offline_set_master_nodes/1,
dump_tables/1, dump_log/1, wait_for_tables/1, force_load_table/1,
@@ -48,7 +49,7 @@
record_name_dirty_access_disc_only/1,
record_name_dirty_access_xets/1]).
--export([info_check/8]).
+-export([info_check/8, index_size/1]).
-define(cleanup(N, Config),
mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}],
@@ -65,13 +66,14 @@ all() ->
db_node_lifecycle, evil_delete_db_node, start_and_stop,
checkpoint, table_lifecycle, storage_options,
add_copy_conflict,
- add_copy_when_going_down, replica_management, clear_table_during_load,
+ add_copy_when_going_down, add_copy_with_down, replica_management,
+ clear_table_during_load,
schema_availability, local_content,
{group, table_access_modifications}, replica_location,
{group, table_sync}, user_properties, unsupp_user_props,
{group, record_name}, {group, snmp_access},
{group, subscriptions}, {group, iteration},
- {group, debug_support}, sorted_ets,
+ {group, debug_support}, sorted_ets, index_cleanup,
{mnesia_dirty_access_test, all},
{mnesia_trans_access_test, all},
{mnesia_evil_backup, all}].
@@ -732,6 +734,49 @@ add_copy_when_going_down(Config) ->
?match_receive({test,{aborted,_}}),
?verify_mnesia([Node2], []).
+add_copy_with_down(suite) -> [];
+add_copy_with_down(Config) ->
+ %% Allow add_table_copy() with ram_copies even all other replicas are down
+ Nodes = [Node1, Node2, Node3] = ?acquire_nodes(3, Config),
+ ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [Node3]}, {disc_copies, [Node2]}])),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match({aborted, _}, mnesia:del_table_copy(a, Node2)),
+ ok = rpc:call(Node3, mnesia, start, []),
+ ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match([], mnesia_test_lib:start_mnesia([Node2], [a])),
+ ?match({atomic, ok}, mnesia:change_table_copy_type(a, Node2, ram_copies)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_only_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?verify_mnesia(Nodes, []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Add, drop and move replicas, change storage types
@@ -2514,3 +2559,55 @@ sorted_ets(Config) when is_list(Config) ->
?match({atomic, [{rec,1,1}, {rec,2,1}]}, mnesia:transaction(TestIt)).
+index_cleanup(Config) when is_list(Config) ->
+ [N1, N2] = All = ?acquire_nodes(2, Config),
+ ?match({atomic, ok}, mnesia:create_table(i_set, [{type, set}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_bag, [{type, bag}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_oset, [{type, ordered_set}, {ram_copies, [N1, N2]},
+ {index, [val]}])),
+
+ Tabs = [i_set, i_bag, i_oset],
+
+ Add = fun(Tab) ->
+ Write = fun(Tab) ->
+ Recs = [{Tab, N, N rem 5} || N <- lists:seq(1,10)],
+ [ok = mnesia:write(Rec) || Rec <- Recs],
+ Recs
+ end,
+ {atomic, Recs} = mnesia:sync_transaction(Write, [Tab]),
+ lists:sort(Recs)
+ end,
+
+ IRead = fun(Tab) ->
+ Read = fun(Tab) ->
+ [mnesia:index_read(Tab, N, val) || N <- lists:seq(0,4)]
+ end,
+ {atomic, Recs} = mnesia:transaction(Read, [Tab]),
+ lists:sort(lists:flatten(Recs))
+ end,
+
+ Delete = fun(Rec) ->
+ Del = fun() -> mnesia:delete_object(Rec) end,
+ {atomic, ok} = mnesia:sync_transaction(Del),
+ ok
+ end,
+
+
+ Recs = [Add(Tab) || Tab <- Tabs],
+ ?match(Recs, [IRead(Tab) || Tab <- Tabs]),
+ [Delete(Rec) || Rec <- lists:flatten(Recs)],
+
+ [?match({Tab,0}, {Tab,mnesia:table_info(Tab, size)}) || Tab <- Tabs],
+
+ [?match({Tab,Node,0, _}, rpc:call(Node, ?MODULE, index_size, [Tab]))
+ || Node <- All, Tab <- Tabs],
+ ?verify_mnesia(All, []).
+
+index_size(Tab) ->
+ %% White box testing
+ case mnesia:table_info(Tab, index_info) of
+ {index, _, [{_, {ram, Ref}}=Dbg]} -> {Tab, node(), ets:info(Ref, size), Dbg};
+ {index, _, [{_, {dets, Ref}}=Dbg]} -> {Tab, node(), dets:info(Ref, size), Dbg}
+ end.
diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl
index b2eea2390b..49bcec14af 100644
--- a/lib/mnesia/test/mnesia_isolation_test.erl
+++ b/lib/mnesia/test/mnesia_isolation_test.erl
@@ -1563,7 +1563,8 @@ trans_update_visible_inside_trans(Config) when is_list(Config) ->
?match({atomic, ok}, mnesia:create_table([{name, Tab},
{ram_copies, [Node1]}])),
ValPos = 3,
- RecA = {Tab, a, 1},
+ RecA = {Tab, a, 1},
+ RecA2 = {Tab, a, 2},
PatA = {Tab, '$1', 1},
RecB = {Tab, b, 3},
PatB = {Tab, '$1', 3},
@@ -1598,6 +1599,14 @@ trans_update_visible_inside_trans(Config) when is_list(Config) ->
?match([], mnesia:index_read(Tab, 3, ValPos)),
%% delete_object
+ ?match(ok, mnesia:delete_object(RecA2)),
+ ?match([RecA], mnesia:read({Tab, a})),
+ ?match([RecA], mnesia:wread({Tab, a})),
+ ?match([RecA], mnesia:match_object(PatA)),
+ ?match([a], mnesia:all_keys(Tab)),
+ ?match([RecA], mnesia:index_match_object(PatA, ValPos)),
+ ?match([RecA], mnesia:index_read(Tab, 1, ValPos)),
+
?match(ok, mnesia:delete_object(RecA)),
?match([], mnesia:read({Tab, a})),
?match([], mnesia:wread({Tab, a})),
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index aaa1c3006f..781a4830a0 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.15.4
+MNESIA_VSN = 4.15.6
diff --git a/lib/observer/doc/src/Makefile b/lib/observer/doc/src/Makefile
index 11bfee1bdb..e843772f0b 100644
--- a/lib/observer/doc/src/Makefile
+++ b/lib/observer/doc/src/Makefile
@@ -105,6 +105,7 @@ html: gifs $(HTML_REF_MAN_FILE) $(ONLY_HTML_FILE:%=$(HTMLDIR)/%)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
diff --git a/lib/observer/doc/src/crashdump.xml b/lib/observer/doc/src/crashdump.xml
index 48f944cbce..62c6ff1f25 100644
--- a/lib/observer/doc/src/crashdump.xml
+++ b/lib/observer/doc/src/crashdump.xml
@@ -34,7 +34,7 @@
<rev>PA1</rev>
<file>crashdump.xml</file>
</header>
- <module>crashdump_viewer</module>
+ <module since="">crashdump_viewer</module>
<modulesummary>A WxWidgets based tool for browsing Erlang
crashdumps.</modulesummary>
<description>
@@ -46,8 +46,8 @@
</description>
<funcs>
<func>
- <name>start() -> ok</name>
- <name>start(File) -> ok</name>
+ <name since="">start() -> ok</name>
+ <name since="OTP 17.0">start(File) -> ok</name>
<fsummary>Start the Crashdump Viewer.</fsummary>
<type>
<v>File = string()</v>
@@ -62,7 +62,7 @@
</desc>
</func>
<func>
- <name>stop() -> ok</name>
+ <name since="">stop() -> ok</name>
<fsummary>Terminate the Crashdump Viewer.</fsummary>
<desc>
<p>Terminates the Crashdump Viewer and closes
diff --git a/lib/observer/doc/src/etop.xml b/lib/observer/doc/src/etop.xml
index e7a83d0514..f0acc7b5d8 100644
--- a/lib/observer/doc/src/etop.xml
+++ b/lib/observer/doc/src/etop.xml
@@ -34,7 +34,7 @@
<rev></rev>
<file></file>
</header>
- <module>etop</module>
+ <module since="">etop</module>
<modulesummary>Erlang Top is a tool for presenting information about Erlang
processes similar to the information presented by "top" in UNIX.</modulesummary>
<description>
@@ -98,7 +98,7 @@
</description>
<funcs>
<func>
- <name>start() -> ok</name>
+ <name since="OTP R15B01">start() -> ok</name>
<fsummary>Start etop.</fsummary>
<desc>
<p>Starts <c>etop</c>.
@@ -106,7 +106,7 @@
</desc>
</func>
<func>
- <name>start(Options) -> ok</name>
+ <name since="OTP R15B01">start(Options) -> ok</name>
<fsummary>Start etop.</fsummary>
<type>
<v>Options = [Option]</v>
@@ -120,7 +120,7 @@
</desc>
</func>
<func>
- <name>help() -> ok</name>
+ <name since="OTP R15B01">help() -> ok</name>
<fsummary>Display the etop help.</fsummary>
<desc>
<p>Displays the help of <c>etop</c> and
@@ -128,7 +128,7 @@
</desc>
</func>
<func>
- <name>config(Key,Value) -> Result</name>
+ <name since="">config(Key,Value) -> Result</name>
<fsummary>Change the configuration of the tool.</fsummary>
<type>
<v>Result = ok | {error,Reason}</v>
@@ -142,7 +142,7 @@
</desc>
</func>
<func>
- <name>dump(File) -> Result</name>
+ <name since="">dump(File) -> Result</name>
<fsummary>Dump the current display to a file.</fsummary>
<type>
<v>Result = ok | {error,Reason}</v>
@@ -153,7 +153,7 @@
</desc>
</func>
<func>
- <name>stop() -> stop</name>
+ <name since="">stop() -> stop</name>
<fsummary>Terminate etop.</fsummary>
<desc>
<p>Terminates <c>etop</c>.</p>
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index 67bba37e39..2d914f8c61 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -32,6 +32,97 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 2.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Since Logger was introduced in OTP-21.0, menu choice
+ <em>Log &gt; Toggle Log View</em> in observer would cause
+ a crash unless an <c>error_logger</c> event handler was
+ explicitly installed. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15553 Aux Id: ERL-848 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Since persistent_term was introduced, observer would
+ sometimes crash when expanding a term from a process
+ state. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15493 Aux Id: ERL-810 </p>
+ </item>
+ <item>
+ <p>
+ Add <c>OBSERVER_SCALE</c> environment variable for HiDPI
+ support.</p>
+ <p>
+ Own Id: OTP-15586 Aux Id: PR-2105 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.8.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Literals such as <c>#{"one"=>1}</c> dumped to a crash
+ dump would cause <c>crashdump_viewer</c> to crash.</p>
+ <p>
+ Own Id: OTP-15365 Aux Id: ERL-722 </p>
+ </item>
+ <item>
+ <p>
+ <c>crashdump_viewer</c> would sometimes crash when
+ processing a dump which was truncated in the
+ <c>literals</c> area. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15377</p>
+ </item>
+ <item>
+ <p>
+ Since OTP-20.2, <c>crashdump_viewer</c> was very slow
+ when opening a crash dump with many processes. An
+ ets:select per process could be removed, which improved
+ the performance a lot.</p>
+ <p>
+ A bug when parsing heap data in a crashdump caused
+ <c>crashdump_viewer</c> to crash when multiple <c>Yc</c>
+ lines referenced the same reference counted binary. This
+ is now corrected.</p>
+ <p>
+ Own Id: OTP-15391</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 2.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/observer/doc/src/observer.xml b/lib/observer/doc/src/observer.xml
index 843be26ee1..7fb1dd044e 100644
--- a/lib/observer/doc/src/observer.xml
+++ b/lib/observer/doc/src/observer.xml
@@ -33,7 +33,7 @@
<rev>PA1</rev>
<file>observer.xml</file>
</header>
- <module>observer</module>
+ <module since="OTP R15B">observer</module>
<modulesummary>A GUI tool for observing an Erlang system.</modulesummary>
<description>
<p>Observer is a graphical tool for observing the characteristics of
@@ -48,7 +48,7 @@
</description>
<funcs>
<func>
- <name>start() -> ok</name>
+ <name since="OTP R15B">start() -> ok</name>
<fsummary>Start the Observer GUI.</fsummary>
<desc>
<p>Starts the Observer GUI.
diff --git a/lib/observer/doc/src/ttb.xml b/lib/observer/doc/src/ttb.xml
index 7cd15e15d3..fee95e0b21 100644
--- a/lib/observer/doc/src/ttb.xml
+++ b/lib/observer/doc/src/ttb.xml
@@ -33,7 +33,7 @@
<rev>PA1</rev>
<file>ttb.xml</file>
</header>
- <module>ttb</module>
+ <module since="">ttb</module>
<modulesummary>A base for building trace tools for distributed systems.</modulesummary>
<description>
<p>The Trace Tool Builder, <c>ttb</c>, is a base for building trace
@@ -44,7 +44,7 @@
</description>
<funcs>
<func>
- <name>start_trace(Nodes, Patterns, FlagSpec, Opts) -> Result</name>
+ <name since="OTP R15B">start_trace(Nodes, Patterns, FlagSpec, Opts) -> Result</name>
<fsummary>Start a trace port on each specified node.</fsummary>
<type>
<v>Result = see p/2</v>
@@ -76,7 +76,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>tracer() -> Result</name>
+ <name since="">tracer() -> Result</name>
<fsummary>Equivalent to tracer(node()).</fsummary>
<desc>
<p>Equivalent to <c>tracer(node())</c>.</p>
@@ -84,7 +84,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>tracer(Shortcut) -> Result</name>
+ <name since="">tracer(Shortcut) -> Result</name>
<fsummary>Handy shortcuts for common tracing settings.</fsummary>
<type>
<v>Shortcut = shell | dbg</v>
@@ -97,7 +97,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>tracer(Nodes) -> Result</name>
+ <name since="">tracer(Nodes) -> Result</name>
<fsummary>Equivalent to tracer(Nodes,[]).</fsummary>
<desc>
<p>Equivalent to <c>tracer(Nodes,[])</c>.</p>
@@ -105,7 +105,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>tracer(Nodes,Opts) -> Result</name>
+ <name since="">tracer(Nodes,Opts) -> Result</name>
<fsummary>Start a trace port on each specified node.</fsummary>
<type>
<v>Result = {ok, ActivatedNodes} | {error,Reason}</v>
@@ -243,7 +243,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>p(Item,Flags) -> Return</name>
+ <name since="">p(Item,Flags) -> Return</name>
<fsummary>Set the specified trace flags on the specified processes or ports.</fsummary>
<type>
<v>Return = {ok,[{Item,MatchDesc}]}</v>
@@ -277,7 +277,8 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>tp, tpl, tpe, ctp, ctpl, ctpg, ctpe</name>
+ <name since="">tp, tpl, ctp, ctpl, ctpg</name>
+ <name since="OTP 19.0">tpe, ctpe</name>
<fsummary>Set and clear trace patterns.</fsummary>
<desc>
<p>These functions are to be used with trace
@@ -338,7 +339,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>list_history() -> History</name>
+ <name since="">list_history() -> History</name>
<fsummary>Return all calls stored in history.</fsummary>
<type>
<v>History = [{N,Func,Args}]</v>
@@ -352,7 +353,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>run_history(N) -> ok | {error, Reason}</name>
+ <name since="">run_history(N) -> ok | {error, Reason}</name>
<fsummary>Execute one entry of the history.</fsummary>
<type>
<v>N = integer() | [integer()]</v>
@@ -364,7 +365,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>write_config(ConfigFile,Config)</name>
+ <name since="">write_config(ConfigFile,Config)</name>
<fsummary>Equivalent to write_config(ConfigFile,Config,[]).</fsummary>
<desc>
<p>Equivalent to <c>write_config(ConfigFile,Config,[])</c>.</p>
@@ -372,7 +373,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>write_config(ConfigFile,Config,Opts) -> ok | {error,Reason}</name>
+ <name since="">write_config(ConfigFile,Config,Opts) -> ok | {error,Reason}</name>
<fsummary>Create a configuration file.</fsummary>
<type>
<v>ConfigFile = string()</v>
@@ -405,7 +406,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>run_config(ConfigFile) -> ok | {error,Reason}</name>
+ <name since="">run_config(ConfigFile) -> ok | {error,Reason}</name>
<fsummary>Execute all entries in a configuration file.</fsummary>
<type>
<v>ConfigFile = string()</v>
@@ -418,7 +419,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>run_config(ConfigFile,NumList) -> ok | {error,Reason}</name>
+ <name since="">run_config(ConfigFile,NumList) -> ok | {error,Reason}</name>
<fsummary>Execute selected entries from a configuration file.</fsummary>
<type>
<v>ConfigFile = string()</v>
@@ -437,7 +438,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>list_config(ConfigFile) -> Config | {error,Reason}</name>
+ <name since="">list_config(ConfigFile) -> Config | {error,Reason}</name>
<fsummary>List all entries in a configuration file.</fsummary>
<type>
<v>ConfigFile = string()</v>
@@ -449,7 +450,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>write_trace_info(Key,Info) -> ok</name>
+ <name since="">write_trace_info(Key,Info) -> ok</name>
<fsummary>Write any information to file <c>.ti</c>.</fsummary>
<type>
<v>Key = term()</v>
@@ -465,7 +466,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>seq_trigger_ms() -> MatchSpec</name>
+ <name since="">seq_trigger_ms() -> MatchSpec</name>
<fsummary>Equivalent to seq_trigger_ms(all).</fsummary>
<desc>
<p>Equivalent to <c>seq_trigger_ms(all)</c>.</p>
@@ -473,7 +474,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>seq_trigger_ms(Flags) -> MatchSpec</name>
+ <name since="">seq_trigger_ms(Flags) -> MatchSpec</name>
<fsummary>Return a match_spec() which starts sequential tracing.</fsummary>
<type>
<v>MatchSpec = match_spec()</v>
@@ -521,7 +522,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>stop()</name>
+ <name since="">stop()</name>
<fsummary>Equivalent to stop([]).</fsummary>
<desc>
<p>Equivalent to <c>stop([])</c>.</p>
@@ -529,7 +530,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>stop(Opts) -> stopped | {stopped, Dir}</name>
+ <name since="">stop(Opts) -> stopped | {stopped, Dir}</name>
<fsummary>Stop tracing and fetch/format logs from all nodes.</fsummary>
<type>
<v>Opts = Opt | [Opt]</v>
@@ -573,7 +574,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>get_et_handler()</name>
+ <name since="OTP R15B">get_et_handler()</name>
<fsummary>Return the <c>et</c> handler.</fsummary>
<desc>
<p>Returns the <c>et</c> handler, which can be used with <c>format/2</c>
@@ -583,7 +584,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>format(File)</name>
+ <name since="">format(File)</name>
<fsummary>Equivalent to <c>format(File,[])</c>.</fsummary>
<desc>
<p>Equivalent to <c>format(File,[])</c>.</p>
@@ -591,7 +592,7 @@ ttb:p(all, call).</input></pre>
</func>
<func>
- <name>format(File,Options) -> ok | {error, Reason}</name>
+ <name since="">format(File,Options) -> ok | {error, Reason}</name>
<fsummary>Format a binary trace log.</fsummary>
<type>
<v>File = string() | [string()]</v>
diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile
index ff2bcbdb99..f9f239db37 100644
--- a/lib/observer/src/Makefile
+++ b/lib/observer/src/Makefile
@@ -50,6 +50,7 @@ MODULES= \
cdv_mem_cb \
cdv_mod_cb \
cdv_multi_wx \
+ cdv_persistent_cb \
cdv_port_cb \
cdv_proc_cb \
cdv_sched_cb \
diff --git a/lib/observer/src/cdv_detail_wx.erl b/lib/observer/src/cdv_detail_wx.erl
index 4b1984c394..5e1137511a 100644
--- a/lib/observer/src/cdv_detail_wx.erl
+++ b/lib/observer/src/cdv_detail_wx.erl
@@ -84,8 +84,9 @@ destroy_progress(_) ->
ok.
init(Id,ParentFrame,Callback,App,Parent,{Title,Info,TW}) ->
+ Scale = observer_wx:get_scale(),
Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [Title],
- [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {850,600}}]),
+ [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {Scale*850,Scale*600}}]),
MenuBar = wxMenuBar:new(),
create_menus(MenuBar),
wxFrame:setMenuBar(Frame, MenuBar),
diff --git a/lib/observer/src/cdv_html_wx.erl b/lib/observer/src/cdv_html_wx.erl
index d9efa7fc2f..8956173c93 100644
--- a/lib/observer/src/cdv_html_wx.erl
+++ b/lib/observer/src/cdv_html_wx.erl
@@ -33,13 +33,17 @@
{panel,
app, %% which tool is the user
expand_table,
- expand_wins=[]}).
+ expand_wins=[],
+ delayed_fetch,
+ trunc_warn=[]}).
start_link(ParentWin, Info) ->
wx_object:start_link(?MODULE, [ParentWin, Info], []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init([ParentWin, Callback]) when is_atom(Callback) ->
+ init(ParentWin, Callback);
init([ParentWin, {App, Fun}]) when is_function(Fun) ->
init([ParentWin, {App, Fun()}]);
init([ParentWin, {expand,HtmlText,Tab}]) ->
@@ -60,9 +64,29 @@ init(ParentWin, HtmlText, Tab, App) ->
wx_misc:endBusyCursor(),
{HtmlWin, #state{panel=HtmlWin,expand_table=Tab,app=App}}.
+init(ParentWin, Callback) ->
+ {HtmlWin, State} = init(ParentWin, "", undefined, cdv),
+ {HtmlWin, State#state{delayed_fetch=Callback}}.
+
%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+handle_info(active, #state{panel=HtmlWin,delayed_fetch=Callback}=State)
+ when Callback=/=undefined ->
+ observer_lib:display_progress_dialog(HtmlWin,
+ "Crashdump Viewer",
+ "Reading data"),
+ {{expand,HtmlText,Tab},TW} = Callback:get_info(),
+ observer_lib:sync_destroy_progress_dialog(),
+ wx_misc:beginBusyCursor(),
+ wxHtmlWindow:setPage(HtmlWin,HtmlText),
+ cdv_wx_set_status(State, TW),
+ wx_misc:endBusyCursor(),
+ {noreply, State#state{expand_table=Tab,
+ delayed_fetch=undefined,
+ trunc_warn=TW}};
+
handle_info(active, State) ->
+ cdv_wx_set_status(State, State#state.trunc_warn),
{noreply, State};
handle_info(Info, State) ->
@@ -140,3 +164,10 @@ expand(Id,Callback,#state{expand_wins=Opened0, app=App}=State) ->
Opened0
end,
State#state{expand_wins=Opened}.
+
+cdv_wx_set_status(#state{app = cdv}, Status) ->
+ %% this module is used by the observer when cdw_wx isn't started
+ %% only try to set status when used by cdv
+ cdv_wx:set_status(Status);
+cdv_wx_set_status(_, _) ->
+ ok.
diff --git a/lib/observer/src/cdv_persistent_cb.erl b/lib/observer/src/cdv_persistent_cb.erl
new file mode 100644
index 0000000000..d5da18f7fc
--- /dev/null
+++ b/lib/observer/src/cdv_persistent_cb.erl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+
+-module(cdv_persistent_cb).
+
+-export([get_info/0]).
+
+-include_lib("wx/include/wx.hrl").
+
+get_info() ->
+ Tab = ets:new(pt_expand,[set,public]),
+ {ok,PT,TW} = crashdump_viewer:persistent_terms(),
+ {{expand,
+ observer_html_lib:expandable_term("Persistent Terms",PT,Tab),
+ Tab},
+ TW}.
diff --git a/lib/observer/src/cdv_table_wx.erl b/lib/observer/src/cdv_table_wx.erl
index 0f28a51017..0cad272262 100644
--- a/lib/observer/src/cdv_table_wx.erl
+++ b/lib/observer/src/cdv_table_wx.erl
@@ -50,11 +50,12 @@ init([ParentWin, {ColumnSpec,Info,TW}]) ->
end,
Grid = wxListCtrl:new(ParentWin, [{style, Style}]),
Li = wxListItem:new(),
+ Scale = observer_wx:get_scale(),
AddListEntry = fun({Name, Align, DefSize}, Col) ->
wxListItem:setText(Li, Name),
wxListItem:setAlign(Li, Align),
wxListCtrl:insertColumn(Grid, Col, Li),
- wxListCtrl:setColumnWidth(Grid, Col, DefSize),
+ wxListCtrl:setColumnWidth(Grid, Col, DefSize*Scale),
Col + 1
end,
lists:foldl(AddListEntry, 0, ColumnSpec),
diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl
index 2702301021..14877b7eab 100644
--- a/lib/observer/src/cdv_virtual_list_wx.erl
+++ b/lib/observer/src/cdv_virtual_list_wx.erl
@@ -132,11 +132,12 @@ create_list_box(Panel, Holder, Callback, Owner) ->
end}
]),
Li = wxListItem:new(),
+ Scale = observer_wx:get_scale(),
AddListEntry = fun({Name, Align, DefSize}, Col) ->
wxListItem:setText(Li, Name),
wxListItem:setAlign(Li, Align),
wxListCtrl:insertColumn(ListCtrl, Col, Li),
- wxListCtrl:setColumnWidth(ListCtrl, Col, DefSize),
+ wxListCtrl:setColumnWidth(ListCtrl, Col, DefSize*Scale),
Col + 1
end,
ListItems = Callback:col_spec(),
diff --git a/lib/observer/src/cdv_wx.erl b/lib/observer/src/cdv_wx.erl
index 78a897111c..811c767e66 100644
--- a/lib/observer/src/cdv_wx.erl
+++ b/lib/observer/src/cdv_wx.erl
@@ -51,6 +51,7 @@
-define(DIST_STR, "Nodes").
-define(MOD_STR, "Modules").
-define(MEM_STR, "Memory").
+-define(PERSISTENT_STR, "Persistent Terms").
-define(INT_STR, "Internal Tables").
%% Records
@@ -74,6 +75,7 @@
dist_panel,
mod_panel,
mem_panel,
+ persistent_panel,
int_panel,
active_tab
}).
@@ -99,8 +101,9 @@ init(File0) ->
{ok,CdvServer} = crashdump_viewer:start_link(),
catch wxSystemOptions:setOption("mac.listctrl.always_use_generic", 1),
+ Scale = observer_wx:get_scale(),
Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Crashdump Viewer",
- [{size, {850, 600}}, {style, ?wxDEFAULT_FRAME_STYLE}]),
+ [{size, {Scale*850, Scale*600}}, {style, ?wxDEFAULT_FRAME_STYLE}]),
IconFile = filename:join(code:priv_dir(observer), "erlang_observer.png"),
Icon = wxIcon:new(IconFile, [{type,?wxBITMAP_TYPE_PNG}]),
wxFrame:setIcon(Frame, Icon),
@@ -193,6 +196,10 @@ setup(#state{frame=Frame, notebook=Notebook}=State) ->
%% Memory Panel
MemPanel = add_page(Notebook, ?MEM_STR, cdv_multi_wx, cdv_mem_cb),
+ %% Persistent Terms Panel
+ PersistentPanel = add_page(Notebook, ?PERSISTENT_STR,
+ cdv_html_wx, cdv_persistent_cb),
+
%% Memory Panel
IntPanel = add_page(Notebook, ?INT_STR, cdv_multi_wx, cdv_int_tab_cb),
@@ -215,6 +222,7 @@ setup(#state{frame=Frame, notebook=Notebook}=State) ->
dist_panel = DistPanel,
mod_panel = ModPanel,
mem_panel = MemPanel,
+ persistent_panel = PersistentPanel,
int_panel = IntPanel,
active_tab = GenPid
}}.
@@ -250,6 +258,7 @@ handle_event(#wx{id = ?wxID_OPEN,
State#state.dist_panel,
State#state.mod_panel,
State#state.mem_panel,
+ State#state.persistent_panel,
State#state.int_panel],
_ = [wx_object:call(Panel,new_dump) || Panel<-Panels],
wxNotebook:setSelection(State#state.notebook,0),
@@ -343,8 +352,8 @@ check_page_title(Notebook) ->
get_active_pid(#state{notebook=Notebook, gen_panel=Gen, pro_panel=Pro,
port_panel=Ports, ets_panel=Ets, timer_panel=Timers,
fun_panel=Funs, atom_panel=Atoms, dist_panel=Dist,
- mod_panel=Mods, mem_panel=Mem, int_panel=Int,
- sched_panel=Sched
+ mod_panel=Mods, mem_panel=Mem, persistent_panel=Persistent,
+ int_panel=Int, sched_panel=Sched
}) ->
Panel = case check_page_title(Notebook) of
?GEN_STR -> Gen;
@@ -358,6 +367,7 @@ get_active_pid(#state{notebook=Notebook, gen_panel=Gen, pro_panel=Pro,
?DIST_STR -> Dist;
?MOD_STR -> Mods;
?MEM_STR -> Mem;
+ ?PERSISTENT_STR -> Persistent;
?INT_STR -> Int
end,
wx_object:get_pid(Panel).
@@ -365,7 +375,7 @@ get_active_pid(#state{notebook=Notebook, gen_panel=Gen, pro_panel=Pro,
pid2panel(Pid, #state{gen_panel=Gen, pro_panel=Pro, port_panel=Ports,
ets_panel=Ets, timer_panel=Timers, fun_panel=Funs,
atom_panel=Atoms, dist_panel=Dist, mod_panel=Mods,
- mem_panel=Mem, int_panel=Int}) ->
+ mem_panel=Mem, persistent_panel=Persistent, int_panel=Int}) ->
case Pid of
Gen -> ?GEN_STR;
Pro -> ?PRO_STR;
@@ -377,6 +387,7 @@ pid2panel(Pid, #state{gen_panel=Gen, pro_panel=Pro, port_panel=Ports,
Dist -> ?DIST_STR;
Mods -> ?MOD_STR;
Mem -> ?MEM_STR;
+ ?PERSISTENT_STR -> Persistent;
Int -> ?INT_STR;
_ -> "unknown"
end.
diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl
index 14b086ff58..97bb344cbf 100644
--- a/lib/observer/src/crashdump_viewer.erl
+++ b/lib/observer/src/crashdump_viewer.erl
@@ -74,6 +74,7 @@
loaded_modules/0,
loaded_mod_details/1,
memory/0,
+ persistent_terms/0,
allocated_areas/0,
allocator_info/0,
hash_tables/0,
@@ -139,6 +140,7 @@
-define(node,node).
-define(not_connected,not_connected).
-define(old_instr_data,old_instr_data).
+-define(persistent_terms,persistent_terms).
-define(port,port).
-define(proc,proc).
-define(proc_dictionary,proc_dictionary).
@@ -293,6 +295,8 @@ loaded_mod_details(Mod) ->
call({loaded_mod_details,Mod}).
memory() ->
call(memory).
+persistent_terms() ->
+ call(persistent_terms).
allocated_areas() ->
call(allocated_areas).
allocator_info() ->
@@ -471,6 +475,11 @@ handle_call(memory,_From,State=#state{file=File}) ->
Memory=memory(File),
TW = truncated_warning([?memory]),
{reply,{ok,Memory,TW},State};
+handle_call(persistent_terms,_From,State=#state{file=File,dump_vsn=DumpVsn}) ->
+ TW = truncated_warning([?persistent_terms,?literals]),
+ DecodeOpts = get_decode_opts(DumpVsn),
+ Terms = persistent_terms(File, DecodeOpts),
+ {reply,{ok,Terms,TW},State};
handle_call(allocated_areas,_From,State=#state{file=File}) ->
AllocatedAreas=allocated_areas(File),
TW = truncated_warning([?allocated_areas]),
@@ -580,9 +589,9 @@ truncated_here(Tag) ->
case get(truncated) of
true ->
case get(last_tag) of
- Tag -> % Tag == {TagType,Id}
+ {Tag,_Pos} -> % Tag == {TagType,Id}
true;
- {Tag,_Id} ->
+ {{Tag,_Id},_Pos} ->
true;
_LastTag ->
truncated_earlier(Tag)
@@ -837,8 +846,8 @@ do_read_file(File) ->
case check_dump_version(Id) of
{ok,DumpVsn} ->
reset_tables(),
- insert_index(Tag,Id,N1+1),
- put_last_tag(Tag,""),
+ insert_index(Tag,Id,Pos=N1+1),
+ put_last_tag(Tag,"",Pos),
DecodeOpts = get_decode_opts(DumpVsn),
indexify(Fd,DecodeOpts,Rest,N1),
end_progress(),
@@ -906,23 +915,11 @@ indexify(Fd,DecodeOpts,Bin,N) ->
_ ->
insert_index(Tag,Id,NewPos)
end,
- case put_last_tag(Tag,Id) of
- {?proc_heap,LastId} ->
- [{_,LastPos}] = lookup_index(?proc_heap,LastId),
+ case put_last_tag(Tag,Id,NewPos) of
+ {{?proc_heap,LastId},LastPos} ->
ets:insert(cdv_heap_file_chars,{LastId,N+Start+1-LastPos});
- {?literals,[]} ->
- case get(truncated_reason) of
- undefined ->
- [{_,LastPos}] = lookup_index(?literals,[]),
- ets:insert(cdv_heap_file_chars,
- {literals,N+Start+1-LastPos});
- _ ->
- %% Literals are truncated. Make sure we never
- %% attempt to read in the literals. (Heaps that
- %% references literals will show markers for
- %% incomplete heaps, but will otherwise work.)
- delete_index(?literals, [])
- end;
+ {{?literals,[]},LastPos} ->
+ ets:insert(cdv_heap_file_chars,{literals,N+Start+1-LastPos});
_ -> ok
end,
indexify(Fd,DecodeOpts,Rest,N1);
@@ -964,10 +961,18 @@ tag(Fd,<<>>,N,Gat,Di,Now) ->
check_if_truncated() ->
case get(last_tag) of
- {?ende,_} ->
+ {{?ende,_},_} ->
put(truncated,false),
put(truncated_proc,false);
- TruncatedTag ->
+ {{?literals,[]},_} ->
+ put(truncated,true),
+ put(truncated_proc,false),
+ %% Literals are truncated. Make sure we never
+ %% attempt to read in the literals. (Heaps that
+ %% references literals will show markers for
+ %% incomplete heaps, but will otherwise work.)
+ delete_index(?literals, []);
+ {TruncatedTag,_} ->
put(truncated,true),
find_truncated_proc(TruncatedTag)
end.
@@ -975,7 +980,6 @@ check_if_truncated() ->
find_truncated_proc({Tag,_Id}) when Tag==?atoms;
Tag==?binary;
Tag==?instr_data;
- Tag==?literals;
Tag==?memory_status;
Tag==?memory_map ->
put(truncated_proc,false);
@@ -1444,15 +1448,7 @@ maybe_other_node2(Channel) ->
expand_memory(Fd,Pid,DumpVsn) ->
DecodeOpts = get_decode_opts(DumpVsn),
put(fd,Fd),
- Dict0 = case get(?literals) of
- undefined ->
- Literals = read_literals(Fd,DecodeOpts),
- put(?literals,Literals),
- put(fd,Fd),
- Literals;
- Literals ->
- Literals
- end,
+ Dict0 = get_literals(Fd,DecodeOpts),
Dict = read_heap(Fd,Pid,DecodeOpts,Dict0),
Expanded = {read_stack_dump(Fd,Pid,DecodeOpts,Dict),
read_messages(Fd,Pid,DecodeOpts,Dict),
@@ -1468,6 +1464,18 @@ expand_memory(Fd,Pid,DumpVsn) ->
end,
{Expanded,IncompleteWarning}.
+get_literals(Fd,DecodeOpts) ->
+ case get(?literals) of
+ undefined ->
+ OldFd = put(fd,Fd),
+ Literals = read_literals(Fd,DecodeOpts),
+ put(fd,OldFd),
+ put(?literals,Literals),
+ Literals;
+ Literals ->
+ Literals
+ end.
+
read_literals(Fd,DecodeOpts) ->
case lookup_index(?literals,[]) of
[{_,Start}] ->
@@ -1594,31 +1602,92 @@ read_heap(Fd,Pid,DecodeOpts,Dict0) ->
Dict0
end.
-read_heap(DecodeOpts,Dict0) ->
- %% This function is never called if the dump is truncated in {?proc_heap,Pid}
- case get(fd) of
- end_of_heap ->
+read_heap(DecodeOpts, Dict0) ->
+ %% This function is never called if the dump is truncated in
+ %% {?proc_heap,Pid}.
+ %%
+ %% It is not always possible to reconstruct the heap terms
+ %% in a single pass, especially if maps are involved.
+ %% See crashdump_helper:literal_map/0 for an example.
+ %%
+ %% Therefore, we need two passes. In the first pass
+ %% we collect all lines without parsing them, and in the
+ %% second pass we parse them.
+ %%
+ %% The first pass follows.
+
+ Lines0 = read_heap_lines(),
+
+ %% Save a map of all unprocessed lines so that deref_ptr() can
+ %% access any line when there are references to terms not yet
+ %% built.
+
+ LineMap = maps:from_list(Lines0),
+ put(line_map, LineMap),
+
+ %% Refc binaries (tag "Yc") must be processed before any sub
+ %% binaries (tag "Ys") referencing them, so we make sure to
+ %% process all the refc binaries first.
+ %%
+ %% The other lines can be processed in any order, but processing
+ %% them in the reverse order compared to how they are printed in
+ %% the crash dump seems to minimize the number of references to
+ %% terms that have not yet been built. That happens to be the
+ %% order of the line list as returned by read_heap_lines/0.
+
+ RefcBins = [Refc || {_,<<"Yc",_/binary>>}=Refc <- Lines0],
+ Lines = RefcBins ++ Lines0,
+
+ %% Second pass.
+
+ init_progress("Processing terms", map_size(LineMap)),
+ Dict = parse_heap_terms(Lines, DecodeOpts, Dict0),
+ erase(line_map),
+ end_progress(),
+ Dict.
+
+read_heap_lines() ->
+ read_heap_lines_1(get(fd), []).
+
+read_heap_lines_1(Fd, Acc) ->
+ case bytes(Fd) of
+ "=" ++ _next_tag ->
end_progress(),
- Dict0;
- Fd ->
- case bytes(Fd) of
- "=" ++ _next_tag ->
- end_progress(),
- put(fd, end_of_heap),
- Dict0;
- Line ->
- update_progress(length(Line)+1),
- Dict = parse(Line,DecodeOpts,Dict0),
- read_heap(DecodeOpts,Dict)
- end
+ put(fd, end_of_heap),
+ Acc;
+ Line0 ->
+ update_progress(length(Line0)+1),
+ {Addr,":"++Line1} = get_hex(Line0),
+
+ %% Reduce the memory consumption by converting the
+ %% line to a binary. Measurements show that it may also
+ %% be benefical for performance, too, because it makes the
+ %% garbage collections cheaper.
+
+ Line = list_to_binary(Line1),
+ read_heap_lines_1(Fd, [{Addr,Line}|Acc])
end.
-parse(Line0, DecodeOpts, Dict0) ->
- {Addr,":"++Line1} = get_hex(Line0),
- {_Term,Line,Dict} = parse_heap_term(Line1, Addr, DecodeOpts, Dict0),
- [] = skip_blanks(Line),
+parse_heap_terms([{Addr,Line0}|T], DecodeOpts, Dict0) ->
+ case gb_trees:is_defined(Addr, Dict0) of
+ true ->
+ %% Already parsed (by a recursive call from do_deref_ptr()
+ %% to parse_line()). Nothing to do.
+ parse_heap_terms(T, DecodeOpts, Dict0);
+ false ->
+ %% Parse this previously unparsed term.
+ Dict = parse_line(Addr, Line0, DecodeOpts, Dict0),
+ parse_heap_terms(T, DecodeOpts, Dict)
+ end;
+parse_heap_terms([], _DecodeOpts, Dict) ->
Dict.
+parse_line(Addr, Line0, DecodeOpts, Dict0) ->
+ update_progress(1),
+ Line1 = binary_to_list(Line0),
+ {_Term,Line,Dict} = parse_heap_term(Line1, Addr, DecodeOpts, Dict0),
+ [] = skip_blanks(Line), %Assertion.
+ Dict.
%%-----------------------------------------------------------------
%% Page with one port
@@ -2142,6 +2211,56 @@ get_atom(Atom) when is_binary(Atom) ->
{Atom,nq}. % not quoted
%%-----------------------------------------------------------------
+%% Page with list of all persistent terms
+persistent_terms(File, DecodeOpts) ->
+ case lookup_index(?persistent_terms) of
+ [{_Id,Start}] ->
+ Fd = open(File),
+ pos_bof(Fd,Start),
+ Terms = get_persistent_terms(Fd),
+ Dict = get_literals(Fd,DecodeOpts),
+ parse_persistent_terms(Terms,DecodeOpts,Dict);
+ _ ->
+ []
+ end.
+
+parse_persistent_terms([[Name0,Val0]|Terms],DecodeOpts,Dict) ->
+ {Name,_,_} = parse_term(binary_to_list(Name0),DecodeOpts,Dict),
+ {Val,_,_} = parse_term(binary_to_list(Val0),DecodeOpts,Dict),
+ [{Name,Val}|parse_persistent_terms(Terms,DecodeOpts,Dict)];
+parse_persistent_terms([],_,_) -> [].
+
+get_persistent_terms(Fd) ->
+ case get_chunk(Fd) of
+ {ok,Bin} ->
+ get_persistent_terms(Fd,Bin,[]);
+ eof ->
+ []
+ end.
+
+
+%% Persistent_Terms are written one per line in the crash dump.
+get_persistent_terms(Fd,Bin,PersistentTerms) ->
+ Bins = binary:split(Bin,<<"\n">>,[global]),
+ get_persistent_terms1(Fd,Bins,PersistentTerms).
+
+get_persistent_terms1(_Fd,[<<"=",_/binary>>|_],PersistentTerms) ->
+ PersistentTerms;
+get_persistent_terms1(Fd,[LastBin],PersistentTerms) ->
+ case get_chunk(Fd) of
+ {ok,Bin0} ->
+ get_persistent_terms(Fd,<<LastBin/binary,Bin0/binary>>,PersistentTerms);
+ eof ->
+ [get_persistent_term(LastBin)|PersistentTerms]
+ end;
+get_persistent_terms1(Fd,[Bin|Bins],Persistent_Terms) ->
+ get_persistent_terms1(Fd,Bins,[get_persistent_term(Bin)|Persistent_Terms]).
+
+get_persistent_term(Bin) ->
+ binary:split(Bin,<<"|">>).
+
+
+%%-----------------------------------------------------------------
%% Page with memory information
memory(File) ->
case lookup_index(?memory) of
@@ -2746,12 +2865,12 @@ parse_heap_term("Yc"++Line0, Addr, DecodeOpts, D0) -> %Reference-counted binary.
SymbolicBin = {'#CDVBin',Start},
Term = cdvbin(Offset, Sz, SymbolicBin),
D1 = gb_trees:insert(Addr, Term, D0),
- D = gb_trees:insert(Binp, SymbolicBin, D1),
+ D = gb_trees:enter(Binp, SymbolicBin, D1),
{Term,Line,D};
[] ->
Term = '#CDVNonexistingBinary',
D1 = gb_trees:insert(Addr, Term, D0),
- D = gb_trees:insert(Binp, Term, D1),
+ D = gb_trees:enter(Binp, Term, D1),
{Term,Line,D}
end;
parse_heap_term("Ys"++Line0, Addr, DecodeOpts, D0) -> %Sub binary.
@@ -2763,12 +2882,17 @@ parse_heap_term("Ys"++Line0, Addr, DecodeOpts, D0) -> %Sub binary.
{Term,Line,D};
parse_heap_term("Mf"++Line0, Addr, DecodeOpts, D0) -> %Flatmap.
{Size,":"++Line1} = get_hex(Line0),
- {Keys,":"++Line2,D1} = parse_term(Line1, DecodeOpts, D0),
- {Values,Line,D2} = parse_tuple(Size, Line2, Addr,DecodeOpts, D1, []),
- Pairs = zip_tuples(tuple_size(Keys), Keys, Values, []),
- Map = maps:from_list(Pairs),
- D = gb_trees:update(Addr, Map, D2),
- {Map,Line,D};
+ case parse_term(Line1, DecodeOpts, D0) of
+ {Keys,":"++Line2,D1} when is_tuple(Keys) ->
+ {Values,Line,D2} = parse_tuple(Size, Line2, Addr,DecodeOpts, D1, []),
+ Pairs = zip_tuples(tuple_size(Keys), Keys, Values, []),
+ Map = maps:from_list(Pairs),
+ D = gb_trees:update(Addr, Map, D2),
+ {Map,Line,D};
+ {Incomplete,_Line,D1} ->
+ D = gb_trees:insert(Addr, Incomplete, D1),
+ {Incomplete,"",D}
+ end;
parse_heap_term("Mh"++Line0, Addr, DecodeOpts, D0) -> %Head node in a hashmap.
{MapSize,":"++Line1} = get_hex(Line0),
{N,":"++Line2} = get_hex(Line1),
@@ -2871,16 +2995,18 @@ parse_atom_translation_table(N, Line0, As) ->
deref_ptr(Ptr, Line, DecodeOpts, D) ->
- Lookup = fun(D0) ->
- gb_trees:lookup(Ptr, D0)
- end,
+ Lookup0 = fun(D0) ->
+ gb_trees:lookup(Ptr, D0)
+ end,
+ Lookup = wrap_line_map(Ptr, Lookup0),
do_deref_ptr(Lookup, Line, DecodeOpts, D).
deref_bin(Binp0, Offset, Sz, Line, DecodeOpts, D) ->
Binp = Binp0 bor DecodeOpts#dec_opts.bin_addr_adj,
- Lookup = fun(D0) ->
- lookup_binary(Binp, Offset, Sz, D0)
- end,
+ Lookup0 = fun(D0) ->
+ lookup_binary(Binp, Offset, Sz, D0)
+ end,
+ Lookup = wrap_line_map(Binp, Lookup0),
do_deref_ptr(Lookup, Line, DecodeOpts, D).
lookup_binary(Binp, Offset, Sz, D) ->
@@ -2899,26 +3025,36 @@ lookup_binary(Binp, Offset, Sz, D) ->
end
end.
+wrap_line_map(Ptr, Lookup) ->
+ wrap_line_map_1(get(line_map), Ptr, Lookup).
+
+wrap_line_map_1(#{}=LineMap, Ptr, Lookup) ->
+ fun(D) ->
+ case Lookup(D) of
+ {value,_}=Res ->
+ Res;
+ none ->
+ case LineMap of
+ #{Ptr:=Line} ->
+ {line,Ptr,Line};
+ #{} ->
+ none
+ end
+ end
+ end;
+wrap_line_map_1(undefined, _Ptr, Lookup) ->
+ Lookup.
+
do_deref_ptr(Lookup, Line, DecodeOpts, D0) ->
case Lookup(D0) of
{value,Term} ->
{Term,Line,D0};
none ->
- case get(fd) of
- end_of_heap ->
- put(incomplete_heap,true),
- {['#CDVIncompleteHeap'],Line,D0};
- Fd ->
- case bytes(Fd) of
- "="++_ ->
- put(fd, end_of_heap),
- do_deref_ptr(Lookup, Line, DecodeOpts, D0);
- L ->
- update_progress(length(L)+1),
- D = parse(L, DecodeOpts, D0),
- do_deref_ptr(Lookup, Line, DecodeOpts, D)
- end
- end
+ put(incomplete_heap, true),
+ {'#CDVIncompleteHeap',Line,D0};
+ {line,Addr,NewLine} ->
+ D = parse_line(Addr, NewLine, DecodeOpts, D0),
+ do_deref_ptr(Lookup, Line, DecodeOpts, D)
end.
get_hex(L) ->
@@ -3119,6 +3255,7 @@ tag_to_atom("literals") -> ?literals;
tag_to_atom("loaded_modules") -> ?loaded_modules;
tag_to_atom("memory") -> ?memory;
tag_to_atom("mod") -> ?mod;
+tag_to_atom("persistent_terms") -> ?persistent_terms;
tag_to_atom("no_distribution") -> ?no_distribution;
tag_to_atom("node") -> ?node;
tag_to_atom("not_connected") -> ?not_connected;
@@ -3138,13 +3275,13 @@ tag_to_atom(UnknownTag) ->
%%%-----------------------------------------------------------------
%%% Store last tag for use when truncated, and reason if aborted
-put_last_tag(?abort,Reason) ->
- %% Don't overwrite the real last tag, and make sure to return
- %% the previous last tag.
- put(truncated_reason,Reason),
- get(last_tag);
-put_last_tag(Tag,Id) ->
- put(last_tag,{Tag,Id}).
+put_last_tag(?abort,Reason,_Pos) ->
+ %% Don't overwrite the real last tag, and don't return it either,
+ %% since that would make the caller of this function believe that
+ %% the tag was complete.
+ put(truncated_reason,Reason);
+put_last_tag(Tag,Id,Pos) ->
+ put(last_tag,{{Tag,Id},Pos}).
%%%-----------------------------------------------------------------
%%% Fetch next chunk from crashdump file
diff --git a/lib/observer/src/observer.app.src b/lib/observer/src/observer.app.src
index d73293a5f9..d48b846ad2 100644
--- a/lib/observer/src/observer.app.src
+++ b/lib/observer/src/observer.app.src
@@ -34,6 +34,7 @@
cdv_mem_cb,
cdv_mod_cb,
cdv_multi_wx,
+ cdv_persistent_cb,
cdv_port_cb,
cdv_proc_cb,
cdv_table_wx,
diff --git a/lib/observer/src/observer_alloc_wx.erl b/lib/observer/src/observer_alloc_wx.erl
index 54e246f247..da47a30fb1 100644
--- a/lib/observer/src/observer_alloc_wx.erl
+++ b/lib/observer/src/observer_alloc_wx.erl
@@ -282,11 +282,12 @@ create_mem_info(Parent) ->
Grid = wxListCtrl:new(Parent, [{style, Style}]),
Li = wxListItem:new(),
+ Scale = observer_wx:get_scale(),
AddListEntry = fun({Name, Align, DefSize}, Col) ->
wxListItem:setText(Li, Name),
wxListItem:setAlign(Li, Align),
wxListCtrl:insertColumn(Grid, Col, Li),
- wxListCtrl:setColumnWidth(Grid, Col, DefSize),
+ wxListCtrl:setColumnWidth(Grid, Col, DefSize*Scale),
Col + 1
end,
ListItems = [{"Allocator Type", ?wxLIST_FORMAT_LEFT, 200},
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
index 2a481966da..8c3eef5411 100644
--- a/lib/observer/src/observer_app_wx.erl
+++ b/lib/observer/src/observer_app_wx.erl
@@ -117,16 +117,19 @@ init([Notebook, Parent, _Config]) ->
UseGC = haveGC(),
Version28 = ?wxMAJOR_VERSION =:= 2 andalso ?wxMINOR_VERSION =:= 8,
+ Scale = observer_wx:get_scale(),
Font = case os:type() of
{unix,_} when UseGC, Version28 ->
- wxFont:new(12,?wxFONTFAMILY_DECORATIVE,?wxFONTSTYLE_NORMAL,?wxFONTWEIGHT_NORMAL);
+ wxFont:new(Scale * 12,?wxFONTFAMILY_DECORATIVE,?wxFONTSTYLE_NORMAL,?wxFONTWEIGHT_NORMAL);
_ ->
- wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT)
+ Font0 = wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT),
+ wxFont:setPointSize(Font0, Scale * wxFont:getPointSize(Font0)),
+ Font0
end,
SelCol = wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT),
GreyBrush = wxBrush:new({230,230,240}),
SelBrush = wxBrush:new(SelCol),
- LinkPen = wxPen:new(SelCol, [{width, 2}]),
+ LinkPen = wxPen:new(SelCol, [{width, Scale * 2}]),
process_flag(trap_exit, true),
{Panel, #state{parent=Parent,
panel =Panel,
@@ -134,7 +137,7 @@ init([Notebook, Parent, _Config]) ->
app_w =DrawingArea,
usegc = UseGC,
paint=#paint{font = Font,
- pen = wxPen:new({80,80,80}, [{width, 2}]),
+ pen = wxPen:new({80,80,80}, [{width, Scale * 2}]),
brush= GreyBrush,
sel = SelBrush,
links= LinkPen
diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl
index 0c4e32af49..c67fa28c6d 100644
--- a/lib/observer/src/observer_html_lib.erl
+++ b/lib/observer/src/observer_html_lib.erl
@@ -62,7 +62,8 @@ expandable_term_body(Heading,[],_Tab) ->
"Dictionary" -> "No dictionary was found";
"ProcState" -> "Information could not be retrieved,"
" system messages may not be handled by this process.";
- "SaslLog" -> "No log entry was found"
+ "SaslLog" -> "No log entry was found";
+ "Persistent Terms" -> "No persistent terms were found"
end];
expandable_term_body(Heading,Expanded,Tab) ->
Attr = "BORDER=0 CELLPADDING=0 CELLSPACING=1 WIDTH=100%",
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
index 21c6d26f49..79271addf2 100644
--- a/lib/observer/src/observer_perf_wx.erl
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -110,25 +110,26 @@ setup_graph_drawing(Panels) ->
_ = [Do(Panel) || Panel <- Panels],
UseGC = haveGC(),
Version28 = ?wxMAJOR_VERSION =:= 2 andalso ?wxMINOR_VERSION =:= 8,
+ Scale = observer_wx:get_scale(),
{Font, SmallFont}
= if UseGC, Version28 ->
%% Def font is really small when using Graphics contexts in 2.8
%% Hardcode it
- F = wxFont:new(12,?wxFONTFAMILY_DECORATIVE,?wxFONTSTYLE_NORMAL,?wxFONTWEIGHT_BOLD),
- SF = wxFont:new(10, ?wxFONTFAMILY_DECORATIVE, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
+ F = wxFont:new(Scale * 12,?wxFONTFAMILY_DECORATIVE,?wxFONTSTYLE_NORMAL,?wxFONTWEIGHT_BOLD),
+ SF = wxFont:new(Scale * 10, ?wxFONTFAMILY_DECORATIVE, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
{F, SF};
true ->
DefFont = wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT),
DefSize = wxFont:getPointSize(DefFont),
DefFamily = wxFont:getFamily(DefFont),
- F = wxFont:new(DefSize-1, DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_BOLD),
- SF = wxFont:new(DefSize-2, DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
+ F = wxFont:new(Scale * (DefSize-1), DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_BOLD),
+ SF = wxFont:new(Scale * (DefSize-2), DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
{F, SF}
end,
- BlackPen = wxPen:new({0,0,0}, [{width, 1}]),
- Pens = [wxPen:new(Col, [{width, 1}, {style, ?wxSOLID}])
+ BlackPen = wxPen:new({0,0,0}, [{width, Scale}]),
+ Pens = [wxPen:new(Col, [{width, Scale}, {style, ?wxSOLID}])
|| Col <- tuple_to_list(colors())],
- DotPens = [wxPen:new(Col, [{width, 1}, {style, ?wxDOT}])
+ DotPens = [wxPen:new(Col, [{width, Scale}, {style, ?wxDOT}])
|| Col <- tuple_to_list(colors())],
#paint{usegc = UseGC,
font = Font,
diff --git a/lib/observer/src/observer_port_wx.erl b/lib/observer/src/observer_port_wx.erl
index 445f3dd6b1..00cf1b5fba 100644
--- a/lib/observer/src/observer_port_wx.erl
+++ b/lib/observer/src/observer_port_wx.erl
@@ -96,11 +96,12 @@ init([Notebook, Parent, Config]) ->
wxListCtrl:setColumnWidth(Grid, Col, DefSize),
Col + 1
end,
- ListItems = [{"Id", ?wxLIST_FORMAT_LEFT, 150},
- {"Connected", ?wxLIST_FORMAT_LEFT, 150},
- {"Name", ?wxLIST_FORMAT_LEFT, 150},
- {"Controls", ?wxLIST_FORMAT_LEFT, 200},
- {"Slot", ?wxLIST_FORMAT_RIGHT, 50}],
+ Scale = observer_wx:get_scale(),
+ ListItems = [{"Id", ?wxLIST_FORMAT_LEFT, Scale*150},
+ {"Connected", ?wxLIST_FORMAT_LEFT, Scale*150},
+ {"Name", ?wxLIST_FORMAT_LEFT, Scale*150},
+ {"Controls", ?wxLIST_FORMAT_LEFT, Scale*200},
+ {"Slot", ?wxLIST_FORMAT_RIGHT, Scale*50}],
lists:foldl(AddListEntry, 0, ListItems),
wxListItem:destroy(Li),
@@ -461,10 +462,11 @@ display_port_info(Parent, PortRec, Opened) ->
do_display_port_info(Parent0, PortRec) ->
Parent = observer_lib:get_wx_parent(Parent0),
Title = "Port Info: " ++ PortRec#port.id_str,
+ Scale = observer_wx:get_scale(),
Frame = wxMiniFrame:new(Parent, ?wxID_ANY, Title,
[{style, ?wxSYSTEM_MENU bor ?wxCAPTION
bor ?wxCLOSE_BOX bor ?wxRESIZE_BORDER},
- {size,{600,400}}]),
+ {size,{Scale * 600, Scale * 400}}]),
ScrolledWin = wxScrolledWindow:new(Frame,[{style,?wxHSCROLL bor ?wxVSCROLL}]),
wxScrolledWindow:enableScrolling(ScrolledWin,true,true),
wxScrolledWindow:setScrollbars(ScrolledWin,20,20,0,0),
diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl
index 04e654a37e..4ab4a78462 100644
--- a/lib/observer/src/observer_pro_wx.erl
+++ b/lib/observer/src/observer_pro_wx.erl
@@ -163,13 +163,14 @@ create_list_box(Panel, Holder) ->
wxListCtrl:setColumnWidth(ListCtrl, Col, DefSize),
Col + 1
end,
- ListItems = [{"Pid", ?wxLIST_FORMAT_CENTRE, 120},
- {"Name or Initial Func", ?wxLIST_FORMAT_LEFT, 200},
-%% {"Time", ?wxLIST_FORMAT_CENTRE, 50},
- {"Reds", ?wxLIST_FORMAT_RIGHT, 100},
- {"Memory", ?wxLIST_FORMAT_RIGHT, 100},
- {"MsgQ", ?wxLIST_FORMAT_RIGHT, 50},
- {"Current Function", ?wxLIST_FORMAT_LEFT, 200}],
+ Scale = observer_wx:get_scale(),
+ ListItems = [{"Pid", ?wxLIST_FORMAT_CENTRE, Scale*120},
+ {"Name or Initial Func", ?wxLIST_FORMAT_LEFT, Scale*200},
+%% {"Time", ?wxLIST_FORMAT_CENTRE, Scale*50},
+ {"Reds", ?wxLIST_FORMAT_RIGHT, Scale*100},
+ {"Memory", ?wxLIST_FORMAT_RIGHT, Scale*100},
+ {"MsgQ", ?wxLIST_FORMAT_RIGHT, Scale*50},
+ {"Current Function", ?wxLIST_FORMAT_LEFT, Scale*200}],
lists:foldl(AddListEntry, 0, ListItems),
wxListItem:destroy(Li),
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index f436886735..bd5fed0951 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -59,8 +59,9 @@ init([Pid, ParentFrame, Parent]) ->
{registered_name, Registered} -> io_lib:format("~tp (~p)",[Registered, Pid]);
undefined -> throw(process_undefined)
end,
+ Scale = observer_wx:get_scale(),
Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [atom_to_list(node(Pid)), $:, Title],
- [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {850,600}}]),
+ [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {Scale * 850, Scale * 600}}]),
MenuBar = wxMenuBar:new(),
create_menus(MenuBar),
wxFrame:setMenuBar(Frame, MenuBar),
@@ -245,12 +246,13 @@ init_dict_page(Parent, Pid, Table) ->
init_stack_page(Parent, Pid) ->
LCtrl = wxListCtrl:new(Parent, [{style, ?wxLC_REPORT bor ?wxLC_HRULES}]),
Li = wxListItem:new(),
+ Scale = observer_wx:get_scale(),
wxListItem:setText(Li, "Module:Function/Arg"),
wxListCtrl:insertColumn(LCtrl, 0, Li),
- wxListCtrl:setColumnWidth(LCtrl, 0, 300),
+ wxListCtrl:setColumnWidth(LCtrl, 0, Scale * 300),
wxListItem:setText(Li, "File:LineNumber"),
wxListCtrl:insertColumn(LCtrl, 1, Li),
- wxListCtrl:setColumnWidth(LCtrl, 1, 300),
+ wxListCtrl:setColumnWidth(LCtrl, 1, Scale * 300),
wxListItem:destroy(Li),
Update = fun() ->
case observer_wx:try_rpc(node(Pid), erlang, process_info,
diff --git a/lib/observer/src/observer_trace_wx.erl b/lib/observer/src/observer_trace_wx.erl
index 2c3b46a3a1..f458c8c34a 100644
--- a/lib/observer/src/observer_trace_wx.erl
+++ b/lib/observer/src/observer_trace_wx.erl
@@ -188,8 +188,9 @@ create_proc_port_view(Parent) ->
wxListCtrl:setColumnWidth(Procs, Col, DefSize),
Col + 1
end,
- ProcListItems = [{"Process Id", ?wxLIST_FORMAT_CENTER, 120},
- {"Trace Options", ?wxLIST_FORMAT_LEFT, 300}],
+ Scale = observer_wx:get_scale(),
+ ProcListItems = [{"Process Id", ?wxLIST_FORMAT_CENTER, Scale*120},
+ {"Trace Options", ?wxLIST_FORMAT_LEFT, Scale*300}],
lists:foldl(AddProc, 0, ProcListItems),
AddPort = fun({Name, Align, DefSize}, Col) ->
@@ -199,8 +200,8 @@ create_proc_port_view(Parent) ->
wxListCtrl:setColumnWidth(Ports, Col, DefSize),
Col + 1
end,
- PortListItems = [{"Port Id", ?wxLIST_FORMAT_CENTER, 120},
- {"Trace Options", ?wxLIST_FORMAT_LEFT, 300}],
+ PortListItems = [{"Port Id", ?wxLIST_FORMAT_CENTER, Scale*120},
+ {"Trace Options", ?wxLIST_FORMAT_LEFT, Scale*300}],
lists:foldl(AddPort, 0, PortListItems),
wxListItem:destroy(Li),
@@ -242,14 +243,15 @@ create_matchspec_view(Parent) ->
Funcs = wxListCtrl:new(Splitter, [{winid, ?FUNCS_WIN}, {style, Style}]),
Li = wxListItem:new(),
+ Scale = observer_wx:get_scale(),
wxListItem:setText(Li, "Modules"),
wxListCtrl:insertColumn(Modules, 0, Li),
wxListItem:setText(Li, "Functions"),
wxListCtrl:insertColumn(Funcs, 0, Li),
- wxListCtrl:setColumnWidth(Funcs, 0, 150),
+ wxListCtrl:setColumnWidth(Funcs, 0, Scale*150),
wxListItem:setText(Li, "Match Spec"),
wxListCtrl:insertColumn(Funcs, 1, Li),
- wxListCtrl:setColumnWidth(Funcs, 1, 300),
+ wxListCtrl:setColumnWidth(Funcs, 1, Scale*300),
wxListItem:destroy(Li),
wxSplitterWindow:setSashGravity(Splitter, 0.0),
@@ -969,7 +971,8 @@ output_file(true, true, Opts) ->
create_logwindow(_Parent, false) -> {false, false};
create_logwindow(Parent, true) ->
- LogWin = wxFrame:new(Parent, ?LOG_WIN, "Trace Log", [{size, {750, 800}}]),
+ Scale = observer_wx:get_scale(),
+ LogWin = wxFrame:new(Parent, ?LOG_WIN, "Trace Log", [{size, {750*Scale, 800*Scale}}]),
MB = wxMenuBar:new(),
File = wxMenu:new(),
wxMenu:append(File, ?LOG_CLEAR, "Clear Log\tCtrl-C"),
diff --git a/lib/observer/src/observer_traceoptions_wx.erl b/lib/observer/src/observer_traceoptions_wx.erl
index ea292b92af..514d55ff24 100644
--- a/lib/observer/src/observer_traceoptions_wx.erl
+++ b/lib/observer/src/observer_traceoptions_wx.erl
@@ -167,9 +167,10 @@ select_nodes(Parent, Nodes) ->
check_selector(Parent, Choices).
module_selector(Parent, Node) ->
+ Scale = observer_wx:get_scale(),
Dialog = wxDialog:new(Parent, ?wxID_ANY, "Select Module or Event",
[{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER},
- {size, {400, 400}}]),
+ {size, {400*Scale, 400*Scale}}]),
Panel = wxPanel:new(Dialog),
PanelSz = wxBoxSizer:new(?wxVERTICAL),
MainSz = wxBoxSizer:new(?wxVERTICAL),
@@ -237,9 +238,10 @@ function_selector(Parent, Node, Module) ->
end.
check_selector(Parent, ParsedChoices) ->
+ Scale = observer_wx:get_scale(),
Dialog = wxDialog:new(Parent, ?wxID_ANY, "Trace Functions",
[{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER},
- {size, {400, 400}}]),
+ {size, {400*Scale, 400*Scale}}]),
Panel = wxPanel:new(Dialog),
PanelSz = wxBoxSizer:new(?wxVERTICAL),
@@ -331,9 +333,10 @@ select_matchspec(Pid, Parent, AllMatchSpecs, Key) ->
{value,{Key,MSs0},Rest} -> {MSs0,Rest};
false -> {[],AllMatchSpecs}
end,
+ Scale = observer_wx:get_scale(),
Dialog = wxDialog:new(Parent, ?wxID_ANY, "Trace Match Specifications",
[{style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER},
- {size, {400, 400}}]),
+ {size, {400*Scale, 400*Scale}}]),
Panel = wxPanel:new(Dialog),
PanelSz = wxBoxSizer:new(?wxVERTICAL),
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index d6dcee2cda..7bd67a0f0b 100644
--- a/lib/observer/src/observer_tv_table.erl
+++ b/lib/observer/src/observer_tv_table.erl
@@ -99,7 +99,8 @@ init([Parent, Opts]) ->
ets -> "TV Ets: " ++ Title0;
mnesia -> "TV Mnesia: " ++ Title0
end,
- Frame = wxFrame:new(Parent, ?wxID_ANY, Title, [{size, {800, 600}}]),
+ Scale = observer_wx:get_scale(),
+ Frame = wxFrame:new(Parent, ?wxID_ANY, Title, [{size, {Scale * 800, Scale * 600}}]),
IconFile = filename:join(code:priv_dir(observer), "erlang_observer.png"),
Icon = wxIcon:new(IconFile, [{type,?wxBITMAP_TYPE_PNG}]),
wxFrame:setIcon(Frame, Icon),
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index 814f3a1260..247b3e869f 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -87,12 +87,13 @@ init([Notebook, Parent, Config]) ->
wxListCtrl:setColumnWidth(Grid, Col, DefSize),
Col + 1
end,
- ListItems = [{"Table Name", ?wxLIST_FORMAT_LEFT, 200},
- {"Objects", ?wxLIST_FORMAT_RIGHT, 100},
- {"Size (kB)", ?wxLIST_FORMAT_RIGHT, 100},
- {"Owner Pid", ?wxLIST_FORMAT_CENTER, 150},
- {"Owner Name", ?wxLIST_FORMAT_LEFT, 200},
- {"Table Id", ?wxLIST_FORMAT_LEFT, 250}
+ Scale = observer_wx:get_scale(),
+ ListItems = [{"Table Name", ?wxLIST_FORMAT_LEFT, Scale*200},
+ {"Objects", ?wxLIST_FORMAT_RIGHT, Scale*100},
+ {"Size (kB)", ?wxLIST_FORMAT_RIGHT, Scale*100},
+ {"Owner Pid", ?wxLIST_FORMAT_CENTER, Scale*150},
+ {"Owner Name", ?wxLIST_FORMAT_LEFT, Scale*200},
+ {"Table Id", ?wxLIST_FORMAT_LEFT, Scale*250}
],
lists:foldl(AddListEntry, 0, ListItems),
wxListItem:destroy(Li),
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 453e3bdc2d..71db586845 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -22,7 +22,7 @@
-export([start/0, stop/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]).
+ get_scale/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,
handle_call/3, handle_info/2, check_page_title/1]).
@@ -91,14 +91,24 @@ get_active_node() ->
get_menubar() ->
wx_object:call(observer, get_menubar).
+get_scale() ->
+ ScaleStr = os:getenv("OBSERVER_SCALE", "1"),
+ try list_to_integer(ScaleStr) of
+ Scale when Scale < 1 -> 1;
+ Scale -> Scale
+ catch _:_ ->
+ 1
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init(_Args) ->
register(observer, self()),
wx:new(),
catch wxSystemOptions:setOption("mac.listctrl.always_use_generic", 1),
+ Scale = get_scale(),
Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Observer",
- [{size, {850, 600}}, {style, ?wxDEFAULT_FRAME_STYLE}]),
+ [{size, {Scale * 850, Scale * 600}}, {style, ?wxDEFAULT_FRAME_STYLE}]),
IconFile = filename:join(code:priv_dir(observer), "erlang_observer.png"),
Icon = wxIcon:new(IconFile, [{type,?wxBITMAP_TYPE_PNG}]),
wxFrame:setIcon(Frame, Icon),
@@ -771,7 +781,11 @@ ensure_sasl_started(Node) ->
ensure_mf_h_handler_used(Node) ->
%% is log_mf_h used ?
- Handlers = rpc:block_call(Node, gen_event, which_handlers, [error_logger]),
+ Handlers =
+ case rpc:block_call(Node, gen_event, which_handlers, [error_logger]) of
+ {badrpc,{'EXIT',noproc}} -> []; % OTP-21+ and no event handler exists
+ Hs -> Hs
+ end,
case lists:any(fun(L)-> L == log_mf_h end, Handlers) of
false -> throw("Error: log_mf_h handler not used in sasl."),
error;
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index 145ff56b71..d6b5eff9b5 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -21,7 +21,9 @@
-module(crashdump_helper).
-export([n1_proc/2,remote_proc/2,
dump_maps/0,create_maps/0,
- create_binaries/0,create_sub_binaries/1]).
+ create_binaries/0,create_sub_binaries/1,
+ dump_persistent_terms/0,
+ create_persistent_terms/0]).
-compile(r18).
-include_lib("common_test/include/ct.hrl").
@@ -62,6 +64,7 @@ n1_proc(Creator,_N2,Pid2,Port2,_L) ->
put(ref,Ref),
put(pid,Pid),
put(bin,Bin),
+ put(proc_bins,create_proc_bins()),
put(bins,create_binaries()),
put(sub_bin,SubBin),
put(sub_bins,create_sub_binaries(get(bins))),
@@ -117,6 +120,23 @@ create_sub_binary(Bin, Start, LenSub) ->
<<_:Start/bytes,Sub:Len/bytes,_/bytes>> = Bin,
Sub.
+create_proc_bins() ->
+ Parent = self(),
+ Pid =
+ spawn(
+ fun() ->
+ %% Just reverse the list here, so this binary is not
+ %% confused with the one created in n1_proc/5 above,
+ %% which is used for testing truncation (see
+ %% crashdump_viewer_SUITE:truncate_dump_binary/1)
+ Bin = list_to_binary(lists:reverse(lists:seq(1, 255))),
+ <<A:65/bytes,B:65/bytes,C/bytes>> = Bin,
+ Parent ! {self(),{A,B,C}}
+ end),
+ receive
+ {Pid,ProcBins} -> ProcBins
+ end.
+
%%%
%%% Test dumping of maps. Dumping of maps only from OTP 20.2.
%%%
@@ -142,4 +162,46 @@ create_maps() ->
Map3 = lists:foldl(fun(I, A) ->
A#{I=>I*I}
end, Map2, lists:seq(-10, 0)),
- #{a=>Map0,b=>Map1,c=>Map2,d=>Map3,e=>#{}}.
+ #{a=>Map0,b=>Map1,c=>Map2,d=>Map3,e=>#{},literal=>literal_map()}.
+
+literal_map() ->
+ %% A literal map such as the one below will produce a heap dump
+ %% like this:
+ %%
+ %% Address1:t4:H<Address3>,H<Address4>,H<Address5>,H<Address6>
+ %% Address2:Mf4:H<Adress1>:I1,I2,I3,I4
+ %% Address3: ... % "one"
+ %% Address4: ... % "two"
+ %% Address5: ... % "three"
+ %% Address6: ... % "four"
+ %%
+ %% The map cannot be reconstructed in a single sequential pass.
+ %%
+ %% To reconstruct the map, first the string keys "one"
+ %% through "four" must be reconstructed, then the tuple at
+ %% Adress1, then the map at Address2.
+
+ #{"one"=>1,"two"=>2,"three"=>3,"four"=>4}.
+
+%%%
+%%% Test dumping of persistent terms (from OTP 21.2).
+%%%
+
+dump_persistent_terms() ->
+ Parent = self(),
+ F = fun() ->
+ register(aaaaaaaa_persistent_terms, self()),
+ put(pts, create_persistent_terms()),
+ Parent ! {self(),done},
+ receive _ -> ok end
+ end,
+ Pid = spawn_link(F),
+ receive
+ {Pid,done} ->
+ {ok,Pid}
+ end.
+
+create_persistent_terms() ->
+ persistent_term:put({?MODULE,first}, {pid,42.0}),
+ persistent_term:put({?MODULE,second}, [1,2,3]),
+ {persistent_term:get({?MODULE,first}),persistent_term:get({?MODULE,second})}.
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl
index 864454cdff..31cf7011d4 100644
--- a/lib/observer/test/crashdump_viewer_SUITE.erl
+++ b/lib/observer/test/crashdump_viewer_SUITE.erl
@@ -345,6 +345,7 @@ browse_file(File) ->
{ok,_AllocINfo,_AllocInfoTW} = crashdump_viewer:allocator_info(),
{ok,_HashTabs,_HashTabsTW} = crashdump_viewer:hash_tables(),
{ok,_IndexTabs,_IndexTabsTW} = crashdump_viewer:index_tables(),
+ {ok,_PTs,_PTsTW} = crashdump_viewer:persistent_terms(),
io:format(" info read",[]),
@@ -399,6 +400,13 @@ special(File,Procs) ->
crashdump_viewer:expand_binary({SOffset,SSize,SPos}),
io:format(" expand binary ok",[]),
+ ProcBins = proplists:get_value(proc_bins,Dict),
+ {['#CDVBin',0,65,ProcBin],
+ ['#CDVBin',65,65,ProcBin],
+ ['#CDVBin',130,125,ProcBin]} = ProcBins,
+ io:format(" ProcBins ok",[]),
+
+
Binaries = crashdump_helper:create_binaries(),
verify_binaries(Binaries, proplists:get_value(bins,Dict)),
io:format(" binaries ok",[]),
@@ -595,6 +603,22 @@ special(File,Procs) ->
Maps = proplists:get_value(maps,Dict),
io:format(" maps ok",[]),
ok;
+ ".persistent_terms" ->
+ %% I registered a process as aaaaaaaa_persistent_term in
+ %% the dump to make sure it will be the first in the list
+ %% when sorted on names.
+ [#proc{pid=Pid0,name=Name}|_Rest] = lists:keysort(#proc.name,Procs),
+ "aaaaaaaa_persistent_terms" = Name,
+ Pid = pid_to_list(Pid0),
+ {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid),
+ io:format(" process details ok",[]),
+
+ #proc{dict=Dict} = ProcDetails,
+ %% io:format("~p\n", [Dict]),
+ Pts = crashdump_helper:create_persistent_terms(),
+ Pts = proplists:get_value(pts,Dict),
+ io:format(" persistent terms ok",[]),
+ ok;
_ ->
ok
end,
@@ -679,9 +703,11 @@ do_create_dumps(DataDir,Rel) ->
CD5 = dump_with_size_limit_reached(DataDir,Rel,"trunc_bytes"),
CD6 = dump_with_unicode_atoms(DataDir,Rel,"unicode"),
CD7 = dump_with_maps(DataDir,Rel,"maps"),
+ CD8 = dump_with_persistent_terms(DataDir,Rel,"persistent_terms"),
TruncDumpMod = truncate_dump_mod(CD1),
TruncatedDumpsBinary = truncate_dump_binary(CD1),
- {[CD1,CD2,CD3,CD4,CD5,CD6,CD7,TruncDumpMod|TruncatedDumpsBinary],
+ {[CD1,CD2,CD3,CD4,CD5,CD6,CD7,CD8,
+ TruncDumpMod|TruncatedDumpsBinary],
DosDump};
_ ->
{[CD1,CD2], DosDump}
@@ -850,6 +876,16 @@ dump_with_maps(DataDir,Rel,DumpName) ->
?t:stop_node(n1),
CD.
+dump_with_persistent_terms(DataDir,Rel,DumpName) ->
+ Opt = rel_opt(Rel),
+ Pz = "-pz \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
+ PzOpt = [{args,Pz}],
+ {ok,N1} = ?t:start_node(n1,peer,Opt ++ PzOpt),
+ {ok,_Pid} = rpc:call(N1,crashdump_helper,dump_persistent_terms,[]),
+ CD = dump(N1,DataDir,Rel,DumpName),
+ ?t:stop_node(n1),
+ CD.
+
dump(Node,DataDir,Rel,DumpName) ->
Crashdump = filename:join(DataDir, dump_prefix(Rel)++DumpName),
rpc:call(Node,os,putenv,["ERL_CRASH_DUMP",Crashdump]),
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index bf6fd2a421..0e9c8b302c 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 2.8
+OBSERVER_VSN = 2.9
diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c
index 8c799f6ff1..fb4f61417e 100644
--- a/lib/odbc/c_src/odbcserver.c
+++ b/lib/odbc/c_src/odbcserver.c
@@ -2749,6 +2749,11 @@ static diagnos get_diagnos(SQLSMALLINT handleType, SQLHANDLE handle, Boolean ext
errmsg_buffer_size = errmsg_buffer_size - errmsg_size;
acc_errmsg_size = acc_errmsg_size + errmsg_size;
current_errmsg_pos = current_errmsg_pos + errmsg_size;
+ } else if(result == SQL_SUCCESS_WITH_INFO && errmsg_size >= errmsg_buffer_size) {
+ memcpy(diagnos.sqlState, current_sql_state, SQL_STATE_SIZE);
+ diagnos.nativeError = nativeError;
+ acc_errmsg_size = errmsg_buffer_size;
+ break;
} else {
break;
}
diff --git a/lib/odbc/doc/src/Makefile b/lib/odbc/doc/src/Makefile
index b3f93a7e9c..a6311ceede 100644
--- a/lib/odbc/doc/src/Makefile
+++ b/lib/odbc/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2017. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -101,6 +101,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index 2aa55ca99c..696fcaa479 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,37 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.12.1</title>
+ <section><title>ODBC 2.12.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling to avoid stack corruption</p>
+ <p>
+ Own Id: OTP-15667 Aux Id: ERL-808, PR-2065 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.12.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.12.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml
index 4bb1f035f9..4d941b3b36 100644
--- a/lib/odbc/doc/src/odbc.xml
+++ b/lib/odbc/doc/src/odbc.xml
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>odbc</module>
+ <module since="">odbc</module>
<modulesummary>Erlang ODBC application</modulesummary>
<description>
<p>This application provides an Erlang interface to communicate
@@ -130,8 +130,8 @@
</section>
<funcs>
<func>
- <name>commit(Ref, CommitMode) -></name>
- <name>commit(Ref, CommitMode, TimeOut) -> ok | {error, Reason} </name>
+ <name since="">commit(Ref, CommitMode) -></name>
+ <name since="">commit(Ref, CommitMode, TimeOut) -> ok | {error, Reason} </name>
<fsummary>Commits or rollbacks a transaction. </fsummary>
<type>
<v>Ref = connection_reference() </v>
@@ -145,7 +145,7 @@
</desc>
</func>
<func>
- <name>connect(ConnectStr, Options) -> {ok, Ref} | {error, Reason} </name>
+ <name since="">connect(ConnectStr, Options) -> {ok, Ref} | {error, Reason} </name>
<fsummary>Opens a connection to the database. </fsummary>
<type>
<v>ConnectStr = string()</v>
@@ -236,7 +236,7 @@
</desc>
</func>
<func>
- <name>disconnect(Ref) -> ok | {error, Reason} </name>
+ <name since="">disconnect(Ref) -> ok | {error, Reason} </name>
<fsummary>Closes a connection to a database. </fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -255,8 +255,8 @@
</desc>
</func>
<func>
- <name>describe_table(Ref, Table) -> </name>
- <name>describe_table(Ref, Table, Timeout) -> {ok, Description} | {error, Reason} </name>
+ <name since="">describe_table(Ref, Table) -> </name>
+ <name since="">describe_table(Ref, Table, Timeout) -> {ok, Description} | {error, Reason} </name>
<fsummary>Queries the database to find out the data types of the columns of the table <c>Table</c>. </fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -271,8 +271,8 @@
</desc>
</func>
<func>
- <name>first(Ref) -></name>
- <name>first(Ref, Timeout) -> {selected, ColNames, Rows} | {error, Reason} </name>
+ <name since="">first(Ref) -></name>
+ <name since="">first(Ref, Timeout) -> {selected, ColNames, Rows} | {error, Reason} </name>
<fsummary>Returns the first row of the result set and positions a cursor at this row.</fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -287,8 +287,8 @@
</desc>
</func>
<func>
- <name>last(Ref) -></name>
- <name>last(Ref, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
+ <name since="">last(Ref) -></name>
+ <name since="">last(Ref, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
<fsummary>Returns the last row of the result set and positions a cursor at this row. </fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -303,8 +303,8 @@
</desc>
</func>
<func>
- <name>next(Ref) -> </name>
- <name>next(Ref, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
+ <name since="">next(Ref) -> </name>
+ <name since="">next(Ref, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
<fsummary>Returns the next row of the result set relative the current cursor position and positions the cursor at this row. </fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -325,8 +325,8 @@
</desc>
</func>
<func>
- <name>param_query(Ref, SQLQuery, Params) -> </name>
- <name>param_query(Ref, SQLQuery, Params, TimeOut) -> ResultTuple | {error, Reason} </name>
+ <name since="">param_query(Ref, SQLQuery, Params) -> </name>
+ <name since="">param_query(Ref, SQLQuery, Params, TimeOut) -> ResultTuple | {error, Reason} </name>
<fsummary>Executes a parameterized SQL query.</fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -353,8 +353,8 @@
</desc>
</func>
<func>
- <name>prev(Ref) -> </name>
- <name>prev(ConnectionReference, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
+ <name since="">prev(Ref) -> </name>
+ <name since="">prev(ConnectionReference, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
<fsummary>Returns the previous row of the result set relative the current cursor position and positions the cursor at this row. </fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -371,8 +371,8 @@
</func>
<func>
- <name>start() -> </name>
- <name>start(Type) -> ok | {error, Reason}</name>
+ <name since="">start() -> </name>
+ <name since="">start(Type) -> ok | {error, Reason}</name>
<fsummary>Starts the odb application. </fsummary>
<type>
@@ -389,7 +389,7 @@
</func>
<func>
- <name>stop() -> ok </name>
+ <name since="">stop() -> ok </name>
<fsummary> Stops the odbc application.</fsummary>
<desc>
@@ -400,8 +400,8 @@
</func>
<func>
- <name>sql_query(Ref, SQLQuery) -> </name>
- <name>sql_query(Ref, SQLQuery, TimeOut) -> ResultTuple | [ResultTuple] |{error, Reason}</name>
+ <name since="">sql_query(Ref, SQLQuery) -> </name>
+ <name since="">sql_query(Ref, SQLQuery, TimeOut) -> ResultTuple | [ResultTuple] |{error, Reason}</name>
<fsummary>Executes a SQL query or a batch of SQL queries. If it is a SELECT query the result set is returned, on the format<c>{selected, ColNames, Rows}</c>. For other query types the tuple <c>{updated, NRows}</c>is returned, and for batched queries, if the driver supports them, this function can also return a list of result tuples.</fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -429,8 +429,8 @@
</desc>
</func>
<func>
- <name>select_count(Ref, SelectQuery) -> </name>
- <name>select_count(Ref, SelectQuery, TimeOut) -> {ok, NrRows} | {error, Reason} </name>
+ <name since="">select_count(Ref, SelectQuery) -> </name>
+ <name since="">select_count(Ref, SelectQuery, TimeOut) -> {ok, NrRows} | {error, Reason} </name>
<fsummary>Executes a SQL SELECT query and associates the result set with the connection. A cursor is positioned before the first row in the result set and the tuple <c>{ok, NrRows}</c>is returned. </fsummary>
<type>
<v>Ref = connection_reference()</v>
@@ -453,8 +453,8 @@
</desc>
</func>
<func>
- <name>select(Ref, Position, N) -></name>
- <name>select(Ref, Position, N, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
+ <name since="">select(Ref, Position, N) -></name>
+ <name since="">select(Ref, Position, N, TimeOut) -> {selected, ColNames, Rows} | {error, Reason} </name>
<fsummary>Selects <c>N</c>consecutive rows of the result set.</fsummary>
<type>
<v>Ref = connection_reference()</v>
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 3f7677a71d..ff023e666b 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.12.1
+ODBC_VSN = 2.12.3
diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
index 17ef48c26e..c96a5c9f7c 100644
--- a/lib/os_mon/c_src/cpu_sup.c
+++ b/lib/os_mon/c_src/cpu_sup.c
@@ -152,6 +152,8 @@ static void util_measure(unsigned int **result_vec, int *result_sz);
#if defined(__sun__)
static unsigned int misc_measure(char* name);
+#elif defined(__linux__)
+static unsigned int misc_measure(char cmd);
#endif
static void sendi(unsigned int data);
static void sendv(unsigned int data[], int ints);
@@ -231,6 +233,11 @@ int main(int argc, char** argv) {
case AVG1: sendi(misc_measure("avenrun_1min")); break;
case AVG5: sendi(misc_measure("avenrun_5min")); break;
case AVG15: sendi(misc_measure("avenrun_15min")); break;
+#elif defined(__linux__)
+ case NPROCS:
+ case AVG1:
+ case AVG5:
+ case AVG15: sendi(misc_measure(cmd)); break;
#elif defined(__OpenBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__DragonFly__)
case NPROCS: bsd_count_procs(); break;
case AVG1: bsd_loadavg(0); break;
@@ -238,7 +245,7 @@ int main(int argc, char** argv) {
case AVG15: bsd_loadavg(2); break;
#endif
#if defined(__sun__) || defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
- case UTIL: util_measure(&rv,&sz); sendv(rv, sz); break;
+ case UTIL: util_measure(&rv,&sz); sendv(rv, sz); break;
#endif
case QUIT: free((void*)rv); return 0;
default: error("Bad command"); break;
@@ -329,6 +336,22 @@ static void bsd_count_procs(void) {
#if defined(__linux__)
+static unsigned int misc_measure(char cmd) {
+ struct sysinfo info;
+
+ if (sysinfo(&info))
+ error(strerror(errno));
+
+ switch (cmd) {
+ case AVG1: return (unsigned int)(info.loads[0] / 256);
+ case AVG5: return (unsigned int)(info.loads[1] / 256);
+ case AVG15: return (unsigned int)(info.loads[2] / 256);
+ case NPROCS: return info.procs;
+ }
+
+ return -1;
+}
+
static cpu_t *read_procstat(FILE *fp, cpu_t *cpu) {
char buffer[BUFFERSIZE];
@@ -357,8 +380,24 @@ static void util_measure(unsigned int **result_vec, int *result_sz) {
FILE *fp;
unsigned int *rv = NULL;
cpu_t cpu;
-
+
+ rv = *result_vec;
+ rv[0] = no_of_cpus;
+
if ( (fp = fopen(PROCSTAT,"r")) == NULL) {
+ if (errno == EACCES) { /* SELinux */
+ rv[1] = 1; /* just the cpu id */
+ ++rv; /* first value is number of cpus */
+ ++rv; /* second value is number of entries */
+ for (i = 0; i < no_of_cpus; ++i) {
+ rv[0] = CU_CPU_ID;
+ rv[1] = i;
+ rv += 1*2;
+ }
+ *result_sz = 2 + 2*1 * no_of_cpus;
+ return;
+ }
+
/* Check if procfs is mounted,
* otherwise:
* try and try again, bad procsfs.
@@ -367,20 +406,19 @@ static void util_measure(unsigned int **result_vec, int *result_sz) {
return;
}
- /*ignore read*/
+ /*ignore read*/
if (fgets(buffer, BUFFERSIZE, fp) == NULL) {
*result_sz = 0;
return;
}
- rv = *result_vec;
- rv[0] = no_of_cpus;
+
rv[1] = CU_VALUES;
++rv; /* first value is number of cpus */
++rv; /* second value is number of entries */
for (i = 0; i < no_of_cpus; ++i) {
read_procstat(fp, &cpu);
-
+
rv[ 0] = CU_CPU_ID; rv[ 1] = cpu.id;
rv[ 2] = CU_USER; rv[ 3] = cpu.user;
rv[ 4] = CU_NICE_USER; rv[ 5] = cpu.nice_user;
diff --git a/lib/os_mon/doc/src/Makefile b/lib/os_mon/doc/src/Makefile
index 4aa8879a91..354f8ed26b 100644
--- a/lib/os_mon/doc/src/Makefile
+++ b/lib/os_mon/doc/src/Makefile
@@ -98,6 +98,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/os_mon/doc/src/cpu_sup.xml b/lib/os_mon/doc/src/cpu_sup.xml
index bada165a06..b7adb2bcd2 100644
--- a/lib/os_mon/doc/src/cpu_sup.xml
+++ b/lib/os_mon/doc/src/cpu_sup.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>cpu_sup</module>
+ <module since="">cpu_sup</module>
<modulesummary>A CPU Load and CPU Utilization Supervisor Process</modulesummary>
<description>
<p><c>cpu_sup</c> is a process which supervises the CPU load
@@ -76,7 +76,7 @@
</description>
<funcs>
<func>
- <name>nprocs() -> UnixProcesses | {error, Reason}</name>
+ <name since="">nprocs() -> UnixProcesses | {error, Reason}</name>
<fsummary>Get the number of UNIX processes running on this host</fsummary>
<type>
<v>UnixProcesses = int()</v>
@@ -90,7 +90,7 @@
</desc>
</func>
<func>
- <name>avg1() -> SystemLoad | {error, Reason}</name>
+ <name since="">avg1() -> SystemLoad | {error, Reason}</name>
<fsummary>Get the system load average for the last minute</fsummary>
<type>
<v>SystemLoad = int()</v>
@@ -104,7 +104,7 @@
</desc>
</func>
<func>
- <name>avg5() -> SystemLoad | {error, Reason}</name>
+ <name since="">avg5() -> SystemLoad | {error, Reason}</name>
<fsummary>Get the system load average for the last five minutes</fsummary>
<type>
<v>SystemLoad = int()</v>
@@ -118,7 +118,7 @@
</desc>
</func>
<func>
- <name>avg15() -> SystemLoad | {error, Reason}</name>
+ <name since="">avg15() -> SystemLoad | {error, Reason}</name>
<fsummary>Get the system load average for the last fifteen minutes</fsummary>
<type>
<v>SystemLoad = int()</v>
@@ -132,7 +132,7 @@
</desc>
</func>
<func>
- <name>util() -> CpuUtil | {error, Reason}</name>
+ <name since="">util() -> CpuUtil | {error, Reason}</name>
<fsummary>Get the CPU utilization</fsummary>
<type>
<v>CpuUtil = float()</v>
@@ -156,7 +156,7 @@
</desc>
</func>
<func>
- <name>util(Opts) -> UtilSpec | {error, Reason}</name>
+ <name since="">util(Opts) -> UtilSpec | {error, Reason}</name>
<fsummary>Get the CPU utilization</fsummary>
<type>
<v>Opts = [detailed | per_cpu]</v>
diff --git a/lib/os_mon/doc/src/disksup.xml b/lib/os_mon/doc/src/disksup.xml
index 610ef2c907..116a6dfd19 100644
--- a/lib/os_mon/doc/src/disksup.xml
+++ b/lib/os_mon/doc/src/disksup.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>disksup</module>
+ <module since="">disksup</module>
<modulesummary>A Disk Supervisor Process</modulesummary>
<description>
<p><c>disksup</c> is a process which supervises the available disk
@@ -92,7 +92,7 @@
</section>
<funcs>
<func>
- <name>get_disk_data() -> [DiskData]</name>
+ <name since="">get_disk_data() -> [DiskData]</name>
<fsummary>Get data for the disks in the system</fsummary>
<type>
<v>DiskData = {Id, KByte, Capacity}</v>
@@ -112,7 +112,7 @@
</desc>
</func>
<func>
- <name>get_check_interval() -> MS</name>
+ <name since="">get_check_interval() -> MS</name>
<fsummary>Get time interval, in milliseconds, for the periodic disk space check</fsummary>
<type>
<v>MS = int()</v>
@@ -123,7 +123,7 @@
</desc>
</func>
<func>
- <name>set_check_interval(Minutes) -> ok</name>
+ <name since="">set_check_interval(Minutes) -> ok</name>
<fsummary>Set time interval, in minutes, for the periodic disk space check</fsummary>
<type>
<v>Minutes = int()>=1</v>
@@ -138,7 +138,7 @@
</desc>
</func>
<func>
- <name>get_almost_full_threshold() -> Percent</name>
+ <name since="">get_almost_full_threshold() -> Percent</name>
<fsummary>Get threshold, in percent, for disk space utilization</fsummary>
<type>
<v>Percent = int()</v>
@@ -148,7 +148,7 @@
</desc>
</func>
<func>
- <name>set_almost_full_threshold(Float) -> ok</name>
+ <name since="">set_almost_full_threshold(Float) -> ok</name>
<fsummary>Set threshold, as percentage represented by a float, for disk space utilization</fsummary>
<type>
<v>Float = float(), 0=&lt;Float=&lt;1</v>
diff --git a/lib/os_mon/doc/src/memsup.xml b/lib/os_mon/doc/src/memsup.xml
index c669e4670a..51c78b07c2 100644
--- a/lib/os_mon/doc/src/memsup.xml
+++ b/lib/os_mon/doc/src/memsup.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>memsup</module>
+ <module since="">memsup</module>
<modulesummary>A Memory Supervisor Process</modulesummary>
<description>
<p><c>memsup</c> is a process which supervises the memory usage for
@@ -127,7 +127,7 @@
</section>
<funcs>
<func>
- <name>get_memory_data() -> {Total,Allocated,Worst}</name>
+ <name since="">get_memory_data() -> {Total,Allocated,Worst}</name>
<fsummary>Get data for the memory in the system</fsummary>
<type>
<v>Total = Allocated = int()</v>
@@ -155,7 +155,7 @@
</desc>
</func>
<func>
- <name>get_system_memory_data() -> MemDataList</name>
+ <name since="">get_system_memory_data() -> MemDataList</name>
<fsummary>Get system dependent memory data</fsummary>
<type>
<v>MemDataList = [{Tag, Size}]</v>
@@ -216,7 +216,7 @@
</desc>
</func>
<func>
- <name>get_os_wordsize() -> Wordsize</name>
+ <name since="">get_os_wordsize() -> Wordsize</name>
<fsummary>Get the wordsize of running os.</fsummary>
<type>
<v>Wordsize = 32 | 64 | unsupported_os</v>
@@ -226,7 +226,7 @@
</desc>
</func>
<func>
- <name>get_check_interval() -> MS</name>
+ <name since="">get_check_interval() -> MS</name>
<fsummary>Get time interval, in milliseconds, for the periodic memory check</fsummary>
<type>
<v>MS = int()</v>
@@ -237,7 +237,7 @@
</desc>
</func>
<func>
- <name>set_check_interval(Minutes) -> ok</name>
+ <name since="">set_check_interval(Minutes) -> ok</name>
<fsummary>Set time interval, in minutes, for the periodic memory check</fsummary>
<type>
<v>Minutes = int()>0</v>
@@ -252,7 +252,7 @@
</desc>
</func>
<func>
- <name>get_procmem_high_watermark() -> int()</name>
+ <name since="">get_procmem_high_watermark() -> int()</name>
<fsummary>Get threshold, in percent, for process memory allocation</fsummary>
<desc>
<p>Returns the threshold, in percent, for process memory
@@ -260,7 +260,7 @@
</desc>
</func>
<func>
- <name>set_procmem_high_watermark(Float) -> ok</name>
+ <name since="">set_procmem_high_watermark(Float) -> ok</name>
<fsummary>Set threshold, as percentage represented by a float, for process memory allocation</fsummary>
<desc>
<p>Changes the threshold, given as a float, for process memory
@@ -273,7 +273,7 @@
</desc>
</func>
<func>
- <name>get_sysmem_high_watermark() -> int()</name>
+ <name since="">get_sysmem_high_watermark() -> int()</name>
<fsummary>Get threshold, in percent, for system memory allocation</fsummary>
<desc>
<p>Returns the threshold, in percent, for system memory
@@ -281,7 +281,7 @@
</desc>
</func>
<func>
- <name>set_sysmem_high_watermark(Float) -> ok</name>
+ <name since="">set_sysmem_high_watermark(Float) -> ok</name>
<fsummary>Set threshold, given as a float, for system memory allocation</fsummary>
<desc>
<p>Changes the threshold, given as a float, for system memory
@@ -294,7 +294,7 @@
</desc>
</func>
<func>
- <name>get_helper_timeout() -> Seconds</name>
+ <name since="">get_helper_timeout() -> Seconds</name>
<fsummary>Get the timeout value, in seconds, for memory checks</fsummary>
<type>
<v>Seconds = int()</v>
@@ -304,7 +304,7 @@
</desc>
</func>
<func>
- <name>set_helper_timeout(Seconds) -> ok</name>
+ <name since="">set_helper_timeout(Seconds) -> ok</name>
<fsummary>Set the timeout value, in seconds, for memory checks</fsummary>
<type>
<v>Seconds = int() (>= 1)</v>
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index 4a878dd704..64e9f281e3 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -31,6 +31,39 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.4.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Due to <c>/proc</c> restrictions in newer Android
+ releases enforced by SELinux, cpu_sup is fixed so that it
+ gets some basic CPU stats using the <c>sysinfo</c>
+ syscall rather than reading <c>/proc/loadavg</c>.</p>
+ <p>
+ Own Id: OTP-15387 Aux Id: PR-1966 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Os_Mon 2.4.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.4.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/os_mon/doc/src/nteventlog.xml b/lib/os_mon/doc/src/nteventlog.xml
index d32427227c..08cf165a24 100644
--- a/lib/os_mon/doc/src/nteventlog.xml
+++ b/lib/os_mon/doc/src/nteventlog.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>nteventlog</module>
+ <module since="">nteventlog</module>
<modulesummary>Interface to Windows Event Log</modulesummary>
<description>
<p><c>nteventlog</c> provides a generic interface to the Windows
@@ -61,8 +61,8 @@
</description>
<funcs>
<func>
- <name>start(Identifier, MFA) -> Result</name>
- <name>start_link(Identifier, MFA) -> Result</name>
+ <name since="">start(Identifier, MFA) -> Result</name>
+ <name since="">start_link(Identifier, MFA) -> Result</name>
<fsummary>Start the NT eventlog server</fsummary>
<type>
<v>Identifier = string() | atom()</v>
@@ -82,7 +82,7 @@
</desc>
</func>
<func>
- <name>stop() -> stopped</name>
+ <name since="">stop() -> stopped</name>
<fsummary>Stop the NT eventlog server</fsummary>
<type>
<v>Result = stopped</v>
diff --git a/lib/os_mon/doc/src/os_mon_mib.xml b/lib/os_mon/doc/src/os_mon_mib.xml
index e995bf3de1..f6d0b20094 100644
--- a/lib/os_mon/doc/src/os_mon_mib.xml
+++ b/lib/os_mon/doc/src/os_mon_mib.xml
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>os_mon_mib</module>
+ <module since="">os_mon_mib</module>
<modulesummary>Loading and Unloading of OTP-OS-MON-MIB</modulesummary>
<description>
<p>Functions for loading and unloading the OTP-OS-MON-MIB into/from
@@ -42,7 +42,7 @@
</description>
<funcs>
<func>
- <name>load(Agent) -> ok | {error, Reason}</name>
+ <name since="">load(Agent) -> ok | {error, Reason}</name>
<fsummary>Load the OTP-OS-MON-MIB</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -53,7 +53,7 @@
</desc>
</func>
<func>
- <name>unload(Agent) -> ok | {error, Reason}</name>
+ <name since="">unload(Agent) -> ok | {error, Reason}</name>
<fsummary>Unload the OTP-OS-MON-MIB</fsummary>
<type>
<v>Agent = pid() | atom() </v>
diff --git a/lib/os_mon/doc/src/os_sup.xml b/lib/os_mon/doc/src/os_sup.xml
index d517f387b4..4a84165a6c 100644
--- a/lib/os_mon/doc/src/os_sup.xml
+++ b/lib/os_mon/doc/src/os_sup.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>os_sup</module>
+ <module since="">os_sup</module>
<modulesummary>Interface to OS System Messages</modulesummary>
<description>
<p><c>os_sup</c> is a process providing a message passing service
@@ -159,8 +159,8 @@
</section>
<funcs>
<func>
- <name>enable() -> ok | {error, Res}</name>
- <name>enable(Dir, Conf) -> ok | {error, Error}</name>
+ <name since="">enable() -> ok | {error, Res}</name>
+ <name since="">enable(Dir, Conf) -> ok | {error, Error}</name>
<fsummary>Enable the service (Solaris only)</fsummary>
<type>
<v>Dir = Conf = Res = string()</v>
@@ -194,8 +194,8 @@
</desc>
</func>
<func>
- <name>disable() -> ok | {error, Res}</name>
- <name>disable(Dir, Conf) -> ok | {error, Error}</name>
+ <name since="">disable() -> ok | {error, Res}</name>
+ <name since="">disable(Dir, Conf) -> ok | {error, Error}</name>
<fsummary>Disable the service (Solaris only)</fsummary>
<type>
<v>Dir = Conf = Res = string()</v>
diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl
index 81e049ef22..ba2d89313e 100644
--- a/lib/os_mon/src/cpu_sup.erl
+++ b/lib/os_mon/src/cpu_sup.erl
@@ -220,17 +220,21 @@ code_change(_OldVsn, State, _Extra) ->
%% internal functions
%%----------------------------------------------------------------------
-get_uint32_measurement(Request, #internal{os_type = {unix, linux}}) ->
- {ok,F} = file:open("/proc/loadavg",[read,raw]),
- {ok,D} = file:read_line(F),
- ok = file:close(F),
- {ok,[Load1,Load5,Load15,_PRun,PTotal],_} = io_lib:fread("~f ~f ~f ~d/~d", D),
- case Request of
- ?avg1 -> sunify(Load1);
- ?avg5 -> sunify(Load5);
- ?avg15 -> sunify(Load15);
- ?ping -> 4711;
- ?nprocs -> PTotal
+get_uint32_measurement(Request, #internal{port = P, os_type = {unix, linux}}) ->
+ case file:open("/proc/loadavg",[read,raw]) of
+ {ok,F} ->
+ {ok,D} = file:read_line(F),
+ ok = file:close(F),
+ {ok,[Load1,Load5,Load15,_PRun,PTotal],_} = io_lib:fread("~f ~f ~f ~d/~d", D),
+ case Request of
+ ?avg1 -> sunify(Load1);
+ ?avg5 -> sunify(Load5);
+ ?avg15 -> sunify(Load15);
+ ?ping -> 4711;
+ ?nprocs -> PTotal
+ end;
+ {error,_} ->
+ port_server_call(P, Request)
end;
get_uint32_measurement(Request, #internal{port = P, os_type = {unix, Sys}}) when
Sys == sunos;
diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl
index 7122d23503..ba28f31f26 100644
--- a/lib/os_mon/test/cpu_sup_SUITE.erl
+++ b/lib/os_mon/test/cpu_sup_SUITE.erl
@@ -122,19 +122,19 @@ util_api(Config) when is_list(Config) ->
%% util([])
{all, Busy1, NonBusy1, []} = cpu_sup:util([]),
- 100.00 = Busy1 + NonBusy1,
+ true = tiny_diff(100.00, Busy1 + NonBusy1),
%% util([detailed])
{Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]),
true = lists:all(fun(X) -> is_integer(X) end, Cpus2),
true = lists:all(BusyP, Busy2),
true = lists:all(NonBusyP, NonBusy2),
- 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2),
+ true = tiny_diff(100.00, lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2)),
%% util([per_cpu])
[{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]),
true = is_integer(Cpu3),
- 100.00 = Busy3 + NonBusy3,
+ true = tiny_diff(100.00, Busy3 + NonBusy3),
%% util([detailed, per_cpu])
[{Cpu4, Busy4, NonBusy4, []}|_] =
@@ -142,7 +142,7 @@ util_api(Config) when is_list(Config) ->
true = is_integer(Cpu4),
true = lists:all(BusyP, Busy2),
true = lists:all(NonBusyP, NonBusy2),
- 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4),
+ true = tiny_diff(100.00, lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4)),
%% bad util/1 calls
{'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)),
@@ -150,6 +150,9 @@ util_api(Config) when is_list(Config) ->
ok.
+tiny_diff(A, B) ->
+ (abs(A - B) < 1.0e-11).
+
-define(SPIN_TIME, 1000).
%% Test utilization values
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index 4a327e5506..9713f6bc6b 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.4.5
+OS_MON_VSN = 2.4.7
diff --git a/lib/otp_mibs/doc/src/Makefile b/lib/otp_mibs/doc/src/Makefile
index c65e2a8e3c..22c3c127ac 100644
--- a/lib/otp_mibs/doc/src/Makefile
+++ b/lib/otp_mibs/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2017. All Rights Reserved.
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -93,6 +93,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/otp_mibs/doc/src/notes.xml b/lib/otp_mibs/doc/src/notes.xml
index ac0777d225..443f08f1e1 100644
--- a/lib/otp_mibs/doc/src/notes.xml
+++ b/lib/otp_mibs/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the OTP_Mibs
application.</p>
+<section><title>Otp_Mibs 1.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Otp_Mibs 1.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/otp_mibs/doc/src/otp_mib.xml b/lib/otp_mibs/doc/src/otp_mib.xml
index 530c529c69..e7d338c165 100644
--- a/lib/otp_mibs/doc/src/otp_mib.xml
+++ b/lib/otp_mibs/doc/src/otp_mib.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>otp_mib</module>
+ <module since="">otp_mib</module>
<modulesummary>Handles the OTP-MIB</modulesummary>
<description>
<p>The SNMP application should be used to start an SNMP agent. Then
@@ -41,7 +41,7 @@
</description>
<funcs>
<func>
- <name>load(Agent) -> ok | {error, Reason}</name>
+ <name since="">load(Agent) -> ok | {error, Reason}</name>
<fsummary>Load the OTP-MIB</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -52,7 +52,7 @@
</desc>
</func>
<func>
- <name>unload(Agent) -> ok | {error, Reason}</name>
+ <name since="">unload(Agent) -> ok | {error, Reason}</name>
<fsummary>Unload the OTP-MIB</fsummary>
<type>
<v>Agent = pid() | atom()</v>
diff --git a/lib/otp_mibs/vsn.mk b/lib/otp_mibs/vsn.mk
index 2e9e367d98..1b0444afcd 100644
--- a/lib/otp_mibs/vsn.mk
+++ b/lib/otp_mibs/vsn.mk
@@ -1,4 +1,4 @@
-OTP_MIBS_VSN = 1.2
+OTP_MIBS_VSN = 1.2.1
# Note: The branch 'otp_mibs' is defunct as of otp_mibs-1.0.4 and
# should NOT be used again.
diff --git a/lib/parsetools/doc/src/Makefile b/lib/parsetools/doc/src/Makefile
index e4cd2c0a76..2e8b232902 100644
--- a/lib/parsetools/doc/src/Makefile
+++ b/lib/parsetools/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -89,6 +89,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/parsetools/doc/src/leex.xml b/lib/parsetools/doc/src/leex.xml
index 1227625287..3b82f60201 100644
--- a/lib/parsetools/doc/src/leex.xml
+++ b/lib/parsetools/doc/src/leex.xml
@@ -21,7 +21,7 @@
<rev>A</rev>
<file>leex.xml</file>
</header>
- <module>leex</module>
+ <module since="">leex</module>
<modulesummary>Lexical analyzer generator for Erlang</modulesummary>
<description>
<p>A regular expression based lexical analyzer generator for
@@ -38,7 +38,8 @@ Token = tuple()</code>
</section>
<funcs>
<func>
- <name>file(FileName, [, Options]) -> LeexRet</name>
+ <name since="">file(FileName) -> LeexRet</name>
+ <name since="OTP R16B02">file(FileName, Options) -> LeexRet</name>
<fsummary>Generate a lexical analyzer</fsummary>
<type>
<v>FileName = filename()</v>
@@ -124,7 +125,7 @@ Token = tuple()</code>
</desc>
</func>
<func>
- <name>format_error(ErrorInfo) -> Chars</name>
+ <name since="">format_error(ErrorInfo) -> Chars</name>
<fsummary>Return an English description of a an error tuple.</fsummary>
<type>
<v>Chars = [char() | Chars]</v>
@@ -145,8 +146,8 @@ Token = tuple()</code>
<funcs>
<func>
- <name>string(String) -> StringRet</name>
- <name>string(String, StartLine) -> StringRet</name>
+ <name since="">string(String) -> StringRet</name>
+ <name since="">string(String, StartLine) -> StringRet</name>
<fsummary>Generated by Leex</fsummary>
<type>
<v>String = string()</v>
@@ -163,9 +164,9 @@ Token = tuple()</code>
</func>
<func>
- <name>token(Cont, Chars) -> {more,Cont1} | {done,TokenRet,RestChars}
+ <name since="">token(Cont, Chars) -> {more,Cont1} | {done,TokenRet,RestChars}
</name>
- <name>token(Cont, Chars, StartLine) -> {more,Cont1}
+ <name since="">token(Cont, Chars, StartLine) -> {more,Cont1}
| {done,TokenRet,RestChars}
</name>
<fsummary>Generated by Leex</fsummary>
@@ -198,9 +199,9 @@ io:request(InFile, {get_until,Prompt,Module,token,[Line]})
</func>
<func>
- <name>tokens(Cont, Chars) -> {more,Cont1} | {done,TokensRet,RestChars}
+ <name since="">tokens(Cont, Chars) -> {more,Cont1} | {done,TokensRet,RestChars}
</name>
- <name>tokens(Cont, Chars, StartLine) ->
+ <name since="">tokens(Cont, Chars, StartLine) ->
{more,Cont1} | {done,TokensRet,RestChars}
</name>
<fsummary>Generated by Leex</fsummary>
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 3e999c8cd0..f8cd9b972d 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.1.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.1.7</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml
index 5f95b5c150..67a2c95c25 100644
--- a/lib/parsetools/doc/src/yecc.xml
+++ b/lib/parsetools/doc/src/yecc.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>yecc.sgml</file>
</header>
- <module>yecc</module>
+ <module since="">yecc</module>
<modulesummary>LALR-1 Parser Generator</modulesummary>
<description>
<p>An LALR-1 parser generator for Erlang, similar to <c>yacc</c>.
@@ -46,7 +46,7 @@
</description>
<funcs>
<func>
- <name>file(Grammarfile [, Options]) -> YeccRet</name>
+ <name since="">file(Grammarfile [, Options]) -> YeccRet</name>
<fsummary>Give information about resolved and unresolved parse action conflicts.</fsummary>
<type>
<v>Grammarfile = filename()</v>
@@ -137,7 +137,7 @@
</desc>
</func>
<func>
- <name>format_error(Reason) -> Chars</name>
+ <name since="">format_error(Reason) -> Chars</name>
<fsummary>Return an English description of a an error tuple.</fsummary>
<type>
<v>Reason =&nbsp;-&nbsp;as returned by yecc:file/1,2&nbsp;-</v>
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index 210723e449..1a5201ce5d 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.1.7
+PARSETOOLS_VSN = 2.1.8
diff --git a/lib/public_key/asn1/OTP-PKIX.asn1 b/lib/public_key/asn1/OTP-PKIX.asn1
index 37196bb9bf..9bcd99fba3 100644
--- a/lib/public_key/asn1/OTP-PKIX.asn1
+++ b/lib/public_key/asn1/OTP-PKIX.asn1
@@ -326,8 +326,13 @@ PublicKeyAlgorithm ::= SEQUENCE {
OPTIONAL }
SupportedSignatureAlgorithms SIGNATURE-ALGORITHM-CLASS ::= {
- dsa-with-sha1 | dsaWithSHA1 | md2-with-rsa-encryption |
- md5-with-rsa-encryption | sha1-with-rsa-encryption | sha-1with-rsa-encryption |
+ dsa-with-sha1 | dsaWithSHA1 |
+ dsa-with-sha224 |
+ dsa-with-sha256 |
+ md2-with-rsa-encryption |
+ md5-with-rsa-encryption |
+ sha1-with-rsa-encryption |
+ sha-1with-rsa-encryption |
sha224-with-rsa-encryption |
sha256-with-rsa-encryption |
sha384-with-rsa-encryption |
@@ -368,6 +373,21 @@ SupportedPublicKeyAlgorithms PUBLIC-KEY-ALGORITHM-CLASS ::= {
ID id-dsaWithSHA1
TYPE DSAParams }
+ dsa-with-sha224 SIGNATURE-ALGORITHM-CLASS ::= {
+ ID id-dsa-with-sha224
+ TYPE DSAParams }
+
+ dsa-with-sha256 SIGNATURE-ALGORITHM-CLASS ::= {
+ ID id-dsa-with-sha256
+ TYPE DSAParams }
+
+ id-dsa-with-sha224 OBJECT IDENTIFIER ::= {
+ joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
+ csor(3) algorithms(4) id-dsa-with-sha2(3) 1 }
+
+ id-dsa-with-sha256 OBJECT IDENTIFIER ::= {
+ joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
+ csor(3) algorithms(4) id-dsa-with-sha2(3) 2 }
--
-- RSA Keys and Signatures
--
diff --git a/lib/public_key/doc/specs/.gitignore b/lib/public_key/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/public_key/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index f5157fe87a..c8647750af 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2017. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -77,12 +77,18 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
DVIPS_FLAGS +=
+SPECS_FLAGS = -I../../include -I../../src -I../../..
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -99,9 +105,11 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
man: $(MAN3_FILES) $(MAN6_FILES)
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index 29e281922c..d83dd24f41 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -35,6 +35,130 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 1.6.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Back port of bug fix ERL-893 from OTP-22 and document
+ enhancements that will solve dialyzer warnings for users
+ of the ssl application.</p>
+ <p>
+ This change also affects public_key, eldap (and inet
+ doc).</p>
+ <p>
+ Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.6.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add export of dialyzer type</p>
+ <p>
+ Own Id: OTP-15624</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.6.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added ed25519 and ed448 sign/verify.</p>
+ <p>
+ Requires OpenSSL 1.1.1 or higher as cryptolib under the
+ OTP application <c>crypto</c>.</p>
+ <p>
+ Own Id: OTP-15419 Aux Id: OTP-15094 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Add DSA SHA2 oids in public_keys ASN1-spec and
+ public_key:pkix_sign_types/1</p>
+ <p>
+ Own Id: OTP-15367</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed <c>#DSAPrivateKey{}</c> as acceptable input to
+ <c>public_key:verify/5</c>.</p>
+ <p>
+ Own Id: OTP-15284</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The typing in the CRYPTO and PUBLIC_KEY applications are
+ reworked and a few mistakes are corrected.</p>
+ <p>
+ The documentation is now generated from the typing and
+ some clarifications are made.</p>
+ <p>
+ A new chapter on Algorithm Details such as key sizes and
+ availability is added to the CRYPTO User's Guide.</p>
+ <p>
+ Own Id: OTP-15134</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Some of the keylengths in the newly generated moduli file
+ in public_key are not universally supported. This could
+ cause the SSH key exchange
+ diffie-hellman-group-exchange-sha* to fail.</p>
+ <p>
+ Those keylengths are now removed.</p>
+ <p>
+ Own Id: OTP-15151 Aux Id: OTP-15113 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index c0a67c25b8..b7589f6653 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -31,7 +31,7 @@
<date></date>
<rev></rev>
</header>
- <module>public_key</module>
+ <module since="">public_key</module>
<modulesummary>API module for public-key infrastructure.</modulesummary>
<description>
<p>Provides functions to handle public-key infrastructure,
@@ -41,7 +41,7 @@
</description>
<section>
- <title>DATA TYPES</title>
+ <title>Common Records and ASN.1 Types</title>
<note><p>All records used in this Reference Manual
<!-- except #policy_tree_node{} -->
@@ -54,193 +54,147 @@
records and constant macros described here and in the User's Guide:</p>
<code> -include_lib("public_key/include/public_key.hrl").</code>
+ </section>
+
+ <datatypes>
+ <datatype>
+ <name name="oid"/>
+ <desc>
+ <p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="der_encoded"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pki_asn1_type"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="asn1_type"/>
+ <desc>
+ <p>ASN.1 type present in the Public Key applications ASN.1 specifications.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pem_entry"/>
+ <name name="der_or_encrypted_der"/>
+ <name name="cipher_info"/>
+ <name name="cipher"/>
+ <name name="salt"/>
+ <name name="cipher_info_params"/>
+ <desc>
+ <code>Cipher = "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC"</code>
+ <p><c>Salt</c> could be generated with
+ <seealso marker="crypto:crypto#strong_rand_bytes-1"><c>crypto:strong_rand_bytes(8)</c></seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="public_key"/>
+ <name name="rsa_public_key"/>
+ <name name="dsa_public_key"/>
+ <name name="ec_public_key"/>
+ <name name="ecpk_parameters"/>
+ <name name="ecpk_parameters_api"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ed_public_key"/>
+ <desc>
+ <warning><p>This format of the EdDSA curves is temporary and may change without prior notice!</p></warning>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="private_key"/>
+ <name name="rsa_private_key"/>
+ <name name="dsa_private_key"/>
+ <name name="ec_private_key"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ed_private_key"/>
+ <desc>
+ <warning><p>This format of the EdDSA curves is temporary and may change without prior notice!</p></warning>
+ </desc>
+ </datatype>
+
+
+ <datatype>
+ <name name="key_params"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="crl_reason"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="issuer_id"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="issuer_name"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ssh_file"/>
+ <desc>
+ </desc>
+ </datatype>
+
+
+
+ </datatypes>
- <p>The following data types are used in the functions for <c>public_key</c>:</p>
-
- <taglist>
- <tag><c>oid()</c></tag>
- <item><p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p></item>
-
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false</c></p></item>
-
- <tag><c>string() =</c></tag>
- <item><p><c>[bytes()]</c></p></item>
-
- <tag><c>der_encoded() =</c></tag>
- <item><p><c>binary()</c></p></item>
-
- <tag><c>pki_asn1_type() =</c></tag>
- <item>
- <p><c>'Certificate'</c></p>
- <p><c>| 'RSAPrivateKey'</c></p>
- <p><c>| 'RSAPublicKey'</c></p>
- <p><c>| 'DSAPrivateKey'</c></p>
- <p><c>| 'DSAPublicKey'</c></p>
- <p><c>| 'DHParameter'</c></p>
- <p><c>| 'SubjectPublicKeyInfo'</c></p>
- <p><c>| 'PrivateKeyInfo'</c></p>
- <p><c>| 'CertificationRequest'</c></p>
- <p><c>| 'CertificateList'</c></p>
- <p><c>| 'ECPrivateKey'</c></p>
- <p><c>| 'EcpkParameters'</c></p>
- </item>
-
- <tag><c>pem_entry () =</c></tag>
- <item><p><c>{pki_asn1_type(), binary(), %% DER or encrypted DER</c></p>
- <p><c> not_encrypted | cipher_info()}</c></p></item>
-
- <tag><c>cipher_info() = </c></tag>
- <item><p><c>{"RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", crypto:strong_rand_bytes(8)</c></p>
- <p><c>| {#'PBEParameter{}, digest_type()} | #'PBES2-params'{}}</c></p>
- </item>
-
- <tag><marker id="type-public_key"/>
- <c>public_key() =</c></tag>
- <item><p><c>rsa_public_key() | dsa_public_key() | ec_public_key()</c></p></item>
-
- <tag><marker id="type-private_key"/>
- <c>private_key() =</c></tag>
- <item><p><c>rsa_private_key() | dsa_private_key() | ec_private_key()</c></p></item>
-
- <tag><c>rsa_public_key() =</c></tag>
- <item><p><c>#'RSAPublicKey'{}</c></p></item>
-
- <tag><c>rsa_private_key() =</c></tag>
- <item><p><c>#'RSAPrivateKey'{}</c></p></item>
-
- <tag><c>dsa_public_key() =</c></tag>
- <item><p><c>{integer(), #'Dss-Parms'{}}</c></p></item>
-
- <tag><c>dsa_private_key() =</c></tag>
- <item><p><c>#'DSAPrivateKey'{}</c></p></item>
-
- <tag><c>ec_public_key()</c></tag>
- <item><p>= <c>{#'ECPoint'{}, #'ECParameters'{} | {namedCurve, oid()}}</c></p></item>
-
- <tag><c>ec_private_key() =</c></tag>
- <item><p><c>#'ECPrivateKey'{}</c></p></item>
-
- <tag><c>key_params() =</c></tag>
- <item><p> #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{}
- | {rsa, Size::integer(), PubExp::integer()} </p></item>
-
- <tag><c>public_crypt_options() =</c></tag>
- <item><p><c>[{rsa_pad, rsa_padding()}]</c></p></item>
-
- <tag><c>rsa_padding() =</c></tag>
- <item>
- <p><c>'rsa_pkcs1_padding'</c></p>
- <p><c>| 'rsa_pkcs1_oaep_padding'</c></p>
- <p><c>| 'rsa_no_padding'</c></p>
- </item>
-
- <tag><c>public_sign_options() =</c></tag>
- <item><p><c>[{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}]</c></p></item>
-
- <tag><c>rsa_sign_padding() =</c></tag>
- <item>
- <p><c>'rsa_pkcs1_padding'</c></p>
- <p><c>| 'rsa_pkcs1_pss_padding'</c></p>
- </item>
-
- <tag><c>digest_type() = </c></tag>
- <item><p>Union of <c>rsa_digest_type()</c>, <c>dss_digest_type()</c>,
- and <c>ecdsa_digest_type()</c>.</p></item>
-
- <tag><c>rsa_digest_type() = </c></tag>
- <item><p><c>'md5' | 'ripemd160' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-
- <tag><c>dss_digest_type() = </c></tag>
- <item><p><c>'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p>
- <p>Note that the actual supported dss_digest_type depends on the underlying crypto library.
- In OpenSSL version >= 1.0.1 the listed digest are supported, while in 1.0.0 only
- sha, sha224 and sha256 are supported. In version 0.9.8 only sha is supported.</p>
- </item>
-
- <tag><c>ecdsa_digest_type() = </c></tag>
- <item><p><c>'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-
- <tag><c>crl_reason() = </c></tag>
- <item>
- <p><c>unspecified</c></p>
- <p><c>| keyCompromise</c></p>
- <p><c>| cACompromise</c></p>
- <p><c>| affiliationChanged</c></p>
- <p><c>| superseded</c></p>
- <p><c>| cessationOfOperation</c></p>
- <p><c>| certificateHold</c></p>
- <p><c>| privilegeWithdrawn</c></p>
- <p><c>| aACompromise</c></p>
- </item>
-
- <tag><c>issuer_name() =</c></tag>
- <item><p><c>{rdnSequence,[#'AttributeTypeAndValue'{}]}</c></p>
- </item>
-
- <tag><c>ssh_file() =</c></tag>
- <item>
- <p><c>openssh_public_key</c></p>
- <p><c>| rfc4716_public_key</c></p>
- <p><c>| known_hosts</c></p>
- <p><c>| auth_keys</c></p>
- </item>
- </taglist>
-
-
-<!-- <p><code>policy_tree() = [Root, Children]</code></p> -->
-
-<!-- <p><code>Root = #policy_tree_node{}</code></p> -->
-
-<!-- <p><code>Children = [] | policy_tree()</code></p> -->
-
-<!-- <p>The <c>policy_tree_node</c> record has the following fields:</p> -->
-
-<!-- <taglist> -->
-
-<!-- <tag>valid_policy</tag> -->
-<!-- <item>A single policy OID representing a -->
-<!-- valid policy for the path of length x.</item> -->
-
-<!-- <tag>qualifier_set</tag> -->
-<!-- <item>A set of policy qualifiers associated -->
-<!-- with the valid policy in certificate x.</item> -->
-
-<!-- <tag>critically_indicator</tag> -->
-<!-- <item>Indicates whether the -->
-<!-- certificate policy extension in certificate x was marked as -->
-<!-- critical.</item> -->
-
-<!-- <tag>expected_policy_set</tag> -->
-<!-- <item>Contains one or more policy OIDs -->
-<!-- that would satisfy this policy in the certificate x+1.</item> -->
-<!-- </taglist> -->
- </section>
<funcs>
<func>
- <name>compute_key(OthersKey, MyKey)-></name>
- <name>compute_key(OthersKey, MyKey, Params)-></name>
+ <name name="compute_key" arity="2" since="OTP R16B01"/>
+ <fsummary>Computes shared secret.</fsummary>
+ <desc>
+ <p>Computes shared secret.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="compute_key" arity="3" since="OTP R16B01"/>
<fsummary>Computes shared secret.</fsummary>
- <type>
- <v>OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()</v>
- <v>Params = #'DHParameter'{}</v>
- </type>
<desc>
<p>Computes shared secret.</p>
</desc>
</func>
<func>
- <name>decrypt_private(CipherText, Key) -> binary()</name>
- <name>decrypt_private(CipherText, Key, Options) -> binary()</name>
+ <name name="decrypt_private" arity="2" since="OTP R14B"/>
+ <name name="decrypt_private" arity="3" since="OTP R14B"/>
<fsummary>Public-key decryption.</fsummary>
- <type>
- <v>CipherText = binary()</v>
- <v>Key = rsa_private_key()</v>
- <v>Options = public_crypt_options()</v>
- </type>
<desc>
<p>Public-key decryption using the private key. See also <seealso
marker="crypto:crypto#private_decrypt/4">crypto:private_decrypt/4</seealso></p>
@@ -248,14 +202,9 @@
</func>
<func>
- <name>decrypt_public(CipherText, Key) - > binary()</name>
- <name>decrypt_public(CipherText, Key, Options) - > binary()</name>
+ <name name="decrypt_public" arity="2" since="OTP R14B"/>
+ <name name="decrypt_public" arity="3" since="OTP R14B"/>
<fsummary>Public-key decryption.</fsummary>
- <type>
- <v>CipherText = binary()</v>
- <v>Key = rsa_public_key()</v>
- <v>Options = public_crypt_options()</v>
- </type>
<desc>
<p>Public-key decryption using the public key. See also <seealso
marker="crypto:crypto#public_decrypt/4">crypto:public_decrypt/4</seealso></p>
@@ -263,47 +212,24 @@
</func>
<func>
- <name>der_decode(Asn1type, Der) -> term()</name>
+ <name name="der_decode" arity="2" since="OTP R14B"/>
<fsummary>Decodes a public-key ASN.1 DER encoded entity.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>ASN.1 type present in the Public Key applications
- ASN.1 specifications.</d>
- <v>Der = der_encoded()</v>
- </type>
- <desc>
+ <desc>
<p>Decodes a public-key ASN.1 DER encoded entity.</p>
</desc>
</func>
-
+
<func>
- <name>der_encode(Asn1Type, Entity) -> der_encoded()</name>
+ <name name="der_encode" arity="2" since="OTP R14B"/>
<fsummary>Encodes a public-key entity with ASN.1 DER encoding.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>ASN.1 type present in the Public Key applications
- ASN.1 specifications.</d>
- <v>Entity = term()</v>
- <d>Erlang representation of <c>Asn1Type</c></d>
- </type>
<desc>
<p>Encodes a public-key entity with ASN.1 DER encoding.</p>
</desc>
</func>
<func>
- <name>dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> {ok, {Size,Group}} | {error,Error}</name>
+ <name name="dh_gex_group" arity="4" since="OTP 18.2"/>
<fsummary>Selects a group for Diffie-Hellman key exchange</fsummary>
- <type>
- <v>MinSize = positive_integer()</v>
- <v>SuggestedSize = positive_integer()</v>
- <v>MaxSize = positive_integer()</v>
- <v>Groups = undefined | [{Size,[{G,P}]}]</v>
- <v>Size = positive_integer()</v>
- <v>Group = {G,P}</v>
- <v>G = positive_integer()</v>
- <v>P = positive_integer()</v>
- </type>
<desc>
<p>Selects a group for Diffie-Hellman key exchange with the key size in the range <c>MinSize...MaxSize</c>
and as close to <c>SuggestedSize</c> as possible. If <c>Groups == undefined</c> a default set will be
@@ -322,13 +248,10 @@
</desc>
</func>
- <func>
- <name>encrypt_private(PlainText, Key) -> binary()</name>
+ <func>
+ <name name="encrypt_private" arity="2" since="OTP R14B"/>
+ <name name="encrypt_private" arity="3" since="OTP 21.1"/>
<fsummary>Public-key encryption using the private key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_private_key()</v>
- </type>
<desc>
<p>Public-key encryption using the private key.
See also <seealso
@@ -337,12 +260,9 @@
</func>
<func>
- <name>encrypt_public(PlainText, Key) -> binary()</name>
+ <name name="encrypt_public" arity="2" since="OTP R14B"/>
+ <name name="encrypt_public" arity="3" since="OTP 21.1"/>
<fsummary>Public-key encryption using the public key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_public_key()</v>
- </type>
<desc>
<p>Public-key encryption using the public key. See also <seealso
marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso>.</p>
@@ -350,11 +270,8 @@
</func>
<func>
- <name>generate_key(Params) -> {Public::binary(), Private::binary()} | #'ECPrivateKey'{} | #'RSAPrivateKey'{}</name>
+ <name name="generate_key" arity="1" since="OTP R16B01"/>
<fsummary>Generates a new keypair.</fsummary>
- <type>
- <v>Params = key_params()</v>
- </type>
<desc>
<p>Generates a new keypair. Note that except for Diffie-Hellman
the public key is included in the private key structure. See also
@@ -364,38 +281,27 @@
</func>
<func>
- <name>pem_decode(PemBin) -> [pem_entry()]</name>
+ <name name="pem_decode" arity="1" since="OTP R14B"/>
<fsummary>Decodes PEM binary data and returns
entries as ASN.1 DER encoded entities.</fsummary>
- <type>
- <v>PemBin = binary()</v>
- <d>Example {ok, PemBin} = file:read_file("cert.pem").</d>
- </type>
<desc>
- <p>Decodes PEM binary data and returns
- entries as ASN.1 DER encoded entities.</p>
+ <p>Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.</p>
+ <p>Example <c>{ok, PemBin} = file:read_file("cert.pem").</c></p>
</desc>
</func>
- <func>
- <name>pem_encode(PemEntries) -> binary()</name>
+ <func>
+ <name name="pem_encode" arity="1" since="OTP R14B"/>
<fsummary>Creates a PEM binary.</fsummary>
- <type>
- <v> PemEntries = [pem_entry()] </v>
- </type>
- <desc>
- <p>Creates a PEM binary.</p>
- </desc>
+ <desc>
+ <p>Creates a PEM binary.</p>
+ </desc>
</func>
- <func>
- <name>pem_entry_decode(PemEntry) -> term()</name>
- <name>pem_entry_decode(PemEntry, Password) -> term()</name>
+ <func>
+ <name name="pem_entry_decode" arity="1" since="OTP R14B"/>
+ <name name="pem_entry_decode" arity="2" since="OTP R14B"/>
<fsummary>Decodes a PEM entry.</fsummary>
- <type>
- <v>PemEntry = pem_entry()</v>
- <v>Password = string()</v>
- </type>
<desc>
<p>Decodes a PEM entry. <c>pem_decode/1</c> returns a list of PEM
entries. Notice that if the PEM entry is of type
@@ -404,51 +310,36 @@
</desc>
</func>
- <func>
- <name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
- <name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
+ <func>
+ <name name="pem_entry_encode" arity="2" since="OTP R14B"/>
+ <name name="pem_entry_encode" arity="3" since="OTP R14B"/>
<fsummary>Creates a PEM entry that can be fed to <c>pem_encode/1</c>.</fsummary>
- <type>
- <v>Asn1Type = pki_asn1_type()</v>
- <v>Entity = term()</v>
- <d>Erlang representation of
- <c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo',
+ <desc>
+ <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
+ <p>If <c>Asn1Type</c> is <c>'SubjectPublicKeyInfo'</c>,
<c>Entity</c> must be either an <c>rsa_public_key()</c>,
<c>dsa_public_key()</c> or an <c>ec_public_key()</c>
and this function creates the appropriate
- 'SubjectPublicKeyInfo' entry.
- </d>
- <v>CipherInfo = cipher_info()</v>
- <v>Password = string()</v>
- </type>
- <desc>
- <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
- </desc>
+ <c>'SubjectPublicKeyInfo'</c> entry.
+ </p>
+ </desc>
</func>
-
+
<func>
- <name>pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name>
+ <name name="pkix_decode_cert" arity="2" since=""/>
<fsummary>Decodes an ASN.1 DER-encoded PKIX x509 certificate.</fsummary>
- <type>
- <v>Cert = der_encoded()</v>
- </type>
- <desc>
- <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
- uses the customized ASN.1 specification OTP-PKIX.asn1 for
- decoding and also recursively decode most of the standard
- parts.</p>
- </desc>
+ <desc>
+ <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
+ uses the customized ASN.1 specification OTP-PKIX.asn1 for
+ decoding and also recursively decode most of the standard
+ parts.</p>
+ </desc>
</func>
<func>
- <name>pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()</name>
+ <name name="pkix_encode" arity="3" since="OTP R14B"/>
<fsummary>DER encodes a PKIX x509 certificate or part of such a
certificate.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either.</d>
- <v>Entity = #'Certificate'{} | #'OTPCertificate'{} | a valid subtype</v>
- </type>
<desc>
<p>DER encodes a PKIX x509 certificate or part of such a
certificate. This function must be used for encoding certificates or parts of certificates
@@ -458,71 +349,49 @@
</func>
<func>
- <name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name>
- <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{} | #'CertificateList'{}</v>
- <v>IssuerCert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p>
- </desc>
- </func>
+ <name name="pkix_is_issuer" arity="2" since="OTP R14B"/>
+ <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
+ <desc>
+ <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name>
- <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p>
- </desc>
- </func>
+ <func>
+ <name name="pkix_is_fixed_dh_cert" arity="1" since="OTP R14B"/>
+ <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
+ <desc>
+ <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_is_self_signed(Cert) -> boolean()</name>
- <fsummary>Checks if a certificate is self-signed.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if a certificate is self-signed.</p>
- </desc>
- </func>
+ <func>
+ <name name="pkix_is_self_signed" arity="1" since="OTP R14B"/>
+ <fsummary>Checks if a certificate is self-signed.</fsummary>
+ <desc>
+ <p>Checks if a certificate is self-signed.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name>
- <fsummary>Returns the issuer id.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- <v>IssuedBy = self | other</v>
- <v>IssuerID = {integer(), issuer_name()}</v>
- <d>The issuer id consists of the serial number and the issuers name.</d>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Returns the issuer id.</p>
- </desc>
- </func>
-
+ <func>
+ <name name="pkix_issuer_id" arity="2" since="OTP R14B"/>
+ <fsummary>Returns the issuer id.</fsummary>
+ <desc>
+ <p>Returns the issuer id.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="pkix_normalize_name" arity="1" since="OTP R14B"/>
+ <fsummary>Normalizes an issuer name so that it can be easily
+ compared to another issuer name.</fsummary>
+ <desc>
+ <p>Normalizes an issuer name so that it can be easily
+ compared to another issuer name.</p>
+ </desc>
+ </func>
+
<func>
- <name>pkix_normalize_name(Issuer) -> Normalized</name>
- <fsummary>Normalizes an issuer name so that it can be easily
- compared to another issuer name.</fsummary>
- <type>
- <v>Issuer = issuer_name()</v>
- <v>Normalized = issuer_name()</v>
- </type>
- <desc>
- <p>Normalizes an issuer name so that it can be easily
- compared to another issuer name.</p>
- </desc>
- </func>
-
- <func>
- <name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
+ <name since="OTP R16B">pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
<fsummary>Performs a basic path validation according to RFC 5280.</fsummary>
<type>
<v>TrustedCert = #'OTPCertificate'{} | der_encoded() | atom()</v>
@@ -622,26 +491,16 @@ fun(OtpCert :: #'OTPCertificate'{},
</func>
<func>
- <name>pkix_crl_issuer(CRL) -> issuer_name()</name>
+ <name name="pkix_crl_issuer" arity="1" since="OTP 17.5"/>
<fsummary>Returns the issuer of the <c>CRL</c>.</fsummary>
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- </type>
<desc>
<p>Returns the issuer of the <c>CRL</c>.</p>
</desc>
</func>
<func>
- <name>pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()</name>
+ <name name="pkix_crls_validate" arity="3" since="OTP R16B"/>
<fsummary>Performs CRL validation.</fsummary>
- <type>
- <v>OTPCertificate = #'OTPCertificate'{}</v>
- <v>DPAndCRLs = [{DP::#'DistributionPoint'{}, {DerCRL::der_encoded(), CRL::#'CertificateList'{}}}] </v>
- <v>Options = proplists:proplist()</v>
- <v>CRLStatus() = valid | {bad_cert, revocation_status_undetermined} | {bad_cert, {revocation_status_undetermined,
- {bad_crls, Details::term()}}} | {bad_cert, {revoked, crl_reason()}}</v>
- </type>
<desc>
<p>Performs CRL validation. It is intended to be called from
the verify fun of <seealso marker="#pkix_path_validation-3"> pkix_path_validation/3
@@ -692,24 +551,16 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_crl_verify(CRL, Cert) -> boolean()</name>
+ <name name="pkix_crl_verify" arity="2" since="OTP 17.5"/>
<fsummary> Verify that <c>Cert</c> is the <c> CRL</c> signer. </fsummary>
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- <v>Cert = der_encoded() | #'OTPCertificate'{} </v>
- </type>
<desc>
<p>Verify that <c>Cert</c> is the <c>CRL</c> signer.</p>
</desc>
</func>
<func>
- <name>pkix_dist_point(Cert) -> DistPoint</name>
+ <name name="pkix_dist_point" arity="1" since="OTP 17.5"/>
<fsummary>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.</fsummary>
- <type>
- <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
- <v> DistPoint = #'DistributionPoint'{}</v>
- </type>
<desc>
<p>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
Can be used as input to <seealso
@@ -719,26 +570,17 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_dist_points(Cert) -> DistPoints</name>
+ <name name="pkix_dist_points" arity="1" since="OTP 17.5"/>
<fsummary> Extracts distribution points from the certificates extensions.</fsummary>
- <type>
- <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
- <v> DistPoints = [#'DistributionPoint'{}]</v>
- </type>
<desc>
<p> Extracts distribution points from the certificates extensions.</p>
</desc>
</func>
<func>
- <name>pkix_match_dist_point(CRL, DistPoint) -> boolean()</name>
+ <name name="pkix_match_dist_point" arity="2" since="OTP 19.0"/>
<fsummary>Checks whether the given distribution point matches the
Issuing Distribution Point of the CRL.</fsummary>
-
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- <v>DistPoint = #'DistributionPoint'{}</v>
- </type>
<desc>
<p>Checks whether the given distribution point matches the
Issuing Distribution Point of the CRL, as described in RFC 5280.
@@ -748,11 +590,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()</name>
+ <name name="pkix_sign" arity="2" since="OTP R14B"/>
<fsummary>Signs certificate.</fsummary>
- <type>
- <v>Key = rsa_private_key() | dsa_private_key()</v>
- </type>
<desc>
<p>Signs an 'OTPTBSCertificate'. Returns the corresponding
DER-encoded certificate.</p>
@@ -760,23 +599,18 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType}</name>
+ <name name="pkix_sign_types" arity="1" since="OTP R16B01"/>
<fsummary>Translates signature algorithm OID to Erlang digest and signature algorithm types.</fsummary>
- <type>
- <v>AlgorithmId = oid()</v>
- <d>Signature OID from a certificate or a certificate revocation list.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type()</v>
- <v>SignatureType = rsa | dsa | ecdsa</v>
- </type>
<desc>
<p>Translates signature algorithm OID to Erlang digest and signature types.
</p>
+ <p>The <c>AlgorithmId</c> is the signature OID from a certificate or a certificate revocation list.</p>
</desc>
</func>
<func>
- <name>pkix_test_data(Options) -> Config </name>
- <name>pkix_test_data([chain_opts()]) -> [conf_opt()]</name>
+ <name since="OTP 20.1">pkix_test_data(Options) -> Config </name>
+ <name since="OTP 20.1">pkix_test_data([chain_opts()]) -> [conf_opt()]</name>
<fsummary>Creates certificate test data.</fsummary>
<type>
<v>Options = #{chain_type() := chain_opts()} </v>
@@ -810,7 +644,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<v>conf_opt() = {cert, der_encoded()} | {key, PrivateKey} |{cacerts, [der_encoded()]}</v>
<d>
This is a subset of the type
- <seealso marker="ssl:ssl#type-ssloption"> ssl:ssl_option()</seealso>.
+ <seealso marker="ssl:ssl#type-tls_option"> ssl:tls_option()</seealso>.
<c>PrivateKey</c> is what
<seealso marker="#generate_key-1">generate_key/1</seealso>
returns.
@@ -908,7 +742,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_test_root_cert(Name, Options) -> RootCert</name>
+ <name since="OTP 20.2">pkix_test_root_cert(Name, Options) -> RootCert</name>
<fsummary>Generates a test data root cert.</fsummary>
<type>
<v>Name = string()</v>
@@ -938,20 +772,16 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_verify(Cert, Key) -> boolean()</name>
+ <name name="pkix_verify" arity="2" since="OTP R14B"/>
<fsummary>Verifies PKIX x.509 certificate signature.</fsummary>
- <type>
- <v>Cert = der_encoded()</v>
- <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
- </type>
<desc>
<p>Verifies PKIX x.509 certificate signature.</p>
</desc>
</func>
<func>
- <name>pkix_verify_hostname(Cert, ReferenceIDs) -> boolean()</name>
- <name>pkix_verify_hostname(Cert, ReferenceIDs, Opts) -> boolean()</name>
+ <name since="OTP 19.3">pkix_verify_hostname(Cert, ReferenceIDs) -> boolean()</name>
+ <name since="OTP 19.3">pkix_verify_hostname(Cert, ReferenceIDs, Opts) -> boolean()</name>
<fsummary>Verifies that a PKIX x.509 certificate <i>presented identifier</i> (e.g hostname) is
an expected one.</fsummary>
<type>
@@ -1034,7 +864,7 @@ end
</func>
<func>
- <name>pkix_verify_hostname_match_fun(Protcol) -> fun(RefId | FQDN::string(), PresentedID) -> boolean() | default</name>
+ <name since="OTP 21.0">pkix_verify_hostname_match_fun(Protcol) -> fun(RefId | FQDN::string(), PresentedID) -> boolean() | default</name>
<fsummary>Returns a fun that is intendended as argument to the match_fun option in pkix_verify_hostname/3.
</fsummary>
<type>
@@ -1059,41 +889,30 @@ end
<func>
- <name>sign(Msg, DigestType, Key) -> binary()</name>
- <name>sign(Msg, DigestType, Key, Options) -> binary()</name>
+ <name name="sign" arity="3" since=""/>
+ <name name="sign" arity="4" since="OTP 20.1"/>
<fsummary>Creates a digital signature.</fsummary>
- <type>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The <c>Msg</c> is either the binary "plain text" data to be
- signed or it is the hashed value of "plain text", that is, the
- digest.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Key = rsa_private_key() | dsa_private_key() | ec_private_key()</v>
- <v>Options = public_sign_options()</v>
- </type>
<desc>
<p>Creates a digital signature.</p>
+ <p>The <c>Msg</c> is either the binary "plain text" data to be
+ signed or it is the hashed value of "plain text", that is, the
+ digest.</p>
</desc>
</func>
<func>
- <name>ssh_decode(SshBin, Type) -> [{public_key(), Attributes::list()}]</name>
+ <name name="ssh_decode" arity="2" since="OTP R14B03"/>
<fsummary>Decodes an SSH file-binary.</fsummary>
- <type>
- <v>SshBin = binary()</v>
- <d>Example <c>{ok, SshBin} = file:read_file("known_hosts")</c>.</d>
- <v>Type = public_key | ssh_file()</v>
- <d>If <c>Type</c> is <c>public_key</c> the binary can be either
- an RFC4716 public key or an OpenSSH public key.</d>
- </type>
- <desc>
- <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
- <c>auth_keys</c>, the binary can include one or more lines of the
- file. Returns a list of public keys and their attributes, possible
- attribute values depends on the file type represented by the
- binary.
- </p>
-
+ <desc>
+ <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
+ <c>auth_keys</c>, the binary can include one or more lines of the
+ file. Returns a list of public keys and their attributes, possible
+ attribute values depends on the file type represented by the
+ binary.
+ </p>
+ <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the result will be
+ <c>Decoded_ssh2_pubkey</c>. Otherwise it will be <c>Decoded_OtherType</c>.
+ </p>
<taglist>
<tag>RFC4716 attributes - see RFC 4716.</tag>
<item><p>{headers, [{string(), utf8_string()}]}</p></item>
@@ -1106,33 +925,35 @@ end
<item>{comment, string()}</item>
<item><p>{bits, integer()} - In SSH version 1 files.</p></item>
</taglist>
-
+ <p>Example: <c>{ok, SshBin} = file:read_file("known_hosts")</c>.
+ </p>
+ <p>If <c>Type</c> is <c>public_key</c> the binary can be either
+ an RFC4716 public key or an OpenSSH public key.</p>
</desc>
</func>
<func>
- <name>ssh_encode([{Key, Attributes}], Type) -> binary()</name>
+ <name name="ssh_encode" arity="2" since="OTP R14B03"/>
<fsummary>Encodes a list of SSH file entries to a binary.</fsummary>
- <type>
- <v>Key = public_key()</v>
- <v>Attributes = list()</v>
- <v>Type = ssh_file()</v>
- </type>
- <desc>
- <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
- attributes depend on the file type, see <seealso
- marker="#ssh_decode-2"> ssh_decode/2 </seealso>.</p>
- </desc>
+ <desc>
+ <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
+ attributes depend on the file type, see
+ <seealso marker="#ssh_decode-2"> ssh_decode/2 </seealso>.
+ </p>
+ <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the <c>InData</c> shall be
+ <c>InData_ssh2_pubkey</c>. Otherwise it shall be <c>OtherInData</c>.
+ </p>
+ </desc>
</func>
<func>
- <name>ssh_hostkey_fingerprint(HostKey) -> string()</name>
- <name>ssh_hostkey_fingerprint(DigestType, HostKey) -> string()</name>
- <name>ssh_hostkey_fingerprint([DigestType], HostKey) -> [string()]</name>
+ <name since="OTP 19.2">ssh_hostkey_fingerprint(HostKey) -> string()</name>
+ <name since="OTP 19.2">ssh_hostkey_fingerprint(DigestType, HostKey) -> string()</name>
+ <name since="OTP 19.2">ssh_hostkey_fingerprint([DigestType], HostKey) -> [string()]</name>
<fsummary>Calculates a ssh fingerprint for a hostkey.</fsummary>
<type>
- <v>Key = public_key()</v>
- <v>DigestType = digest_type()</v>
+ <v>HostKey = <seealso marker="#type-public_key">public_key()</seealso></v>
+ <v>DigestType = <seealso marker="#type-digest_type">digest_type()</seealso></v>
</type>
<desc>
<p>Calculates a ssh fingerprint from a public host key as openssh does.</p>
@@ -1161,29 +982,19 @@ end
</func>
<func>
- <name>verify(Msg, DigestType, Signature, Key) -> boolean()</name>
- <name>verify(Msg, DigestType, Signature, Key, Options) -> boolean()</name>
+ <name name="verify" arity="4" since="OTP R14B"/>
+ <name name="verify" arity="5" since="OTP 20.1"/>
<fsummary>Verifies a digital signature.</fsummary>
- <type>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The <c>Msg</c> is either the binary "plain text" data
- or it is the hashed value of "plain text", that is, the digest.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Signature = binary()</v>
- <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
- <v>Options = public_sign_options()</v>
- </type>
<desc>
<p>Verifies a digital signature.</p>
+ <p>The <c>Msg</c> is either the binary "plain text" data
+ or it is the hashed value of "plain text", that is, the digest.</p>
</desc>
</func>
<func>
- <name>short_name_hash(Name) -> string()</name>
+ <name name="short_name_hash" arity="1" since="OTP 19.0"/>
<fsummary>Generates a short hash of an issuer name.</fsummary>
- <type>
- <v>Name = issuer_name()</v>
- </type>
<desc>
<p>Generates a short hash of an issuer name. The hash is
returned as a string containing eight hexadecimal digits.</p>
diff --git a/lib/public_key/doc/src/specs.xml b/lib/public_key/doc/src/specs.xml
new file mode 100644
index 0000000000..e358ea1154
--- /dev/null
+++ b/lib/public_key/doc/src/specs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_public_key.xml"/>
+</specs>
diff --git a/lib/public_key/priv/moduli b/lib/public_key/priv/moduli
index 0c44d525ba..83e8767a5e 100644
--- a/lib/public_key/priv/moduli
+++ b/lib/public_key/priv/moduli
@@ -172,40 +172,6 @@
20180605201507 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F737264DFF
20180605201935 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F737F47113
20180605202538 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7390F0743
-20180605210627 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFBDE9C663
-20180605211229 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFBE5D31FF
-20180605212615 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFBF726B37
-20180605213758 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC05E3C97
-20180605214634 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC108344F
-20180605221135 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC2F6C7EF
-20180605221612 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC34A2373
-20180605222719 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC426CF47
-20180605225054 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC5FF2A63
-20180605230438 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC70EA13F
-20180605232516 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC8A507BF
-20180606000440 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCBB897D3
-20180606003911 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCE5E6DDF
-20180606004021 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCE6D003B
-20180606004054 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCE6EF7C3
-20180606011249 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD0E6DF43
-20180606013848 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD2E87873
-20180606020718 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD5166B47
-20180606021121 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD55F3E2B
-20180606030823 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD9C61CC3
-20180606033204 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDB8F4F47
-20180606033802 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDBF98B5B
-20180606035103 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDCF1AF47
-20180606041154 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDE894FEF
-20180606041520 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDEC4EE7B
-20180606043713 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE06AD163
-20180606053417 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE4C5AD13
-20180606060033 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE6C71C97
-20180606061040 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE77EB58B
-20180606062720 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE8BC530F
-20180606065112 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEA7F6853
-20180606065226 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEA8EAA53
-20180606071446 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEC3498CF
-20180606073822 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEDF3BF93
20180606081635 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3819B8FC5F
20180606083850 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381B1D13EB
20180606084353 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381B65B5F7
@@ -235,38 +201,6 @@
20180607010449 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A385542D20F
20180607022006 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3859892A7B
20180607022905 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A385A0321EB
-20180607045001 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EA3B1267B
-20180607051849 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EA4D3FCDB
-20180607052645 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EA51AE857
-20180607074455 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EAABB372F
-20180607085512 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EAD8764F3
-20180607101435 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EB0B93D7F
-20180607122858 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EB613F7A7
-20180607163002 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EBF961A17
-20180607164733 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EC03FE5D7
-20180607170431 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EC0E41B93
-20180607210523 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ECA453803
-20180608000228 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED1125EF3
-20180608010403 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED3657E33
-20180608015201 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED537E7FB
-20180608023333 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED6C3867B
-20180608023523 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED6CC5597
-20180608025418 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED77890BB
-20180608052209 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EDD073603
-20180608064909 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EE0434A13
-20180608083049 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EE410EA0B
-20180608084134 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EE46EFA03
-20180608113212 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EEAB7B3A3
-20180608123538 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EED06D17F
-20180608133606 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EEF40EF2B
-20180608134723 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EEFA3A923
-20180608141153 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EF0866973
-20180608154036 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EF3C931BF
-20180608155132 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EF42B6B9B
-20180608192033 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EFBB82C37
-20180608203618 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EFE7167C7
-20180608203803 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EFE777583
-20180608231830 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0F04486A93
20180607113212 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9285F38A617
20180607125146 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928617A82F3
20180607125328 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928617CB5DF
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index 61a1239d26..12c61e158f 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -1187,6 +1187,8 @@ sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) ->
parameters = Parms}.
rsa_digest_oid(sha1) ->
?'sha1WithRSAEncryption';
+rsa_digest_oid(sha) ->
+ ?'sha1WithRSAEncryption';
rsa_digest_oid(sha512) ->
?'sha512WithRSAEncryption';
rsa_digest_oid(sha384) ->
@@ -1198,6 +1200,8 @@ rsa_digest_oid(md5) ->
ecdsa_digest_oid(sha1) ->
?'ecdsa-with-SHA1';
+ecdsa_digest_oid(sha) ->
+ ?'ecdsa-with-SHA1';
ecdsa_digest_oid(sha512) ->
?'ecdsa-with-SHA512';
ecdsa_digest_oid(sha384) ->
diff --git a/lib/public_key/src/pubkey_moduli.hrl b/lib/public_key/src/pubkey_moduli.hrl
index d3e2492cf2..768db624c7 100644
--- a/lib/public_key/src/pubkey_moduli.hrl
+++ b/lib/public_key/src/pubkey_moduli.hrl
@@ -352,75 +352,6 @@
822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908676438567},
{5,
822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908697685503}]},
- {5121,
- [{2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247097689699},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247187891059},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247233309283},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247329347539},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247374725179},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247374854083},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247416266563},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247449925747},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247491264043},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247565114563},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247602039643},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247648923259},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247676572003},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247749635347},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247795316107},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247845693523},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247846693459},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247903649683},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247105253887},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247123422007},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247138876567},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247150015567},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247182428143},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247202352967},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247251099967},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247277733823},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247373770207},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247486491463},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247595077447},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247618301767},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247645016047},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247783283863},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247816131343},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247874345167}]},
{6143,
[{2,
30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066212697067},
@@ -480,71 +411,6 @@
30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067042481887},
{5,
30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067188249103}]},
- {7167,
- [{2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680505796219},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680524856539},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680670831859},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680995675027},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681153034243},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681267142387},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681306144307},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681336711163},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681362638459},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681374503099},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681467737603},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681522006547},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681585814027},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681591978499},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681697407907},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681773510443},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681779980579},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681794840947},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681855986587},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284682028742019},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284682126322323},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680529504343},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680623896367},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680724430207},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680814262183},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680973785623},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680984913367},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681363215767},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681736147327},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681849549247},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681982651447},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284682028345287}]},
{8191,
[{2,
881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408345391859},
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index b92790554f..d7e5bc3ad8 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -222,7 +222,9 @@ pem_start('CertificateList') ->
pem_start('EcpkParameters') ->
<<"-----BEGIN EC PARAMETERS-----">>;
pem_start('ECPrivateKey') ->
- <<"-----BEGIN EC PRIVATE KEY-----">>.
+ <<"-----BEGIN EC PRIVATE KEY-----">>;
+pem_start({no_asn1, new_openssh}) -> %% Temporarily in the prototype of this format
+ <<"-----BEGIN OPENSSH PRIVATE KEY-----">>.
pem_end(<<"-----BEGIN CERTIFICATE-----">>) ->
<<"-----END CERTIFICATE-----">>;
@@ -250,6 +252,8 @@ pem_end(<<"-----BEGIN EC PARAMETERS-----">>) ->
<<"-----END EC PARAMETERS-----">>;
pem_end(<<"-----BEGIN EC PRIVATE KEY-----">>) ->
<<"-----END EC PRIVATE KEY-----">>;
+pem_end(<<"-----BEGIN OPENSSH PRIVATE KEY-----">>) ->
+ <<"-----END OPENSSH PRIVATE KEY-----">>;
pem_end(_) ->
undefined.
@@ -278,7 +282,10 @@ asn1_type(<<"-----BEGIN X509 CRL-----">>) ->
asn1_type(<<"-----BEGIN EC PARAMETERS-----">>) ->
'EcpkParameters';
asn1_type(<<"-----BEGIN EC PRIVATE KEY-----">>) ->
- 'ECPrivateKey'.
+ 'ECPrivateKey';
+asn1_type(<<"-----BEGIN OPENSSH PRIVATE KEY-----">>) ->
+ {no_asn1, new_openssh}. %% Temporarily in the prototype of this format
+
pem_decrypt() ->
<<"Proc-Type: 4,ENCRYPTED">>.
diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl
index 02c061efc9..d0ef4abfb1 100644
--- a/lib/public_key/src/pubkey_ssh.erl
+++ b/lib/public_key/src/pubkey_ssh.erl
@@ -25,7 +25,8 @@
-export([decode/2, encode/2,
dh_gex_group/4,
- dh_gex_group_sizes/0
+ dh_gex_group_sizes/0,
+pad/2, new_openssh_encode/1, new_openssh_decode/1 % For test and experiments
]).
-define(UINT32(X), X:32/unsigned-big-integer).
@@ -67,6 +68,8 @@ decode(Bin, rfc4716_public_key) ->
rfc4716_decode(Bin);
decode(Bin, ssh2_pubkey) ->
ssh2_pubkey_decode(Bin);
+decode(Bin, new_openssh) ->
+ new_openssh_decode(Bin);
decode(Bin, Type) ->
openssh_decode(Bin, Type).
@@ -177,6 +180,70 @@ join_entry([Line | Lines], Entry) ->
rfc4716_pubkey_decode(BinKey) -> ssh2_pubkey_decode(BinKey).
+%% From https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
+new_openssh_decode(<<"openssh-key-v1",0,
+ ?DEC_BIN(CipherName, _L1),
+ ?DEC_BIN(KdfName, _L2),
+ ?DEC_BIN(KdfOptions, _L3),
+ ?UINT32(N), % number of keys
+ ?DEC_BIN(PublicKey, _L4),
+ ?DEC_BIN(Encrypted, _L5),
+ _Rest/binary
+ >>) ->
+ %%io:format("CipherName = ~p~nKdfName = ~p~nKdfOptions = ~p~nPublicKey = ~p~nN = ~p~nEncrypted = ~p~nRest = ~p~n", [CipherName, KdfName, KdfOptions, PublicKey, N, Encrypted, _Rest]),
+ new_openssh_decode(CipherName, KdfName, KdfOptions, PublicKey, N, Encrypted).
+
+new_openssh_decode(<<"none">>, <<"none">>, <<"">>, _PublicKey, 1,
+ <<?UINT32(CheckInt),
+ ?UINT32(CheckInt),
+ ?DEC_BIN(Type, _Lt),
+ ?DEC_BIN(PubKey, _Lpu),
+ ?DEC_BIN(PrivPubKey, _Lpripub),
+ ?DEC_BIN(_Comment, _C1),
+ _Pad/binary>>) ->
+ case {Type,PrivPubKey} of
+ {<<"ssh-ed25519">>,
+ <<PrivKey:32/binary, PubKey:32/binary>>} ->
+ {ed_pri, ed25519, PubKey, PrivKey};
+
+ {<<"ssh-ed448">>,
+ <<PrivKey:57/binary, PubKey/binary>>} -> % "Intelligent" guess from
+ % https://tools.ietf.org/html/draft-ietf-curdle-ssh-ed25519-ed448
+ {ed_pri, ed448, PubKey, PrivKey}
+ end.
+
+
+new_openssh_encode({ed_pri,_,PubKey,PrivKey}=Key) ->
+ Type = key_type(Key),
+ CheckInt = 17*256+17, %crypto:strong_rand_bytes(4),
+ Comment = <<>>,
+ PublicKey = <<?STRING(Type),?STRING(PubKey)>>,
+ CipherName = <<"none">>,
+ KdfName = <<"none">>,
+ KdfOptions = <<>>,
+ BlockSize = 8, % Crypto dependent
+ NumKeys = 1,
+ Encrypted0 = <<?UINT32(CheckInt),
+ ?UINT32(CheckInt),
+ ?STRING(Type),
+ ?STRING(PubKey),
+ ?STRING(<<PrivKey/binary,PubKey/binary>>),
+ ?STRING(Comment)
+ >>,
+ Pad = pad(size(Encrypted0), BlockSize),
+ Encrypted = <<Encrypted0/binary, Pad/binary>>,
+ <<"openssh-key-v1",0,
+ ?STRING(CipherName),
+ ?STRING(KdfName),
+ ?STRING(KdfOptions),
+ ?UINT32(NumKeys),
+ ?STRING(PublicKey),
+ ?STRING(Encrypted)>>.
+
+pad(N, BlockSize) when N>BlockSize -> pad(N rem BlockSize, BlockSize);
+pad(N, BlockSize) -> list_to_binary(lists:seq(1,BlockSize-N)).
+
+
openssh_decode(Bin, FileType) ->
Lines = binary:split(Bin, <<"\n">>, [global]),
do_openssh_decode(FileType, Lines, []).
@@ -235,6 +302,8 @@ do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
<<"ssh-rsa">> -> true;
<<"ssh-dss">> -> true;
<<"ecdsa-sha2-",Curve/binary>> -> is_ssh_curvename(Curve);
+ <<"ssh-ed25519">> -> true;
+ <<"ssh-ed448">> -> true;
_ -> false
end,
@@ -247,7 +316,9 @@ do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
Comment = string:strip(string_decode(iolist_to_binary(Comment0)), right, $\n),
do_openssh_decode(FileType, Lines,
[{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, Comment}]} | Acc])
+ [{comment, Comment}]} | Acc]);
+ _ when KnownKeyType==false ->
+ do_openssh_decode(FileType, Lines, Acc)
end.
@@ -386,6 +457,10 @@ line_end(Comment) ->
key_type(#'RSAPublicKey'{}) -> <<"ssh-rsa">>;
key_type({_, #'Dss-Parms'{}}) -> <<"ssh-dss">>;
+key_type({ed_pub,ed25519,_}) -> <<"ssh-ed25519">>;
+key_type({ed_pub,ed448,_}) -> <<"ssh-ed448">>;
+key_type({ed_pri,ed25519,_,_}) -> <<"ssh-ed25519">>;
+key_type({ed_pri,ed448,_,_}) -> <<"ssh-ed448">>;
key_type({#'ECPoint'{}, {namedCurve,Curve}}) -> <<"ecdsa-sha2-", (public_key:oid2ssh_curvename(Curve))/binary>>.
comma_list_encode([Option], []) ->
@@ -404,7 +479,12 @@ ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) ->
<<?STRING(<<"ssh-dss">>), ?Empint(P), ?Empint(Q), ?Empint(G), ?Empint(Y)>>;
ssh2_pubkey_encode(Key={#'ECPoint'{point = Q}, {namedCurve,OID}}) ->
Curve = public_key:oid2ssh_curvename(OID),
- <<?STRING(key_type(Key)), ?Estring(Curve), ?Estring(Q)>>.
+ <<?STRING(key_type(Key)), ?Estring(Curve), ?Estring(Q)>>;
+ssh2_pubkey_encode({ed_pub, ed25519, Key}) ->
+ <<?STRING(<<"ssh-ed25519">>), ?Estring(Key)>>;
+ssh2_pubkey_encode({ed_pub, ed448, Key}) ->
+ <<?STRING(<<"ssh-ed448">>), ?Estring(Key)>>.
+
ssh2_pubkey_decode(<<?DEC_BIN(Type,_TL), Bin/binary>>) ->
@@ -430,12 +510,23 @@ ssh2_pubkey_decode(<<"ssh-dss">>,
ssh2_pubkey_decode(<<"ecdsa-sha2-",Id/binary>>,
<<?DEC_BIN(Id, _IL),
?DEC_BIN(Q, _QL)>>) ->
- {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}.
+ {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}};
+
+ssh2_pubkey_decode(<<"ssh-ed25519">>,
+ <<?DEC_BIN(Key, _L)>>) ->
+ {ed_pub, ed25519, Key};
+
+ssh2_pubkey_decode(<<"ssh-ed448">>,
+ <<?DEC_BIN(Key, _L)>>) ->
+ {ed_pub, ed448, Key}.
+
is_key_field(<<"ssh-dss">>) -> true;
is_key_field(<<"ssh-rsa">>) -> true;
+is_key_field(<<"ssh-ed25519">>) -> true;
+is_key_field(<<"ssh-ed448">>) -> true;
is_key_field(<<"ecdsa-sha2-",Id/binary>>) -> is_ssh_curvename(Id);
is_key_field(_) -> false.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index b34f905fc3..d02df27a00 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -66,19 +66,22 @@
-export_type([public_key/0, private_key/0, pem_entry/0,
pki_asn1_type/0, asn1_type/0, ssh_file/0, der_encoded/0,
- key_params/0, digest_type/0]).
+ key_params/0, digest_type/0, issuer_name/0, oid/0]).
--type public_key() :: rsa_public_key() | dsa_public_key() | ec_public_key().
--type private_key() :: rsa_private_key() | dsa_private_key() | ec_private_key().
+-type public_key() :: rsa_public_key() | dsa_public_key() | ec_public_key() | ed_public_key() .
+-type private_key() :: rsa_private_key() | dsa_private_key() | ec_private_key() | ed_private_key() .
-type rsa_public_key() :: #'RSAPublicKey'{}.
-type rsa_private_key() :: #'RSAPrivateKey'{}.
-type dsa_private_key() :: #'DSAPrivateKey'{}.
-type dsa_public_key() :: {integer(), #'Dss-Parms'{}}.
-type ecpk_parameters() :: {ecParameters, #'ECParameters'{}} | {namedCurve, Oid::tuple()}.
--type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::atom()}.
+-type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::crypto:ec_named_curve()}.
-type ec_public_key() :: {#'ECPoint'{}, ecpk_parameters_api()}.
-type ec_private_key() :: #'ECPrivateKey'{}.
+-type ed_public_key() :: {ed_pub, ed25519|ed448, Key::binary()}.
+-type ed_private_key() :: {ed_pri, ed25519|ed448, Pub::binary(), Priv::binary()}.
+
-type key_params() :: #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} |
{rsa, Size::integer(), PubExp::integer()}.
-type der_encoded() :: binary().
@@ -88,28 +91,42 @@
'CertificationRequest' | 'CertificateList' |
'ECPrivateKey' | 'EcpkParameters'.
-type pem_entry() :: {pki_asn1_type(),
- binary(), %% DER or Encrypted DER
- not_encrypted | {Cipher :: string(), Salt :: binary()} |
- {Cipher :: string(), #'PBES2-params'{}} |
- {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+ der_or_encrypted_der(),
+ not_encrypted | cipher_info()
}.
+-type der_or_encrypted_der() :: binary().
+-type cipher_info() :: {cipher(),
+ cipher_info_params()} .
+-type cipher() :: string() . % "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC",
+-type cipher_info_params() :: salt()
+ | {#'PBEParameter'{}, digest_type()}
+ | #'PBES2-params'{} .
+
+-type salt() :: binary(). % crypto:strong_rand_bytes(8)
+%% -type cipher_info() :: {Cipher :: string(), Salt :: binary()} |
+%% {Cipher :: string(), #'PBES2-params'{}} |
+%% {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+%% .
+
-type asn1_type() :: atom(). %% see "OTP-PUB-KEY.hrl
-type ssh_file() :: openssh_public_key | rfc4716_public_key | known_hosts |
auth_keys.
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
- | 'rsa_no_padding'.
--type rsa_sign_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_pss_padding'.
--type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
--type rsa_digest_type() :: 'md5' | 'ripemd160' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type dss_digest_type() :: 'none' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. %% None is for backwards compatibility
--type ecdsa_digest_type() :: 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type public_sign_options() :: [{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}].
--type digest_type() :: rsa_digest_type() | dss_digest_type() | ecdsa_digest_type().
+-type digest_type() :: none % None is for backwards compatibility
+ | sha1 % Backwards compatibility
+ | crypto:rsa_digest_type()
+ | crypto:dss_digest_type()
+ | crypto:ecdsa_digest_type().
-type crl_reason() :: unspecified | keyCompromise | cACompromise | affiliationChanged | superseded
| cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise.
-type oid() :: tuple().
-type chain_type() :: server_chain | client_chain.
+-type issuer_id() :: {SerialNr::integer(), issuer_name()} .
+
+-type issuer_name() :: {rdnSequence,[#'AttributeTypeAndValue'{}]} .
+
+
+
-define(UINT32(X), X:32/unsigned-big-integer).
-define(DER_NULL, <<5, 0>>).
@@ -134,11 +151,11 @@ pem_encode(PemEntries) when is_list(PemEntries) ->
iolist_to_binary(pubkey_pem:encode(PemEntries)).
%%--------------------------------------------------------------------
--spec pem_entry_decode(pem_entry(), string()) -> term().
-%
%% Description: Decodes a pem entry. pem_decode/1 returns a list of
%% pem entries.
%%--------------------------------------------------------------------
+-spec pem_entry_decode(PemEntry) -> term() when PemEntry :: pem_entry() .
+
pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
{_, {'AlgorithmIdentifier', AlgId, Params}, Key0}
= der_decode('SubjectPublicKeyInfo', Der),
@@ -153,9 +170,14 @@ pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
ECCParams = der_decode('EcpkParameters', Params),
{#'ECPoint'{point = Key0}, ECCParams}
end;
+pem_entry_decode({{no_asn1,new_openssh}, Special, not_encrypted}) ->
+ ssh_decode(Special, new_openssh);
pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der).
+
+-spec pem_entry_decode(PemEntry, Password) -> term() when PemEntry :: pem_entry(),
+ Password :: string() .
pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der);
@@ -181,11 +203,12 @@ pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
%%--------------------------------------------------------------------
--spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
--spec pem_entry_encode(pki_asn1_type(), term(), term()) -> pem_entry().
%%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
+-spec pem_entry_encode(Asn1Type, Entity) -> pem_entry() when Asn1Type :: pki_asn1_type(),
+ Entity :: term() .
+
pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
Der = der_encode('RSAPublicKey', Entity),
Spki = {'SubjectPublicKeyInfo',
@@ -208,6 +231,13 @@ pem_entry_encode('SubjectPublicKeyInfo',
pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Der = der_encode(Asn1Type, Entity),
{Asn1Type, Der, not_encrypted}.
+
+-spec pem_entry_encode(Asn1Type, Entity, InfoPwd) ->
+ pem_entry() when Asn1Type :: pki_asn1_type(),
+ Entity :: term(),
+ InfoPwd :: {CipherInfo,Password},
+ CipherInfo :: cipher_info(),
+ Password :: string() .
pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo,
Password}) when is_atom(Asn1Type) andalso
is_list(Password) andalso
@@ -229,7 +259,9 @@ pem_entry_encode(Asn1Type, Entity, {{Cipher, Salt} = CipherInfo,
do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password).
%%--------------------------------------------------------------------
--spec der_decode(asn1_type(), Der::binary()) -> term().
+-spec der_decode(Asn1Type, Der) -> Entity when Asn1Type :: asn1_type(),
+ Der :: binary(),
+ Entity :: term().
%%
%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
@@ -269,7 +301,9 @@ der_priv_key_decode(PKCS8Key) ->
PKCS8Key.
%%--------------------------------------------------------------------
--spec der_encode(asn1_type(), term()) -> Der::binary().
+-spec der_encode(Asn1Type, Entity) -> Der when Asn1Type :: asn1_type(),
+ Entity :: term(),
+ Der :: binary() .
%%
%% Description: Encodes a public key entity with asn1 DER encoding.
%%--------------------------------------------------------------------
@@ -311,8 +345,10 @@ der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
end.
%%--------------------------------------------------------------------
--spec pkix_decode_cert(Cert::binary(), plain | otp) ->
- #'Certificate'{} | #'OTPCertificate'{}.
+-spec pkix_decode_cert(Cert, Type) ->
+ #'Certificate'{} | #'OTPCertificate'{}
+ when Cert :: der_encoded(),
+ Type :: plain | otp .
%%
%% Description: Decodes an asn1 der encoded pkix certificate. The otp
%% option will use the customized asn1 specification OTP-PKIX.asn1 for
@@ -332,7 +368,11 @@ pkix_decode_cert(DerCert, otp) when is_binary(DerCert) ->
end.
%%--------------------------------------------------------------------
--spec pkix_encode(asn1_type(), term(), otp | plain) -> Der::binary().
+-spec pkix_encode(Asn1Type, Entity, Type) -> Der
+ when Asn1Type :: asn1_type(),
+ Entity :: term(),
+ Type :: otp | plain,
+ Der :: der_encoded() .
%%
%% Description: Der encodes a certificate or part of a certificate.
%% This function must be used for encoding certificates or parts of certificates
@@ -347,16 +387,21 @@ pkix_encode(Asn1Type, Term0, otp) when is_atom(Asn1Type) ->
der_encode(Asn1Type, Term).
%%--------------------------------------------------------------------
--spec decrypt_private(CipherText :: binary(), rsa_private_key()) ->
- PlainText :: binary().
--spec decrypt_private(CipherText :: binary(), rsa_private_key(),
- public_crypt_options()) -> PlainText :: binary().
%%
%% Description: Public key decryption using the private key.
%%--------------------------------------------------------------------
+-spec decrypt_private(CipherText, Key) ->
+ PlainText when CipherText :: binary(),
+ Key :: rsa_private_key(),
+ PlainText :: binary() .
decrypt_private(CipherText, Key) ->
decrypt_private(CipherText, Key, []).
+-spec decrypt_private(CipherText, Key, Options) ->
+ PlainText when CipherText :: binary(),
+ Key :: rsa_private_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
decrypt_private(CipherText,
#'RSAPrivateKey'{} = Key,
Options)
@@ -366,61 +411,69 @@ decrypt_private(CipherText,
crypto:private_decrypt(rsa, CipherText, format_rsa_private_key(Key), Padding).
%%--------------------------------------------------------------------
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key()) ->
- PlainText :: binary().
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key(),
- public_crypt_options()) -> PlainText :: binary().
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
%% Description: Public key decryption using the public key.
%%--------------------------------------------------------------------
+-spec decrypt_public(CipherText, Key) ->
+ PlainText
+ when CipherText :: binary(),
+ Key :: rsa_public_key(),
+ PlainText :: binary() .
decrypt_public(CipherText, Key) ->
decrypt_public(CipherText, Key, []).
+-spec decrypt_public(CipherText, Key, Options) ->
+ PlainText
+ when CipherText :: binary(),
+ Key :: rsa_public_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E},
Options) when is_binary(CipherText), is_list(Options) ->
- decrypt_public(CipherText, N,E, Options);
-
-decrypt_public(CipherText,#'RSAPrivateKey'{modulus = N, publicExponent = E},
- Options) when is_binary(CipherText), is_list(Options) ->
- decrypt_public(CipherText, N,E, Options).
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
%%--------------------------------------------------------------------
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key()) ->
- CipherText :: binary().
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key(),
- public_crypt_options()) -> CipherText :: binary().
-
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
%% Description: Public key encryption using the public key.
%%--------------------------------------------------------------------
+-spec encrypt_public(PlainText, Key) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_public_key(),
+ CipherText :: binary() .
encrypt_public(PlainText, Key) ->
encrypt_public(PlainText, Key, []).
-encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
- Options) when is_binary(PlainText), is_list(Options) ->
- encrypt_public(PlainText, N,E, Options);
-encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E},
+-spec encrypt_public(PlainText, Key, Options) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_public_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ CipherText :: binary() .
+encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
Options) when is_binary(PlainText), is_list(Options) ->
- encrypt_public(PlainText, N,E, Options).
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
%%--------------------------------------------------------------------
--spec encrypt_private(PlainText :: binary(), rsa_private_key()) ->
- CipherText :: binary().
--spec encrypt_private(PlainText :: binary(), rsa_private_key(),
- public_crypt_options()) -> CipherText :: binary().
%%
%% Description: Public key encryption using the private key.
%%--------------------------------------------------------------------
+-spec encrypt_private(PlainText, Key) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_private_key(),
+ CipherText :: binary() .
encrypt_private(PlainText, Key) ->
encrypt_private(PlainText, Key, []).
+
+-spec encrypt_private(PlainText, Key, Options) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_private_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ CipherText :: binary() .
encrypt_private(PlainText,
#'RSAPrivateKey'{modulus = N, publicExponent = E,
privateExponent = D} = Key,
@@ -432,22 +485,42 @@ encrypt_private(PlainText,
crypto:private_encrypt(rsa, PlainText, format_rsa_private_key(Key), Padding).
%%--------------------------------------------------------------------
+%% Description: List available group sizes among the pre-computed dh groups
+%%--------------------------------------------------------------------
+-spec dh_gex_group_sizes() -> [pos_integer()].
dh_gex_group_sizes() ->
pubkey_ssh:dh_gex_group_sizes().
+%%--------------------------------------------------------------------
+%% Description: Select a precomputed group
+%%--------------------------------------------------------------------
+-spec dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) ->
+ {ok,{Size,Group}} | {error,term()}
+ when MinSize :: pos_integer(),
+ SuggestedSize :: pos_integer(),
+ MaxSize :: pos_integer(),
+ Groups :: undefined | [{Size,[Group]}],
+ Size :: pos_integer(),
+ Group :: {G,P},
+ G :: pos_integer(),
+ P :: pos_integer() .
dh_gex_group(Min, N, Max, Groups) ->
pubkey_ssh:dh_gex_group(Min, N, Max, Groups).
%%--------------------------------------------------------------------
--spec generate_key(#'DHParameter'{}) ->
- {Public::binary(), Private::binary()};
- (ecpk_parameters_api()) ->
- #'ECPrivateKey'{};
- ({rsa, Size::pos_integer(), PubExp::pos_integer()}) ->
- #'RSAPrivateKey'{}.
-
-%% Description: Generates a new keypair
+%% Description: Generate a new key pair
%%--------------------------------------------------------------------
+-spec generate_key(DHparams | ECparams | RSAparams) ->
+ DHkeys | ECkey | RSAkey
+ when DHparams :: #'DHParameter'{},
+ DHkeys :: {PublicDH::binary(), PrivateDH::binary()},
+ ECparams :: ecpk_parameters_api(),
+ ECkey :: #'ECPrivateKey'{},
+ RSAparams :: {rsa, Size, PubExp},
+ Size::pos_integer(),
+ PubExp::pos_integer(),
+ RSAkey :: #'RSAPrivateKey'{} .
+
generate_key(#'DHParameter'{prime = P, base = G}) ->
crypto:generate_key(dh, [P, G]);
generate_key({namedCurve, _} = Params) ->
@@ -494,24 +567,34 @@ generate_key({rsa, ModulusSize, PublicExponent}) ->
end.
%%--------------------------------------------------------------------
--spec compute_key(#'ECPoint'{} , #'ECPrivateKey'{}) -> binary().
--spec compute_key(OthersKey ::binary(), MyKey::binary(), #'DHParameter'{}) -> binary().
%% Description: Compute shared secret
%%--------------------------------------------------------------------
+-spec compute_key(OthersECDHkey, MyECDHkey) ->
+ SharedSecret
+ when OthersECDHkey :: #'ECPoint'{},
+ MyECDHkey :: #'ECPrivateKey'{},
+ SharedSecret :: binary().
compute_key(#'ECPoint'{point = Point}, #'ECPrivateKey'{privateKey = PrivKey,
parameters = Param}) ->
ECCurve = ec_curve_spec(Param),
crypto:compute_key(ecdh, Point, PrivKey, ECCurve).
+-spec compute_key(OthersDHkey, MyDHkey, DHparms) ->
+ SharedSecret
+ when OthersDHkey :: crypto:dh_public(), % Was: binary(),
+ MyDHkey :: crypto:dh_private(), % Was: binary(),
+ DHparms :: #'DHParameter'{},
+ SharedSecret :: binary().
compute_key(PubKey, PrivKey, #'DHParameter'{prime = P, base = G}) ->
crypto:compute_key(dh, PubKey, PrivKey, [P, G]).
%%--------------------------------------------------------------------
--spec pkix_sign_types(SignatureAlg::oid()) ->
- %% Relevant dsa digest type is subpart of rsa digest type
- { DigestType :: rsa_digest_type(),
- SignatureType :: rsa | dsa | ecdsa
- }.
+-spec pkix_sign_types(AlgorithmId) ->
+ {DigestType, SignatureType}
+ when AlgorithmId :: oid(),
+ %% Relevant dsa digest type is a subset of rsa_digest_type()
+ DigestType :: crypto:rsa_digest_type(),
+ SignatureType :: rsa | dsa | ecdsa .
%% Description:
%%--------------------------------------------------------------------
pkix_sign_types(?sha1WithRSAEncryption) ->
@@ -532,6 +615,10 @@ pkix_sign_types(?'id-dsa-with-sha1') ->
{sha, dsa};
pkix_sign_types(?'id-dsaWithSHA1') ->
{sha, dsa};
+pkix_sign_types(?'id-dsa-with-sha224') ->
+ {sha224, dsa};
+pkix_sign_types(?'id-dsa-with-sha256') ->
+ {sha256, dsa};
pkix_sign_types(?'ecdsa-with-SHA1') ->
{sha, ecdsa};
pkix_sign_types(?'ecdsa-with-SHA256') ->
@@ -542,24 +629,24 @@ pkix_sign_types(?'ecdsa-with-SHA512') ->
{sha512, ecdsa}.
%%--------------------------------------------------------------------
--spec sign(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- rsa_private_key() | dsa_private_key() | ec_private_key()
- ) -> Signature :: binary().
-
--spec sign(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- rsa_private_key() | dsa_private_key() | ec_private_key(),
- public_sign_options()
- ) -> Signature :: binary().
-
%% Description: Create digital signature.
%%--------------------------------------------------------------------
+-spec sign(Msg, DigestType, Key) ->
+ Signature when Msg :: binary() | {digest,binary()},
+ DigestType :: digest_type(),
+ Key :: private_key(),
+ Signature :: binary() .
sign(DigestOrPlainText, DigestType, Key) ->
sign(DigestOrPlainText, DigestType, Key, []).
-%% Backwards compatible
+-spec sign(Msg, DigestType, Key, Options) ->
+ Signature when Msg :: binary() | {digest,binary()},
+ DigestType :: digest_type(),
+ Key :: private_key(),
+ Options :: crypto:pk_sign_verify_opts(),
+ Signature :: binary() .
sign(Digest, none, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) ->
+ %% Backwards compatible
sign({digest, Digest}, sha, Key, Options);
sign(DigestOrPlainText, DigestType, Key, Options) ->
case format_sign_key(Key) of
@@ -570,30 +657,26 @@ sign(DigestOrPlainText, DigestType, Key, Options) ->
end.
%%--------------------------------------------------------------------
--spec verify(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- Signature :: binary(),
- rsa_public_key() | dsa_public_key() | ec_public_key()
- | rsa_private_key() | dsa_private_key() | ec_private_key()
- ) -> boolean().
-
--spec verify(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- Signature :: binary(),
- rsa_public_key() | dsa_public_key() | ec_public_key()
- | rsa_private_key() | dsa_private_key() | ec_private_key(),
- public_sign_options()
- ) -> boolean().
-
%% Description: Verifies a digital signature.
%%--------------------------------------------------------------------
+-spec verify(Msg, DigestType, Signature, Key) ->
+ boolean() when Msg :: binary() | {digest, binary()},
+ DigestType :: digest_type(),
+ Signature :: binary(),
+ Key :: public_key() .
+
verify(DigestOrPlainText, DigestType, Signature, Key) ->
verify(DigestOrPlainText, DigestType, Signature, Key, []).
-%% Backwards compatible
+-spec verify(Msg, DigestType, Signature, Key, Options) ->
+ boolean() when Msg :: binary() | {digest, binary()},
+ DigestType :: digest_type(),
+ Signature :: binary(),
+ Key :: public_key(),
+ Options :: crypto:pk_sign_verify_opts().
+
verify(Digest, none, Signature, Key = {_, #'Dss-Parms'{}}, Options) when is_binary(Digest) ->
- verify({digest, Digest}, sha, Signature, Key, Options);
-verify(Digest, none, Signature, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) ->
+ %% Backwards compatible
verify({digest, Digest}, sha, Signature, Key, Options);
verify(DigestOrPlainText, DigestType, Signature, Key, Options) when is_binary(Signature) ->
case format_verify_key(Key) of
@@ -608,8 +691,8 @@ verify(_,_,_,_,_) ->
false.
%%--------------------------------------------------------------------
--spec pkix_dist_point(der_encoded() | #'OTPCertificate'{}) ->
- #'DistributionPoint'{}.
+-spec pkix_dist_point(Cert) -> DistPoint when Cert :: der_encoded() | #'OTPCertificate'{},
+ DistPoint :: #'DistributionPoint'{}.
%% Description: Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
%%--------------------------------------------------------------------
pkix_dist_point(OtpCert) when is_binary(OtpCert) ->
@@ -632,8 +715,8 @@ pkix_dist_point(OtpCert) ->
reasons = asn1_NOVALUE,
distributionPoint = Point}.
%%--------------------------------------------------------------------
--spec pkix_dist_points(der_encoded() | #'OTPCertificate'{}) ->
- [#'DistributionPoint'{}].
+-spec pkix_dist_points(Cert) -> DistPoints when Cert :: der_encoded() | #'OTPCertificate'{},
+ DistPoints :: [ #'DistributionPoint'{} ].
%% Description: Extracts distributionpoints specified in the certificates extensions.
%%--------------------------------------------------------------------
pkix_dist_points(OtpCert) when is_binary(OtpCert) ->
@@ -647,8 +730,10 @@ pkix_dist_points(OtpCert) ->
[], Value).
%%--------------------------------------------------------------------
--spec pkix_match_dist_point(der_encoded() | #'CertificateList'{},
- #'DistributionPoint'{}) -> boolean().
+-spec pkix_match_dist_point(CRL, DistPoint) ->
+ boolean()
+ when CRL :: der_encoded() | #'CertificateList'{},
+ DistPoint :: #'DistributionPoint'{}.
%% Description: Check whether the given distribution point matches
%% the "issuing distribution point" of the CRL.
%%--------------------------------------------------------------------
@@ -679,8 +764,9 @@ pkix_match_dist_point(#'CertificateList'{
end.
%%--------------------------------------------------------------------
--spec pkix_sign(#'OTPTBSCertificate'{},
- rsa_private_key() | dsa_private_key() | ec_private_key()) -> Der::binary().
+-spec pkix_sign(Cert, Key) -> Der when Cert :: #'OTPTBSCertificate'{},
+ Key :: private_key(),
+ Der :: der_encoded() .
%%
%% Description: Sign a pkix x.509 certificate. Returns the corresponding
%% der encoded 'Certificate'{}
@@ -699,8 +785,8 @@ pkix_sign(#'OTPTBSCertificate'{signature =
pkix_encode('OTPCertificate', Cert, otp).
%%--------------------------------------------------------------------
--spec pkix_verify(Cert::binary(), rsa_public_key()|
- dsa_public_key() | ec_public_key()) -> boolean().
+-spec pkix_verify(Cert, Key) -> boolean() when Cert :: der_encoded(),
+ Key :: public_key() .
%%
%% Description: Verify pkix x.509 certificate signature.
%%--------------------------------------------------------------------
@@ -720,7 +806,9 @@ pkix_verify(DerCert, Key = {#'ECPoint'{}, _})
verify(PlainText, DigestType, Signature, Key).
%%--------------------------------------------------------------------
--spec pkix_crl_verify(CRL::binary() | #'CertificateList'{}, Cert::binary() | #'OTPCertificate'{}) -> boolean().
+-spec pkix_crl_verify(CRL, Cert) -> boolean()
+ when CRL :: der_encoded() | #'CertificateList'{},
+ Cert :: der_encoded() | #'OTPCertificate'{} .
%%
%% Description: Verify that Cert is the CRL signer.
%%--------------------------------------------------------------------
@@ -739,9 +827,12 @@ pkix_crl_verify(#'CertificateList'{} = CRL, #'OTPCertificate'{} = Cert) ->
PublicKey, PublicKeyParams).
%%--------------------------------------------------------------------
--spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{} | #'CertificateList'{},
- IssuerCert :: der_encoded()|
- #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_issuer(Cert, IssuerCert) ->
+ boolean() when Cert :: der_encoded()
+ | #'OTPCertificate'{}
+ | #'CertificateList'{},
+ IssuerCert :: der_encoded()
+ | #'OTPCertificate'{} .
%%
%% Description: Checks if <IssuerCert> issued <Cert>.
%%--------------------------------------------------------------------
@@ -761,7 +852,7 @@ pkix_is_issuer(#'CertificateList'{tbsCertList = TBSCRL},
pubkey_cert_records:transform(TBSCRL#'TBSCertList'.issuer, decode)).
%%--------------------------------------------------------------------
--spec pkix_is_self_signed(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_self_signed(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
%%
%% Description: Checks if a Certificate is self signed.
%%--------------------------------------------------------------------
@@ -772,7 +863,7 @@ pkix_is_self_signed(Cert) when is_binary(Cert) ->
pkix_is_self_signed(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_is_fixed_dh_cert(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_fixed_dh_cert(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
%%
%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert.
%%--------------------------------------------------------------------
@@ -783,13 +874,12 @@ pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
pkix_is_fixed_dh_cert(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_issuer_id(Cert::binary()| #'OTPCertificate'{},
- IssuedBy :: self | other) ->
- {ok, {SerialNr :: integer(),
- Issuer :: {rdnSequence,
- [#'AttributeTypeAndValue'{}]}}}
- | {error, Reason :: term()}.
-%
+-spec pkix_issuer_id(Cert, IssuedBy) ->
+ {ok, issuer_id()} | {error, Reason}
+ when Cert::der_encoded()| #'OTPCertificate'{},
+ IssuedBy :: self | other,
+ Reason :: term() .
+
%% Description: Returns the issuer id.
%%--------------------------------------------------------------------
pkix_issuer_id(#'OTPCertificate'{} = OtpCert, Signed) when (Signed == self) or
@@ -800,9 +890,9 @@ pkix_issuer_id(Cert, Signed) when is_binary(Cert) ->
pkix_issuer_id(OtpCert, Signed).
%%--------------------------------------------------------------------
--spec pkix_crl_issuer(CRL::binary()| #'CertificateList'{}) ->
- {rdnSequence,
- [#'AttributeTypeAndValue'{}]}.
+-spec pkix_crl_issuer(CRL| #'CertificateList'{}) ->
+ Issuer when CRL :: der_encoded(),
+ Issuer :: issuer_name() .
%
%% Description: Returns the issuer.
%%--------------------------------------------------------------------
@@ -813,10 +903,9 @@ pkix_crl_issuer(#'CertificateList'{} = CRL) ->
CRL#'CertificateList'.tbsCertList#'TBSCertList'.issuer, decode).
%%--------------------------------------------------------------------
--spec pkix_normalize_name({rdnSequence,
- [#'AttributeTypeAndValue'{}]}) ->
- {rdnSequence,
- [#'AttributeTypeAndValue'{}]}.
+-spec pkix_normalize_name(Issuer) -> Normalized
+ when Issuer :: issuer_name(),
+ Normalized :: issuer_name() .
%%
%% Description: Normalizes a issuer name so that it can be easily
%% compared to another issuer name.
@@ -827,7 +916,7 @@ pkix_normalize_name(Issuer) ->
%%--------------------------------------------------------------------
-spec pkix_path_validation(Cert::binary()| #'OTPCertificate'{} | atom(),
CertChain :: [binary()] ,
- Options :: proplists:proplist()) ->
+ Options :: [{atom(),term()}]) ->
{ok, {PublicKeyInfo :: term(),
PolicyTree :: term()}} |
{error, {bad_cert, Reason :: term()}}.
@@ -863,11 +952,19 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
path_validation(CertChain, ValidationState).
%--------------------------------------------------------------------
--spec pkix_crls_validate(#'OTPCertificate'{},
- [{DP::#'DistributionPoint'{}, {DerCRL::binary(), CRL::#'CertificateList'{}}}],
- Options :: proplists:proplist()) -> valid | {bad_cert, revocation_status_undetermined} |
- {bad_cert, {revocation_status_undetermined, Reason::term()}} |
- {bad_cert, {revoked, crl_reason()}}.
+-spec pkix_crls_validate(OTPcertificate, DPandCRLs, Options) ->
+ CRLstatus when OTPcertificate :: #'OTPCertificate'{},
+ DPandCRLs :: [DPandCRL],
+ DPandCRL :: {DP, {DerCRL, CRL}},
+ DP :: #'DistributionPoint'{},
+ DerCRL :: der_encoded(),
+ CRL :: #'CertificateList'{},
+ Options :: [{atom(),term()}],
+ CRLstatus :: valid
+ | {bad_cert, BadCertReason},
+ BadCertReason :: revocation_status_undetermined
+ | {revocation_status_undetermined, Reason::term()}
+ | {revoked, crl_reason()}.
%% Description: Performs a CRL validation according to RFC 5280.
%%--------------------------------------------------------------------
@@ -884,20 +981,10 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
Options, pubkey_crl:init_revokation_state()).
%--------------------------------------------------------------------
--spec pkix_verify_hostname(#'OTPCertificate'{} | binary(),
- referenceIDs()
- ) -> boolean().
-
--spec pkix_verify_hostname(#'OTPCertificate'{} | binary(),
- referenceIDs(),
- proplists:proplist()) -> boolean().
-
-type referenceIDs() :: [referenceID()] .
-type referenceID() :: {uri_id | dns_id | ip | srv_id | oid(), string()}
| {ip, inet:ip_address()} .
--spec pkix_verify_hostname_match_fun(high_level_alg()) -> match_fun() .
-
-type high_level_alg() :: https .
-type match_fun() :: fun((ReferenceID::referenceID() | string(),
PresentedID::{atom()|oid(),string()}) -> match_fun_result() ) .
@@ -905,9 +992,20 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
%% Description: Validates a hostname to RFC 6125
%%--------------------------------------------------------------------
+-spec pkix_verify_hostname(Cert, ReferenceIDs) -> boolean()
+ when Cert :: der_encoded()
+ | #'OTPCertificate'{},
+ ReferenceIDs :: referenceIDs() .
pkix_verify_hostname(Cert, ReferenceIDs) ->
pkix_verify_hostname(Cert, ReferenceIDs, []).
+-spec pkix_verify_hostname(Cert, ReferenceIDs, Options) ->
+ boolean()
+ when Cert :: der_encoded()
+ | #'OTPCertificate'{},
+ ReferenceIDs :: referenceIDs(),
+ Options :: [{atom(),term()}] .
+
pkix_verify_hostname(BinCert, ReferenceIDs, Options) when is_binary(BinCert) ->
pkix_verify_hostname(pkix_decode_cert(BinCert,otp), ReferenceIDs, Options);
@@ -966,15 +1064,26 @@ pkix_verify_hostname(Cert = #'OTPCertificate'{tbsCertificate = TbsCert}, Referen
end
end.
+
+-spec pkix_verify_hostname_match_fun(high_level_alg()) -> match_fun() .
+
pkix_verify_hostname_match_fun(https) ->
fun({dns_id,FQDN=[_|_]}, {dNSName,Name=[_|_]}) -> verify_hostname_match_wildcard(FQDN, Name);
(_, _) -> default
end.
%%--------------------------------------------------------------------
--spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}]
- ; (binary(), ssh2_pubkey) -> public_key()
- .
+-spec ssh_decode(SshBin, Type) ->
+ Decoded
+ when SshBin :: binary(),
+ Type :: ssh2_pubkey | OtherType | InternalType,
+ OtherType :: public_key | ssh_file(),
+ InternalType :: new_openssh,
+ Decoded :: Decoded_ssh2_pubkey
+ | Decoded_OtherType,
+ Decoded_ssh2_pubkey :: public_key(),
+ Decoded_OtherType :: [{public_key(), Attributes}],
+ Attributes :: [{atom(),term()}] .
%%
%% Description: Decodes a ssh file-binary. In the case of know_hosts
%% or auth_keys the binary may include one or more lines of the
@@ -988,13 +1097,20 @@ ssh_decode(SshBin, Type) when is_binary(SshBin),
Type == openssh_public_key;
Type == auth_keys;
Type == known_hosts;
- Type == ssh2_pubkey ->
+ Type == ssh2_pubkey;
+ Type == new_openssh ->
pubkey_ssh:decode(SshBin, Type).
%%--------------------------------------------------------------------
--spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> binary()
- ; (public_key(), ssh2_pubkey) -> binary()
- .
+-spec ssh_encode(InData, Type) ->
+ binary()
+ when Type :: ssh2_pubkey | OtherType,
+ OtherType :: public_key | ssh_file(),
+ InData :: InData_ssh2_pubkey | OtherInData,
+ InData_ssh2_pubkey :: public_key(),
+ OtherInData :: [{Key,Attributes}],
+ Key :: public_key(),
+ Attributes :: [{atom(),term()}] .
%%
%% Description: Encodes a list of ssh file entries (public keys and
%% attributes) to a binary. Possible attributes depends on the file
@@ -1029,13 +1145,14 @@ oid2ssh_curvename(?'secp521r1') -> <<"nistp521">>.
%%--------------------------------------------------------------------
-spec ssh_hostkey_fingerprint(public_key()) -> string().
--spec ssh_hostkey_fingerprint( digest_type(), public_key()) -> string()
- ; ([digest_type()], public_key()) -> [string()]
- .
ssh_hostkey_fingerprint(Key) ->
sshfp_string(md5, public_key:ssh_encode(Key,ssh2_pubkey) ).
+
+-spec ssh_hostkey_fingerprint( digest_type(), public_key()) -> string()
+ ; ([digest_type()], public_key()) -> [string()]
+ .
ssh_hostkey_fingerprint(HashAlgs, Key) when is_list(HashAlgs) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
[sshfp_full_string(HashAlg,EncKey) || HashAlg <- HashAlgs];
@@ -1073,8 +1190,7 @@ fp_fmt(b64, Bin) ->
[lists:nth(C+1,B64Chars) || <<C:6>> <= <<Bin/binary,0:Padding>> ].
%%--------------------------------------------------------------------
--spec short_name_hash({rdnSequence, [#'AttributeTypeAndValue'{}]}) ->
- string().
+-spec short_name_hash(Name) -> string() when Name :: issuer_name() .
%% Description: Generates OpenSSL-style hash of a name.
%%--------------------------------------------------------------------
@@ -1105,10 +1221,11 @@ pkix_test_data(#{} = Chain) ->
pubkey_cert:gen_test_certs(maps:merge(Default, Chain)).
%%--------------------------------------------------------------------
--spec pkix_test_root_cert(
- Name :: string(), Opts :: [pubkey_cert:cert_opt()]) ->
- pubkey_cert:test_root_cert().
-
+-spec pkix_test_root_cert(Name, Options) ->
+ RootCert
+ when Name :: string(),
+ Options :: [{atom(),term()}], %[cert_opt()],
+ RootCert :: pubkey_cert:test_root_cert().
%% Description: Generates a root cert suitable for pkix_test_data/1
%%--------------------------------------------------------------------
@@ -1124,6 +1241,8 @@ format_sign_key(#'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
{dss, [P, Q, G, X]};
format_sign_key(#'ECPrivateKey'{privateKey = PrivKey, parameters = Param}) ->
{ecdsa, [PrivKey, ec_curve_spec(Param)]};
+format_sign_key({ed_pri, Curve, _Pub, Priv}) ->
+ {eddsa, [Priv,Curve]};
format_sign_key(_) ->
badarg.
@@ -1133,6 +1252,8 @@ format_verify_key({#'ECPoint'{point = Point}, Param}) ->
{ecdsa, [Point, ec_curve_spec(Param)]};
format_verify_key({Key, #'Dss-Parms'{p = P, q = Q, g = G}}) ->
{dss, [P, Q, G, Key]};
+format_verify_key({ed_pub, Curve, Key}) ->
+ {eddsa, [Key,Curve]};
%% Convert private keys to public keys
format_verify_key(#'RSAPrivateKey'{modulus = Mod, publicExponent = Exp}) ->
format_verify_key(#'RSAPublicKey'{modulus = Mod, publicExponent = Exp});
@@ -1154,14 +1275,6 @@ do_pem_entry_decode({Asn1Type,_, _} = PemEntry, Password) ->
Der = pubkey_pem:decipher(PemEntry, Password),
der_decode(Asn1Type, Der).
-encrypt_public(PlainText, N, E, Options)->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
-
-decrypt_public(CipherText, N,E, Options) ->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
-
path_validation([], #path_validation_state{working_public_key_algorithm
= Algorithm,
working_public_key =
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index cfd8e7a34b..878489eb0f 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -44,7 +44,9 @@ all() ->
encrypt_decrypt,
{group, sign_verify},
pkix, pkix_countryname, pkix_emailaddress, pkix_path_validation,
- pkix_iso_rsa_oid, pkix_iso_dsa_oid, pkix_crl, general_name,
+ pkix_iso_rsa_oid, pkix_iso_dsa_oid,
+ pkix_dsa_sha2_oid,
+ pkix_crl, general_name,
pkix_verify_hostname_cn,
pkix_verify_hostname_subjAltName,
pkix_verify_hostname_subjAltName_IP,
@@ -718,12 +720,8 @@ encrypt_decrypt(Config) when is_list(Config) ->
Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")),
RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),
- Msg = public_key:decrypt_public(RsaEncrypted, PrivateKey),
RsaEncrypted2 = public_key:encrypt_public(Msg, PublicKey),
- RsaEncrypted3 = public_key:encrypt_public(Msg, PrivateKey),
Msg = public_key:decrypt_private(RsaEncrypted2, PrivateKey),
- Msg = public_key:decrypt_private(RsaEncrypted3, PrivateKey),
-
ok.
%%--------------------------------------------------------------------
@@ -1118,6 +1116,13 @@ pkix_iso_dsa_oid(Config) when is_list(Config) ->
{_, dsa} = public_key:pkix_sign_types(SigAlg#'SignatureAlgorithm'.algorithm).
%%--------------------------------------------------------------------
+pkix_dsa_sha2_oid() ->
+ [{doc, "Test support dsa_sha2 oid"}].
+pkix_dsa_sha2_oid(Config) when is_list(Config) ->
+ {sha224, dsa} = public_key:pkix_sign_types(?'id-dsa-with-sha224'),
+ {sha256, dsa} = public_key:pkix_sign_types(?'id-dsa-with-sha256').
+
+%%--------------------------------------------------------------------
pkix_crl() ->
[{doc, "test pkix_crl_* functions"}].
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index f7faadb8fb..c68806d856 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.6
+PUBLIC_KEY_VSN = 1.6.6
diff --git a/lib/reltool/doc/src/Makefile b/lib/reltool/doc/src/Makefile
index e378cdf980..dce8059616 100644
--- a/lib/reltool/doc/src/Makefile
+++ b/lib/reltool/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -88,6 +88,7 @@ clean clean_docs:
fi \
done
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index 52419259c6..165ae6db6a 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -38,7 +38,40 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.7.6</title>
+ <section><title>Reltool 0.7.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Reltool would earlier erroneously split paths like
+ <c>"c:\foo"</c> into <c>["c","\foo"]</c> when reading the
+ <c>$ERL_LIBS</c> variable on windows. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-15454</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.7.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.7.6</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 5bfbee966b..5afbad0ba8 100644
--- a/lib/reltool/doc/src/reltool.xml
+++ b/lib/reltool/doc/src/reltool.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -33,7 +33,7 @@
<date></date>
<rev>%VSN%</rev>
</header>
- <module>reltool</module>
+ <module since="">reltool</module>
<modulesummary>Main API of the Reltool application</modulesummary>
<description>
<p>This is an interface module for the Reltool application.</p>
@@ -591,7 +591,7 @@ target_spec() = [target_spec()]
<funcs>
<func>
- <name>create_target(Server, TargetDir) -> ok | {error, Reason}</name>
+ <name since="">create_target(Server, TargetDir) -> ok | {error, Reason}</name>
<fsummary>Create a target system</fsummary>
<type>
<v>Server = server()</v>
@@ -604,7 +604,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>eval_target_spec(TargetSpec, RootDir, TargetDir) -> ok | {error, Reason}</name>
+ <name since="">eval_target_spec(TargetSpec, RootDir, TargetDir) -> ok | {error, Reason}</name>
<fsummary>Create a target system</fsummary>
<type>
<v>TargetSpec = target_spec()</v>
@@ -655,7 +655,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_config(Server) -> {ok, Config} | {error, Reason}</name>
+ <name since="">get_config(Server) -> {ok, Config} | {error, Reason}</name>
<fsummary>Get reltool configuration</fsummary>
<type>
<v>Server = server()</v>
@@ -667,7 +667,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_config(Server, InclDefaults, InclDerived) -> {ok, Config} | {error, Reason}</name>
+ <name since="">get_config(Server, InclDefaults, InclDerived) -> {ok, Config} | {error, Reason}</name>
<fsummary>Get reltool configuration</fsummary>
<type>
<v>Server = server()</v>
@@ -685,7 +685,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_rel(Server, Relname) -> {ok, RelFile} | {error, Reason}</name>
+ <name since="">get_rel(Server, Relname) -> {ok, RelFile} | {error, Reason}</name>
<fsummary>Get contents of a release file</fsummary>
<type>
<v>Server = server()</v>
@@ -698,7 +698,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_script(Server, Relname) -> {ok, ScriptFile | {error, Reason}</name>
+ <name since="">get_script(Server, Relname) -> {ok, ScriptFile | {error, Reason}</name>
<fsummary>Get contents of a boot script file</fsummary>
<type>
<v>Server = server()</v>
@@ -711,7 +711,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_status(Server) -> {ok, [Warning]} | {error, Reason}</name>
+ <name since="OTP R14B">get_status(Server) -> {ok, [Warning]} | {error, Reason}</name>
<fsummary>Get contents of a release file</fsummary>
<type>
<v>Server = server()</v>
@@ -722,7 +722,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_server(WindowPid) -> {ok, ServerPid} | {error, Reason}</name>
+ <name since="">get_server(WindowPid) -> {ok, ServerPid} | {error, Reason}</name>
<fsummary>Start server process with options</fsummary>
<type>
<v>WindowPid = window_pid()</v>
@@ -733,7 +733,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>get_target_spec(Server) -> {ok, TargetSpec} | {error, Reason}</name>
+ <name since="">get_target_spec(Server) -> {ok, TargetSpec} | {error, Reason}</name>
<fsummary>Return a specification of the target system</fsummary>
<type>
<v>Server = server()</v>
@@ -747,7 +747,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>install(RelName, TargetDir) -> ok | {error, Reason}</name>
+ <name since="">install(RelName, TargetDir) -> ok | {error, Reason}</name>
<fsummary>Install a target system</fsummary>
<type>
<v>RelName = rel_name()</v>
@@ -758,7 +758,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>start() -> {ok, WindowPid} | {error, Reason}</name>
+ <name since="">start() -> {ok, WindowPid} | {error, Reason}</name>
<fsummary>Start main window process</fsummary>
<type>
<v>WindowPid = window_pid()</v>
@@ -768,7 +768,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>start(Options) -> {ok, WindowPid} | {error, Reason}</name>
+ <name since="">start(Options) -> {ok, WindowPid} | {error, Reason}</name>
<fsummary>Start main window process with options</fsummary>
<type>
<v>Options = options()</v>
@@ -779,7 +779,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>start_link(Options) -> {ok, WindowPid} | {error, Reason}</name>
+ <name since="">start_link(Options) -> {ok, WindowPid} | {error, Reason}</name>
<fsummary>Start main window process with options</fsummary>
<type>
<v>Options = options()</v>
@@ -790,7 +790,7 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>start_server(Options) -> {ok, ServerPid} | {error, Reason}</name>
+ <name since="">start_server(Options) -> {ok, ServerPid} | {error, Reason}</name>
<fsummary>Start server process with options</fsummary>
<type>
<v>Options = options()</v>
@@ -803,10 +803,10 @@ target_spec() = [target_spec()]
</func>
<func>
- <name>stop(Pid) -> ok | {error, Reason}</name>
+ <name since="">stop(Pid) -> ok | {error, Reason}</name>
<fsummary>Stop a server or window process</fsummary>
<type>
- <v>Pid = server_pid() | window_pid()()</v>
+ <v>Pid = server_pid() | window_pid()</v>
<v>Reason = reason()</v>
</type>
<desc><p>Stop a server or window process</p></desc>
diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl
index 060a0912f9..2afa386cb3 100644
--- a/lib/reltool/src/reltool_utils.erl
+++ b/lib/reltool/src/reltool_utils.erl
@@ -47,6 +47,9 @@
call/2, cast/2, reply/3]).
+%% For testing
+-export([erl_libs/2]).
+
-include_lib("kernel/include/file.hrl").
-include_lib("wx/include/wx.hrl").
-include("reltool.hrl").
@@ -55,7 +58,15 @@ root_dir() ->
code:root_dir().
erl_libs() ->
- string:lexemes(os:getenv("ERL_LIBS", ""), ":;").
+ erl_libs(os:getenv("ERL_LIBS", ""), os:type()).
+
+erl_libs(ErlLibs, OsType) when is_list(ErlLibs) ->
+ Sep =
+ case OsType of
+ {win32, _} -> ";";
+ _ -> ":"
+ end,
+ string:lexemes(ErlLibs, Sep).
lib_dirs(Dir) ->
case erl_prim_loader:list_dir(Dir) of
diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index 4e1937d479..9ee61b595d 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -142,7 +142,8 @@ all() ->
use_selected_vsn,
use_selected_vsn_relative_path,
non_standard_vsn_id,
- undefined_regexp].
+ undefined_regexp,
+ windows_erl_libs].
groups() ->
[].
@@ -2546,10 +2547,21 @@ undefined_regexp(_Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Checks that reltool_utils can correctly read Windows ERL_LIBS
+
+windows_erl_libs(_Config) ->
+ WinErlLibs =
+ "C:\\Program Files\\Erlang Libs;C:\\Program Files\\More Erlang Libs",
+ Ret = reltool_utils:erl_libs(WinErlLibs, {win32, nt}),
+ ?m(["C:\\Program Files\\Erlang Libs","C:\\Program Files\\More Erlang Libs"],
+ Ret),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Library functions
erl_libs() ->
- string:lexemes(os:getenv("ERL_LIBS", ""), ":;").
+ reltool_utils:erl_libs().
datadir(Config) ->
%% Removes the trailing slash...
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index c698790ede..a649a3e0c0 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.7.6
+RELTOOL_VSN = 0.7.8
diff --git a/lib/runtime_tools/doc/src/Makefile b/lib/runtime_tools/doc/src/Makefile
index b788ef55ff..2399ed51e0 100644
--- a/lib/runtime_tools/doc/src/Makefile
+++ b/lib/runtime_tools/doc/src/Makefile
@@ -120,6 +120,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index 3262cafefc..941a880778 100644
--- a/lib/runtime_tools/doc/src/dbg.xml
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>dbg.sgml</file>
</header>
- <module>dbg</module>
+ <module since="">dbg</module>
<modulesummary>The Text Based Trace Facility</modulesummary>
<description>
<p>This module implements a text based interface to the
@@ -68,7 +68,7 @@
</description>
<funcs>
<func>
- <name>fun2ms(LiteralFun) -> MatchSpec</name>
+ <name since="">fun2ms(LiteralFun) -> MatchSpec</name>
<fsummary>Pseudo function that transforms fun syntax to match_spec.</fsummary>
<type>
<v>LiteralFun = fun() literal</v>
@@ -145,14 +145,14 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>h() -> ok </name>
+ <name since="">h() -> ok </name>
<fsummary>Give a list of available help items on standard output.</fsummary>
<desc>
<p>Gives a list of items for brief online help.</p>
</desc>
</func>
<func>
- <name>h(Item) -> ok </name>
+ <name since="">h(Item) -> ok </name>
<fsummary>Give brief help for an item.</fsummary>
<type>
<v>Item = atom()</v>
@@ -163,14 +163,14 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>p(Item) -> {ok, MatchDesc} | {error, term()} </name>
+ <name since="">p(Item) -> {ok, MatchDesc} | {error, term()} </name>
<fsummary>Trace messages to and from Item.</fsummary>
<desc>
<p>Equivalent to <c>p(Item, [m])</c>.</p>
</desc>
</func>
<func>
- <name>p(Item, Flags) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="">p(Item, Flags) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Trace Item according to Flags.</fsummary>
<type>
<v>MatchDesc = [MatchNum]</v>
@@ -303,14 +303,14 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>c(Mod, Fun, Args)</name>
+ <name since="">c(Mod, Fun, Args)</name>
<fsummary>Evaluate <c>apply(M,F,Args)</c>with <c>all</c>trace flags set.</fsummary>
<desc>
<p>Equivalent to <c>c(Mod, Fun, Args, all)</c>.</p>
</desc>
</func>
<func>
- <name>c(Mod, Fun, Args, Flags)</name>
+ <name since="">c(Mod, Fun, Args, Flags)</name>
<fsummary>Evaluate <c>apply(M,F,Args)</c>with <c>Flags</c>trace flags set.</fsummary>
<desc>
<p>Evaluates the expression <c>apply(Mod, Fun, Args)</c> with the trace
@@ -319,35 +319,35 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>i() -> ok</name>
+ <name since="">i() -> ok</name>
<fsummary>Display information about all traced processes and ports.</fsummary>
<desc>
<p>Displays information about all traced processes and ports.</p>
</desc>
</func>
<func>
- <name>tp(Module,MatchSpec)</name>
+ <name since="">tp(Module,MatchSpec)</name>
<fsummary>Set pattern for traced global function calls</fsummary>
<desc>
<p>Same as tp({Module, '_', '_'}, MatchSpec)</p>
</desc>
</func>
<func>
- <name>tp(Module,Function,MatchSpec)</name>
+ <name since="">tp(Module,Function,MatchSpec)</name>
<fsummary>Set pattern for traced global function calls</fsummary>
<desc>
<p>Same as tp({Module, Function, '_'}, MatchSpec)</p>
</desc>
</func>
<func>
- <name>tp(Module, Function, Arity, MatchSpec)</name>
+ <name since="">tp(Module, Function, Arity, MatchSpec)</name>
<fsummary>Set pattern for traced global function calls</fsummary>
<desc>
<p>Same as tp({Module, Function, Arity}, MatchSpec)</p>
</desc>
</func>
<func>
- <name>tp({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="">tp({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Set pattern for traced global function calls</fsummary>
<type>
<v>Module = atom() | '_'</v>
@@ -410,28 +410,28 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>tpl(Module,MatchSpec)</name>
+ <name since="">tpl(Module,MatchSpec)</name>
<fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
<desc>
<p>Same as tpl({Module, '_', '_'}, MatchSpec)</p>
</desc>
</func>
<func>
- <name>tpl(Module,Function,MatchSpec)</name>
+ <name since="">tpl(Module,Function,MatchSpec)</name>
<fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
<desc>
<p>Same as tpl({Module, Function, '_'}, MatchSpec)</p>
</desc>
</func>
<func>
- <name>tpl(Module, Function, Arity, MatchSpec)</name>
+ <name since="">tpl(Module, Function, Arity, MatchSpec)</name>
<fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
<desc>
<p>Same as tpl({Module, Function, Arity}, MatchSpec)</p>
</desc>
</func>
<func>
- <name>tpl({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="">tpl({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
<desc>
<p>This function works as <seealso marker="#tp-2"><c>tp/2</c></seealso>, but enables
@@ -442,7 +442,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
<func>
- <name>tpe(Event, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="OTP 19.0">tpe(Event, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Set pattern for traced event</fsummary>
<type>
<v>Event = send | 'receive'</v>
@@ -484,35 +484,35 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>ctp()</name>
+ <name since="">ctp()</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctp({'_', '_', '_'})</p>
</desc>
</func>
<func>
- <name>ctp(Module)</name>
+ <name since="">ctp(Module)</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctp({Module, '_', '_'})</p>
</desc>
</func>
<func>
- <name>ctp(Module, Function)</name>
+ <name since="">ctp(Module, Function)</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctp({Module, Function, '_'})</p>
</desc>
</func>
<func>
- <name>ctp(Module, Function, Arity)</name>
+ <name since="">ctp(Module, Function, Arity)</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctp({Module, Function, Arity})</p>
</desc>
</func>
<func>
- <name>ctp({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="">ctp({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<type>
<v>Module = atom() | '_'</v>
@@ -533,35 +533,35 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>ctpl()</name>
+ <name since="">ctpl()</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpl({'_', '_', '_'})</p>
</desc>
</func>
<func>
- <name>ctpl(Module)</name>
+ <name since="">ctpl(Module)</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpl({Module, '_', '_'})</p>
</desc>
</func>
<func>
- <name>ctpl(Module, Function)</name>
+ <name since="">ctpl(Module, Function)</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpl({Module, Function, '_'})</p>
</desc>
</func>
<func>
- <name>ctpl(Module, Function, Arity)</name>
+ <name since="">ctpl(Module, Function, Arity)</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpl({Module, Function, Arity})</p>
</desc>
</func>
<func>
- <name>ctpl({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="">ctpl({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>This function works as <seealso marker="#ctp-1"><c>ctp/1</c></seealso>, but only disables
@@ -570,35 +570,35 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>ctpg()</name>
+ <name since="">ctpg()</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpg({'_', '_', '_'})</p>
</desc>
</func>
<func>
- <name>ctpg(Module)</name>
+ <name since="">ctpg(Module)</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpg({Module, '_', '_'})</p>
</desc>
</func>
<func>
- <name>ctpg(Module, Function)</name>
+ <name since="">ctpg(Module, Function)</name>
<fsummary>>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpg({Module, Function, '_'})</p>
</desc>
</func>
<func>
- <name>ctpg(Module, Function, Arity)</name>
+ <name since="">ctpg(Module, Function, Arity)</name>
<fsummary>>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>Same as ctpg({Module, Function, Arity})</p>
</desc>
</func>
<func>
- <name>ctpg({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="">ctpg({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Clear call trace pattern for the specified functions</fsummary>
<desc>
<p>This function works as <seealso marker="#ctp-1"><c>ctp/1</c></seealso>, but only disables
@@ -607,7 +607,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>ctpe(Event) -> {ok, MatchDesc} | {error, term()}</name>
+ <name since="OTP 19.0">ctpe(Event) -> {ok, MatchDesc} | {error, term()}</name>
<fsummary>Clear trace pattern for the specified event</fsummary>
<type>
<v>Event = send | 'receive'</v>
@@ -623,7 +623,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>ltp() -> ok</name>
+ <name since="">ltp() -> ok</name>
<fsummary>List saved and built-in match specifications on the console.</fsummary>
<desc>
<p>Use this function to recall all match specifications previously
@@ -654,7 +654,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>dtp() -> ok</name>
+ <name since="">dtp() -> ok</name>
<fsummary>Delete all saved match specifications.</fsummary>
<desc>
<p>Use this function to "forget" all match specifications
@@ -665,7 +665,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>dtp(N) -> ok</name>
+ <name since="">dtp(N) -> ok</name>
<fsummary>Delete a specific saved match_spec.</fsummary>
<type>
<v>N = integer()</v>
@@ -676,7 +676,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>wtp(Name) -> ok | {error, IOError}</name>
+ <name since="">wtp(Name) -> ok | {error, IOError}</name>
<fsummary>Write all saved and built-in match specifications to a file</fsummary>
<type>
<v>Name = string()</v>
@@ -699,7 +699,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>rtp(Name) -> ok | {error, Error}</name>
+ <name since="">rtp(Name) -> ok | {error, Error}</name>
<fsummary>Read saved match specifications from file.</fsummary>
<type>
<v>Name = string()</v>
@@ -728,7 +728,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>n(Nodename) -> {ok, Nodename} | {error, Reason}</name>
+ <name since="">n(Nodename) -> {ok, Nodename} | {error, Reason}</name>
<fsummary>Add a remote node to the list of traced nodes</fsummary>
<type>
<v>Nodename = atom()</v>
@@ -767,7 +767,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>cn(Nodename) -> ok</name>
+ <name since="">cn(Nodename) -> ok</name>
<fsummary>Clear a node from the list of traced nodes.</fsummary>
<type>
<v>Nodename = atom()</v>
@@ -782,14 +782,14 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>ln() -> ok</name>
+ <name since="">ln() -> ok</name>
<fsummary>Show the list of traced nodes on the console.</fsummary>
<desc>
<p>Shows the list of traced nodes on the console.</p>
</desc>
</func>
<func>
- <name>tracer() -> {ok, pid()} | {error, already_started}</name>
+ <name since="">tracer() -> {ok, pid()} | {error, already_started}</name>
<fsummary>Start a tracer server that handles trace messages.</fsummary>
<desc>
<p>This function starts a server on the local node that will
@@ -805,7 +805,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>tracer(Type, Data) -> {ok, pid()} | {error, Error}</name>
+ <name since="">tracer(Type, Data) -> {ok, pid()} | {error, Error}</name>
<fsummary>Start a tracer server with additional parameters</fsummary>
<type>
<v>Type = port | process | module</v>
@@ -859,7 +859,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>tracer(Nodename, Type, Data) -> {ok, Nodename} | {error, Reason}</name>
+ <name since="">tracer(Nodename, Type, Data) -> {ok, Nodename} | {error, Reason}</name>
<fsummary>Start a tracer server on given node with additional parameters</fsummary>
<type>
<v>Nodename = atom()</v>
@@ -881,7 +881,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>trace_port(Type, Parameters) -> fun()</name>
+ <name since="">trace_port(Type, Parameters) -> fun()</name>
<fsummary>Create and returns a trace port generating<em>fun</em></fsummary>
<type>
<v>Type = ip | file</v>
@@ -958,28 +958,28 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>flush_trace_port()</name>
+ <name since="">flush_trace_port()</name>
<fsummary>Equivalent to flush_trace_port(node()).</fsummary>
<desc>
<p>Equivalent to <c>flush_trace_port(node())</c>.</p>
</desc>
</func>
<func>
- <name>flush_trace_port(Nodename) -> ok | {error, Reason}</name>
+ <name since="">flush_trace_port(Nodename) -> ok | {error, Reason}</name>
<fsummary>Flush internal data buffers in a trace driver on the given node.</fsummary>
<desc>
<p>Equivalent to <c>trace_port_control(Nodename,flush)</c>.</p>
</desc>
</func>
<func>
- <name>trace_port_control(Operation)</name>
+ <name since="">trace_port_control(Operation)</name>
<fsummary>Equivalent to trace_port_control(node(),Operation).</fsummary>
<desc>
<p>Equivalent to <c>trace_port_control(node(),Operation)</c>.</p>
</desc>
</func>
<func>
- <name>trace_port_control(Nodename,Operation) -> ok | {ok, Result} | {error, Reason}</name>
+ <name since="">trace_port_control(Nodename,Operation) -> ok | {ok, Result} | {error, Reason}</name>
<fsummary>Perform a control operation on the active trace port driver on the given node.</fsummary>
<type>
<v>Nodename = atom()</v>
@@ -1013,7 +1013,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
</desc>
</func>
<func>
- <name>trace_client(Type, Parameters) -> pid()</name>
+ <name since="">trace_client(Type, Parameters) -> pid()</name>
<fsummary>Start a trace client that reads messages created by a trace port driver</fsummary>
<type>
<v>Type = ip | file | follow_file</v>
@@ -1080,7 +1080,7 @@ hello</pre>
</desc>
</func>
<func>
- <name>trace_client(Type, Parameters, HandlerSpec) -> pid()</name>
+ <name since="">trace_client(Type, Parameters, HandlerSpec) -> pid()</name>
<fsummary>Start a trace client that reads messages created by a trace port driver, with a user defined handler</fsummary>
<type>
<v>Type = ip | file | follow_file</v>
@@ -1110,7 +1110,7 @@ hello</pre>
</desc>
</func>
<func>
- <name>stop_trace_client(Pid) -> ok</name>
+ <name since="">stop_trace_client(Pid) -> ok</name>
<fsummary>Stop a trace client gracefully.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -1123,14 +1123,14 @@ hello</pre>
</desc>
</func>
<func>
- <name>get_tracer()</name>
+ <name since="">get_tracer()</name>
<fsummary>Equivalent to get_tracer(node()).</fsummary>
<desc>
<p>Equivalent to <c>get_tracer(node())</c>.</p>
</desc>
</func>
<func>
- <name>get_tracer(Nodename) -> {ok, Tracer}</name>
+ <name since="">get_tracer(Nodename) -> {ok, Tracer}</name>
<fsummary>Return the process or port to which all trace messages are sent.</fsummary>
<type>
<v>Nodename = atom()</v>
@@ -1142,7 +1142,7 @@ hello</pre>
</desc>
</func>
<func>
- <name>stop() -> ok</name>
+ <name since="">stop() -> ok</name>
<fsummary>Stop the <c>dbg</c>server and the tracing of all processes.</fsummary>
<desc>
<p>Stops the <c>dbg</c> server and clears all trace flags for
@@ -1153,7 +1153,7 @@ hello</pre>
</desc>
</func>
<func>
- <name>stop_clear() -> ok</name>
+ <name since="">stop_clear() -> ok</name>
<fsummary>Stop the <c>dbg</c>server and the tracing of all processes, and clears trace patterns.</fsummary>
<desc>
<p>Same as stop/0, but also clears all trace patterns on global functions calls.</p>
diff --git a/lib/runtime_tools/doc/src/dyntrace.xml b/lib/runtime_tools/doc/src/dyntrace.xml
index 0cdcecab68..4935dfcd71 100644
--- a/lib/runtime_tools/doc/src/dyntrace.xml
+++ b/lib/runtime_tools/doc/src/dyntrace.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>dyntrace.xml</file>
</header>
- <module>dyntrace</module>
+ <module since="OTP R15B01">dyntrace</module>
<modulesummary>Interface to dynamic tracing</modulesummary>
<description>
<p>This module implements interfaces to dynamic tracing, should such be compiled into the virtual machine. For a standard and/or commercial build, no dynamic tracing is available, in which case none of the functions in this module is usable or give any effect.</p>
@@ -47,7 +47,7 @@
</description>
<funcs>
<func>
- <name>available() -> boolean()</name>
+ <name since="OTP R15B01">available() -> boolean()</name>
<fsummary>Check if dynamic tracing is available</fsummary>
<desc>
<p>This function uses the NIF library to determine if dynamic
@@ -59,42 +59,42 @@
</desc>
</func>
<func>
- <name>p() -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p() -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message only containing the user tag and zeroes/empty strings in all other fields.</p>
</desc>
</func>
<func>
- <name>p(integer() | string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer() | string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer or string parameter in the first integer/string field.</p>
</desc>
</func>
<func>
- <name>p(integer() | string(), integer() | string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer() | string(), integer() | string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters. I.e. <c>p(1,"Hello")</c> is ok, as is <c>p(1,1)</c> and <c>p("Hello","Again")</c>, but not <c>p("Hello",1)</c>.</p>
</desc>
</func>
<func>
- <name>p(integer() | string(), integer() | string(), integer() | string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer() | string(), integer() | string(), integer() | string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
</desc>
</func>
<func>
- <name>p(integer() | string(), integer() | string(), integer() | string(), integer() | string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer() | string(), integer() | string(), integer() | string(), integer() | string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
</desc>
</func>
<func>
- <name>p(integer(), integer() | string(), integer() | string(), integer() | string(), string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer(), integer() | string(), integer() | string(), integer() | string(), string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
@@ -102,7 +102,7 @@
</desc>
</func>
<func>
- <name>p(integer(), integer(), integer() | string(), integer() | string(), string(), string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer(), integer(), integer() | string(), integer() | string(), string(), string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
@@ -110,7 +110,7 @@
</desc>
</func>
<func>
- <name>p(integer(), integer(), integer(), integer() | string(), string(), string(), string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer(), integer(), integer(), integer() | string(), string(), string(), string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing the user tag and the integer() or string() parameters as the first fields of respective type. integer() parameters should be put before any string() parameters, as in <seealso marker="#p/2">p/2</seealso>.</p>
@@ -118,14 +118,14 @@
</desc>
</func>
<func>
- <name>p(integer(), integer(), integer(), integer(), string(), string(), string(), string()) -> true | false | error | badarg</name>
+ <name since="OTP R15B01">p(integer(), integer(), integer(), integer(), string(), string(), string(), string()) -> true | false | error | badarg</name>
<fsummary>Trigger the user trace probe.</fsummary>
<desc>
<p>Calling this function will trigger the "user" trace probe user_trace_i4s4 in the dyntrace NIF module, sending a trace message containing all the integer()'s and string()'s provided, as well as any user tag set in the current process.</p>
</desc>
</func>
<func>
- <name>get_tag() -> binary() | undefined</name>
+ <name since="OTP R15B01">get_tag() -> binary() | undefined</name>
<fsummary>Get the user tag set in the process.</fsummary>
<desc>
<p>This function returns the user tag set in the current
@@ -134,7 +134,7 @@
</desc>
</func>
<func>
- <name>get_tag() -> binary() | undefined</name>
+ <name since="OTP R15B01">get_tag() -> binary() | undefined</name>
<fsummary>Get the user tag set in the process or sent to the process.</fsummary>
<desc>
<p>This function returns the user tag set in the current
@@ -151,7 +151,7 @@
</func>
<func>
- <name>put_tag(Item) -> binary() | undefined </name>
+ <name since="OTP R15B01">put_tag(Item) -> binary() | undefined </name>
<fsummary>Set the user tag of the current process.</fsummary>
<type>
<v>Item = iodata()</v>
@@ -163,7 +163,7 @@
</desc>
</func>
<func>
- <name>spread_tag(boolean()) -> TagData</name>
+ <name since="OTP R15B01">spread_tag(boolean()) -> TagData</name>
<fsummary>Start or stop spreading dynamic trace user tags with the next message.</fsummary>
<type>
<v>TagData = opaque data that can be used as parameter to <seealso marker="#restore_tag/1">restore_tag/1</seealso></v>
@@ -185,7 +185,7 @@ f() ->
</desc>
</func>
<func>
- <name>restore_tag(TagData) -> true</name>
+ <name since="OTP R15B01">restore_tag(TagData) -> true</name>
<fsummary>Restore to a previous state of user tag spreading.</fsummary>
<type>
<v>TagData = opaque data returned by <seealso marker="#spread_tag/1">spread_tag/1</seealso></v>
diff --git a/lib/runtime_tools/doc/src/erts_alloc_config.xml b/lib/runtime_tools/doc/src/erts_alloc_config.xml
index ffc4ec5285..5bcce1b5e3 100644
--- a/lib/runtime_tools/doc/src/erts_alloc_config.xml
+++ b/lib/runtime_tools/doc/src/erts_alloc_config.xml
@@ -29,7 +29,7 @@
<rev>1</rev>
<file>erts_alloc_config.sgml</file>
</header>
- <module>erts_alloc_config</module>
+ <module since="">erts_alloc_config</module>
<modulesummary>Configuration tool for erts_alloc</modulesummary>
<description>
<note>
@@ -136,7 +136,7 @@
</description>
<funcs>
<func>
- <name>save_scenario() -> ok | {error, Error}</name>
+ <name since="">save_scenario() -> ok | {error, Error}</name>
<fsummary>Saves information about current runtime scenario</fsummary>
<type>
<v>Error = term()</v>
@@ -154,7 +154,7 @@
</desc>
</func>
<func>
- <name>make_config() -> ok | {error, Error}</name>
+ <name since="">make_config() -> ok | {error, Error}</name>
<fsummary>Creates an erts_alloc configuration</fsummary>
<type>
<v>Error = term()</v>
@@ -165,7 +165,7 @@
</desc>
</func>
<func>
- <name>make_config(FileNameOrIODev) -> ok | {error, Error}</name>
+ <name since="">make_config(FileNameOrIODev) -> ok | {error, Error}</name>
<fsummary>Creates an erts_alloc configuration</fsummary>
<type>
<v>FileNameOrIODev = string() | io_device()</v>
@@ -190,7 +190,7 @@
</desc>
</func>
<func>
- <name>stop() -> ok | {error, Error}</name>
+ <name since="">stop() -> ok | {error, Error}</name>
<fsummary></fsummary>
<type>
<v>Error = term()</v>
diff --git a/lib/runtime_tools/doc/src/msacc.xml b/lib/runtime_tools/doc/src/msacc.xml
index 129da3d230..ae089de8d0 100644
--- a/lib/runtime_tools/doc/src/msacc.xml
+++ b/lib/runtime_tools/doc/src/msacc.xml
@@ -31,7 +31,7 @@
<rev>A</rev>
<file>msacc.xml</file>
</header>
- <module>msacc</module>
+ <module since="OTP 19.0">msacc</module>
<modulesummary>Convenience functions for microstate accounting</modulesummary>
<description>
<p>This module implements some convenience functions for analyzing
@@ -146,7 +146,7 @@ ok
</datatypes>
<funcs>
<func>
- <name name="available" arity="0"/>
+ <name name="available" arity="0" since="OTP 19.0"/>
<fsummary>Check if microstate accounting is available</fsummary>
<desc>
<p>This function checks whether microstate accounting
@@ -154,7 +154,7 @@ ok
</desc>
</func>
<func>
- <name name="start" arity="0"/>
+ <name name="start" arity="0" since="OTP 19.0"/>
<fsummary>Start microstate accounting.</fsummary>
<desc>
<p>Start microstate accounting. Returns whether it was
@@ -162,7 +162,7 @@ ok
</desc>
</func>
<func>
- <name name="start" arity="1"/>
+ <name name="start" arity="1" since="OTP 19.0"/>
<fsummary>Start microstate accounting for a time.</fsummary>
<desc>
<p>Resets all counters and then starts microstate accounting
@@ -170,7 +170,7 @@ ok
</desc>
</func>
<func>
- <name name="stop" arity="0"/>
+ <name name="stop" arity="0" since="OTP 19.0"/>
<fsummary>Stop microstate accounting.</fsummary>
<desc>
<p>Stop microstate accounting.
@@ -178,7 +178,7 @@ ok
</desc>
</func>
<func>
- <name name="reset" arity="0"/>
+ <name name="reset" arity="0" since="OTP 19.0"/>
<fsummary>Reset microstate accounting counters</fsummary>
<desc>
<p>Reset microstate accounting counters.
@@ -186,7 +186,7 @@ ok
</desc>
</func>
<func>
- <name name="print" arity="0"/>
+ <name name="print" arity="0" since="OTP 19.0"/>
<fsummary>Print microstate statistics</fsummary>
<desc>
<p>
@@ -199,7 +199,7 @@ ok
</desc>
</func>
<func>
- <name name="print" arity="1"/>
+ <name name="print" arity="1" since="OTP 19.0"/>
<fsummary>Print microstate statistics</fsummary>
<desc>
<p>Print the given microstate statistics values to stdout.
@@ -211,7 +211,7 @@ ok
</desc>
</func>
<func>
- <name name="print" arity="2"/>
+ <name name="print" arity="2" since="OTP 19.0"/>
<fsummary>Print microstate statistics</fsummary>
<desc>
<p>Print the given microstate statistics values to standard out.
@@ -234,7 +234,7 @@ ok
</desc>
</func>
<func>
- <name name="print" arity="3"/>
+ <name name="print" arity="3" since="OTP 19.0"/>
<fsummary>Print microstate statistics</fsummary>
<desc>
<p>Print the given microstate statistics values to the given file
@@ -243,7 +243,7 @@ ok
</desc>
</func>
<func>
- <name name="stats" arity="0"/>
+ <name name="stats" arity="0" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a runtime system independent version of the microstate
@@ -254,7 +254,7 @@ ok
</desc>
</func>
<func>
- <name name="stats" arity="2" clause_i="1"/>
+ <name name="stats" arity="2" clause_i="1" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Returns the system time for the given microstate statistics values.
@@ -269,7 +269,7 @@ ok
</desc>
</func>
<func>
- <name name="stats" arity="2" clause_i="2"/>
+ <name name="stats" arity="2" clause_i="2" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Returns fractions of real-time or run-time spent in the various
@@ -277,7 +277,7 @@ ok
</desc>
</func>
<func>
- <name name="stats" arity="2" clause_i="3"/>
+ <name name="stats" arity="2" clause_i="3" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a list of microstate statistics values where the values
@@ -285,7 +285,7 @@ ok
</desc>
</func>
<func>
- <name name="to_file" arity="1"/>
+ <name name="to_file" arity="1" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Dumps the current microstate statistics counters to a file that can
@@ -294,7 +294,7 @@ ok
</desc>
</func>
<func>
- <name name="from_file" arity="1"/>
+ <name name="from_file" arity="1" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Read a file dump produced by <seealso marker="#to_file/1">
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 5692df2ab4..58a2a66c4b 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -32,6 +32,38 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.13.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update of systemtap trace example scripts.</p>
+ <p>
+ Own Id: OTP-15670</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.13.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Optimize <c>observer</c> by using new
+ <c>system_info(ets_count)</c> instead of more expensive
+ <c>length(ets:all())</c>.</p>
+ <p>
+ Own Id: OTP-15163 Aux Id: PR-1844 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.13</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/doc/src/scheduler.xml b/lib/runtime_tools/doc/src/scheduler.xml
index dd8bf73bae..b033430183 100644
--- a/lib/runtime_tools/doc/src/scheduler.xml
+++ b/lib/runtime_tools/doc/src/scheduler.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>scheduler.xml</file>
</header>
- <module>scheduler</module>
+ <module since="OTP 21.0">scheduler</module>
<modulesummary>Measure scheduler utilization</modulesummary>
<description>
<p>This module contains utility functions for easier measurement and
@@ -84,7 +84,7 @@
<funcs>
<func>
- <name name="sample" arity="0"/>
+ <name name="sample" arity="0" since="OTP 21.0"/>
<fsummary>Get scheduler utilization sample.</fsummary>
<desc>
<p>Return a scheduler utilization sample for normal and dirty-cpu
@@ -93,7 +93,7 @@
</func>
<func>
- <name name="sample_all" arity="0"/>
+ <name name="sample_all" arity="0" since="OTP 21.0"/>
<fsummary>Get scheduler utilization sample.</fsummary>
<desc>
<p>Return a scheduler utilization sample for all schedulers,
@@ -102,7 +102,7 @@
</func>
<func>
- <name name="utilization" arity="1" clause_i="1"/>
+ <name name="utilization" arity="1" clause_i="1" since="OTP 21.0"/>
<fsummary>Measure scheduler utilizations during a period of time.</fsummary>
<desc>
<p>Measure utilization for normal and dirty-cpu schedulers during
@@ -111,7 +111,7 @@
</func>
<func>
- <name name="utilization" arity="1" clause_i="2"/>
+ <name name="utilization" arity="1" clause_i="2" since="OTP 21.0"/>
<fsummary>Measure scheduler utilizations since sample.</fsummary>
<desc>
<p>Calculate scheduler utilizations for the time interval from when
@@ -121,7 +121,7 @@
</func>
<func>
- <name name="utilization" arity="2"/>
+ <name name="utilization" arity="2" since="OTP 21.0"/>
<fsummary>Measure scheduler utilizations between two samples.</fsummary>
<desc>
<p>Calculates scheduler utilizations for the time interval between
diff --git a/lib/runtime_tools/doc/src/system_information.xml b/lib/runtime_tools/doc/src/system_information.xml
index 53dc595e64..a356b5c6f8 100644
--- a/lib/runtime_tools/doc/src/system_information.xml
+++ b/lib/runtime_tools/doc/src/system_information.xml
@@ -32,14 +32,14 @@
<rev></rev>
<file>system_information.xml</file>
</header>
- <module>system_information</module>
+ <module since="OTP 17.0">system_information</module>
<modulesummary>System Information</modulesummary>
<description>
<p></p>
</description>
<funcs>
<func>
- <name name="sanity_check" arity="0"/>
+ <name name="sanity_check" arity="0" since="OTP 17.0"/>
<fsummary>Perform a sanity check</fsummary>
<desc>
<p>Performs a sanity check on the system. If no issues
@@ -88,7 +88,7 @@
</desc>
</func>
<func>
- <name name="to_file" arity="1"/>
+ <name name="to_file" arity="1" since="OTP 17.0"/>
<fsummary>Write miscellaneous system information to file</fsummary>
<desc><p>Writes miscellaneous system information to file. This
information will typically be requested by the Erlang/OTP team
diff --git a/lib/runtime_tools/examples/dist.systemtap b/lib/runtime_tools/examples/dist.systemtap
index bb20d617e1..4102a5243c 100644
--- a/lib/runtime_tools/examples/dist.systemtap
+++ b/lib/runtime_tools/examples/dist.systemtap
@@ -19,18 +19,18 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("dist-monitor")
+probe process("beam.smp").mark("dist-monitor")
{
printf("monitor: pid %d, who %s, what %s, node %s, type %s, reason %s\n",
pid(),
@@ -38,38 +38,38 @@ probe process("beam").mark("dist-monitor")
user_string($arg5));
}
-probe process("beam").mark("dist-port_busy")
+probe process("beam.smp").mark("dist-port_busy")
{
printf("dist port_busy: node %s, port %s, remote_node %s, blocked pid %s\n",
user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
- blocked_procs[user_string($arg4)] = timestamp;
+ blocked_procs[user_string($arg4)] = local_clock_ns();
}
-probe process("beam").mark("dist-port_busy")
+probe process("beam.smp").mark("dist-port_busy")
{
printf("dist port_busy: node %s, port %s, remote_node %s, blocked pid %s\n",
user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
- blocked_procs[user_string($arg4)] = timestamp;
+ blocked_procs[user_string($arg4)] = local_clock_ns();
}
-probe process("beam").mark("dist-output")
+probe process("beam.smp").mark("dist-output")
{
printf("dist output: node %s, port %s, remote_node %s bytes %d\n",
user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
}
-probe process("beam").mark("dist-outputv")
+probe process("beam.smp").mark("dist-outputv")
{
printf("port outputv: node %s, port %s, remote_node %s bytes %d\n",
user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
}
-probe process("beam").mark("process-scheduled")
+probe process("beam.smp").mark("process-scheduled")
{
pidstr = user_string($arg1);
if (pidstr in blocked_procs) {
printf("blocked pid %s scheduled now, waited %d microseconds\n",
- pidstr, (timestamp - blocked_procs[pidstr]) / 1000);
+ pidstr, (local_clock_ns() - blocked_procs[pidstr]) / 1000);
delete blocked_procs[pidstr];
}
}
diff --git a/lib/runtime_tools/examples/driver1.systemtap b/lib/runtime_tools/examples/driver1.systemtap
index e1ee8ecffc..f5bc28b42d 100644
--- a/lib/runtime_tools/examples/driver1.systemtap
+++ b/lib/runtime_tools/examples/driver1.systemtap
@@ -19,108 +19,102 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("driver-init")
+probe process("beam.smp").mark("driver__init")
{
printf("driver init name %s major %d minor %d flags %d\n",
user_string($arg1), $arg2, $arg3, $arg4);
}
-probe process("beam").mark("driver-start")
+probe process("beam.smp").mark("driver__start")
{
printf("driver start pid %s driver name %s port %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-stop")
+probe process("beam.smp").mark("driver__stop")
{
printf("driver stop pid %s driver name %s port %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-finish")
+probe process("beam.smp").mark("driver__finish")
{
printf("driver finish driver name %s\n",
user_string($arg1));
}
-probe process("beam").mark("driver-flush")
+probe process("beam.smp").mark("driver__flush")
{
printf("driver flush pid %s port %s port name %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-output")
+probe process("beam.smp").mark("driver__output")
{
printf("driver output pid %s port %s port name %s bytes %d\n",
user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
}
-probe process("beam").mark("driver-outputv")
+probe process("beam.smp").mark("driver__outputv")
{
printf("driver outputv pid %s port %s port name %s bytes %d\n",
user_string($arg1), user_string($arg2), user_string($arg3), $arg4);
}
-probe process("beam").mark("driver-control")
+probe process("beam.smp").mark("driver__control")
{
printf("driver control pid %s port %s port name %s command %d bytes %d\n",
user_string($arg1), user_string($arg2), user_string($arg3), $arg4, $arg5);
}
-probe process("beam").mark("driver-call")
+probe process("beam.smp").mark("driver__call")
{
printf("driver call pid %s port %s port name %s command %d bytes %d\n",
user_string($arg1), user_string($arg2), user_string($arg3), $arg4, $arg5);
}
-probe process("beam").mark("driver-event")
-{
- printf("driver event pid %s port %s port name %s\n",
- user_string($arg1), user_string($arg2), user_string($arg3));
-}
-
-probe process("beam").mark("driver-ready_input")
+probe process("beam.smp").mark("driver__ready_input")
{
printf("driver ready_input pid %s port %s port name %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-ready_output")
+probe process("beam.smp").mark("driver__ready_output")
{
printf("driver ready_output pid %s port %s port name %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-timeout")
+probe process("beam.smp").mark("driver__timeout")
{
printf("driver timeout pid %s port %s port name %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-ready_async")
+probe process("beam.smp").mark("driver__ready_async")
{
printf("driver ready_async pid %s port %s port name %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-process_exit")
+probe process("beam.smp").mark("driver__process_exit")
{
printf("driver process_exit pid %s port %s port name %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("driver-stop_select")
+probe process("beam.smp").mark("driver__stop_select")
{
printf("driver stop_select driver name %s\n", user_string($arg1));
}
diff --git a/lib/runtime_tools/examples/function-calls.systemtap b/lib/runtime_tools/examples/function-calls.systemtap
index 9c44b2d014..6bb173b3ec 100644
--- a/lib/runtime_tools/examples/function-calls.systemtap
+++ b/lib/runtime_tools/examples/function-calls.systemtap
@@ -18,51 +18,51 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("local-function-entry")
+probe process("beam.smp").mark("local-function-entry")
{
printf("pid %s enter (local) %s depth %d\n",
user_string($arg1), user_string($arg2), $arg3);
}
-probe process("beam").mark("global-function-entry")
+probe process("beam.smp").mark("global-function-entry")
{
printf("pid %s enter (global) %s depth %d\n",
user_string($arg1), user_string($arg2), $arg3);
}
-probe process("beam").mark("function-return")
+probe process("beam.smp").mark("function-return")
{
printf("pid %s return %s depth %d\n",
user_string($arg1), user_string($arg2), $arg3);
}
-probe process("beam").mark("bif-entry")
+probe process("beam.smp").mark("bif-entry")
{
printf("pid %s BIF entry mfa %s\n", user_string($arg1), user_string($arg2));
}
-probe process("beam").mark("bif-return")
+probe process("beam.smp").mark("bif-return")
{
printf("pid %s BIF return mfa %s\n", user_string($arg1), user_string($arg2));
}
-probe process("beam").mark("nif-entry")
+probe process("beam.smp").mark("nif-entry")
{
printf("pid %s NIF entry mfa %s\n", user_string($arg1), user_string($arg2));
}
-probe process("beam").mark("nif-return")
+probe process("beam.smp").mark("nif-return")
{
printf("pid %s NIF return mfa %s\n", user_string($arg1), user_string($arg2));
}
diff --git a/lib/runtime_tools/examples/garbage-collection.systemtap b/lib/runtime_tools/examples/garbage-collection.systemtap
index e414eea821..14f0d6851c 100644
--- a/lib/runtime_tools/examples/garbage-collection.systemtap
+++ b/lib/runtime_tools/examples/garbage-collection.systemtap
@@ -18,33 +18,33 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("gc_major-start")
+probe process("beam.smp").mark("gc_major-start")
{
printf("GC major start pid %s need %d words\n", user_string($arg1), $arg2);
}
-probe process("beam").mark("gc_minor-start")
+probe process("beam.smp").mark("gc_minor-start")
{
printf("GC minor start pid %s need %d words\n", user_string($arg1), $arg2);
}
-probe process("beam").mark("gc_major-end")
+probe process("beam.smp").mark("gc_major-end")
{
printf("GC major end pid %s reclaimed %d words\n", user_string($arg1), $arg2);
}
-probe process("beam").mark("gc_minor-start")
+probe process("beam.smp").mark("gc_minor-start")
{
printf("GC minor end pid %s reclaimed %d words\n", user_string($arg1), $arg2);
}
diff --git a/lib/runtime_tools/examples/memory1.systemtap b/lib/runtime_tools/examples/memory1.systemtap
index 04df4d64c4..2fdc5a796c 100644
--- a/lib/runtime_tools/examples/memory1.systemtap
+++ b/lib/runtime_tools/examples/memory1.systemtap
@@ -18,34 +18,34 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("copy-struct")
+probe process("beam.smp").mark("copy-struct")
{
printf("copy_struct %d bytes\n", $arg1);
}
-probe process("beam").mark("copy-object")
+probe process("beam.smp").mark("copy-object")
{
printf("copy_object pid %s %d bytes\n", user_string($arg1), $arg2);
}
-probe process("beam").mark("process-heap_grow")
+probe process("beam.smp").mark("process-heap_grow")
{
printf("proc heap grow pid %s %d -> %d bytes\n", user_string($arg1),
$arg2, $arg3);
}
-probe process("beam").mark("process-heap_shrink")
+probe process("beam.smp").mark("process-heap_shrink")
{
printf("proc heap shrink pid %s %d -> %d bytes\n", user_string($arg1),
$arg2, $arg3);
diff --git a/lib/runtime_tools/examples/messages.systemtap b/lib/runtime_tools/examples/messages.systemtap
index f2ef56a22b..49b7f46d69 100644
--- a/lib/runtime_tools/examples/messages.systemtap
+++ b/lib/runtime_tools/examples/messages.systemtap
@@ -18,15 +18,15 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
probe begin
@@ -38,7 +38,7 @@ probe begin
printf("\n");
}
-probe process("beam").mark("message-send")
+probe process("beam.smp").mark("message-send")
{
if ($arg4 == 0 && $arg5 == 0 && $arg6 == 0) {
printf("send: %s -> %s: %d words\n",
@@ -51,7 +51,7 @@ probe process("beam").mark("message-send")
}
}
-probe process("beam").mark("message-send-remote")
+probe process("beam.smp").mark("message-send-remote")
{
if ($arg5 == 0 && $arg6 == 0 && $arg7 == 0) {
printf("send : %s -> %s %s: %d words\n",
@@ -64,7 +64,7 @@ probe process("beam").mark("message-send-remote")
}
}
-probe process("beam").mark("message-queued")
+probe process("beam.smp").mark("message-queued")
{
if ($arg4 == 0 && $arg5 == 0 && $arg6 == 0) {
printf("queued: %s: %d words, queue len %d\n", user_string($arg1), $arg2, $arg3);
@@ -75,7 +75,7 @@ probe process("beam").mark("message-queued")
}
}
-probe process("beam").mark("message-receive")
+probe process("beam.smp").mark("message-receive")
{
if ($arg4 == 0 && $arg5 == 0 && $arg6 == 0) {
printf("receive: %s: %d words, queue len %d\n",
diff --git a/lib/runtime_tools/examples/port1.systemtap b/lib/runtime_tools/examples/port1.systemtap
index f7ce03a65e..235581b0b1 100644
--- a/lib/runtime_tools/examples/port1.systemtap
+++ b/lib/runtime_tools/examples/port1.systemtap
@@ -18,15 +18,15 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
probe begin
@@ -96,19 +96,19 @@ probe begin
driver_map["udp_inet", 62] = "BINDX";
}
-probe process("beam").mark("port-open")
+probe process("beam.smp").mark("port-open")
{
printf("port open pid %s port name %s port %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("port-command")
+probe process("beam.smp").mark("port-command")
{
printf("port command pid %s port %s port name %s command type %s\n",
user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
}
-probe process("beam").mark("port-control")
+probe process("beam.smp").mark("port-control")
{
cmd = driver_map[user_string($arg3), $arg4];
cmd_str = (cmd == "") ? "unknown" : cmd;
@@ -118,36 +118,36 @@ probe process("beam").mark("port-control")
/* port-exit is fired as a result of port_close() or exit signal */
-probe process("beam").mark("port-exit")
+probe process("beam.smp").mark("port-exit")
{
printf("port exit pid %s port %s port name %s reason %s\n",
user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
}
-probe process("beam").mark("port-connect")
+probe process("beam.smp").mark("port-connect")
{
printf("port connect pid %s port %s port name %s new pid %s\n",
user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
}
-probe process("beam").mark("port-busy")
+probe process("beam.smp").mark("port-busy")
{
printf("port busy %s\n", user_string($arg1));
}
-probe process("beam").mark("port-not_busy")
+probe process("beam.smp").mark("port-not_busy")
{
printf("port not busy %s\n", user_string($arg1));
}
-probe process("beam").mark("aio_pool-add")
+probe process("beam.smp").mark("aio_pool-add")
{
printf("async I/O pool add thread %d queue len %d\n", $arg1, $arg2);
}
-probe process("beam").mark("aio_pool-get")
+probe process("beam.smp").mark("aio_pool-get")
{
printf("async I/O pool get thread %d queue len %d\n", $arg1, $arg2);
}
-global driver_map; \ No newline at end of file
+global driver_map;
diff --git a/lib/runtime_tools/examples/process-scheduling.systemtap b/lib/runtime_tools/examples/process-scheduling.systemtap
index b0b74257b3..231c589f64 100644
--- a/lib/runtime_tools/examples/process-scheduling.systemtap
+++ b/lib/runtime_tools/examples/process-scheduling.systemtap
@@ -18,28 +18,28 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("process-scheduled")
+probe process("beam.smp").mark("process-scheduled")
{
printf(" Schedule pid %s mfa %s\n", user_string($arg1), user_string($arg2));
}
-probe process("beam").mark("process-unscheduled")
+probe process("beam.smp").mark("process-unscheduled")
{
printf("Unschedule pid %s\n", user_string($arg1));
}
-probe process("beam").mark("process-hibernate")
+probe process("beam.smp").mark("process-hibernate")
{
printf(" Hibernate pid %s resume mfa %s\n",
user_string($arg1), user_string($arg2));
diff --git a/lib/runtime_tools/examples/spawn-exit.systemtap b/lib/runtime_tools/examples/spawn-exit.systemtap
index 89bca14496..a7b4a0a3ea 100644
--- a/lib/runtime_tools/examples/spawn-exit.systemtap
+++ b/lib/runtime_tools/examples/spawn-exit.systemtap
@@ -18,34 +18,34 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("process-spawn")
+probe process("beam.smp").mark("process-spawn")
{
printf("pid %s mfa %s\n", user_string($arg1), user_string($arg2));
}
-probe process("beam").mark("process-exit")
+probe process("beam.smp").mark("process-exit")
{
printf("pid %s reason %s\n", user_string($arg1), user_string($arg2));
}
-probe process("beam").mark("process-exit_signal")
+probe process("beam.smp").mark("process-exit_signal")
{
printf("sender %s -> pid %s reason %s\n",
user_string($arg1), user_string($arg2), user_string($arg3));
}
-probe process("beam").mark("process-exit_signal-remote")
+probe process("beam.smp").mark("process-exit_signal-remote")
{
printf("sender %s -> node %s pid %s reason %s\n",
user_string($arg1), user_string($arg2), user_string($arg3), user_string($arg4));
diff --git a/lib/runtime_tools/examples/user-probe-n.systemtap b/lib/runtime_tools/examples/user-probe-n.systemtap
index 25f7503283..8a0a89c931 100644
--- a/lib/runtime_tools/examples/user-probe-n.systemtap
+++ b/lib/runtime_tools/examples/user-probe-n.systemtap
@@ -18,18 +18,19 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("user_trace-n0")
+
+probe process("beam.smp").mark("user_trace-n0")
{
printf("probe n0: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
user_string($arg1),
@@ -41,7 +42,7 @@ probe process("beam").mark("user_trace-n0")
$arg9 == NULL ? "" : user_string($arg9));
}
-probe process("beam").mark("user_trace-n1")
+probe process("beam.smp").mark("user_trace-n1")
{
printf("probe n1: %s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
user_string($arg1),
diff --git a/lib/runtime_tools/examples/user-probe.systemtap b/lib/runtime_tools/examples/user-probe.systemtap
index 1777476e54..ce9dde30f8 100644
--- a/lib/runtime_tools/examples/user-probe.systemtap
+++ b/lib/runtime_tools/examples/user-probe.systemtap
@@ -18,23 +18,23 @@
* %CopyrightEnd%
*/
/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
+ * Note: This file assumes that you're using the SMP-enabled Erlang
+ * virtual machine, "beam.smp".
* Note that other variations of the virtual machine also have
* different names, e.g. the debug build of the SMP-enabled VM
* is "beam.debug.smp".
*
* To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
+ * "beam.smp" with "beam.debug.smp" or the VM name appropriate
+ * to your environment.
*/
-probe process("beam").mark("user_trace-s1")
+probe process("beam.smp").mark("user_trace-s1")
{
printf("%s\n", user_string($arg1));
}
-probe process("beam").mark("user_trace-i4s4")
+probe process("beam.smp").mark("user_trace-i4s4")
{
printf("%s %s %d %d %d %d '%s' '%s' '%s' '%s'\n",
user_string($arg1),
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index 063b19e533..3a24986381 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -94,7 +94,7 @@ sys_info() ->
{port_limit, erlang:system_info(port_limit)},
{port_count, erlang:system_info(port_count)},
{ets_limit, erlang:system_info(ets_limit)},
- {ets_count, length(ets:all())},
+ {ets_count, erlang:system_info(ets_count)},
{dist_buf_busy_limit, erlang:system_info(dist_buf_busy_limit)}
| MemInfo].
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 0a4ad61537..fa2f338ec2 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.13
+RUNTIME_TOOLS_VSN = 1.13.2
diff --git a/lib/sasl/doc/src/Makefile b/lib/sasl/doc/src/Makefile
index baf563ca62..8e1e8b502c 100644
--- a/lib/sasl/doc/src/Makefile
+++ b/lib/sasl/doc/src/Makefile
@@ -101,6 +101,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
diff --git a/lib/sasl/doc/src/alarm_handler.xml b/lib/sasl/doc/src/alarm_handler.xml
index 4160757164..6e74f833cd 100644
--- a/lib/sasl/doc/src/alarm_handler.xml
+++ b/lib/sasl/doc/src/alarm_handler.xml
@@ -34,7 +34,7 @@
<rev>A</rev>
<file>alarm_handler.sgml.t1</file>
</header>
- <module>alarm_handler</module>
+ <module since="">alarm_handler</module>
<modulesummary>An Alarm Handling Process</modulesummary>
<description>
<p>The alarm handler process is a
@@ -81,7 +81,7 @@
<funcs>
<func>
- <name>clear_alarm(AlarmId) -> void()</name>
+ <name since="">clear_alarm(AlarmId) -> void()</name>
<fsummary>Clears the specified alarms.</fsummary>
<type>
<v>AlarmId = term()</v>
@@ -94,7 +94,7 @@
</func>
<func>
- <name>get_alarms() -> [alarm()]</name>
+ <name since="">get_alarms() -> [alarm()]</name>
<fsummary>Gets all active alarms.</fsummary>
<desc>
<p>Returns a list of all active alarms. This function can only
@@ -103,7 +103,7 @@
</func>
<func>
- <name>set_alarm(alarm())</name>
+ <name since="">set_alarm(alarm())</name>
<fsummary>Sets an alarm with an id.</fsummary>
<type>
<v>alarm() = {AlarmId, AlarmDescription}</v>
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index 3dda5b06e8..982c874117 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -31,6 +31,38 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 3.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ New <c>counters</c> and <c>atomics</c> modules supplies
+ access to highly efficient operations on mutable fixed
+ word sized variables.</p>
+ <p>
+ Own Id: OTP-13468</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SASL 3.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 3.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/sasl/doc/src/rb.xml b/lib/sasl/doc/src/rb.xml
index d5df4fd345..0ed7e91c11 100644
--- a/lib/sasl/doc/src/rb.xml
+++ b/lib/sasl/doc/src/rb.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>rb.sgml</file>
</header>
- <module>rb</module>
+ <module since="">rb</module>
<modulesummary>The Report Browser Tool</modulesummary>
<description>
<p>The Report Browser (RB) tool is used to browse and
@@ -43,8 +43,8 @@
<funcs>
<func>
- <name>filter(Filters)</name>
- <name>filter(Filters, Dates)</name>
+ <name since="OTP R13B04">filter(Filters)</name>
+ <name since="OTP R13B04">filter(Filters, Dates)</name>
<fsummary>Filters reports and displays them on the screen.</fsummary>
<type>
<v>Filters = [filter()]</v>
@@ -86,7 +86,7 @@
</func>
<func>
- <name>grep(RegExp)</name>
+ <name since="">grep(RegExp)</name>
<fsummary>Searches the reports for a regular expression.</fsummary>
<type>
<v>RegExp = string() | {string(), Options} | re:mp() | {re:mp(), Options}</v>
@@ -109,8 +109,8 @@
</func>
<func>
- <name>h()</name>
- <name>help()</name>
+ <name since="">h()</name>
+ <name since="">help()</name>
<fsummary>Displays help information.</fsummary>
<desc>
<p>Displays online help information.</p>
@@ -118,8 +118,8 @@
</func>
<func>
- <name>list()</name>
- <name>list(Type)</name>
+ <name since="">list()</name>
+ <name since="">list(Type)</name>
<fsummary>Lists all reports.</fsummary>
<type>
<v>Type = type()</v>
@@ -137,8 +137,8 @@
</func>
<func>
- <name>log_list()</name>
- <name>log_list(Type)</name>
+ <name since="OTP R16B02">log_list()</name>
+ <name since="OTP R16B02">log_list(Type)</name>
<fsummary>Logs report lists.</fsummary>
<type>
<v>Type = type()</v>
@@ -157,8 +157,8 @@
</func>
<func>
- <name>rescan()</name>
- <name>rescan(Options)</name>
+ <name since="">rescan()</name>
+ <name since="">rescan(Options)</name>
<fsummary>Rescans the report directory.</fsummary>
<type>
<v>Options = [opt()]</v>
@@ -171,8 +171,8 @@
</func>
<func>
- <name>show()</name>
- <name>show(Report)</name>
+ <name since="">show()</name>
+ <name since="">show(Report)</name>
<fsummary>Displays reports.</fsummary>
<type>
<v>Report = integer() | type()</v>
@@ -186,8 +186,8 @@
</func>
<func>
- <name>start()</name>
- <name>start(Options)</name>
+ <name since="">start()</name>
+ <name since="">start(Options)</name>
<fsummary>Starts the <c>rb_server</c>.</fsummary>
<type>
<v>Options = [opt()]</v>
@@ -256,7 +256,7 @@
</func>
<func>
- <name>start_log(FileName)</name>
+ <name since="">start_log(FileName)</name>
<fsummary>Redirects all output to <c>FileName</c>.</fsummary>
<type>
<v>FileName = string() | atom() | pid()</v>
@@ -268,7 +268,7 @@
</func>
<func>
- <name>stop()</name>
+ <name since="">stop()</name>
<fsummary>Stops the <c>rb_server</c>.</fsummary>
<desc>
<p>Stops <c>rb_server</c>.</p>
@@ -276,7 +276,7 @@
</func>
<func>
- <name>stop_log()</name>
+ <name since="">stop_log()</name>
<fsummary>Stops logging to file.</fsummary>
<desc>
<p>Closes the log file. The output from the RB tool is
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index 9ba276aeac..f8ee0306d8 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>release_handler</module>
+ <module since="">release_handler</module>
<modulesummary>Unpacking and Installation of Release Packages</modulesummary>
<description>
<p>The <em>release handler</em> process belongs to the SASL
@@ -168,8 +168,8 @@
<funcs>
<func>
- <name>check_install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
- <name>check_install_release(Vsn,Opts) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
+ <name since="">check_install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
+ <name since="OTP R14B04">check_install_release(Vsn,Opts) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
<fsummary>Checks installation of a release in the system.</fsummary>
<type>
<v>Vsn = OtherVsn = string()</v>
@@ -202,7 +202,7 @@
</func>
<func>
- <name>create_RELEASES(Root, RelDir, RelFile, AppDirs) -> ok | {error, Reason}</name>
+ <name since="">create_RELEASES(Root, RelDir, RelFile, AppDirs) -> ok | {error, Reason}</name>
<fsummary>Creates an initial <c>RELEASES</c> file.</fsummary>
<type>
<v>Root = RelDir = RelFile = string()</v>
@@ -233,7 +233,7 @@
</func>
<func>
- <name>install_file(Vsn, File) -> ok | {error, Reason}</name>
+ <name since="">install_file(Vsn, File) -> ok | {error, Reason}</name>
<fsummary>Installs a release file in the release structure.</fsummary>
<type>
<v>Vsn = File = string()</v>
@@ -252,8 +252,8 @@
</func>
<func>
- <name>install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
- <name>install_release(Vsn, [Opt]) -> {ok, OtherVsn, Descr} | {continue_after_restart, OtherVsn, Descr} | {error, Reason}</name>
+ <name since="">install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
+ <name since="">install_release(Vsn, [Opt]) -> {ok, OtherVsn, Descr} | {continue_after_restart, OtherVsn, Descr} | {error, Reason}</name>
<fsummary>Installs a release in the system.</fsummary>
<type>
<v>Vsn = OtherVsn = string()</v>
@@ -383,7 +383,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>make_permanent(Vsn) -> ok | {error, Reason}</name>
+ <name since="">make_permanent(Vsn) -> ok | {error, Reason}</name>
<fsummary>Makes the specified release version permanent.</fsummary>
<type>
<v>Vsn = string()</v>
@@ -396,7 +396,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>remove_release(Vsn) -> ok | {error, Reason}</name>
+ <name since="">remove_release(Vsn) -> ok | {error, Reason}</name>
<fsummary>Removes a release from the system.</fsummary>
<type>
<v>Vsn = string()</v>
@@ -410,7 +410,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>reboot_old_release(Vsn) -> ok | {error, Reason}</name>
+ <name since="">reboot_old_release(Vsn) -> ok | {error, Reason}</name>
<fsummary>Reboots the system from an old release.</fsummary>
<type>
<v>Vsn = string()</v>
@@ -425,7 +425,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>set_removed(Vsn) -> ok | {error, Reason}</name>
+ <name since="">set_removed(Vsn) -> ok | {error, Reason}</name>
<fsummary>Marks a release as removed.</fsummary>
<type>
<v>Vsn = string()</v>
@@ -440,7 +440,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>set_unpacked(RelFile, AppDirs) -> {ok, Vsn} | {error, Reason}</name>
+ <name since="">set_unpacked(RelFile, AppDirs) -> {ok, Vsn} | {error, Reason}</name>
<fsummary>Marks a release as unpacked.</fsummary>
<type>
<v>RelFile = string()</v>
@@ -466,7 +466,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>unpack_release(Name) -> {ok, Vsn} | {error, Reason}</name>
+ <name since="">unpack_release(Name) -> {ok, Vsn} | {error, Reason}</name>
<fsummary>Unpacks a release package.</fsummary>
<type>
<v>Name = Vsn = string()</v>
@@ -482,7 +482,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>which_releases() -> [{Name, Vsn, Apps, Status}]</name>
+ <name since="">which_releases() -> [{Name, Vsn, Apps, Status}]</name>
<fsummary>Returns all known releases.</fsummary>
<type>
<v>Name = Vsn = string()</v>
@@ -495,7 +495,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>which_releases(Status) -> [{Name, Vsn, Apps, Status}]</name>
+ <name since="OTP R15B">which_releases(Status) -> [{Name, Vsn, Apps, Status}]</name>
<fsummary>Returns all known releases of a specific status.</fsummary>
<type>
<v>Name = Vsn = string()</v>
@@ -537,7 +537,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<funcs>
<func>
- <name>upgrade_app(App, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
+ <name since="">upgrade_app(App, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
<fsummary>Upgrades to a new application version.</fsummary>
<type>
<v>App = atom()</v>
@@ -586,8 +586,8 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>downgrade_app(App, Dir) -></name>
- <name>downgrade_app(App, OldVsn, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
+ <name since="">downgrade_app(App, Dir) -></name>
+ <name since="">downgrade_app(App, OldVsn, Dir) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
<fsummary>Downgrades to a previous application version.</fsummary>
<type>
<v>App = atom()</v>
@@ -633,7 +633,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>upgrade_script(App, Dir) -> {ok, NewVsn, Script}</name>
+ <name since="">upgrade_script(App, Dir) -> {ok, NewVsn, Script}</name>
<fsummary>Finds an application upgrade script.</fsummary>
<type>
<v>App = atom()</v>
@@ -671,7 +671,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>downgrade_script(App, OldVsn, Dir) -> {ok, Script}</name>
+ <name since="">downgrade_script(App, OldVsn, Dir) -> {ok, Script}</name>
<fsummary>Finds an application downgrade script.</fsummary>
<type>
<v>App = atom()</v>
@@ -710,7 +710,7 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
</func>
<func>
- <name>eval_appup_script(App, ToVsn, ToDir, Script) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
+ <name since="">eval_appup_script(App, ToVsn, ToDir, Script) -> {ok, Unpurged} | restart_emulator | {error, Reason}</name>
<fsummary>Evaluates an application upgrade or downgrade script.</fsummary>
<type>
<v>App = atom()</v>
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index 4842c732b1..6facb8ddae 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>systools</module>
+ <module since="">systools</module>
<modulesummary>A Set of Release Handling Tools</modulesummary>
<description>
<p>This module contains functions to generate boot scripts
@@ -40,8 +40,8 @@
<funcs>
<func>
- <name>make_relup(Name, UpFrom, DownTo) -> Result</name>
- <name>make_relup(Name, UpFrom, DownTo, [Opt]) -> Result</name>
+ <name since="">make_relup(Name, UpFrom, DownTo) -> Result</name>
+ <name since="">make_relup(Name, UpFrom, DownTo, [Opt]) -> Result</name>
<fsummary>Generates a release upgrade file <c>relup</c>.</fsummary>
<type>
<v>Name = string()</v>
@@ -136,8 +136,8 @@
</func>
<func>
- <name>make_script(Name) -> Result</name>
- <name>make_script(Name, [Opt]) -> Result</name>
+ <name since="">make_script(Name) -> Result</name>
+ <name since="">make_script(Name, [Opt]) -> Result</name>
<fsummary>Generates a boot script <c>.script/.boot</c>.</fsummary>
<type>
<v>Name = string()</v>
@@ -263,8 +263,8 @@
</func>
<func>
- <name>make_tar(Name) -> Result</name>
- <name>make_tar(Name, [Opt]) -> Result</name>
+ <name since="">make_tar(Name) -> Result</name>
+ <name since="">make_tar(Name, [Opt]) -> Result</name>
<fsummary>Creates a release package.</fsummary>
<type>
<v>Name = string()</v>
@@ -369,7 +369,7 @@ myapp-1/ebin/myapp.app
</func>
<func>
- <name>script2boot(File) -> ok | error</name>
+ <name since="">script2boot(File) -> ok | error</name>
<fsummary>Generates a binary version of a boot script.</fsummary>
<type>
<v>File = string()</v>
diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src
index 688aff16f1..293af504df 100644
--- a/lib/sasl/src/sasl.app.src
+++ b/lib/sasl/src/sasl.app.src
@@ -43,5 +43,5 @@
{env, []},
{mod, {sasl, []}},
{runtime_dependencies, ["tools-2.6.14","stdlib-3.4","kernel-5.3",
- "erts-9.0"]}]}.
+ "erts-10.2"]}]}.
diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src
index 83ee328af2..26127eae84 100644
--- a/lib/sasl/src/sasl.appup.src
+++ b/lib/sasl/src/sasl.appup.src
@@ -16,13 +16,30 @@
%% limitations under the License.
%%
%% %CopyrightEnd%
+%%
+%% We allow upgrade from, and downgrade to all previous
+%% versions from the following OTP releases:
+%% - OTP 20
+%% - OTP 21
+%%
+%% We also allow upgrade from, and downgrade to all
+%% versions that have branched off from the above
+%% stated previous versions.
+%%
{"%VSN%",
- %% Up from - max one major revision back
- [{<<"3\\.0\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.0
- {<<"3\\.1(\\.[0-2]+)*">>,[restart_new_emulator]}, % OTP-20.1+
- {<<"3\\.1(\\.[3-9]+)*">>,[restart_new_emulator]}], % OTP-21
- %% Down to - max one major revision back
- [{<<"3\\.0\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.*
- {<<"3\\.1(\\.[0-2]+)*">>,[restart_new_emulator]}, % OTP-20.1+
- {<<"3\\.1(\\.[3-9]+)*">>,[restart_new_emulator]}] % OTP-21
-}.
+ [{<<"^3\\.0\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.1$">>,[restart_new_emulator]},
+ {<<"^3\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.2$">>,[restart_new_emulator]},
+ {<<"^3\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
+ [{<<"^3\\.0\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.1$">>,[restart_new_emulator]},
+ {<<"^3\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.2$">>,[restart_new_emulator]},
+ {<<"^3\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 6916107623..f085246924 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1562,10 +1562,10 @@ mandatory_modules() ->
preloaded() ->
%% Sorted
- [erl_prim_loader,erl_tracer,erlang,
+ [atomics, counters, erl_prim_loader,erl_tracer,erlang,
erts_code_purger,erts_dirty_process_signal_handler,
erts_internal,erts_literal_area_collector,
- init,otp_ring0,prim_buffer,prim_eval,prim_file,
+ init,otp_ring0,persistent_term,prim_buffer,prim_eval,prim_file,
prim_inet,prim_zip,zlib].
%%______________________________________________________________________
diff --git a/lib/sasl/test/sasl_report_SUITE.erl b/lib/sasl/test/sasl_report_SUITE.erl
index 863b765645..e639b55cee 100644
--- a/lib/sasl/test/sasl_report_SUITE.erl
+++ b/lib/sasl/test/sasl_report_SUITE.erl
@@ -21,6 +21,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([gen_server_crash/1, gen_server_crash_unicode/1]).
+-export([legacy_gen_server_crash/1, legacy_gen_server_crash_unicode/1]).
-export([crash_me/0,start_link/0,init/1,handle_cast/2,terminate/2]).
@@ -29,7 +30,10 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [gen_server_crash, gen_server_crash_unicode].
+ [gen_server_crash,
+ gen_server_crash_unicode,
+ legacy_gen_server_crash,
+ legacy_gen_server_crash_unicode].
groups() ->
[].
@@ -52,17 +56,80 @@ gen_server_crash(Config) ->
gen_server_crash_unicode(Config) ->
gen_server_crash(Config, unicode).
+legacy_gen_server_crash(Config) ->
+ legacy_gen_server_crash(Config,latin1).
+
+legacy_gen_server_crash_unicode(Config) ->
+ legacy_gen_server_crash(Config,unicode).
+
gen_server_crash(Config, Encoding) ->
+ TC = list_to_atom(lists:concat([?FUNCTION_NAME,"_",Encoding])),
+ PrivDir = filename:join(?config(priv_dir,Config),?MODULE),
+ ConfigFileName = filename:join(PrivDir,TC),
+ KernelLog = filename:join(PrivDir,lists:concat([TC,"_kernel.log"])),
+ SaslLog = filename:join(PrivDir,lists:concat([TC,"_sasl.log"])),
+ KernelConfig = [{logger,[{handler,default,logger_std_h,
+ #{config=>#{type=>{file,KernelLog}}}}]},
+ {logger_sasl_compatible,true}],
+ Modes = [write, {encoding, Encoding}],
+ SaslConfig = [{sasl_error_logger,{file,SaslLog,Modes}}],
+ ok = filelib:ensure_dir(SaslLog),
+
+ ok = file:write_file(ConfigFileName ++ ".config",
+ io_lib:format("[{kernel, ~p},~n{sasl, ~p}].",
+ [KernelConfig,SaslConfig])),
+ {ok,Node} =
+ test_server:start_node(
+ TC, peer,
+ [{args, ["-pa ",filename:dirname(code:which(?MODULE)),
+ " -boot start_sasl -kernel start_timer true "
+ "-config ",ConfigFileName]}]),
+
+ %% Set depth
+ ok = rpc:call(Node,logger,update_formatter_config,[default,depth,30]),
+ ok = rpc:call(Node,logger,update_formatter_config,[sasl,depth,30]),
+
+ %% Make sure remote node logs it's own logs, and current node does
+ %% not log them.
+ ok = rpc:call(Node,logger,remove_handler_filter,[default,remote_gl]),
+ ok = rpc:call(Node,logger,remove_handler_filter,[sasl,remote_gl]),
+ ok = logger:add_primary_filter(no_remote,{fun(#{meta:=#{pid:=Pid}},_)
+ when node(Pid)=/=node() -> stop;
+ (_,_) -> ignore
+ end,[]}),
+ ct:log("Local node Logger config:~n~p",
+ [rpc:call(Node,logger,get_config,[])]),
+ ct:log("Remote node Logger config:~n~p",
+ [rpc:call(Node,logger,get_config,[])]),
+ ct:log("Remote node error_logger handlers: ~p",
+ [rpc:call(Node,error_logger,which_report_handlers,[])]),
+
+ ok = rpc:call(Node,?MODULE,crash_me,[]),
+
+ ok = rpc:call(Node,logger_std_h,filesync,[default]),
+ ok = rpc:call(Node,logger_std_h,filesync,[sasl]),
+
+ test_server:stop_node(Node),
+ ok = logger:remove_primary_filter(no_remote),
+
+ check_file(KernelLog, utf8, 70000, 150000),
+ check_file(SaslLog, Encoding, 70000, 150000),
+
+ ok = file:delete(KernelLog),
+ ok = file:delete(SaslLog),
+
+ ok.
+
+legacy_gen_server_crash(Config, Encoding) ->
StopFilter = {fun(_,_) -> stop end, ok},
logger:add_handler_filter(default,stop_all,StopFilter),
+ logger:add_handler_filter(sasl,stop_all,StopFilter),
logger:add_handler_filter(cth_log_redirect,stop_all,StopFilter),
try
do_gen_server_crash(Config, Encoding)
after
- ok = application:unset_env(kernel, logger_sasl_compatible),
- ok = application:unset_env(sasl, sasl_error_logger),
- ok = application:unset_env(kernel, error_logger_format_depth),
logger:remove_handler_filter(default,stop_all),
+ logger:remove_handler_filter(sasl,stop_all),
logger:remove_handler_filter(cth_log_redirect,stop_all)
end,
ok.
@@ -74,22 +141,17 @@ do_gen_server_crash(Config, Encoding) ->
SaslLog = filename:join(LogDir, "sasl.log"),
ok = filelib:ensure_dir(SaslLog),
- application:stop(sasl),
Modes = [write, {encoding, Encoding}],
- ok = application:set_env(kernel, logger_sasl_compatible, true),
- ok = application:set_env(sasl, sasl_error_logger, {file,SaslLog,Modes},
- [{persistent,true}]),
application:set_env(kernel, error_logger_format_depth, 30),
error_logger:logfile({open,KernelLog}),
- application:start(sasl),
+ error_logger:add_report_handler(sasl_report_file_h,{SaslLog,Modes,all}),
ct:log("Logger config:~n~p",[logger:get_config()]),
ct:log("error_logger handlers: ~p",[error_logger:which_report_handlers()]),
crash_me(),
-
error_logger:logfile(close),
- application:stop(sasl),
+ error_logger:delete_report_handler(sasl_report_file_h),
check_file(KernelLog, utf8, 70000, 150000),
check_file(SaslLog, Encoding, 70000, 150000),
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index 0972ae20ba..c1f80752a7 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 3.2
+SASL_VSN = 3.3
diff --git a/lib/snmp/doc/src/Makefile b/lib/snmp/doc/src/Makefile
index 3ebee792f9..e7ab491eef 100644
--- a/lib/snmp/doc/src/Makefile
+++ b/lib/snmp/doc/src/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -140,6 +140,7 @@ clean_man:
clean_html:
@echo "cleaning html:"
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
$(MAN7DIR)/%.7: $(MIBSDIR)/%.mib
@echo "processing $*"
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index f64e0cca97..423d90fef6 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,7 +34,46 @@
</header>
- <section><title>SNMP 5.2.11</title>
+ <section><title>SNMP 5.2.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Conversion of (agent) Audit Trail Log (ATL) failed due
+ to invalid log entries.</p> <p>The conversion aborted
+ completely midway because the ATL contained invalid
+ entries. The conversion has been improved so that it now
+ firstly handles encountered errors and write an
+ informative message (into the converted stream) and
+ secondly keeps count of the number of successful or
+ failed entry conversions. See <seealso
+ marker="snmpa#log_to_txt">log_to_txt</seealso> for more
+ info. </p> <p>The reason the ATL contained invalid
+ entries have also been fixed. The reason was that for
+ some outgoing messages (not response):</p> <list
+ type="bulleted"> <item> <p>encrypted (v3 messages)</p>
+ <p>Was logged "as is" (encrypted) without the info to
+ decrypt, making conversion impossible (which was the
+ reason the log contained bad entries).</p> </item> <item>
+ <p>un-encrypted</p> <p>Was not logged at all. </p>
+ </item> </list>
+ <p>
+ Own Id: OTP-15287 Aux Id: ERIERL-206 </p>
+ </item>
+ <item>
+ <p>
+ [compiler] Spurious version message removed. The snmp mib
+ compiler printed an spurious version message if the
+ 'version' option was provided.</p>
+ <p>
+ Own Id: OTP-15290</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.11</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -48,7 +87,7 @@
</list>
</section>
-</section>
+ </section>
<section><title>SNMP 5.2.10</title>
diff --git a/lib/snmp/doc/src/snmp.xml b/lib/snmp/doc/src/snmp.xml
index 801193675c..d20f1a8d06 100644
--- a/lib/snmp/doc/src/snmp.xml
+++ b/lib/snmp/doc/src/snmp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp.xml</file>
</header>
- <module>snmp</module>
+ <module since="">snmp</module>
<modulesummary>Interface functions to the SNMP toolkit</modulesummary>
<description>
<p>The module <c>snmp</c> contains interface functions to the
@@ -56,7 +56,7 @@
<funcs>
<func>
- <name>config() -> ok | {error, Reason}</name>
+ <name since="">config() -> ok | {error, Reason}</name>
<fsummary>Configure with a simple interactive tool</fsummary>
<desc>
<p>A simple interactive configuration tool. Simple
@@ -78,8 +78,8 @@
</func>
<func>
- <name>start() -> ok | {error, Reason}</name>
- <name>start(Type) -> ok | {error, Reason}</name>
+ <name since="">start() -> ok | {error, Reason}</name>
+ <name since="">start(Type) -> ok | {error, Reason}</name>
<fsummary>Start the SNMP application</fsummary>
<type>
<v>Type = start_type()</v>
@@ -93,8 +93,8 @@
</func>
<func>
- <name>start_agent() -> ok | {error, Reason}</name>
- <name>start_agent(Type) -> ok | {error, Reason}</name>
+ <name since="">start_agent() -> ok | {error, Reason}</name>
+ <name since="">start_agent(Type) -> ok | {error, Reason}</name>
<fsummary>Start the agent part of the SNMP application</fsummary>
<type>
<v>Type = start_type()</v>
@@ -117,8 +117,8 @@
</func>
<func>
- <name>start_manager() -> ok | {error, Reason}</name>
- <name>start_manager(Type) -> ok | {error, Reason}</name>
+ <name since="">start_manager() -> ok | {error, Reason}</name>
+ <name since="">start_manager(Type) -> ok | {error, Reason}</name>
<fsummary>Start the manager part of the SNMP application</fsummary>
<type>
<v>Type = start_type()</v>
@@ -141,7 +141,7 @@
</func>
<func>
- <name>date_and_time() -> DateAndTime</name>
+ <name since="">date_and_time() -> DateAndTime</name>
<fsummary>Return the current date and time as an OCTET STRING</fsummary>
<type>
<v>DateAndTime = [int()]</v>
@@ -155,7 +155,7 @@
</func>
<func>
- <name>date_and_time_to_universal_time_dst(DateAndTime) -> [utc()]</name>
+ <name since="">date_and_time_to_universal_time_dst(DateAndTime) -> [utc()]</name>
<fsummary>Convert a DateAndTime value to a list of possible utc()</fsummary>
<type>
<v>DateAndTime = [int()]</v>
@@ -171,8 +171,8 @@
</func>
<func>
- <name>date_and_time_to_string(DateAndTime) -> string()</name>
- <name>date_and_time_to_string(DateAndTime, Validate) -> string()</name>
+ <name since="">date_and_time_to_string(DateAndTime) -> string()</name>
+ <name since="">date_and_time_to_string(DateAndTime, Validate) -> string()</name>
<fsummary>Convert a DateAndTime value to a string</fsummary>
<type>
<v>DateAndTime = [int()]</v>
@@ -194,7 +194,7 @@
</func>
<func>
- <name>date_and_time_to_string2(DateAndTime) -> string()</name>
+ <name since="">date_and_time_to_string2(DateAndTime) -> string()</name>
<fsummary>Convert a DateAndTime value to a string</fsummary>
<type>
<v>DateAndTime = [int()]</v>
@@ -210,7 +210,7 @@
</func>
<func>
- <name>local_time_to_date_and_time_dst(Local) -> [DateAndTime]</name>
+ <name since="">local_time_to_date_and_time_dst(Local) -> [DateAndTime]</name>
<fsummary>Convert a Local time value to a list of possible DateAndTime(s)</fsummary>
<type>
<v>Local = {{Y,Mo,D},{H,M,S}}</v>
@@ -226,7 +226,7 @@
</func>
<func>
- <name>universal_time_to_date_and_time(UTC) -> DateAndTime</name>
+ <name since="">universal_time_to_date_and_time(UTC) -> DateAndTime</name>
<fsummary>Convert a UTC value to DateAndTime</fsummary>
<type>
<v>UTC = {{Y,Mo,D},{H,M,S}}</v>
@@ -241,8 +241,8 @@
</func>
<func>
- <name>validate_date_and_time(DateAndTime) -> bool()</name>
- <name>validate_date_and_time(DateAndTime, Validate) -> bool()</name>
+ <name since="">validate_date_and_time(DateAndTime) -> bool()</name>
+ <name since="">validate_date_and_time(DateAndTime, Validate) -> bool()</name>
<fsummary>Check if a DateAndTime value is correct</fsummary>
<type>
<v>DateAndTime = term()</v>
@@ -279,7 +279,7 @@
</func>
<func>
- <name>passwd2localized_key(Alg, Passwd, EngineID) -> Key</name>
+ <name since="">passwd2localized_key(Alg, Passwd, EngineID) -> Key</name>
<fsummary>Generates an localized key</fsummary>
<type>
<v>Alg = algorithm()</v>
@@ -298,7 +298,7 @@
</func>
<func>
- <name>octet_string_to_bits(S) -> Val</name>
+ <name since="">octet_string_to_bits(S) -> Val</name>
<fsummary>Convert an OCTET-STRING to BITS</fsummary>
<type>
<v>Val = bits()</v>
@@ -312,7 +312,7 @@
</func>
<func>
- <name>bits_to_octet_string(B) -> Val</name>
+ <name since="">bits_to_octet_string(B) -> Val</name>
<fsummary>Convert an OCTET-STRING to BITS</fsummary>
<type>
<v>Val = octet_string()</v>
@@ -326,7 +326,7 @@
</func>
<func>
- <name>read_mib(FileName) -> {ok, mib()} | {error, Reason}</name>
+ <name since="">read_mib(FileName) -> {ok, mib()} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>FileName = string()</v>
@@ -341,10 +341,10 @@
</func>
<func>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Block | Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop, Block) -> ok | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Block | Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R16B03">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop, Block) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -355,6 +355,9 @@
<v>LogFile = string()</v>
<v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
<v>Block = boolean()</v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = term()</v>
</type>
<desc>
@@ -394,16 +397,25 @@
and <c>Vsn</c> is the SNMP version. <c>PDU</c> is a textual
version of the protocol data unit. There is a new line
between <c>Vsn</c> and <c>PDU</c>.</p>
+
+ <p>If the entire log is successfully converted, the function
+ will return <c>ok</c>.
+ If one of more entries fail to convert, the function will instead
+ return <c>{ok, {NumOK, NumERR}}</c>, where the counters indicate
+ how many valid and erroneous entries where found.
+ If instead <c>{error, Reason}</c> is returned, the conversion
+ encountered a fatal error and where either never done of aborted
+ midway. </p>
<marker id="log_to_io"></marker>
</desc>
</func>
<func>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Block | Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop, Block) -> ok | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Start, Block | Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R16B03">log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop, Block) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -412,6 +424,9 @@
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = term()</v>
</type>
<desc>
@@ -425,7 +440,7 @@
</func>
<func>
- <name>change_log_size(LogName, NewSize) -> ok | {error, Reason}</name>
+ <name since="">change_log_size(LogName, NewSize) -> ok | {error, Reason}</name>
<fsummary>Change the size of the Audit Trail Log</fsummary>
<type>
<v>LogName = string()</v>
@@ -448,8 +463,8 @@
</func>
<func>
- <name>print_version_info() -> void()</name>
- <name>print_version_info(Prefix) -> void()</name>
+ <name since="">print_version_info() -> void()</name>
+ <name since="">print_version_info(Prefix) -> void()</name>
<fsummary>Formatted print of result of the versions functions</fsummary>
<type>
<v>Prefix = string() | integer()</v>
@@ -469,8 +484,8 @@
</func>
<func>
- <name>versions1() -> {ok, Info} | {error, Reason}</name>
- <name>versions2() -> {ok, Info} | {error, Reason}</name>
+ <name since="">versions1() -> {ok, Info} | {error, Reason}</name>
+ <name since="">versions2() -> {ok, Info} | {error, Reason}</name>
<fsummary>Retrieve various system and application info</fsummary>
<type>
<v>Info = [info()]</v>
@@ -489,8 +504,8 @@
</func>
<func>
- <name>print_versions(VersionInfo) -> void()</name>
- <name>print_versions(Prefix, VersionInfo) -> void()</name>
+ <name since="">print_versions(VersionInfo) -> void()</name>
+ <name since="">print_versions(Prefix, VersionInfo) -> void()</name>
<fsummary>Formatted print of result of the versions functions</fsummary>
<type>
<v>VersionInfo = [version_info()]</v>
@@ -512,7 +527,7 @@
</func>
<func>
- <name>enable_trace() -> void()</name>
+ <name since="">enable_trace() -> void()</name>
<fsummary>Starts a tracer</fsummary>
<!--
<type>
@@ -528,7 +543,7 @@
</func>
<func>
- <name>disable_trace() -> void()</name>
+ <name since="">disable_trace() -> void()</name>
<fsummary>Stop the tracer</fsummary>
<!--
<type>
@@ -543,7 +558,7 @@
</func>
<func>
- <name>set_trace(Targets) -> void()</name>
+ <name since="">set_trace(Targets) -> void()</name>
<fsummary>Set trace target</fsummary>
<type>
<v>Targets = target() | targets()</v>
@@ -567,7 +582,7 @@
</func>
<func>
- <name>reset_trace(Targets) -> void()</name>
+ <name since="">reset_trace(Targets) -> void()</name>
<fsummary>Reset trace target</fsummary>
<type>
<v>Targets = module() | modules()</v>
@@ -583,7 +598,7 @@
</func>
<func>
- <name>set_trace(Targets, Opts) -> void()</name>
+ <name since="">set_trace(Targets, Opts) -> void()</name>
<fsummary>Set trace target</fsummary>
<type>
<v>Targets = target() | targets()</v>
diff --git a/lib/snmp/doc/src/snmp_community_mib.xml b/lib/snmp/doc/src/snmp_community_mib.xml
index 61dea05950..9800fb6c00 100644
--- a/lib/snmp/doc/src/snmp_community_mib.xml
+++ b/lib/snmp/doc/src/snmp_community_mib.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_community_mib.xml</file>
</header>
- <module>snmp_community_mib</module>
+ <module since="">snmp_community_mib</module>
<modulesummary>Instrumentation Functions for SNMP-COMMUNITY-MIB</modulesummary>
<description>
<p>The module <c>snmp_community_mib</c> implements the instrumentation
@@ -45,7 +45,7 @@
<funcs>
<func>
- <name>configure(ConfDir) -> void()</name>
+ <name since="">configure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-COMMUNITY-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -77,7 +77,7 @@
</func>
<func>
- <name>reconfigure(ConfDir) -> void()</name>
+ <name since="">reconfigure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-COMMUNITY-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -108,8 +108,8 @@
</func>
<func>
- <name>add_community(Idx, CommName, SecName, CtxName, TransportTag) -> Ret</name>
- <name>add_community(Idx, CommName, SecName, EngineId, CtxName, TransportTag) -> Ret</name>
+ <name since="">add_community(Idx, CommName, SecName, CtxName, TransportTag) -> Ret</name>
+ <name since="OTP R14B03">add_community(Idx, CommName, SecName, EngineId, CtxName, TransportTag) -> Ret</name>
<fsummary>Added one community</fsummary>
<type>
<v>Idx = string()</v>
@@ -132,7 +132,7 @@
</func>
<func>
- <name>delete_community(Key) -> Ret</name>
+ <name since="">delete_community(Key) -> Ret</name>
<fsummary>Delete one community</fsummary>
<type>
<v>Key = term()</v>
diff --git a/lib/snmp/doc/src/snmp_framework_mib.xml b/lib/snmp/doc/src/snmp_framework_mib.xml
index 64e5df6ff5..d84327d4d5 100644
--- a/lib/snmp/doc/src/snmp_framework_mib.xml
+++ b/lib/snmp/doc/src/snmp_framework_mib.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_framework_mib.xml</file>
</header>
- <module>snmp_framework_mib</module>
+ <module since="">snmp_framework_mib</module>
<modulesummary>Instrumentation Functions for SNMP-FRAMEWORK-MIB</modulesummary>
<description>
<p>The module <c>snmp_framework_mib</c> implements instrumentation
@@ -44,7 +44,7 @@
</description>
<funcs>
<func>
- <name>configure(ConfDir) -> void()</name>
+ <name since="">configure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-FRAMEWORK-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -75,7 +75,7 @@
</desc>
</func>
<func>
- <name>init() -> void()</name>
+ <name since="">init() -> void()</name>
<fsummary>Initialize the SNMP-FRAMEWORK-MIB</fsummary>
<desc>
<p>This function is called from the supervisor at system
@@ -88,7 +88,7 @@
</desc>
</func>
<func>
- <name>add_context(Ctx) -> Ret</name>
+ <name since="">add_context(Ctx) -> Ret</name>
<fsummary>Added one context</fsummary>
<type>
<v>Ctx = string()</v>
@@ -103,7 +103,7 @@
</desc>
</func>
<func>
- <name>delete_context(Key) -> Ret</name>
+ <name since="">delete_context(Key) -> Ret</name>
<fsummary>Delete one context</fsummary>
<type>
<v>Key = term()</v>
diff --git a/lib/snmp/doc/src/snmp_generic.xml b/lib/snmp/doc/src/snmp_generic.xml
index 44762dec59..6fb714907c 100644
--- a/lib/snmp/doc/src/snmp_generic.xml
+++ b/lib/snmp/doc/src/snmp_generic.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_generic.xml</file>
</header>
- <module>snmp_generic</module>
+ <module since="">snmp_generic</module>
<modulesummary>Generic Functions for Implementing SNMP Objects in a Database</modulesummary>
<description>
<marker id="description"></marker>
@@ -127,8 +127,8 @@ value() = term()
<funcs>
<func>
- <name>get_status_col(Name, Cols)</name>
- <name>get_status_col(NameDb, Cols) -> {ok, StatusVal} | false</name>
+ <name since="">get_status_col(Name, Cols)</name>
+ <name since="">get_status_col(NameDb, Cols) -> {ok, StatusVal} | false</name>
<fsummary>Get the value of the status column from <c>Cols</c></fsummary>
<type>
<v>Name = name()</v>
@@ -148,7 +148,7 @@ value() = term()
</func>
<func>
- <name>get_index_types(Name)</name>
+ <name since="">get_index_types(Name)</name>
<fsummary>Get the index types of <c>Name</c></fsummary>
<type>
<v>Name = name()</v>
@@ -163,7 +163,7 @@ value() = term()
</func>
<func>
- <name>get_table_info(Name, Item) -> table_info_result()</name>
+ <name since="OTP R15B01">get_table_info(Name, Item) -> table_info_result()</name>
<fsummary>Get table info item of MIB table <c>Name</c></fsummary>
<type>
<v>Name = name()</v>
@@ -187,8 +187,8 @@ value() = term()
</func>
<func>
- <name>table_func(Op1, NameDb)</name>
- <name>table_func(Op2, RowIndex, Cols, NameDb) -> Ret</name>
+ <name since="">table_func(Op1, NameDb)</name>
+ <name since="">table_func(Op2, RowIndex, Cols, NameDb) -> Ret</name>
<fsummary>Default instrumentation function for tables</fsummary>
<type>
<v>Op1 = new | delete </v>
@@ -232,7 +232,7 @@ value() = term()
</func>
<func>
- <name>table_get_elements(NameDb, RowIndex, Cols) -> Values</name>
+ <name since="">table_get_elements(NameDb, RowIndex, Cols) -> Values</name>
<fsummary>Get elements in a table row</fsummary>
<type>
<v>NameDb = name_db()</v>
@@ -249,7 +249,7 @@ value() = term()
</func>
<func>
- <name>table_next(NameDb, RestOid) -> RowIndex | endOfTable</name>
+ <name since="">table_next(NameDb, RestOid) -> RowIndex | endOfTable</name>
<fsummary>Find the next row in the table</fsummary>
<type>
<v>NameDb = name_db()</v>
@@ -265,7 +265,7 @@ value() = term()
</func>
<func>
- <name>table_row_exists(NameDb, RowIndex) -> bool()</name>
+ <name since="">table_row_exists(NameDb, RowIndex) -> bool()</name>
<fsummary>Check if a row in a table exists</fsummary>
<type>
<v>NameDb = name_db()</v>
@@ -279,7 +279,7 @@ value() = term()
</func>
<func>
- <name>table_set_elements(NameDb, RowIndex, Cols) -> bool()</name>
+ <name since="">table_set_elements(NameDb, RowIndex, Cols) -> bool()</name>
<fsummary>Set elements in a table row</fsummary>
<type>
<v>NameDb = name_db()</v>
@@ -300,8 +300,8 @@ value() = term()
</func>
<func>
- <name>variable_func(Op1, NameDb)</name>
- <name>variable_func(Op2, Val, NameDb) -> Ret</name>
+ <name since="">variable_func(Op1, NameDb)</name>
+ <name since="">variable_func(Op2, Val, NameDb) -> Ret</name>
<fsummary>Default instrumentation function for tables</fsummary>
<type>
<v>Op1 = new | delete | get</v>
@@ -325,7 +325,7 @@ value() = term()
</func>
<func>
- <name>variable_get(NameDb) -> {value, Value} | undefined</name>
+ <name since="">variable_get(NameDb) -> {value, Value} | undefined</name>
<fsummary>Get the value of a variable</fsummary>
<type>
<v>NameDb = name_db()</v>
@@ -339,7 +339,7 @@ value() = term()
</func>
<func>
- <name>variable_set(NameDb, NewVal) -> true | false</name>
+ <name since="">variable_set(NameDb, NewVal) -> true | false</name>
<fsummary>Set a value for a variable</fsummary>
<type>
<v>NameDb = name_db()</v>
diff --git a/lib/snmp/doc/src/snmp_impl_example_agent.xml b/lib/snmp/doc/src/snmp_impl_example_agent.xml
index e576fa51f3..7dda3dd5cd 100644
--- a/lib/snmp/doc/src/snmp_impl_example_agent.xml
+++ b/lib/snmp/doc/src/snmp_impl_example_agent.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/snmp/doc/src/snmp_index.xml b/lib/snmp/doc/src/snmp_index.xml
index 646e9661a3..1497f4cf67 100644
--- a/lib/snmp/doc/src/snmp_index.xml
+++ b/lib/snmp/doc/src/snmp_index.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_index.xml</file>
</header>
- <module>snmp_index</module>
+ <module since="">snmp_index</module>
<modulesummary>Abstract Data Type for SNMP Indexing</modulesummary>
<description>
<p>The module <c>snmp_index</c> implements an Abstract
@@ -159,7 +159,7 @@ get_next_pid(Oid, SnmpIndex) ->
</section>
<funcs>
<func>
- <name>delete(Index) -> true</name>
+ <name since="">delete(Index) -> true</name>
<fsummary>Delete an index table</fsummary>
<type>
<v>Index = NewIndex = index()</v>
@@ -173,7 +173,7 @@ get_next_pid(Oid, SnmpIndex) ->
</desc>
</func>
<func>
- <name>delete(Index, Key) -> NewIndex</name>
+ <name since="">delete(Index, Key) -> NewIndex</name>
<fsummary>Delete an item from the index</fsummary>
<type>
<v>Index = NewIndex = index()</v>
@@ -185,7 +185,7 @@ get_next_pid(Oid, SnmpIndex) ->
</desc>
</func>
<func>
- <name>get(Index, KeyOid) -> {ok, {KeyOid, Value}} | undefined</name>
+ <name since="">get(Index, KeyOid) -> {ok, {KeyOid, Value}} | undefined</name>
<fsummary>Get the item with <c>KeyOid</c></fsummary>
<type>
<v>Index = index()</v>
@@ -198,7 +198,7 @@ get_next_pid(Oid, SnmpIndex) ->
</desc>
</func>
<func>
- <name>get_last(Index) -> {ok, {KeyOid, Value}} | undefined</name>
+ <name since="">get_last(Index) -> {ok, {KeyOid, Value}} | undefined</name>
<fsummary>Get the last item in the index structure</fsummary>
<type>
<v>Index = index()</v>
@@ -210,7 +210,7 @@ get_next_pid(Oid, SnmpIndex) ->
</desc>
</func>
<func>
- <name>get_next(Index, KeyOid) -> {ok, {NextKeyOid, Value}} | undefined</name>
+ <name since="">get_next(Index, KeyOid) -> {ok, {NextKeyOid, Value}} | undefined</name>
<fsummary>Get the next item</fsummary>
<type>
<v>Index = index()</v>
@@ -224,7 +224,7 @@ get_next_pid(Oid, SnmpIndex) ->
</desc>
</func>
<func>
- <name>insert(Index, Key, Value) -> NewIndex</name>
+ <name since="">insert(Index, Key, Value) -> NewIndex</name>
<fsummary>Insert an item into the index</fsummary>
<type>
<v>Index = NewIndex = index()</v>
@@ -238,7 +238,7 @@ get_next_pid(Oid, SnmpIndex) ->
</desc>
</func>
<func>
- <name>key_to_oid(Index, Key) -> KeyOid</name>
+ <name since="">key_to_oid(Index, Key) -> KeyOid</name>
<fsummary>Convert a key to an OBJECT IDENTIFIER</fsummary>
<type>
<v>Index = index()</v>
@@ -250,7 +250,7 @@ get_next_pid(Oid, SnmpIndex) ->
</desc>
</func>
<func>
- <name>new(KeyTypes) -> Index</name>
+ <name since="">new(KeyTypes) -> Index</name>
<fsummary>Create a new snmp index structure</fsummary>
<type>
<v>KeyTypes = key_types()</v>
diff --git a/lib/snmp/doc/src/snmp_notification_mib.xml b/lib/snmp/doc/src/snmp_notification_mib.xml
index d2e288ec15..9395edf155 100644
--- a/lib/snmp/doc/src/snmp_notification_mib.xml
+++ b/lib/snmp/doc/src/snmp_notification_mib.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_notification_mib.xml</file>
</header>
- <module>snmp_notification_mib</module>
+ <module since="">snmp_notification_mib</module>
<modulesummary>Instrumentation Functions for SNMP-NOTIFICATION-MIB</modulesummary>
<description>
<p>The module <c>snmp_notification_mib</c> implements the
@@ -43,7 +43,7 @@
</description>
<funcs>
<func>
- <name>configure(ConfDir) -> void()</name>
+ <name since="">configure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-NOTIFICATION-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -70,7 +70,7 @@
</desc>
</func>
<func>
- <name>reconfigure(ConfDir) -> void()</name>
+ <name since="">reconfigure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-NOTIFICATION-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -98,7 +98,7 @@
</desc>
</func>
<func>
- <name>add_notify(Name, Tag, Type) -> Ret</name>
+ <name since="">add_notify(Name, Tag, Type) -> Ret</name>
<fsummary>Added one notify definition</fsummary>
<type>
<v>Name = string()</v>
@@ -115,7 +115,7 @@
</desc>
</func>
<func>
- <name>delete_notify(Key) -> Ret</name>
+ <name since="">delete_notify(Key) -> Ret</name>
<fsummary>Delete one notify definition</fsummary>
<type>
<v>Key = term()</v>
diff --git a/lib/snmp/doc/src/snmp_pdus.xml b/lib/snmp/doc/src/snmp_pdus.xml
index 1d086e6f48..f403b6edf4 100644
--- a/lib/snmp/doc/src/snmp_pdus.xml
+++ b/lib/snmp/doc/src/snmp_pdus.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_pdus.xml</file>
</header>
- <module>snmp_pdus</module>
+ <module since="">snmp_pdus</module>
<modulesummary>Encode and Decode Functions for SNMP PDUs</modulesummary>
<description>
<p>RFC1157, RFC1905 and/or RFC2272 should be studied carefully
@@ -55,7 +55,7 @@
</description>
<funcs>
<func>
- <name>dec_message([byte()]) -> Message</name>
+ <name since="">dec_message([byte()]) -> Message</name>
<fsummary>Decode an SNMP Message</fsummary>
<type>
<v>Message = #message</v>
@@ -71,7 +71,7 @@
</desc>
</func>
<func>
- <name>dec_message_only([byte()]) -> Message</name>
+ <name since="">dec_message_only([byte()]) -> Message</name>
<fsummary>Decode an SNMP Message, but not the data part</fsummary>
<type>
<v>Message = #message</v>
@@ -84,7 +84,7 @@
</desc>
</func>
<func>
- <name>dec_pdu([byte()]) -> Pdu</name>
+ <name since="">dec_pdu([byte()]) -> Pdu</name>
<fsummary>Decode an SNMP Pdu</fsummary>
<type>
<v>Pdu = #pdu</v>
@@ -94,7 +94,7 @@
</desc>
</func>
<func>
- <name>dec_scoped_pdu([byte()]) -> ScopedPdu</name>
+ <name since="">dec_scoped_pdu([byte()]) -> ScopedPdu</name>
<fsummary>Decode an SNMP ScopedPdu</fsummary>
<type>
<v>ScopedPdu = #scoped_pdu</v>
@@ -104,7 +104,7 @@
</desc>
</func>
<func>
- <name>dec_scoped_pdu_data([byte()]) -> ScopedPduData</name>
+ <name since="">dec_scoped_pdu_data([byte()]) -> ScopedPduData</name>
<fsummary>Decode an SNMP ScopedPduData</fsummary>
<type>
<v>ScopedPduData = #scoped_pdu | EncryptedPDU</v>
@@ -116,7 +116,7 @@
</desc>
</func>
<func>
- <name>dec_usm_security_parameters([byte()]) -> UsmSecParams</name>
+ <name since="">dec_usm_security_parameters([byte()]) -> UsmSecParams</name>
<fsummary>Decode SNMP UsmSecurityParameters</fsummary>
<type>
<v>UsmSecParams = #usmSecurityParameters</v>
@@ -126,7 +126,7 @@
</desc>
</func>
<func>
- <name>enc_encrypted_scoped_pdu(EncryptedScopedPdu) -> [byte()]</name>
+ <name since="">enc_encrypted_scoped_pdu(EncryptedScopedPdu) -> [byte()]</name>
<fsummary>Encode an encrypted SNMP scopedPDU</fsummary>
<type>
<v>EncryptedScopedPdu = [byte()]</v>
@@ -142,7 +142,7 @@
</desc>
</func>
<func>
- <name>enc_message(Message) -> [byte()]</name>
+ <name since="">enc_message(Message) -> [byte()]</name>
<fsummary>Encode an SNMP Message</fsummary>
<type>
<v>Message = #message</v>
@@ -152,7 +152,7 @@
</desc>
</func>
<func>
- <name>enc_message_only(Message) -> [byte()]</name>
+ <name since="">enc_message_only(Message) -> [byte()]</name>
<fsummary>Encode an SNMP Message, but not the data part</fsummary>
<type>
<v>Message = #message</v>
@@ -166,7 +166,7 @@
</desc>
</func>
<func>
- <name>enc_pdu(Pd) -> [byte()]</name>
+ <name since="">enc_pdu(Pd) -> [byte()]</name>
<fsummary>Encode an SNMP Pdu</fsummary>
<type>
<v>Pdu = #pdu</v>
@@ -176,7 +176,7 @@
</desc>
</func>
<func>
- <name>enc_scoped_pdu(ScopedPdu) -> [byte()]</name>
+ <name since="">enc_scoped_pdu(ScopedPdu) -> [byte()]</name>
<fsummary>Encode an SNMP scopedPDU</fsummary>
<type>
<v>ScopedPdu = #scoped_pdu</v>
@@ -190,7 +190,7 @@
</desc>
</func>
<func>
- <name>enc_usm_security_parameters(UsmSecParams) -> [byte()]</name>
+ <name since="">enc_usm_security_parameters(UsmSecParams) -> [byte()]</name>
<fsummary>Encode SNMP UsmSecurityParameters</fsummary>
<type>
<v>UsmSecParams = #usmSecurityParameters</v>
diff --git a/lib/snmp/doc/src/snmp_standard_mib.xml b/lib/snmp/doc/src/snmp_standard_mib.xml
index 35efbba483..eb4e2fd097 100644
--- a/lib/snmp/doc/src/snmp_standard_mib.xml
+++ b/lib/snmp/doc/src/snmp_standard_mib.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_standard_mib.xml</file>
</header>
- <module>snmp_standard_mib</module>
+ <module since="">snmp_standard_mib</module>
<modulesummary>Instrumentation Functions for STANDARD-MIB and SNMPv2-MIB</modulesummary>
<description>
<p>The module <c>snmp_standard_mib</c> implements the instrumentation functions for the
@@ -42,7 +42,7 @@
</description>
<funcs>
<func>
- <name>configure(ConfDir) -> void()</name>
+ <name since="">configure(ConfDir) -> void()</name>
<fsummary>Configure the STANDARD-MIB and SNMPv2-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -71,8 +71,8 @@
</desc>
</func>
<func>
- <name>inc(Name) -> void()</name>
- <name>inc(Name, N) -> void()</name>
+ <name since="">inc(Name) -> void()</name>
+ <name since="">inc(Name, N) -> void()</name>
<fsummary>Increment a variable in the MIB</fsummary>
<type>
<v>Name = atom()</v>
@@ -84,7 +84,7 @@
</desc>
</func>
<func>
- <name>reconfigure(ConfDir) -> void()</name>
+ <name since="">reconfigure(ConfDir) -> void()</name>
<fsummary>Configure the STANDARD-MIB and SNMPv2-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -114,14 +114,14 @@
</desc>
</func>
<func>
- <name>reset() -> void()</name>
+ <name since="">reset() -> void()</name>
<fsummary>Reset all <c>snmp</c>counters to 0</fsummary>
<desc>
<p>Resets all <c>snmp</c> counters to 0.</p>
</desc>
</func>
<func>
- <name>sys_up_time() -> Time</name>
+ <name since="">sys_up_time() -> Time</name>
<fsummary>Get the system up time</fsummary>
<type>
<v>Time = int()</v>
diff --git a/lib/snmp/doc/src/snmp_target_mib.xml b/lib/snmp/doc/src/snmp_target_mib.xml
index c3bcd3b4e3..c46edb810d 100644
--- a/lib/snmp/doc/src/snmp_target_mib.xml
+++ b/lib/snmp/doc/src/snmp_target_mib.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_target_mib.xml</file>
</header>
- <module>snmp_target_mib</module>
+ <module since="">snmp_target_mib</module>
<modulesummary>Instrumentation Functions for SNMP-TARGET-MIB</modulesummary>
<description>
<p>The module <c>snmp_target_mib</c> implements the instrumentation
@@ -57,7 +57,7 @@
<funcs>
<func>
- <name>configure(ConfDir) -> void()</name>
+ <name since="">configure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-TARGET-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -85,7 +85,7 @@
</func>
<func>
- <name>reconfigure(ConfDir) -> void()</name>
+ <name since="">reconfigure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-TARGET-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -113,7 +113,7 @@
</func>
<func>
- <name>set_target_engine_id(TargetAddrName, EngineId) -> boolean()</name>
+ <name since="">set_target_engine_id(TargetAddrName, EngineId) -> boolean()</name>
<fsummary>Set the engine id for a targetAddr row.</fsummary>
<type>
<v>TargetAddrName = string()</v>
@@ -130,7 +130,7 @@
</func>
<func>
- <name>add_addr(Name, Domain, Addr, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> Ret</name>
+ <name since="">add_addr(Name, Domain, Addr, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> Ret</name>
<fsummary>Add one target address definition</fsummary>
<type>
<v>Name = string()</v>
@@ -156,7 +156,7 @@
</func>
<func>
- <name>delete_addr(Key) -> Ret</name>
+ <name since="">delete_addr(Key) -> Ret</name>
<fsummary>Delete one target address definition</fsummary>
<type>
<v>Key = term()</v>
@@ -171,7 +171,7 @@
</func>
<func>
- <name>add_params(Name, MPModel, SecModel, SecName, SecLevel) -> Ret</name>
+ <name since="">add_params(Name, MPModel, SecModel, SecName, SecLevel) -> Ret</name>
<fsummary>Add one target parameter definition</fsummary>
<type>
<v>Name = string()</v>
@@ -191,7 +191,7 @@
</desc>
</func>
<func>
- <name>delete_params(Key) -> Ret</name>
+ <name since="">delete_params(Key) -> Ret</name>
<fsummary>Delete one target parameter definition</fsummary>
<type>
<v>Key = term()</v>
diff --git a/lib/snmp/doc/src/snmp_user_based_sm_mib.xml b/lib/snmp/doc/src/snmp_user_based_sm_mib.xml
index cc376ac118..6c2203ed22 100644
--- a/lib/snmp/doc/src/snmp_user_based_sm_mib.xml
+++ b/lib/snmp/doc/src/snmp_user_based_sm_mib.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_user_based_sm_mib.xml</file>
</header>
- <module>snmp_user_based_sm_mib</module>
+ <module since="">snmp_user_based_sm_mib</module>
<modulesummary>Instrumentation Functions for SNMP-USER-BASED-SM-MIB</modulesummary>
<description>
<p>The module <c>snmp_user_based_sm_mib</c> implements the instrumentation
@@ -43,7 +43,7 @@
</description>
<funcs>
<func>
- <name>configure(ConfDir) -> void()</name>
+ <name since="">configure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-USER-BASED-SM-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -72,7 +72,7 @@
</desc>
</func>
<func>
- <name>reconfigure(ConfDir) -> void()</name>
+ <name since="">reconfigure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-USER-BASED-SM-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -103,7 +103,7 @@
</desc>
</func>
<func>
- <name>add_user(EngineID, Name, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey) -> Ret</name>
+ <name since="">add_user(EngineID, Name, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey) -> Ret</name>
<fsummary>Add one user</fsummary>
<type>
<v>EngineID = string()</v>
@@ -130,7 +130,7 @@
</desc>
</func>
<func>
- <name>delete_user(Key) -> Ret</name>
+ <name since="">delete_user(Key) -> Ret</name>
<fsummary>Delete one user</fsummary>
<type>
<v>Key = term()</v>
diff --git a/lib/snmp/doc/src/snmp_view_based_acm_mib.xml b/lib/snmp/doc/src/snmp_view_based_acm_mib.xml
index fdad735e71..c5e98a3eb5 100644
--- a/lib/snmp/doc/src/snmp_view_based_acm_mib.xml
+++ b/lib/snmp/doc/src/snmp_view_based_acm_mib.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmp_view_based_acm_mib.xml</file>
</header>
- <module>snmp_view_based_acm_mib</module>
+ <module since="">snmp_view_based_acm_mib</module>
<modulesummary>Instrumentation Functions for SNMP-VIEW-BASED-ACM-MIB</modulesummary>
<description>
<p>The module <c>snmp_view_based_acm_mib</c> implements the instrumentation functions for the
@@ -45,7 +45,7 @@
<funcs>
<func>
- <name>configure(ConfDir) -> void()</name>
+ <name since="">configure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-VIEW-BASED-ACM-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -71,7 +71,7 @@
</func>
<func>
- <name>reconfigure(ConfDir) -> void()</name>
+ <name since="">reconfigure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-VIEW-BASED-ACM-MIB</fsummary>
<type>
<v>ConfDir = string()</v>
@@ -104,7 +104,7 @@
</func>
<func>
- <name>add_sec2group(SecModel, SecName, GroupName) -> Ret</name>
+ <name since="">add_sec2group(SecModel, SecName, GroupName) -> Ret</name>
<fsummary>Add one security to group definition</fsummary>
<type>
<v>SecModel = v1 | v2c | usm</v>
@@ -124,7 +124,7 @@
</func>
<func>
- <name>delete_sec2group(Key) -> Ret</name>
+ <name since="">delete_sec2group(Key) -> Ret</name>
<fsummary>Delete one security to group definition</fsummary>
<type>
<v>Key = term()</v>
@@ -139,7 +139,7 @@
</func>
<func>
- <name>add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) -> Ret</name>
+ <name since="">add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) -> Ret</name>
<fsummary>Add one access definition</fsummary>
<type>
<v>GroupName = string()</v>
@@ -163,7 +163,7 @@
</func>
<func>
- <name>delete_access(Key) -> Ret</name>
+ <name since="">delete_access(Key) -> Ret</name>
<fsummary>Delete one access definition</fsummary>
<type>
<v>Key = term()</v>
@@ -178,7 +178,7 @@
</func>
<func>
- <name>add_view_tree_fam(ViewIndex, SubTree, Status, Mask) -> Ret</name>
+ <name since="">add_view_tree_fam(ViewIndex, SubTree, Status, Mask) -> Ret</name>
<fsummary>Add one view tree family definition</fsummary>
<type>
<v>ViewIndex = integer()</v>
@@ -199,7 +199,7 @@
</func>
<func>
- <name>delete_view_tree_fam(Key) -> Ret</name>
+ <name since="">delete_view_tree_fam(Key) -> Ret</name>
<fsummary>Delete one view tree family definition</fsummary>
<type>
<v>Key = term()</v>
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index d756ff7a65..dc2f4e6d66 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa.xml</file>
</header>
- <module>snmpa</module>
+ <module since="">snmpa</module>
<modulesummary>Interface Functions to the SNMP toolkit agent</modulesummary>
<description>
<p>The module <c>snmpa</c> contains interface functions to the
@@ -77,7 +77,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<funcs>
<func>
- <name>add_agent_caps(SysORID, SysORDescr) -> SysORIndex</name>
+ <name since="">add_agent_caps(SysORID, SysORDescr) -> SysORIndex</name>
<fsummary>Add an AGENT-CAPABILITY definition to the agent</fsummary>
<type>
<v>SysORID = oid()</v>
@@ -93,7 +93,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>del_agent_caps(SysORIndex) -> void()</name>
+ <name since="">del_agent_caps(SysORIndex) -> void()</name>
<fsummary>Delete an AGENT-CAPABILITY definition from the agent</fsummary>
<type>
<v>SysORIndex = integer()</v>
@@ -108,7 +108,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>get_agent_caps() -> [[SysORIndex, SysORID, SysORDescr, SysORUpTime]]</name>
+ <name since="">get_agent_caps() -> [[SysORIndex, SysORID, SysORDescr, SysORUpTime]]</name>
<fsummary>Return all AGENT-CAPABILITY definitions in the agent</fsummary>
<type>
<v>SysORIndex = integer()</v>
@@ -125,8 +125,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>get(Agent, Vars) -> Values | {error, Reason}</name>
- <name>get(Agent, Vars, Context) -> Values | {error, Reason}</name>
+ <name since="">get(Agent, Vars) -> Values | {error, Reason}</name>
+ <name since="">get(Agent, Vars, Context) -> Values | {error, Reason}</name>
<fsummary>Perform a get operation on the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -150,8 +150,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>get_next(Agent, Vars) -> Values | {error, Reason}</name>
- <name>get_next(Agent, Vars, Context) -> Values | {error, Reason}</name>
+ <name since="">get_next(Agent, Vars) -> Values | {error, Reason}</name>
+ <name since="">get_next(Agent, Vars, Context) -> Values | {error, Reason}</name>
<fsummary>Perform a get-next operation on the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -176,7 +176,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<!--
<func>
- <name>get_symbolic_store_db() -> Db</name>
+ <name since="">get_symbolic_store_db() -> Db</name>
<fsummary>Retrieve the symbolic store database reference</fsummary>
<type>
<v>Db = term()</v>
@@ -193,8 +193,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
-->
<func>
- <name>backup(BackupDir) -> ok | {error, Reason}</name>
- <name>backup(Agent, BackupDir) -> ok | {error, Reason}</name>
+ <name since="">backup(BackupDir) -> ok | {error, Reason}</name>
+ <name since="">backup(Agent, BackupDir) -> ok | {error, Reason}</name>
<fsummary>Backup agent data</fsummary>
<type>
<v>BackupDir = string()</v>
@@ -216,8 +216,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</desc>
</func>
<func>
- <name>info() -> [{Key, Value}]</name>
- <name>info(Agent) -> [{Key, Value}]</name>
+ <name since="">info() -> [{Key, Value}]</name>
+ <name since="">info(Agent) -> [{Key, Value}]</name>
<fsummary>Return information about the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -236,7 +236,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>old_info_format(NewInfo) -> OldInfo</name>
+ <name since="">old_info_format(NewInfo) -> OldInfo</name>
<fsummary>Return information about the agent</fsummary>
<type>
<v>OldInfo = NewInfo = [{Key, Value}]</v>
@@ -251,8 +251,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>load_mib(Mib) -> ok | {error, Reason}</name>
- <name>load_mib(Agent, Mib) -> ok | {error, Reason}</name>
+ <name since="OTP R16B02">load_mib(Mib) -> ok | {error, Reason}</name>
+ <name since="OTP R16B02">load_mib(Agent, Mib) -> ok | {error, Reason}</name>
<fsummary>Load single MIB into the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -273,10 +273,10 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>load_mibs(Mibs) -> ok | {error, Reason}</name>
- <name>load_mibs(Mibs, Force) -> ok | {error, Reason}</name>
- <name>load_mibs(Agent, Mibs) -> ok | {error, Reason}</name>
- <name>load_mibs(Agent, Mibs, Force) -> ok | {error, Reason}</name>
+ <name since="">load_mibs(Mibs) -> ok | {error, Reason}</name>
+ <name since="">load_mibs(Mibs, Force) -> ok | {error, Reason}</name>
+ <name since="">load_mibs(Agent, Mibs) -> ok | {error, Reason}</name>
+ <name since="OTP R16B02">load_mibs(Agent, Mibs, Force) -> ok | {error, Reason}</name>
<fsummary>Load MIBs into the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -305,8 +305,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>unload_mib(Mib) -> ok | {error, Reason}</name>
- <name>unload_mib(Agent, Mib) -> ok | {error, Reason}</name>
+ <name since="OTP R16B02">unload_mib(Mib) -> ok | {error, Reason}</name>
+ <name since="OTP R16B02">unload_mib(Agent, Mib) -> ok | {error, Reason}</name>
<fsummary>Unload single MIB from the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -321,10 +321,10 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>unload_mibs(Mibs) -> ok | {error, Reason}</name>
- <name>unload_mibs(Mibs, Force) -> ok | {error, Reason}</name>
- <name>unload_mibs(Agent, Mibs) -> ok | {error, Reason}</name>
- <name>unload_mibs(Agent, Mibs, Force) -> ok | {error, Reason}</name>
+ <name since="">unload_mibs(Mibs) -> ok | {error, Reason}</name>
+ <name since="">unload_mibs(Mibs, Force) -> ok | {error, Reason}</name>
+ <name since="">unload_mibs(Agent, Mibs) -> ok | {error, Reason}</name>
+ <name since="OTP R16B02">unload_mibs(Agent, Mibs, Force) -> ok | {error, Reason}</name>
<fsummary>Unload MIBs from the agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -347,8 +347,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>which_mibs() -> Mibs</name>
- <name>which_mibs(Agent) -> Mibs</name>
+ <name since="">which_mibs() -> Mibs</name>
+ <name since="">which_mibs(Agent) -> Mibs</name>
<fsummary>Get a list of all the loaded mibs</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -365,8 +365,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>whereis_mib(MibName) -> {ok, MibFile} | {error, Reason}</name>
- <name>whereis_mib(Agent, MibName) -> {ok, MibFile} | {error, Reason}</name>
+ <name since="">whereis_mib(MibName) -> {ok, MibFile} | {error, Reason}</name>
+ <name since="">whereis_mib(Agent, MibName) -> {ok, MibFile} | {error, Reason}</name>
<fsummary>Get the path to the mib file</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -385,10 +385,10 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>current_request_id() -> {value, RequestId} | false</name>
- <name>current_context() -> {value, Context} | false</name>
- <name>current_community() -> {value, Community} | false</name>
- <name>current_address() -> {value, Address} | false</name>
+ <name since="">current_request_id() -> {value, RequestId} | false</name>
+ <name since="">current_context() -> {value, Context} | false</name>
+ <name since="">current_community() -> {value, Community} | false</name>
+ <name since="">current_address() -> {value, Address} | false</name>
<fsummary>Get the request-id, context, community and address of the current request</fsummary>
<type>
<v>RequestId = integer()</v>
@@ -409,8 +409,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>enum_to_int(Name, Enum) -> {value, Int} | false</name>
- <name>enum_to_int(Db, Name, Enum) -> {value, Int} | false</name>
+ <name since="">enum_to_int(Name, Enum) -> {value, Int} | false</name>
+ <name since="">enum_to_int(Db, Name, Enum) -> {value, Int} | false</name>
<fsummary>Convert an enum value to an integer</fsummary>
<type>
<v>Db = term()</v>
@@ -435,8 +435,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>int_to_enum(Name, Int) -> {value, Enum} | false</name>
- <name>int_to_enum(Db, Name, Int) -> {value, Enum} | false</name>
+ <name since="">int_to_enum(Name, Int) -> {value, Enum} | false</name>
+ <name since="">int_to_enum(Db, Name, Int) -> {value, Enum} | false</name>
<fsummary>Convert an integer to an enum value</fsummary>
<type>
<v>Db = term()</v>
@@ -461,8 +461,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>name_to_oid(Name) -> {value, oid()} | false</name>
- <name>name_to_oid(Db, Name) -> {value, oid()} | false</name>
+ <name since="">name_to_oid(Name) -> {value, oid()} | false</name>
+ <name since="">name_to_oid(Db, Name) -> {value, oid()} | false</name>
<fsummary>Convert a symbolic name to an OID</fsummary>
<type>
<v>Db = term()</v>
@@ -482,8 +482,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>oid_to_name(OID) -> {value, Name} | false</name>
- <name>oid_to_name(Db, OID) -> {value, Name} | false</name>
+ <name since="">oid_to_name(OID) -> {value, Name} | false</name>
+ <name since="">oid_to_name(Db, OID) -> {value, Name} | false</name>
<fsummary>Convert an OID to a symbolic name</fsummary>
<type>
<v>Db = term()</v>
@@ -503,7 +503,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>which_aliasnames() -> Result</name>
+ <name since="">which_aliasnames() -> Result</name>
<fsummary>Get all alias-names known to the agent</fsummary>
<type>
<v>Result = [atom()]</v>
@@ -515,7 +515,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>which_tables() -> Result</name>
+ <name since="">which_tables() -> Result</name>
<fsummary>Get all tables known to the agent</fsummary>
<type>
<v>Result = [atom()]</v>
@@ -528,7 +528,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>which_variables() -> Result</name>
+ <name since="">which_variables() -> Result</name>
<fsummary>Get all variables known to the agent</fsummary>
<type>
<v>Result = [atom()]</v>
@@ -541,7 +541,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>which_notifications() -> Result</name>
+ <name since="">which_notifications() -> Result</name>
<fsummary>Get all notifications known to the agent</fsummary>
<type>
<v>Result = [{Name, MibName, Info}]</v>
@@ -557,15 +557,15 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>log_to_txt(LogDir)</name>
- <name>log_to_txt(LogDir, Block | Mibs)</name>
- <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_txt(LogDir)</name>
+ <name since="">log_to_txt(LogDir, Block | Mibs)</name>
+ <name since="">log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R16B03">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -576,6 +576,9 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -597,14 +600,14 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Block | Mibs) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Block | Mibs) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R16B03">log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -614,6 +617,9 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -635,7 +641,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>change_log_size(NewSize) -> ok | {error, Reason}</name>
+ <name since="">change_log_size(NewSize) -> ok | {error, Reason}</name>
<fsummary>Change the size of the Audit Trail Log</fsummary>
<type>
<v>NewSize = {MaxBytes, MaxFiles}</v>
@@ -656,8 +662,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>set_log_type(NewType) -> {ok, OldType} | {error, Reason}</name>
- <name>set_log_type(Agent, NewType) -> {ok, OldType} | {error, Reason}</name>
+ <name since="">set_log_type(NewType) -> {ok, OldType} | {error, Reason}</name>
+ <name since="">set_log_type(Agent, NewType) -> {ok, OldType} | {error, Reason}</name>
<fsummary>Change the type of the Audit Trail Log</fsummary>
<type>
<v>NewType = OldType = atl_type()</v>
@@ -678,8 +684,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>mib_of(Oid) -> {ok, MibName} | {error, Reason}</name>
- <name>mib_of(Agent, Oid) -> {ok, MibName} | {error, Reason}</name>
+ <name since="">mib_of(Oid) -> {ok, MibName} | {error, Reason}</name>
+ <name since="">mib_of(Agent, Oid) -> {ok, MibName} | {error, Reason}</name>
<fsummary>Which mib an Oid belongs to</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -698,8 +704,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>me_of(Oid) -> {ok, Me} | {error, Reason}</name>
- <name>me_of(Agent, Oid) -> {ok, Me} | {error, Reason}</name>
+ <name since="">me_of(Oid) -> {ok, Me} | {error, Reason}</name>
+ <name since="">me_of(Agent, Oid) -> {ok, Me} | {error, Reason}</name>
<fsummary>Retrieve the mib-entry of an Oid</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -718,8 +724,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>invalidate_mibs_cache() -> void()</name>
- <name>invalidate_mibs_cache(Agent) -> void()</name>
+ <name since="">invalidate_mibs_cache() -> void()</name>
+ <name since="">invalidate_mibs_cache(Agent) -> void()</name>
<fsummary>Invalidate the mib server cache</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -733,8 +739,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>enable_mibs_cache() -> void()</name>
- <name>enable_mibs_cache(Agent) -> void()</name>
+ <name since="">enable_mibs_cache() -> void()</name>
+ <name since="">enable_mibs_cache(Agent) -> void()</name>
<fsummary>Enable the mib server cache</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -747,8 +753,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>disable_mibs_cache() -> void()</name>
- <name>disable_mibs_cache(Agent) -> void()</name>
+ <name since="">disable_mibs_cache() -> void()</name>
+ <name since="">disable_mibs_cache(Agent) -> void()</name>
<fsummary>Disable the mib server cache</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -761,8 +767,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>which_mibs_cache_size() -> void()</name>
- <name>which_mibs_cache_size(Agent) -> void()</name>
+ <name since="OTP R14B">which_mibs_cache_size() -> void()</name>
+ <name since="OTP R14B">which_mibs_cache_size(Agent) -> void()</name>
<fsummary>The size of the mib server cache</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -775,12 +781,12 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>gc_mibs_cache() -> {ok, NumElementsGCed} | {error, Reason}</name>
- <name>gc_mibs_cache(Agent) -> {ok, NumElementsGCed} | {error, Reason}</name>
- <name>gc_mibs_cache(Age) -> {ok, NumElementsGCed} | {error, Reason}</name>
- <name>gc_mibs_cache(Agent, Age) -> {ok, NumElementsGCed} | {error, Reason}</name>
- <name>gc_mibs_cache(Age, GcLimit) -> {ok, NumElementsGCed} | {error, Reason}</name>
- <name>gc_mibs_cache(Agent, Age, GcLimit) -> {ok, NumElementsGCed} | {error, Reason}</name>
+ <name since="">gc_mibs_cache() -> {ok, NumElementsGCed} | {error, Reason}</name>
+ <name since="">gc_mibs_cache(Agent) -> {ok, NumElementsGCed} | {error, Reason}</name>
+ <name since="">gc_mibs_cache(Age) -> {ok, NumElementsGCed} | {error, Reason}</name>
+ <name since="">gc_mibs_cache(Agent, Age) -> {ok, NumElementsGCed} | {error, Reason}</name>
+ <name since="">gc_mibs_cache(Age, GcLimit) -> {ok, NumElementsGCed} | {error, Reason}</name>
+ <name since="">gc_mibs_cache(Agent, Age, GcLimit) -> {ok, NumElementsGCed} | {error, Reason}</name>
<fsummary>Perform mib server cache gc</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -802,8 +808,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>enable_mibs_cache_autogc() -> void()</name>
- <name>enable_mibs_cache_autogc(Agent) -> void()</name>
+ <name since="">enable_mibs_cache_autogc() -> void()</name>
+ <name since="">enable_mibs_cache_autogc(Agent) -> void()</name>
<fsummary>Enable automatic gc of the mib server cache</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -816,8 +822,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>disable_mibs_cache_autogc() -> void()</name>
- <name>disable_mibs_cache_autogc(Agent) -> void()</name>
+ <name since="">disable_mibs_cache_autogc() -> void()</name>
+ <name since="">disable_mibs_cache_autogc(Agent) -> void()</name>
<fsummary>Disable automatic gc of the mib server cache</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -830,8 +836,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>update_mibs_cache_age(NewAge) -> ok | {error, Reason}</name>
- <name>update_mibs_cache_age(Agent, NewAge) -> ok | {error, Reason}</name>
+ <name since="">update_mibs_cache_age(NewAge) -> ok | {error, Reason}</name>
+ <name since="">update_mibs_cache_age(Agent, NewAge) -> ok | {error, Reason}</name>
<fsummary>Change the mib server cache age property</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -846,8 +852,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>update_mibs_cache_gclimit(NewGcLimit) -> ok | {error, Reason}</name>
- <name>update_mibs_cache_gclimit(Agent, NewGCLimit) -> ok | {error, Reason}</name>
+ <name since="">update_mibs_cache_gclimit(NewGcLimit) -> ok | {error, Reason}</name>
+ <name since="">update_mibs_cache_gclimit(Agent, NewGCLimit) -> ok | {error, Reason}</name>
<fsummary>Change the mib server cache gclimit property</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -863,10 +869,10 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<func>
- <name>register_notification_filter(Id, Mod, Data) -> ok | {error, Reason}</name>
- <name>register_notification_filter(Agent, Id, Mod, Data) -> ok | {error, Reason}</name>
- <name>register_notification_filter(Id, Mod, Data, Where) -> ok | {error, Reason}</name>
- <name>register_notification_filter(Agent, Id, Mod, Data, Where) -> ok | {error, Reason}</name>
+ <name since="">register_notification_filter(Id, Mod, Data) -> ok | {error, Reason}</name>
+ <name since="">register_notification_filter(Agent, Id, Mod, Data) -> ok | {error, Reason}</name>
+ <name since="">register_notification_filter(Id, Mod, Data, Where) -> ok | {error, Reason}</name>
+ <name since="">register_notification_filter(Agent, Id, Mod, Data, Where) -> ok | {error, Reason}</name>
<fsummary>Register a notification filter</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -891,8 +897,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>unregister_notification_filter(Id) -> ok | {error, Reason}</name>
- <name>unregister_notification_filter(Agent, Id) -> ok | {error, Reason}</name>
+ <name since="">unregister_notification_filter(Id) -> ok | {error, Reason}</name>
+ <name since="">unregister_notification_filter(Agent, Id) -> ok | {error, Reason}</name>
<fsummary>Unregister a notification filter</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -907,8 +913,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>which_notification_filter() -> Filters</name>
- <name>which_notification_filter(Agent) -> Filters</name>
+ <name since="">which_notification_filter() -> Filters</name>
+ <name since="">which_notification_filter(Agent) -> Filters</name>
<fsummary>Which notification filter</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -923,8 +929,8 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>set_request_limit(NewLimit) -> {ok, OldLimit} | {error, Reason}</name>
- <name>set_request_limit(Agent, NewLimit) -> {ok, OldLimit} | {error, Reason}</name>
+ <name since="">set_request_limit(NewLimit) -> {ok, OldLimit} | {error, Reason}</name>
+ <name since="">set_request_limit(Agent, NewLimit) -> {ok, OldLimit} | {error, Reason}</name>
<fsummary>Change the request limit</fsummary>
<type>
<v>NewLimit = OldLimit = infinity | integer() >= 0</v>
@@ -944,7 +950,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>register_subagent(Agent, SubTreeOid, Subagent) -> ok | {error, Reason}</name>
+ <name since="">register_subagent(Agent, SubTreeOid, Subagent) -> ok | {error, Reason}</name>
<fsummary>Register a sub-agent under a sub-tree</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -969,7 +975,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>unregister_subagent(Agent, SubagentOidOrPid) -> ok | {ok, SubAgentPid} | {error, Reason}</name>
+ <name since="">unregister_subagent(Agent, SubagentOidOrPid) -> ok | {ok, SubAgentPid} | {error, Reason}</name>
<fsummary>Unregister a sub-agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -986,7 +992,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
<func>
- <name>send_notification2(Agent, Notification, SendOpts) -> void()</name>
+ <name since="OTP R14B03">send_notification2(Agent, Notification, SendOpts) -> void()</name>
<fsummary>Send notification</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -1113,11 +1119,11 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
<func>
- <name>send_notification(Agent, Notification, Receiver)</name>
- <name>send_notification(Agent, Notification, Receiver, Varbinds)</name>
- <name>send_notification(Agent, Notification, Receiver, NotifyName, Varbinds)</name>
- <name>send_notification(Agent, Notification, Receiver, NotifyName, ContextName, Varbinds) -> void() </name>
- <name>send_notification(Agent, Notification, Receiver, NotifyName, ContextName, Varbinds, LocalEngineID) -> void() </name>
+ <name since="">send_notification(Agent, Notification, Receiver)</name>
+ <name since="">send_notification(Agent, Notification, Receiver, Varbinds)</name>
+ <name since="">send_notification(Agent, Notification, Receiver, NotifyName, Varbinds)</name>
+ <name since="">send_notification(Agent, Notification, Receiver, NotifyName, ContextName, Varbinds) -> void() </name>
+ <name since="OTP R14B">send_notification(Agent, Notification, Receiver, NotifyName, ContextName, Varbinds, LocalEngineID) -> void() </name>
<fsummary>Send a notification</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -1318,13 +1324,13 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
<func>
- <name>discovery(TargetName, Notification) -> {ok, ManagerEngineID} | {error, Reason}</name>
- <name>discovery(TargetName, Notification, Varbinds) -> {ok, ManagerEngineID} | {error, Reason}</name>
- <name>discovery(TargetName, Notification, DiscoHandler) -> {ok, ManagerEngineID} | {error, Reason}</name>
- <name>discovery(TargetName, Notification, ContextName, Varbinds) -> {ok, ManagerEngineID} | {error, Reason}</name>
- <name>discovery(TargetName, Notification, Varbinds, DiscoHandler) -> {ok, ManagerEngineID} | {error, Reason}</name>
- <name>discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler) -> {ok, ManagerEngineID} | {error, Reason}</name>
- <name>discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler, ExtraInfo) -> {ok, ManagerEngineID} | {error, Reason}</name>
+ <name since="">discovery(TargetName, Notification) -> {ok, ManagerEngineID} | {error, Reason}</name>
+ <name since="">discovery(TargetName, Notification, Varbinds) -> {ok, ManagerEngineID} | {error, Reason}</name>
+ <name since="">discovery(TargetName, Notification, DiscoHandler) -> {ok, ManagerEngineID} | {error, Reason}</name>
+ <name since="">discovery(TargetName, Notification, ContextName, Varbinds) -> {ok, ManagerEngineID} | {error, Reason}</name>
+ <name since="">discovery(TargetName, Notification, Varbinds, DiscoHandler) -> {ok, ManagerEngineID} | {error, Reason}</name>
+ <name since="">discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler) -> {ok, ManagerEngineID} | {error, Reason}</name>
+ <name since="">discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler, ExtraInfo) -> {ok, ManagerEngineID} | {error, Reason}</name>
<fsummary>Initiate the discovery process with a manager</fsummary>
<type>
<v>TargetName = string()</v>
@@ -1373,7 +1379,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>convert_config(OldConfig) -> AgentConfig</name>
+ <name since="">convert_config(OldConfig) -> AgentConfig</name>
<fsummary>Convert old snmp config to new agent config</fsummary>
<type>
<v>OldConfig = list()</v>
@@ -1397,8 +1403,8 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>restart_worker() -> void()</name>
- <name>restart_worker(Agent) -> void()</name>
+ <name since="">restart_worker() -> void()</name>
+ <name since="">restart_worker(Agent) -> void()</name>
<fsummary>Restart the worker process of a multi-threaded agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -1413,8 +1419,8 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>restart_set_worker() -> void()</name>
- <name>restart_set_worker(Agent) -> void()</name>
+ <name since="">restart_set_worker() -> void()</name>
+ <name since="">restart_set_worker(Agent) -> void()</name>
<fsummary>Restart the set worker process of a multi-threaded agent</fsummary>
<type>
<v>Agent = pid() | atom()</v>
@@ -1429,7 +1435,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>print_mib_info() -> void()</name>
+ <name since="OTP R14B02">print_mib_info() -> void()</name>
<fsummary>Print mib info</fsummary>
<desc>
<p>Prints the content of all the (snmp) tables and variables
@@ -1440,7 +1446,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>print_mib_tables() -> void()</name>
+ <name since="OTP R14B02">print_mib_tables() -> void()</name>
<fsummary>Print mib tables</fsummary>
<desc>
<p>Prints the content of all the (snmp) tables
@@ -1451,7 +1457,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>print_mib_variables() -> void()</name>
+ <name since="OTP R14B02">print_mib_variables() -> void()</name>
<fsummary>Print mib variables</fsummary>
<desc>
<p>Prints the content of all the (snmp) variables
@@ -1462,7 +1468,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</func>
<func>
- <name>verbosity(Ref,Verbosity) -> void()</name>
+ <name since="">verbosity(Ref,Verbosity) -> void()</name>
<fsummary>Assign a new verbosity for the process</fsummary>
<type>
<v>Ref = pid() | sub_agents | master_agent | net_if | mib_server | symbolic_store | note_store | local_db</v>
diff --git a/lib/snmp/doc/src/snmpa_conf.xml b/lib/snmp/doc/src/snmpa_conf.xml
index 503e44a6a2..4134a81c0c 100644
--- a/lib/snmp/doc/src/snmpa_conf.xml
+++ b/lib/snmp/doc/src/snmpa_conf.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_conf.xml</file>
</header>
- <module>snmpa_conf</module>
+ <module since="">snmpa_conf</module>
<modulesummary>Utility functions for handling the agent config files.</modulesummary>
<description>
<p>The module <c>snmpa_conf</c> contains various utility functions to
@@ -92,7 +92,7 @@ word() = 0..65535
<funcs>
<func>
- <name>agent_entry(Tag, Val) -> agent_entry()</name>
+ <name since="">agent_entry(Tag, Val) -> agent_entry()</name>
<fsummary>Create an agent entry</fsummary>
<type>
<v>Tag = intAgentTransports | intAgentUDPPort | intAgentMaxPacketSize | snmpEngineMaxMessageSize | snmpEngineID</v>
@@ -111,8 +111,8 @@ word() = 0..65535
</func>
<func>
- <name>write_agent_config(Dir, Conf) -> ok</name>
- <name>write_agent_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_agent_config(Dir, Conf) -> ok</name>
+ <name since="">write_agent_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -134,7 +134,7 @@ word() = 0..65535
</func>
<func>
- <name>append_agent_config(Dir, Conf) -> ok</name>
+ <name since="">append_agent_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -153,7 +153,7 @@ word() = 0..65535
</func>
<func>
- <name>read_agent_config(Dir) -> Conf</name>
+ <name since="">read_agent_config(Dir) -> Conf</name>
<fsummary>Read the agent config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -172,7 +172,7 @@ word() = 0..65535
</func>
<func>
- <name>standard_entry(Tag, Val) -> standard_entry()</name>
+ <name since="">standard_entry(Tag, Val) -> standard_entry()</name>
<fsummary>Create an standard entry</fsummary>
<type>
<v>Tag = sysDescr | sysObjectID | sysContact | sysName | sysLocation | sysServices | snmpEnableAuthenTraps</v>
@@ -192,8 +192,8 @@ word() = 0..65535
</func>
<func>
- <name>write_standard_config(Dir, Conf) -> ok</name>
- <name>write_standard_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_standard_config(Dir, Conf) -> ok</name>
+ <name since="">write_standard_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent standard config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -216,7 +216,7 @@ word() = 0..65535
</func>
<func>
- <name>append_standard_config(Dir, Conf) -> ok</name>
+ <name since="">append_standard_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent standard config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -236,7 +236,7 @@ word() = 0..65535
</func>
<func>
- <name>read_standard_config(Dir) -> Conf</name>
+ <name since="">read_standard_config(Dir) -> Conf</name>
<fsummary>Read the agent standard config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -255,7 +255,7 @@ word() = 0..65535
</func>
<func>
- <name>context_entry(Context) -> context_entry()</name>
+ <name since="">context_entry(Context) -> context_entry()</name>
<fsummary>Create an context entry</fsummary>
<type>
<v>Context = string()</v>
@@ -273,8 +273,8 @@ word() = 0..65535
</func>
<func>
- <name>write_context_config(Dir, Conf) -> ok</name>
- <name>write_context_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_context_config(Dir, Conf) -> ok</name>
+ <name since="">write_context_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent context(s) to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -297,7 +297,7 @@ word() = 0..65535
</func>
<func>
- <name>append_context_config(Dir, Conf) -> ok</name>
+ <name since="">append_context_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent context(s) to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -317,7 +317,7 @@ word() = 0..65535
</func>
<func>
- <name>read_context_config(Dir) -> Conf</name>
+ <name since="">read_context_config(Dir) -> Conf</name>
<fsummary>Read the agent context config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -336,8 +336,8 @@ word() = 0..65535
</func>
<func>
- <name>community_entry(CommunityIndex) -> community_entry()</name>
- <name>community_entry(CommunityIndex, CommunityName, SecName, ContextName, TransportTag) -> community_entry()</name>
+ <name since="">community_entry(CommunityIndex) -> community_entry()</name>
+ <name since="">community_entry(CommunityIndex, CommunityName, SecName, ContextName, TransportTag) -> community_entry()</name>
<fsummary>Create an community entry</fsummary>
<type>
<v>CommunityIndex = string()</v>
@@ -364,8 +364,8 @@ word() = 0..65535
</func>
<func>
- <name>write_community_config(Dir, Conf) -> ok</name>
- <name>write_community_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_community_config(Dir, Conf) -> ok</name>
+ <name since="">write_community_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent community config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -388,7 +388,7 @@ word() = 0..65535
</func>
<func>
- <name>append_community_config(Dir, Conf) -> ok</name>
+ <name since="">append_community_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent community config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -408,7 +408,7 @@ word() = 0..65535
</func>
<func>
- <name>read_community_config(Dir) -> Conf</name>
+ <name since="">read_community_config(Dir) -> Conf</name>
<fsummary>Read the agent community config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -427,10 +427,10 @@ word() = 0..65535
</func>
<func>
- <name>target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId) -> target_addr_entry()</name>
- <name>target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, TMask) -> target_addr_entry()</name>
- <name>target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry()</name>
- <name>target_addr_entry(Name, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry()</name>
+ <name since="">target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId) -> target_addr_entry()</name>
+ <name since="OTP 17.3">target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, TMask) -> target_addr_entry()</name>
+ <name since="">target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry()</name>
+ <name since="">target_addr_entry(Name, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry()</name>
<fsummary>Create an target_addr entry</fsummary>
<type>
<v>Name = string()</v>
@@ -464,8 +464,8 @@ word() = 0..65535
</func>
<func>
- <name>write_target_addr_config(Dir, Conf) -> ok</name>
- <name>write_target_addr_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_target_addr_config(Dir, Conf) -> ok</name>
+ <name since="">write_target_addr_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent target_addr config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -488,7 +488,7 @@ word() = 0..65535
</func>
<func>
- <name>append_target_addr_config(Dir, Conf) -> ok</name>
+ <name since="">append_target_addr_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent target_addr config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -508,7 +508,7 @@ word() = 0..65535
</func>
<func>
- <name>read_target_addr_config(Dir) -> Conf</name>
+ <name since="">read_target_addr_config(Dir) -> Conf</name>
<fsummary>Read the agent target_addr config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -527,9 +527,9 @@ word() = 0..65535
</func>
<func>
- <name>target_params_entry(Name, Vsn) -> target_params_entry()</name>
- <name>target_params_entry(Name, Vsn, SecName, SecLevel) -> target_params_entry()</name>
- <name>target_params_entry(Name, MPModel, SecModel, SecName, SecLevel) -> target_params_entry()</name>
+ <name since="">target_params_entry(Name, Vsn) -> target_params_entry()</name>
+ <name since="">target_params_entry(Name, Vsn, SecName, SecLevel) -> target_params_entry()</name>
+ <name since="">target_params_entry(Name, MPModel, SecModel, SecName, SecLevel) -> target_params_entry()</name>
<fsummary>Create an target_params entry</fsummary>
<type>
<v>Name = string()</v>
@@ -564,8 +564,8 @@ word() = 0..65535
</func>
<func>
- <name>write_target_params_config(Dir, Conf) -> ok</name>
- <name>write_target_params_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_target_params_config(Dir, Conf) -> ok</name>
+ <name since="">write_target_params_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent target_params config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -588,7 +588,7 @@ word() = 0..65535
</func>
<func>
- <name>append_target_params_config(Dir, Conf) -> ok</name>
+ <name since="">append_target_params_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent target_params config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -608,7 +608,7 @@ word() = 0..65535
</func>
<func>
- <name>read_target_params_config(Dir) -> Conf</name>
+ <name since="">read_target_params_config(Dir) -> Conf</name>
<fsummary>Read the agent target_params config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -627,10 +627,10 @@ word() = 0..65535
</func>
<func>
- <name>vacm_s2g_entry(SecModel, SecName, GroupName) -> vacm_s2g_entry()</name>
- <name>vacm_acc_entry(GroupName, Prefix, SecModel, SecLevel, Match, ReadView, WriteView, NotifyView) -> vacm_acc_entry()</name>
- <name>vacm_vtf_entry(ViewIndex, ViewSubtree) -> vacm_vtf_entry()</name>
- <name>vacm_vtf_entry(ViewIndex, ViewSubtree, ViewStatus, ViewMask) -> vacm_vtf_entry()</name>
+ <name since="">vacm_s2g_entry(SecModel, SecName, GroupName) -> vacm_s2g_entry()</name>
+ <name since="">vacm_acc_entry(GroupName, Prefix, SecModel, SecLevel, Match, ReadView, WriteView, NotifyView) -> vacm_acc_entry()</name>
+ <name since="">vacm_vtf_entry(ViewIndex, ViewSubtree) -> vacm_vtf_entry()</name>
+ <name since="">vacm_vtf_entry(ViewIndex, ViewSubtree, ViewStatus, ViewMask) -> vacm_vtf_entry()</name>
<fsummary>Create an vacm entry</fsummary>
<type>
<v>SecModel = v1 | v2c | usm</v>
@@ -665,8 +665,8 @@ word() = 0..65535
</func>
<func>
- <name>write_vacm_config(Dir, Conf) -> ok</name>
- <name>write_vacm_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_vacm_config(Dir, Conf) -> ok</name>
+ <name since="">write_vacm_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent vacm config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -690,7 +690,7 @@ word() = 0..65535
</func>
<func>
- <name>append_vacm_config(Dir, Conf) -> ok</name>
+ <name since="">append_vacm_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent vacm config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -710,7 +710,7 @@ word() = 0..65535
</func>
<func>
- <name>read_vacm_config(Dir) -> Conf</name>
+ <name since="">read_vacm_config(Dir) -> Conf</name>
<fsummary>Read the agent vacm config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -729,8 +729,8 @@ word() = 0..65535
</func>
<func>
- <name>usm_entry(EngineId) -> usm_entry()</name>
- <name>usm_entry(EngineID, UserName, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey) -> usm_entry()</name>
+ <name since="">usm_entry(EngineId) -> usm_entry()</name>
+ <name since="">usm_entry(EngineID, UserName, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey) -> usm_entry()</name>
<fsummary>Create an usm entry</fsummary>
<type>
<v>EngineId = string()</v>
@@ -762,8 +762,8 @@ word() = 0..65535
</func>
<func>
- <name>write_usm_config(Dir, Conf) -> ok</name>
- <name>write_usm_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_usm_config(Dir, Conf) -> ok</name>
+ <name since="">write_usm_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent usm config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -786,7 +786,7 @@ word() = 0..65535
</func>
<func>
- <name>append_usm_config(Dir, Conf) -> ok</name>
+ <name since="">append_usm_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent usm config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -805,7 +805,7 @@ word() = 0..65535
</func>
<func>
- <name>read_usm_config(Dir) -> Conf</name>
+ <name since="">read_usm_config(Dir) -> Conf</name>
<fsummary>Read the agent usm config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -824,7 +824,7 @@ word() = 0..65535
</func>
<func>
- <name>notify_entry(Name, Tag, Type) -> notify_entry()</name>
+ <name since="">notify_entry(Name, Tag, Type) -> notify_entry()</name>
<fsummary>Create an notify entry</fsummary>
<type>
<v>Name = string()</v>
@@ -845,8 +845,8 @@ word() = 0..65535
</func>
<func>
- <name>write_notify_config(Dir, Conf) -> ok</name>
- <name>write_notify_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_notify_config(Dir, Conf) -> ok</name>
+ <name since="">write_notify_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the agent notify config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -869,7 +869,7 @@ word() = 0..65535
</func>
<func>
- <name>append_notify_config(Dir, Conf) -> ok</name>
+ <name since="">append_notify_config(Dir, Conf) -> ok</name>
<fsummary>Append the agent notify config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -889,7 +889,7 @@ word() = 0..65535
</func>
<func>
- <name>read_notify_config(Dir) -> Conf</name>
+ <name since="">read_notify_config(Dir) -> Conf</name>
<fsummary>Read the agent notify config from the config file</fsummary>
<type>
<v>Dir = string()</v>
diff --git a/lib/snmp/doc/src/snmpa_discovery_handler.xml b/lib/snmp/doc/src/snmpa_discovery_handler.xml
index 0ea72a880c..21b8746c11 100644
--- a/lib/snmp/doc/src/snmpa_discovery_handler.xml
+++ b/lib/snmp/doc/src/snmpa_discovery_handler.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_discovery_handler.xml</file>
</header>
- <module>snmpa_discovery_handler</module>
+ <module since="">snmpa_discovery_handler</module>
<modulesummary>Behaviour module for the SNMP agent discovery handler.</modulesummary>
<description>
<p>This module defines the behaviour of the agent discovery
@@ -51,7 +51,7 @@
<funcs>
<func>
- <name>stage1_finish(TargetName, ManagerEngineID, ExtraInfo) -> ignore | {ok, usm_entry() | [usm_entry()]} | {ok, usm_entry() | [usm_entry()], NewExtraInfo}</name>
+ <name since="">stage1_finish(TargetName, ManagerEngineID, ExtraInfo) -> ignore | {ok, usm_entry() | [usm_entry()]} | {ok, usm_entry() | [usm_entry()], NewExtraInfo}</name>
<fsummary>Discovery stage 1 finish</fsummary>
<type>
<v>TargetName = string()</v>
diff --git a/lib/snmp/doc/src/snmpa_error.xml b/lib/snmp/doc/src/snmpa_error.xml
index 7cc4a3513d..6e6761b7a5 100644
--- a/lib/snmp/doc/src/snmpa_error.xml
+++ b/lib/snmp/doc/src/snmpa_error.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_error.xml</file>
</header>
- <module>snmpa_error</module>
+ <module since="">snmpa_error</module>
<modulesummary>Functions for Reporting SNMP Errors</modulesummary>
<description>
<marker id="desc"></marker>
@@ -57,7 +57,7 @@
</description>
<funcs>
<func>
- <name>config_err(Format, Args) -> void()</name>
+ <name since="">config_err(Format, Args) -> void()</name>
<fsummary>Called if a configuration error occurs</fsummary>
<type>
<v>Format = string()</v>
@@ -76,7 +76,7 @@
</func>
<func>
- <name>user_err(Format, Args) -> void()</name>
+ <name since="">user_err(Format, Args) -> void()</name>
<fsummary>Called if a user related error occurs</fsummary>
<type>
<v>Format = string()</v>
diff --git a/lib/snmp/doc/src/snmpa_error_io.xml b/lib/snmp/doc/src/snmpa_error_io.xml
index bcb2688646..d78e09ff13 100644
--- a/lib/snmp/doc/src/snmpa_error_io.xml
+++ b/lib/snmp/doc/src/snmpa_error_io.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_error_io.xml</file>
</header>
- <module>snmpa_error_io</module>
+ <module since="">snmpa_error_io</module>
<modulesummary>Functions for Reporting SNMP Errors on stdio</modulesummary>
<description>
<p>The module <c>snmpa_error_io</c> implements the
@@ -52,7 +52,7 @@
</description>
<funcs>
<func>
- <name>config_err(Format, Args) -> void()</name>
+ <name since="">config_err(Format, Args) -> void()</name>
<fsummary>Called if a configuration error occurs</fsummary>
<type>
<v>Format = string()</v>
@@ -68,7 +68,7 @@
</desc>
</func>
<func>
- <name>user_err(Format, Args) -> void()</name>
+ <name since="">user_err(Format, Args) -> void()</name>
<fsummary>Called if a user related error occurs</fsummary>
<type>
<v>Format = string()</v>
diff --git a/lib/snmp/doc/src/snmpa_error_logger.xml b/lib/snmp/doc/src/snmpa_error_logger.xml
index 4feb2e7f32..b0565a6839 100644
--- a/lib/snmp/doc/src/snmpa_error_logger.xml
+++ b/lib/snmp/doc/src/snmpa_error_logger.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_error_logger.xml</file>
</header>
- <module>snmpa_error_logger</module>
+ <module since="">snmpa_error_logger</module>
<modulesummary>Functions for Reporting SNMP Errors through the error_logger</modulesummary>
<description>
<p>The module <c>snmpa_error_logger</c> implements the
@@ -54,7 +54,7 @@
</description>
<funcs>
<func>
- <name>config_err(Format, Args) -> void()</name>
+ <name since="">config_err(Format, Args) -> void()</name>
<fsummary>Called if a configuration error occurs</fsummary>
<type>
<v>Format = string()</v>
@@ -70,7 +70,7 @@
</desc>
</func>
<func>
- <name>user_err(Format, Args) -> void()</name>
+ <name since="">user_err(Format, Args) -> void()</name>
<fsummary>Called if a user related error occurs</fsummary>
<type>
<v>Format = string()</v>
diff --git a/lib/snmp/doc/src/snmpa_error_report.xml b/lib/snmp/doc/src/snmpa_error_report.xml
index 282d9b4e59..f08dc1df23 100644
--- a/lib/snmp/doc/src/snmpa_error_report.xml
+++ b/lib/snmp/doc/src/snmpa_error_report.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_error_report.xml</file>
</header>
- <module>snmpa_error_report</module>
+ <module since="">snmpa_error_report</module>
<modulesummary>Behaviour module for reporting SNMP agent errors</modulesummary>
<description>
<marker id="desc"></marker>
@@ -52,7 +52,7 @@
</description>
<funcs>
<func>
- <name>config_err(Format, Args) -> void()</name>
+ <name since="">config_err(Format, Args) -> void()</name>
<fsummary>Called if a configuration error occurs</fsummary>
<type>
<v>Format = string()</v>
@@ -68,7 +68,7 @@
</desc>
</func>
<func>
- <name>user_err(Format, Args) -> void()</name>
+ <name since="">user_err(Format, Args) -> void()</name>
<fsummary>Called if a user related error occurs</fsummary>
<type>
<v>Format = string()</v>
diff --git a/lib/snmp/doc/src/snmpa_local_db.xml b/lib/snmp/doc/src/snmpa_local_db.xml
index ac8d466ab3..229f22ab70 100644
--- a/lib/snmp/doc/src/snmpa_local_db.xml
+++ b/lib/snmp/doc/src/snmpa_local_db.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_local_db.xml</file>
</header>
- <module>snmpa_local_db</module>
+ <module since="">snmpa_local_db</module>
<modulesummary>The SNMP built-in database</modulesummary>
<description>
<p>The module <c>snmpa_local_db</c> contains functions for
@@ -86,7 +86,7 @@
</section>
<funcs>
<func>
- <name>dump() -> ok | {error, Reason}</name>
+ <name since="">dump() -> ok | {error, Reason}</name>
<fsummary>Dump the database to disk</fsummary>
<type>
<v>Reason = term()</v>
@@ -97,7 +97,7 @@
</desc>
</func>
<func>
- <name>match(NameDb, Pattern)</name>
+ <name since="">match(NameDb, Pattern)</name>
<fsummary>Perform a match on the table</fsummary>
<desc>
<p>Performs an ets/dets matching on the table.
@@ -106,9 +106,9 @@
</desc>
</func>
<func>
- <name>print()</name>
- <name>print(TableName)</name>
- <name>print(TableName, Db)</name>
+ <name since="">print()</name>
+ <name since="">print(TableName)</name>
+ <name since="">print(TableName, Db)</name>
<fsummary>Print the database to screen</fsummary>
<type>
<v>TableName = atom()</v>
@@ -124,7 +124,7 @@
</desc>
</func>
<func>
- <name>table_create(NameDb) -> bool()</name>
+ <name since="">table_create(NameDb) -> bool()</name>
<fsummary>Create a table</fsummary>
<desc>
<p>Creates a table. If the table already exist, the old copy
@@ -135,7 +135,7 @@
</desc>
</func>
<func>
- <name>table_create_row(NameDb, RowIndex, Row) -> bool()</name>
+ <name since="">table_create_row(NameDb, RowIndex, Row) -> bool()</name>
<fsummary>Create a row in a table</fsummary>
<type>
<v>Row = {Val1, Val2, ..., ValN}</v>
@@ -147,28 +147,28 @@
</desc>
</func>
<func>
- <name>table_delete(NameDb) -> void()</name>
+ <name since="">table_delete(NameDb) -> void()</name>
<fsummary>Delete a table</fsummary>
<desc>
<p>Deletes a table.</p>
</desc>
</func>
<func>
- <name>table_delete_row(NameDb, RowIndex) -> bool()</name>
+ <name since="">table_delete_row(NameDb, RowIndex) -> bool()</name>
<fsummary>Delete the row in the table</fsummary>
<desc>
<p>Deletes the row in the table.</p>
</desc>
</func>
<func>
- <name>table_exists(NameDb) -> bool()</name>
+ <name since="">table_exists(NameDb) -> bool()</name>
<fsummary>Check if a table exists</fsummary>
<desc>
<p>Checks if a table exists.</p>
</desc>
</func>
<func>
- <name>table_get_row(NameDb, RowIndex) -> Row | undefined</name>
+ <name since="">table_get_row(NameDb, RowIndex) -> Row | undefined</name>
<fsummary>Get a row from the table</fsummary>
<type>
<v>Row = {Val1, Val2, ..., ValN}</v>
diff --git a/lib/snmp/doc/src/snmpa_mib_data.xml b/lib/snmp/doc/src/snmpa_mib_data.xml
index 1a73c9b634..b849a2826a 100644
--- a/lib/snmp/doc/src/snmpa_mib_data.xml
+++ b/lib/snmp/doc/src/snmpa_mib_data.xml
@@ -30,7 +30,7 @@
<file>snmpa_mib_data.xml</file>
</header>
- <module>snmpa_mib_data</module>
+ <module since="OTP R16B01">snmpa_mib_data</module>
<modulesummary>Behaviour module for the SNMP agent mib-server
data module.</modulesummary>
<description>
@@ -108,7 +108,7 @@
<funcs>
<func>
- <name>Module:new(Storage) -> State</name>
+ <name since="OTP R16B01">Module:new(Storage) -> State</name>
<fsummary>Create new (mib-server) data instance</fsummary>
<type>
<v>Storage = mib_storage()</v>
@@ -122,7 +122,7 @@
</func>
<func>
- <name>Module:close(State) -> void()</name>
+ <name since="OTP R16B01">Module:close(State) -> void()</name>
<fsummary>Close the mib-server data instance</fsummary>
<type>
<v>State = term()</v>
@@ -135,7 +135,7 @@
</func>
<func>
- <name>Module:sync(State) -> void()</name>
+ <name since="OTP R16B01">Module:sync(State) -> void()</name>
<fsummary>Synchronize to disc</fsummary>
<type>
<v>State = term()</v>
@@ -151,7 +151,7 @@
</func>
<func>
- <name>Module:load_mib(State, Filename, MeOverride, TeOverride) -> {ok, NewState} | {error, Reason}</name>
+ <name since="OTP R16B01">Module:load_mib(State, Filename, MeOverride, TeOverride) -> {ok, NewState} | {error, Reason}</name>
<fsummary>Load a mib into the mib-server</fsummary>
<type>
<v>State = NewState = term()</v>
@@ -172,7 +172,7 @@
</func>
<func>
- <name>Module:unload_mib(State, Filename) -> {ok, NewState} | {error, Reason}</name>
+ <name since="OTP R16B01">Module:unload_mib(State, Filename) -> {ok, NewState} | {error, Reason}</name>
<fsummary>Unload mib from the mib-server</fsummary>
<type>
<v>State = NewState = term()</v>
@@ -188,7 +188,7 @@
</func>
<func>
- <name>Module:lookup(State, Oid) -> Reply</name>
+ <name since="OTP R16B01">Module:lookup(State, Oid) -> Reply</name>
<fsummary>Find the mib-entry corresponding to the Oid</fsummary>
<type>
<v>State = term()</v>
@@ -210,7 +210,7 @@
</func>
<func>
- <name>Module:next(State, Oid, MibView) -> Reply</name>
+ <name since="OTP R16B01">Module:next(State, Oid, MibView) -> Reply</name>
<fsummary>Finds the lexicographically next oid</fsummary>
<type>
<v>State = term()</v>
@@ -227,7 +227,7 @@
</func>
<func>
- <name>Module:register_subagent(State, Oid, Pid) -> Reply</name>
+ <name since="OTP R16B01">Module:register_subagent(State, Oid, Pid) -> Reply</name>
<fsummary>Register the subagent</fsummary>
<type>
<v>State = NewState = term()</v>
@@ -245,7 +245,7 @@
</func>
<func>
- <name>Module:unregister_subagent(State, PidOrOid) -> Reply</name>
+ <name since="OTP R16B01">Module:unregister_subagent(State, PidOrOid) -> Reply</name>
<fsummary>Unregister the subagent</fsummary>
<type>
<v>State = NewState = term()</v>
@@ -266,7 +266,7 @@
</func>
<func>
- <name>Module:dump(State, Destination) -> Reply</name>
+ <name since="OTP R16B01">Module:dump(State, Destination) -> Reply</name>
<fsummary>Unregister the subagent</fsummary>
<type>
<v>State = term()</v>
@@ -284,7 +284,7 @@
</func>
<func>
- <name>Module:which_mib(State, Oid) -> Reply</name>
+ <name since="OTP R16B01">Module:which_mib(State, Oid) -> Reply</name>
<fsummary>Retrieve the mib file for an oid()</fsummary>
<type>
<v>State = term()</v>
@@ -301,7 +301,7 @@
</func>
<func>
- <name>Module:which_mibs(State) -> Reply</name>
+ <name since="OTP R16B01">Module:which_mibs(State) -> Reply</name>
<fsummary>Retrieve all loaded mib files</fsummary>
<type>
<v>State = term()</v>
@@ -317,7 +317,7 @@
</func>
<func>
- <name>Module:whereis_mib(State, MibName) -> Reply</name>
+ <name since="OTP R16B01">Module:whereis_mib(State, MibName) -> Reply</name>
<fsummary>Retrieve the mib file for the mib</fsummary>
<type>
<v>State = term()</v>
@@ -334,7 +334,7 @@
</func>
<func>
- <name>Module:info(State) -> Reply</name>
+ <name since="OTP R16B01">Module:info(State) -> Reply</name>
<fsummary>Retrieve misc info for the mib data</fsummary>
<type>
<v>State = term()</v>
@@ -352,7 +352,7 @@
</func>
<func>
- <name>Module:backup(State, BackupDir) -> Reply</name>
+ <name since="OTP R16B01">Module:backup(State, BackupDir) -> Reply</name>
<fsummary>Perform a backup of the mib-server data</fsummary>
<type>
<v>State = term()</v>
@@ -370,7 +370,7 @@
</func>
<func>
- <name>Module:code_change(Destination, Vsn, Extra, State) -> NewState</name>
+ <name since="OTP R16B01">Module:code_change(Destination, Vsn, Extra, State) -> NewState</name>
<fsummary>Perform a code-change</fsummary>
<type>
<v>Destination = up | down</v>
diff --git a/lib/snmp/doc/src/snmpa_mib_storage.xml b/lib/snmp/doc/src/snmpa_mib_storage.xml
index 58ce2167ec..ee2b009e77 100644
--- a/lib/snmp/doc/src/snmpa_mib_storage.xml
+++ b/lib/snmp/doc/src/snmpa_mib_storage.xml
@@ -30,7 +30,7 @@
<file>snmpa_mib_storage.xml</file>
</header>
- <module>snmpa_mib_storage</module>
+ <module since="OTP R16B01">snmpa_mib_storage</module>
<modulesummary>
Behaviour module for the SNMP agent mib storage.
</modulesummary>
@@ -96,7 +96,7 @@
<funcs>
<func>
- <name>Module:open(Name, RecordName, Fields, Type, Options) -> {ok, TabId} | {error, Reason}</name>
+ <name since="OTP R16B01">Module:open(Name, RecordName, Fields, Type, Options) -> {ok, TabId} | {error, Reason}</name>
<fsummary>Create new (mib-server) data instance</fsummary>
<type>
<v>Name = atom()</v>
@@ -122,7 +122,7 @@
</func>
<func>
- <name>Module:close(TabId) -> void()</name>
+ <name since="OTP R16B01">Module:close(TabId) -> void()</name>
<fsummary>Close the mib-storage table</fsummary>
<type>
<v>State = term()</v>
@@ -135,7 +135,7 @@
</func>
<func>
- <name>Module:read(TabId, Key) -> false | {value, Record}</name>
+ <name since="OTP R16B01">Module:read(TabId, Key) -> false | {value, Record}</name>
<fsummary>Read a record from the mib-storage table</fsummary>
<type>
<v>TabId = term()</v>
@@ -150,7 +150,7 @@
</func>
<func>
- <name>Module:write(TabId, Record) -> ok | {error, Reason}</name>
+ <name since="OTP R16B01">Module:write(TabId, Record) -> ok | {error, Reason}</name>
<fsummary>Write a record to the mib-storage table</fsummary>
<type>
<v>TabId = term()</v>
@@ -165,7 +165,7 @@
</func>
<func>
- <name>Module:delete(TabId) -> void()</name>
+ <name since="OTP R16B01">Module:delete(TabId) -> void()</name>
<fsummary>Delete an entire mib-storage table</fsummary>
<type>
<v>TabId = term()</v>
@@ -178,7 +178,7 @@
</func>
<func>
- <name>Module:delete(TabId, Key) -> ok | {error, Reason}</name>
+ <name since="OTP R16B01">Module:delete(TabId, Key) -> ok | {error, Reason}</name>
<fsummary>Delete a record from the mib-storage table</fsummary>
<type>
<v>TabId = term()</v>
@@ -193,7 +193,7 @@
</func>
<func>
- <name>Module:match_object(TabId, Pattern) -> {ok, Recs} | {error, Reason}</name>
+ <name since="OTP R16B01">Module:match_object(TabId, Pattern) -> {ok, Recs} | {error, Reason}</name>
<fsummary>Search the mib-storage table for record matching pattern</fsummary>
<type>
<v>TabId = term()</v>
@@ -210,7 +210,7 @@
</func>
<func>
- <name>Module:match_delete(TabId, Pattern) -> {ok, Recs} | {error, Reason}</name>
+ <name since="OTP R16B01">Module:match_delete(TabId, Pattern) -> {ok, Recs} | {error, Reason}</name>
<fsummary>Delete records in the mib-storage table matching pattern</fsummary>
<type>
<v>TabId = term()</v>
@@ -228,7 +228,7 @@
</func>
<func>
- <name>Module:tab2list(TabId) -> Recs</name>
+ <name since="OTP R16B01">Module:tab2list(TabId) -> Recs</name>
<fsummary>Return all records of the mib-storage table</fsummary>
<type>
<v>TabId = term()</v>
@@ -243,7 +243,7 @@
</func>
<func>
- <name>Module:info(TabId) -> {ok, Info} | {error, Reason}</name>
+ <name since="OTP R16B01">Module:info(TabId) -> {ok, Info} | {error, Reason}</name>
<fsummary>Returns information about the mib-storage table. </fsummary>
<type>
<v>TabId = term()</v>
@@ -259,7 +259,7 @@
</func>
<func>
- <name>Module:sync(TabId) -> void()</name>
+ <name since="OTP R16B01">Module:sync(TabId) -> void()</name>
<fsummary>Synchronize mib-storage table</fsummary>
<type>
<v>TabId = term()</v>
@@ -273,7 +273,7 @@
</func>
<func>
- <name>Module:backup(TabId, BackupDir) -> ok | {error, Reason}</name>
+ <name since="OTP R16B01">Module:backup(TabId, BackupDir) -> ok | {error, Reason}</name>
<fsummary>Perform a backup of the mib-storage table</fsummary>
<type>
<v>TabId = term()</v>
diff --git a/lib/snmp/doc/src/snmpa_mpd.xml b/lib/snmp/doc/src/snmpa_mpd.xml
index a39c087c20..d76a9c4a94 100644
--- a/lib/snmp/doc/src/snmpa_mpd.xml
+++ b/lib/snmp/doc/src/snmpa_mpd.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_mpd.xml</file>
</header>
- <module>snmpa_mpd</module>
+ <module since="">snmpa_mpd</module>
<modulesummary>Message Processing and Dispatch module for the SNMP agent</modulesummary>
<description>
<p>The module <c>snmpa_mpd</c> implements the version independent
@@ -52,7 +52,7 @@
<funcs>
<func>
- <name>init(Vsns) -> mpd_state()</name>
+ <name since="">init(Vsns) -> mpd_state()</name>
<fsummary>Initialize the MPD module</fsummary>
<type>
<v>Vsns = [Vsn]</v>
@@ -70,8 +70,8 @@
</func>
<func>
- <name>process_packet(Packet, From, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket}</name>
- <name>process_packet(Packet, From, LocalEngineID, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket}</name>
+ <name since="OTP 17.3">process_packet(Packet, From, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket}</name>
+ <name since="OTP R14B">process_packet(Packet, From, LocalEngineID, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket}</name>
<fsummary>Process a packet received from the network</fsummary>
<type>
<v>Packet = binary()</v>
@@ -108,8 +108,8 @@
</func>
<func>
- <name>generate_response_msg(Vsn, RePdu, Type, ACMData, Log) -> {ok, Packet} | {discarded, Reason}</name>
- <name>generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log) -> {ok, Packet} | {discarded, Reason}</name>
+ <name since="OTP R14B">generate_response_msg(Vsn, RePdu, Type, ACMData, Log) -> {ok, Packet} | {discarded, Reason}</name>
+ <name since="OTP R14B">generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log) -> {ok, Packet} | {discarded, Reason}</name>
<fsummary>Generate a response packet to be sent to the network</fsummary>
<type>
<v>Vsn = 'version-1' | 'version-2' | 'version-3'</v>
@@ -136,8 +136,8 @@
</func>
<func>
- <name>generate_msg(Vsn, NoteStore, Pdu, MsgData, To) -> {ok, PacketsAndAddresses} | {discarded, Reason}</name>
- <name>generate_msg(Vsn, NoteStore, Pdu, MsgData, LocalEngineID, To) -> {ok, PacketsAndAddresses} | {discarded, Reason}</name>
+ <name since="OTP R14B">generate_msg(Vsn, NoteStore, Pdu, MsgData, To) -> {ok, PacketsAndAddresses} | {discarded, Reason}</name>
+ <name since="OTP R14B">generate_msg(Vsn, NoteStore, Pdu, MsgData, LocalEngineID, To) -> {ok, PacketsAndAddresses} | {discarded, Reason}</name>
<fsummary>Generate a request message to be sent to the network</fsummary>
<type>
<v>Vsn = 'version-1' | 'version-2' | 'version-3'</v>
@@ -185,7 +185,7 @@
</func>
<func>
- <name>process_taddrs(TDests) -> Dests</name>
+ <name since="OTP 17.3">process_taddrs(TDests) -> Dests</name>
<fsummary>Transform addresses from internal MIB format to a less internal
</fsummary>
<type>
@@ -211,7 +211,7 @@
</func>
<func>
- <name>discarded_pdu(Variable) -> void()</name>
+ <name since="">discarded_pdu(Variable) -> void()</name>
<fsummary>Increment the variable associated with a discarded pdu</fsummary>
<type>
<v>Variable = atom()</v>
diff --git a/lib/snmp/doc/src/snmpa_network_interface.xml b/lib/snmp/doc/src/snmpa_network_interface.xml
index d4d4989e90..3e79df11b1 100644
--- a/lib/snmp/doc/src/snmpa_network_interface.xml
+++ b/lib/snmp/doc/src/snmpa_network_interface.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_network_interface.xml</file>
</header>
- <module>snmpa_network_interface</module>
+ <module since="">snmpa_network_interface</module>
<modulesummary>Behaviour module for the SNMP agent network interface.</modulesummary>
<description>
<p>This module defines the behaviour of the agent network
@@ -68,7 +68,7 @@
<funcs>
<func>
- <name>start_link(Prio, NoteStore, MasterAgent, Opts) -> {ok, Pid} | {error, Reason}</name>
+ <name since="">start_link(Prio, NoteStore, MasterAgent, Opts) -> {ok, Pid} | {error, Reason}</name>
<fsummary>Start-link the network interface process</fsummary>
<type>
<v>Prio = priority()</v>
@@ -93,7 +93,7 @@
</func>
<func>
- <name>info(Pid) -> [{Key, Value}]</name>
+ <name since="">info(Pid) -> [{Key, Value}]</name>
<fsummary>Return information about the running network interface process</fsummary>
<type>
<v>Pid = pid()</v>
@@ -112,7 +112,7 @@
</func>
<func>
- <name>verbosity(Pid, Verbosity) -> void()</name>
+ <name since="">verbosity(Pid, Verbosity) -> void()</name>
<fsummary>Change the verbosity of a running network interface process</fsummary>
<type>
<v>Pid = pid()</v>
@@ -126,7 +126,7 @@
</func>
<func>
- <name>get_log_type(Pid) -> {ok, LogType} | {error, Reason}</name>
+ <name since="">get_log_type(Pid) -> {ok, LogType} | {error, Reason}</name>
<fsummary>Get the Audit Trail Log type</fsummary>
<type>
<v>Pid = pid()</v>
@@ -147,7 +147,7 @@
</func>
<func>
- <name>set_log_type(Pid, NewType) -> {ok, OldType} | {error, Reason}</name>
+ <name since="">set_log_type(Pid, NewType) -> {ok, OldType} | {error, Reason}</name>
<fsummary>Change the Audit Trail Log type</fsummary>
<type>
<v>Pid = pid()</v>
diff --git a/lib/snmp/doc/src/snmpa_network_interface_filter.xml b/lib/snmp/doc/src/snmpa_network_interface_filter.xml
index 7cd08f8935..02c7d291dd 100644
--- a/lib/snmp/doc/src/snmpa_network_interface_filter.xml
+++ b/lib/snmp/doc/src/snmpa_network_interface_filter.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_network_interface_filter.xml</file>
</header>
- <module>snmpa_network_interface_filter</module>
+ <module since="">snmpa_network_interface_filter</module>
<modulesummary>Behaviour module for the SNMP agent network-interface filter.</modulesummary>
<description>
<p>This module defines the behaviour of the agent network interface
@@ -101,7 +101,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
</section>
<funcs>
<func>
- <name>accept_recv(Domain, Addr) -> boolean()</name>
+ <name since="">accept_recv(Domain, Addr) -> boolean()</name>
<fsummary>Shall the received message be accepted</fsummary>
<type>
<v>Domain = transportDomain()</v>
@@ -116,7 +116,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
</desc>
</func>
<func>
- <name>accept_send(Domain, Addr) -> boolean()</name>
+ <name since="">accept_send(Domain, Addr) -> boolean()</name>
<fsummary>Shall the message be sent</fsummary>
<type>
<v>Domain = transportDomain()</v>
@@ -131,7 +131,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
</desc>
</func>
<func>
- <name>accept_recv_pdu(Domain, Addr, PduType) -> boolean()</name>
+ <name since="">accept_recv_pdu(Domain, Addr, PduType) -> boolean()</name>
<fsummary>Shall the received pdu be accepted</fsummary>
<type>
<v>Domain = transportDomain()</v>
@@ -148,7 +148,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
</desc>
</func>
<func>
- <name>accept_send_pdu(Targets, PduType) -> Reply</name>
+ <name since="">accept_send_pdu(Targets, PduType) -> Reply</name>
<fsummary>Shall the pdu be sent</fsummary>
<type>
<v>Targets = targets()</v>
diff --git a/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml b/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml
index cbae158544..5dad372710 100644
--- a/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml
+++ b/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml
@@ -34,7 +34,7 @@
<rev></rev>
<file>snmpa_notification_delivery_info_receiver.xml</file>
</header>
- <module>snmpa_notification_delivery_info_receiver</module>
+ <module since="">snmpa_notification_delivery_info_receiver</module>
<modulesummary>
Behaviour module for the SNMP agent notification delivery
information receiver.
@@ -76,7 +76,7 @@
<funcs>
<func>
- <name>delivery_targets(Tag, Targets, Extra) -> void()</name>
+ <name since="">delivery_targets(Tag, Targets, Extra) -> void()</name>
<fsummary>Inform about target addresses</fsummary>
<type>
<v>Tag = term()</v>
@@ -97,7 +97,7 @@
</func>
<func>
- <name>delivery_info(Tag, Target, DeliveryResult, Extra) -> void()</name>
+ <name since="">delivery_info(Tag, Target, DeliveryResult, Extra) -> void()</name>
<fsummary>Inform about delivery result</fsummary>
<type>
<v>Tag = term()</v>
diff --git a/lib/snmp/doc/src/snmpa_notification_filter.xml b/lib/snmp/doc/src/snmpa_notification_filter.xml
index 0f16ba4440..902412ccc5 100644
--- a/lib/snmp/doc/src/snmpa_notification_filter.xml
+++ b/lib/snmp/doc/src/snmpa_notification_filter.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_notification_filter.xml</file>
</header>
- <module>snmpa_notification_filter</module>
+ <module since="">snmpa_notification_filter</module>
<modulesummary>Behaviour module for the SNMP agent notification filters.</modulesummary>
<description>
<p>This module defines the behaviour of the agent notification
@@ -51,7 +51,7 @@
</description>
<funcs>
<func>
- <name>handle_notification(Notif, Data) -> Reply</name>
+ <name since="">handle_notification(Notif, Data) -> Reply</name>
<fsummary>Handle a notification</fsummary>
<type>
<v>Reply = send | {send, NewNotif} | dont_send</v>
diff --git a/lib/snmp/doc/src/snmpa_supervisor.xml b/lib/snmp/doc/src/snmpa_supervisor.xml
index 86c6fbc350..e11cde390f 100644
--- a/lib/snmp/doc/src/snmpa_supervisor.xml
+++ b/lib/snmp/doc/src/snmpa_supervisor.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpa_supervisor.xml</file>
</header>
- <module>snmpa_supervisor</module>
+ <module since="">snmpa_supervisor</module>
<modulesummary>A supervisor for the SNMP agent Processes</modulesummary>
<description>
<p>This is the top supervisor for the agent part of the SNMP
@@ -42,7 +42,7 @@
</description>
<funcs>
<func>
- <name>start_sub_sup(Opts) -> {ok, pid()} | {error, {already_started, pid()}} | {error, Reason}</name>
+ <name since="">start_sub_sup(Opts) -> {ok, pid()} | {error, {already_started, pid()}} | {error, Reason}</name>
<fsummary>Start the SNMP supervisor for sub-agents only</fsummary>
<type>
<v>Opts = [opt()]</v>
@@ -60,7 +60,7 @@
</desc>
</func>
<func>
- <name>start_master_sup(Opts) -> {ok, pid()} | {error, {already_started, pid()}} | {error, Reason}</name>
+ <name since="">start_master_sup(Opts) -> {ok, pid()} | {error, {already_started, pid()}} | {error, Reason}</name>
<fsummary>Start the SNMP supervisor for all agents</fsummary>
<type>
<v>Opts = [opt()]</v>
@@ -82,7 +82,7 @@
</desc>
</func>
<func>
- <name>start_sub_agent(ParentAgent,Subtree,Mibs) -> {ok, pid()} | {error, Reason}</name>
+ <name since="">start_sub_agent(ParentAgent,Subtree,Mibs) -> {ok, pid()} | {error, Reason}</name>
<fsummary>Start a sub-agent</fsummary>
<type>
<v>ParentAgent = pid()</v>
@@ -99,7 +99,7 @@
</desc>
</func>
<func>
- <name>stop_sub_agent(SubAgent) -> ok | no_such_child</name>
+ <name since="">stop_sub_agent(SubAgent) -> ok | no_such_child</name>
<fsummary>Stop a sub-agent</fsummary>
<type>
<v>SubAgent = pid()</v>
diff --git a/lib/snmp/doc/src/snmpc.xml b/lib/snmp/doc/src/snmpc.xml
index aba51bb500..b22b32a133 100644
--- a/lib/snmp/doc/src/snmpc.xml
+++ b/lib/snmp/doc/src/snmpc.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpc.xml</file>
</header>
- <module>snmpc</module>
+ <module since="">snmpc</module>
<modulesummary>Interface Functions to the SNMP toolkit MIB compiler</modulesummary>
<description>
<p>The module <c>snmpc</c> contains interface functions to the
@@ -43,8 +43,8 @@
<funcs>
<func>
- <name>compile(File)</name>
- <name>compile(File, Options) -> {ok, BinFileName} | {error, Reason}</name>
+ <name since="">compile(File)</name>
+ <name since="">compile(File, Options) -> {ok, BinFileName} | {error, Reason}</name>
<fsummary>Compile the specified MIB</fsummary>
<type>
<v>File = string()</v>
@@ -236,7 +236,7 @@
</func>
<func>
- <name>is_consistent(Mibs) -> ok | {error, Reason}</name>
+ <name since="">is_consistent(Mibs) -> ok | {error, Reason}</name>
<fsummary>Check for OID conflicts between MIBs</fsummary>
<type>
<v>Mibs = [MibName]</v>
@@ -252,7 +252,7 @@
</func>
<func>
- <name>mib_to_hrl(MibName) -> ok | {error, Reason}</name>
+ <name since="">mib_to_hrl(MibName) -> ok | {error, Reason}</name>
<fsummary>Generate constants for the objects in the MIB</fsummary>
<type>
<v>MibName = string()</v>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index 4818aeb697..c45df98ee0 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpm.xml</file>
</header>
- <module>snmpm</module>
+ <module since="">snmpm</module>
<modulesummary>Interface functions to the SNMP toolkit manager</modulesummary>
<description>
<p>The module <c>snmpm</c> contains interface functions to the
@@ -77,7 +77,7 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv
</section>
<funcs>
<func>
- <name>monitor() -> Ref</name>
+ <name since="">monitor() -> Ref</name>
<fsummary>Monitor the snmp manager</fsummary>
<type>
<v>Ref = reference()</v>
@@ -92,7 +92,7 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>demonitor(Ref) -> void()</name>
+ <name since="">demonitor(Ref) -> void()</name>
<fsummary>Turn off monitoring of the snmp manager</fsummary>
<type>
<v>Ref = reference()</v>
@@ -105,7 +105,7 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>notify_started(Timeout) -> Pid</name>
+ <name since="">notify_started(Timeout) -> Pid</name>
<fsummary>Request to be notified when manager started</fsummary>
<type>
<v>Timeout = integer()</v>
@@ -148,7 +148,7 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>cancel_notify_started(Pid) -> void()</name>
+ <name since="">cancel_notify_started(Pid) -> void()</name>
<fsummary>Cancel request to be notified when manager started</fsummary>
<type>
<v>Pid = pid()</v>
@@ -161,8 +161,8 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>register_user(Id, Module, Data) -> ok | {error, Reason}</name>
- <name>register_user(Id, Module, Data, DefaultAgentConfig) -> ok | {error, Reason}</name>
+ <name since="">register_user(Id, Module, Data) -> ok | {error, Reason}</name>
+ <name since="">register_user(Id, Module, Data, DefaultAgentConfig) -> ok | {error, Reason}</name>
<fsummary>Register a user of the manager</fsummary>
<type>
<v>Id = term()</v>
@@ -204,8 +204,8 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>register_user_monitor(Id, Module, Data) -> ok | {error, Reason}</name>
- <name>register_user_monitor(Id, Module, Data, DefaultAgentConfig) -> ok | {error, Reason}</name>
+ <name since="">register_user_monitor(Id, Module, Data) -> ok | {error, Reason}</name>
+ <name since="">register_user_monitor(Id, Module, Data, DefaultAgentConfig) -> ok | {error, Reason}</name>
<fsummary>Register a monitored user of the manager</fsummary>
<type>
<v>Id = term()</v>
@@ -252,7 +252,7 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>unregister_user(Id) -> ok | {error, Reason}</name>
+ <name since="">unregister_user(Id) -> ok | {error, Reason}</name>
<fsummary>Unregister the user</fsummary>
<type>
<v>Id = term()</v>
@@ -265,7 +265,7 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>which_users() -> Users</name>
+ <name since="">which_users() -> Users</name>
<fsummary>Get a list of all users</fsummary>
<type>
<v>Users = [UserId]</v>
@@ -279,7 +279,7 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>register_agent(UserId, TargetName, Config) -> ok | {error, Reason}</name>
+ <name since="">register_agent(UserId, TargetName, Config) -> ok | {error, Reason}</name>
<fsummary>Register this agent</fsummary>
<type>
<v>UserId = term()</v>
@@ -325,7 +325,7 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>unregister_agent(UserId, TargetName) -> ok | {error, Reason}</name>
+ <name since="">unregister_agent(UserId, TargetName) -> ok | {error, Reason}</name>
<fsummary>Unregister the user</fsummary>
<type>
<v>UserId = term()</v>
@@ -339,7 +339,7 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>agent_info(TargetName, Item) -> {ok, Val} | {error, Reason}</name>
+ <name since="">agent_info(TargetName, Item) -> {ok, Val} | {error, Reason}</name>
<fsummary>Retrieve agent config</fsummary>
<type>
<v>TargetName = target_name()</v>
@@ -354,8 +354,8 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>update_agent_info(UserId, TargetName, Info) -> ok | {error, Reason}</name>
- <name>update_agent_info(UserId, TargetName, Item, Val) -> ok | {error, Reason}</name>
+ <name since="OTP R14B04">update_agent_info(UserId, TargetName, Info) -> ok | {error, Reason}</name>
+ <name since="">update_agent_info(UserId, TargetName, Item, Val) -> ok | {error, Reason}</name>
<fsummary>Update agent config</fsummary>
<type>
<v>UserId = term()</v>
@@ -379,8 +379,8 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>which_agents() -> Agents</name>
- <name>which_agents(UserId) -> Agents</name>
+ <name since="">which_agents() -> Agents</name>
+ <name since="">which_agents(UserId) -> Agents</name>
<fsummary>List the registered agents</fsummary>
<type>
<v>UserId = term()</v>
@@ -396,7 +396,7 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
- <name>register_usm_user(EngineID, UserName, Conf) -> ok | {error, Reason}</name>
+ <name since="">register_usm_user(EngineID, UserName, Conf) -> ok | {error, Reason}</name>
<fsummary>Register this USM user</fsummary>
<type>
<v>EngineID = string()</v>
@@ -427,7 +427,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>unregister_usm_user(EngineID, UserName) -> ok | {error, Reason}</name>
+ <name since="">unregister_usm_user(EngineID, UserName) -> ok | {error, Reason}</name>
<fsummary>Unregister this USM user</fsummary>
<type>
<v>EngineID = string()</v>
@@ -442,7 +442,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>usm_user_info(EngineID, UserName, Item) -> {ok, Val} | {error, Reason}</name>
+ <name since="">usm_user_info(EngineID, UserName, Item) -> {ok, Val} | {error, Reason}</name>
<fsummary>Retrieve usm user config</fsummary>
<type>
<v>EngineID = string()</v>
@@ -458,7 +458,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>update_usm_user_info(EngineID, UserName, Item, Val) -> ok | {error, Reason}</name>
+ <name since="">update_usm_user_info(EngineID, UserName, Item, Val) -> ok | {error, Reason}</name>
<fsummary>Update agent config</fsummary>
<type>
<v>EngineID = string()</v>
@@ -475,7 +475,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>which_usm_users() -> UsmUsers</name>
+ <name since="">which_usm_users() -> UsmUsers</name>
<fsummary>List all the registered usm users</fsummary>
<type>
<v>UsmUsers = [{EngineID,UserName}]</v>
@@ -490,7 +490,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>which_usm_users(EngineID) -> UsmUsers</name>
+ <name since="">which_usm_users(EngineID) -> UsmUsers</name>
<fsummary>List the registered usm users</fsummary>
<type>
<v>UsmUsers = [UserName]</v>
@@ -505,8 +505,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_get2(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get2(UserId, TargetName, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_get2(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_get2(UserId, TargetName, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>get-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -559,11 +559,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_get(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get(UserId, TargetName, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get(UserId, TargetName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get(UserId, TargetName, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get(UserId, TargetName, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get(UserId, TargetName, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get(UserId, TargetName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get(UserId, TargetName, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get(UserId, TargetName, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>get-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -605,8 +605,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_get2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get2(UserId, TargetName, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_get2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_get2(UserId, TargetName, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>get-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -647,11 +647,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_get(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get(UserId, TargetName, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get(UserId, TargetName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get(UserId, TargetName, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get(UserId, TargetName, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get(UserId, TargetName, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get(UserId, TargetName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get(UserId, TargetName, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get(UserId, TargetName, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>get-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -683,8 +683,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_get_next2(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_next2(UserId, TargetName, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_get_next2(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_get_next2(UserId, TargetName, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>get-next-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -737,11 +737,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_get_next(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_next(UserId, TargetName, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_next(UserId, TargetName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_next(UserId, TargetName, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_next(UserId, TargetName, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_next(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_next(UserId, TargetName, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_next(UserId, TargetName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_next(UserId, TargetName, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_next(UserId, TargetName, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>get-next-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -775,8 +775,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_get_next2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_next2(UserId, TargetName, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_get_next2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_get_next2(UserId, TargetName, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>get-next-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -814,11 +814,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_get_next(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_next(UserId, TargetName, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_next(UserId, TargetName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_next(UserId, TargetName, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_next(UserId, TargetName, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_next(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_next(UserId, TargetName, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_next(UserId, TargetName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_next(UserId, TargetName, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_next(UserId, TargetName, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>get-next-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -849,8 +849,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_set2(UserId, TargetName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_set2(UserId, TargetName, VarsAndVals, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_set2(UserId, TargetName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_set2(UserId, TargetName, VarsAndVals, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>set-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -906,11 +906,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_set(UserId, TargetName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_set(UserId, TargetName, ContextName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_set(UserId, TargetName, VarsAndVals, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_set(UserId, TargetName, ContextName, VarsAndVals, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_set(UserId, TargetName, ContextName, VarsAndVals, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_set(UserId, TargetName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_set(UserId, TargetName, ContextName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_set(UserId, TargetName, VarsAndVals, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_set(UserId, TargetName, ContextName, VarsAndVals, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_set(UserId, TargetName, ContextName, VarsAndVals, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>set-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -946,8 +946,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_set2(UserId, TargetName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_set2(UserId, TargetName, VarsAndVals, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_set2(UserId, TargetName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_set2(UserId, TargetName, VarsAndVals, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>set-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -990,11 +990,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_set(UserId, TargetName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_set(UserId, TargetName, ContextName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_set(UserId, TargetName, VarsAndVals, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_set(UserId, TargetName, ContextName, VarsAndVals, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_set(UserId, TargetName, ContextName, VarsAndVals, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_set(UserId, TargetName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_set(UserId, TargetName, ContextName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_set(UserId, TargetName, VarsAndVals, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_set(UserId, TargetName, ContextName, VarsAndVals, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_set(UserId, TargetName, ContextName, VarsAndVals, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>set-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -1026,8 +1026,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_get_bulk2(UserId, TragetName, NonRep, MaxRep, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_bulk2(UserId, TragetName, NonRep, MaxRep, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_get_bulk2(UserId, TragetName, NonRep, MaxRep, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="OTP R14B03">sync_get_bulk2(UserId, TragetName, NonRep, MaxRep, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>get-bulk-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -1082,11 +1082,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>sync_get_bulk(UserId, TragetName, NonRep, MaxRep, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_bulk(UserId, TragetName, NonRep, MaxRep, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name>sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<fsummary>Synchronous <c>get-bulk-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -1121,8 +1121,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="OTP R14B03">async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>get-bulk-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -1162,11 +1162,11 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name>async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
+ <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
<fsummary>Asynchronous <c>get-bulk-request</c></fsummary>
<type>
<v>UserId = term()</v>
@@ -1199,7 +1199,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>cancel_async_request(UserId, ReqId) -> ok | {error, Reason}</name>
+ <name since="">cancel_async_request(UserId, ReqId) -> ok | {error, Reason}</name>
<fsummary>Cancel a asynchronous request</fsummary>
<type>
<v>UserId = term()</v>
@@ -1214,15 +1214,15 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>log_to_txt(LogDir)</name>
- <name>log_to_txt(LogDir, Block | Mibs)</name>
- <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name since="OTP R16B03">log_to_txt(LogDir)</name>
+ <name since="">log_to_txt(LogDir, Block | Mibs)</name>
+ <name since="">log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R16B03">log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -1233,6 +1233,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -1254,15 +1257,15 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Block | Mibs) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Block | Mibs) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R15B01">log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name since="OTP R16B03">log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -1272,6 +1275,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -1293,7 +1299,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>change_log_size(NewSize) -> ok | {error, Reason}</name>
+ <name since="">change_log_size(NewSize) -> ok | {error, Reason}</name>
<fsummary>Change the size of the Audit Trail Log</fsummary>
<type>
<v>NewSize = {MaxBytes, MaxFiles}</v>
@@ -1315,7 +1321,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>set_log_type(NewType) -> {ok, OldType} | {error, Reason}</name>
+ <name since="">set_log_type(NewType) -> {ok, OldType} | {error, Reason}</name>
<fsummary>Change the Audit Trail Log type</fsummary>
<type>
<v>NewType = OldType = atl_type()</v>
@@ -1334,7 +1340,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>load_mib(Mib) -> ok | {error, Reason}</name>
+ <name since="">load_mib(Mib) -> ok | {error, Reason}</name>
<fsummary>Load a MIB into the manager</fsummary>
<type>
<v>Mib = MibName</v>
@@ -1355,7 +1361,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>unload_mib(Mib) -> ok | {error, Reason}</name>
+ <name since="">unload_mib(Mib) -> ok | {error, Reason}</name>
<fsummary>Unload a MIB from the manager</fsummary>
<type>
<v>Mib = MibName</v>
@@ -1376,7 +1382,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>which_mibs() -> Mibs</name>
+ <name since="">which_mibs() -> Mibs</name>
<fsummary>Which mibs are loaded into the manager</fsummary>
<type>
<v>Mibs = [{MibName, MibFile}]</v>
@@ -1391,7 +1397,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>name_to_oid(Name) -> {ok, Oids} | {error, Reason}</name>
+ <name since="">name_to_oid(Name) -> {ok, Oids} | {error, Reason}</name>
<fsummary>Get all the possible oid's for an alias-name</fsummary>
<type>
<v>Name = atom()</v>
@@ -1408,7 +1414,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>oid_to_name(Oid) -> {ok, Name} | {error, Reason}</name>
+ <name since="">oid_to_name(Oid) -> {ok, Name} | {error, Reason}</name>
<fsummary>Get the alias-name of the oid </fsummary>
<type>
<v>Oid = oid()</v>
@@ -1423,7 +1429,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>oid_to_type(Oid) -> {ok, Type} | {error, Reason}</name>
+ <name since="">oid_to_type(Oid) -> {ok, Type} | {error, Reason}</name>
<fsummary>Get the type of the the oid</fsummary>
<type>
<v>Oid = oid()</v>
@@ -1438,7 +1444,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>backup(BackupDir) -> ok | {error, Reason}</name>
+ <name since="">backup(BackupDir) -> ok | {error, Reason}</name>
<fsummary>Backup manager data</fsummary>
<type>
<v>BackupDir = string()</v>
@@ -1452,7 +1458,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>info() -> [{Key, Value}]</name>
+ <name since="">info() -> [{Key, Value}]</name>
<fsummary>Return information about the manager</fsummary>
<type>
<v>Key = atom()</v>
@@ -1469,7 +1475,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>verbosity(Ref, Verbosity) -> void()</name>
+ <name since="">verbosity(Ref, Verbosity) -> void()</name>
<fsummary>Assign a new verbosity for the process</fsummary>
<type>
<v>Ref = server | config | net_if | note_store | all</v>
@@ -1486,8 +1492,8 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>format_reason(Reason) -> string()</name>
- <name>format_reason(Prefix, Reason) -> string()</name>
+ <name since="">format_reason(Reason) -> string()</name>
+ <name since="">format_reason(Prefix, Reason) -> string()</name>
<fsummary>Assign a new verbosity for the process</fsummary>
<type>
<v>Reason = term()</v>
diff --git a/lib/snmp/doc/src/snmpm_conf.xml b/lib/snmp/doc/src/snmpm_conf.xml
index a3097e5f7e..17ecf2df7c 100644
--- a/lib/snmp/doc/src/snmpm_conf.xml
+++ b/lib/snmp/doc/src/snmpm_conf.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpm_conf.xml</file>
</header>
- <module>snmpm_conf</module>
+ <module since="">snmpm_conf</module>
<modulesummary>Utility functions for handling the manager config files.</modulesummary>
<description>
<p>The module <c>snmpm_conf</c> contains various utility functions to
@@ -42,7 +42,7 @@
</description>
<funcs>
<func>
- <name>manager_entry(Tag, Val) -> manager_entry()</name>
+ <name since="">manager_entry(Tag, Val) -> manager_entry()</name>
<fsummary>Create an manager entry</fsummary>
<type>
<v>Tag = address | port | engine_id | max_message_size</v>
@@ -60,8 +60,8 @@
</desc>
</func>
<func>
- <name>write_manager_config(Dir, Conf) -> ok</name>
- <name>write_manager_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_manager_config(Dir, Conf) -> ok</name>
+ <name since="">write_manager_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the manager config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -81,7 +81,7 @@
</desc>
</func>
<func>
- <name>append_manager_config(Dir, Conf) -> ok</name>
+ <name since="">append_manager_config(Dir, Conf) -> ok</name>
<fsummary>Append the manager config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -98,7 +98,7 @@
</desc>
</func>
<func>
- <name>read_manager_config(Dir) -> Conf</name>
+ <name since="">read_manager_config(Dir) -> Conf</name>
<fsummary>Read the manager config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -115,9 +115,9 @@
</desc>
</func>
<func>
- <name>users_entry(UserId) -> users_entry()</name>
- <name>users_entry(UserId, UserMod) -> users_entry()</name>
- <name>users_entry(UserId, UserMod, UserData) -> users_entry()</name>
+ <name since="">users_entry(UserId) -> users_entry()</name>
+ <name since="">users_entry(UserId, UserMod) -> users_entry()</name>
+ <name since="">users_entry(UserId, UserMod, UserData) -> users_entry()</name>
<fsummary>Create an users entry</fsummary>
<type>
<v>UserId = term()</v>
@@ -139,8 +139,8 @@
</desc>
</func>
<func>
- <name>write_users_config(Dir, Conf) -> ok</name>
- <name>write_users_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_users_config(Dir, Conf) -> ok</name>
+ <name since="">write_users_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the manager users config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -161,7 +161,7 @@
</desc>
</func>
<func>
- <name>append_users_config(Dir, Conf) -> ok</name>
+ <name since="">append_users_config(Dir, Conf) -> ok</name>
<fsummary>Append the manager users config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -179,7 +179,7 @@
</desc>
</func>
<func>
- <name>read_users_config(Dir) -> Conf</name>
+ <name since="">read_users_config(Dir) -> Conf</name>
<fsummary>Read the manager users config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -196,7 +196,7 @@
</desc>
</func>
<func>
- <name>agents_entry(UserId, TargetName, Comm, Domain, Addr, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel) -> agents_entry()</name>
+ <name since="">agents_entry(UserId, TargetName, Comm, Domain, Addr, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel) -> agents_entry()</name>
<fsummary>Create an agents entry</fsummary>
<type>
<v>UserId = term()</v>
@@ -223,8 +223,8 @@
</desc>
</func>
<func>
- <name>write_agents_config(Dir, Conf) -> ok</name>
- <name>write_agents_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_agents_config(Dir, Conf) -> ok</name>
+ <name since="">write_agents_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the manager agents to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -245,7 +245,7 @@
</desc>
</func>
<func>
- <name>append_agents_config(Dir, Conf) -> ok</name>
+ <name since="">append_agents_config(Dir, Conf) -> ok</name>
<fsummary>Append the manager agents to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -263,7 +263,7 @@
</desc>
</func>
<func>
- <name>read_agents_config(Dir) -> Conf</name>
+ <name since="">read_agents_config(Dir) -> Conf</name>
<fsummary>Read the manager agents config from the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -280,8 +280,8 @@
</desc>
</func>
<func>
- <name>usm_entry(EngineID, UserName, AuthP, AuthKey, PrivP, PrivKey) -> usm_entry()</name>
- <name>usm_entry(EngineID, UserName, SecName, AuthP, AuthKey, PrivP, PrivKey) -> usm_entry()</name>
+ <name since="">usm_entry(EngineID, UserName, AuthP, AuthKey, PrivP, PrivKey) -> usm_entry()</name>
+ <name since="">usm_entry(EngineID, UserName, SecName, AuthP, AuthKey, PrivP, PrivKey) -> usm_entry()</name>
<fsummary>Create an usm entry</fsummary>
<type>
<v>EngineID = string()</v>
@@ -303,8 +303,8 @@
</desc>
</func>
<func>
- <name>write_usm_config(Dir, Conf) -> ok</name>
- <name>write_usm_config(Dir, Hdr, Conf) -> ok</name>
+ <name since="">write_usm_config(Dir, Conf) -> ok</name>
+ <name since="">write_usm_config(Dir, Hdr, Conf) -> ok</name>
<fsummary>Write the manager usm config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -325,7 +325,7 @@
</desc>
</func>
<func>
- <name>append_usm_config(Dir, Conf) -> ok</name>
+ <name since="">append_usm_config(Dir, Conf) -> ok</name>
<fsummary>Append the manager usm config to the config file</fsummary>
<type>
<v>Dir = string()</v>
@@ -343,7 +343,7 @@
</desc>
</func>
<func>
- <name>read_usm_config(Dir) -> Conf</name>
+ <name since="">read_usm_config(Dir) -> Conf</name>
<fsummary>Read the manager usm config from the config file</fsummary>
<type>
<v>Dir = string()</v>
diff --git a/lib/snmp/doc/src/snmpm_mpd.xml b/lib/snmp/doc/src/snmpm_mpd.xml
index 08276e4b30..b024f8d294 100644
--- a/lib/snmp/doc/src/snmpm_mpd.xml
+++ b/lib/snmp/doc/src/snmpm_mpd.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpm_mpd.xml</file>
</header>
- <module>snmpm_mpd</module>
+ <module since="">snmpm_mpd</module>
<modulesummary>Message Processing and Dispatch module for the SNMP manager</modulesummary>
<description>
<p>The module <c>snmpm_mpd</c> implements the version independent
@@ -48,7 +48,7 @@
<funcs>
<func>
- <name>init_mpd(Vsns) -> mpd_state()</name>
+ <name since="">init_mpd(Vsns) -> mpd_state()</name>
<fsummary>Initialize the MPD module</fsummary>
<type>
<v>Vsns = [Vsn]</v>
@@ -64,7 +64,7 @@
</desc>
</func>
<func>
- <name>process_msg(Msg, Domain, Addr, State, NoteStore, Logger) -> {ok, Vsn, Pdu, PduMS, MsgData} | {discarded, Reason}</name>
+ <name since="OTP 17.3">process_msg(Msg, Domain, Addr, State, NoteStore, Logger) -> {ok, Vsn, Pdu, PduMS, MsgData} | {discarded, Reason}</name>
<fsummary>Process a message received from the network</fsummary>
<type>
<v>Msg = binary()</v>
@@ -92,7 +92,7 @@
</desc>
</func>
<func>
- <name>generate_msg(Vsn, NoteStore, Pdu, MsgData, Logger) -> {ok, Packet} | {discarded, Reason}</name>
+ <name since="">generate_msg(Vsn, NoteStore, Pdu, MsgData, Logger) -> {ok, Packet} | {discarded, Reason}</name>
<fsummary>Generate a request message to be sent to the network</fsummary>
<type>
<v>Vsn = 'version-1' | 'version-2' | 'version-3'</v>
@@ -117,7 +117,7 @@
</desc>
</func>
<func>
- <name>generate_response_msg(Vsn, Pdu, MsgData, Logger) -> {ok, Packet} | {discarded, Reason}</name>
+ <name since="">generate_response_msg(Vsn, Pdu, MsgData, Logger) -> {ok, Packet} | {discarded, Reason}</name>
<fsummary>Generate a response packet to be sent to the network</fsummary>
<type>
<v>Vsn = 'version-1' | 'version-2' | 'version-3'</v>
diff --git a/lib/snmp/doc/src/snmpm_network_interface.xml b/lib/snmp/doc/src/snmpm_network_interface.xml
index 73892aa2e8..e4a66ceef2 100644
--- a/lib/snmp/doc/src/snmpm_network_interface.xml
+++ b/lib/snmp/doc/src/snmpm_network_interface.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpm_network_interface.xml</file>
</header>
- <module>snmpm_network_interface</module>
+ <module since="">snmpm_network_interface</module>
<modulesummary>Behaviour module for the SNMP manager network interface.</modulesummary>
<description>
<p>This module defines the behaviour of the manager network
@@ -79,7 +79,7 @@
<funcs>
<func>
- <name>start_link(Server, NoteStore) -> {ok, Pid} | {error, Reason}</name>
+ <name since="">start_link(Server, NoteStore) -> {ok, Pid} | {error, Reason}</name>
<fsummary>Start-link the network interface process</fsummary>
<type>
<v>Server = pid()</v>
@@ -95,7 +95,7 @@
</func>
<func>
- <name>stop(Pid) -> void()</name>
+ <name since="">stop(Pid) -> void()</name>
<fsummary>Stop the network interface process</fsummary>
<type>
<v>Pid = pid()</v>
@@ -108,7 +108,7 @@
</func>
<func>
- <name>send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo) -> void()</name>
+ <name since="">send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo) -> void()</name>
<fsummary>Request the network interface process to send this pdu</fsummary>
<type>
<v>Pid = pid()</v>
@@ -142,7 +142,7 @@
</func>
<func>
- <name>inform_response(Pid, Ref, Addr, Port) -> void()</name>
+ <name since="">inform_response(Pid, Ref, Addr, Port) -> void()</name>
<fsummary>Send the inform-request ack</fsummary>
<type>
<v>Pid = pid()</v>
@@ -163,7 +163,7 @@
</func>
<func>
- <name>note_store(Pid, NoteStore) -> void()</name>
+ <name since="">note_store(Pid, NoteStore) -> void()</name>
<fsummary>Change the verbosity of the network interface process</fsummary>
<type>
<v>Pid = pid()</v>
@@ -179,7 +179,7 @@
</func>
<func>
- <name>info(Pid) -> [{Key, Value}]</name>
+ <name since="">info(Pid) -> [{Key, Value}]</name>
<fsummary>Return information about the running network interface process</fsummary>
<type>
<v>Pid = pid()</v>
@@ -198,7 +198,7 @@
</func>
<func>
- <name>verbosity(Pid, Verbosity) -> void()</name>
+ <name since="">verbosity(Pid, Verbosity) -> void()</name>
<fsummary>Change the verbosity of the network interface process</fsummary>
<type>
<v>Pid = pid()</v>
@@ -212,7 +212,7 @@
</func>
<func>
- <name>get_log_type(Pid) -> {ok, LogType} | {error, Reason}</name>
+ <name since="">get_log_type(Pid) -> {ok, LogType} | {error, Reason}</name>
<fsummary>Get the Audit Trail Log type</fsummary>
<type>
<v>Pid = pid()</v>
@@ -233,7 +233,7 @@
</func>
<func>
- <name>set_log_type(Pid, NewType) -> {ok, OldType} | {error, Reason}</name>
+ <name since="">set_log_type(Pid, NewType) -> {ok, OldType} | {error, Reason}</name>
<fsummary>Change the Audit Trail Log type</fsummary>
<type>
<v>Pid = pid()</v>
diff --git a/lib/snmp/doc/src/snmpm_network_interface_filter.xml b/lib/snmp/doc/src/snmpm_network_interface_filter.xml
index 742cd53fc6..a50572da51 100644
--- a/lib/snmp/doc/src/snmpm_network_interface_filter.xml
+++ b/lib/snmp/doc/src/snmpm_network_interface_filter.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpm_network_interface_filter.xml</file>
</header>
- <module>snmpm_network_interface_filter</module>
+ <module since="">snmpm_network_interface_filter</module>
<modulesummary>Behaviour module for the SNMP manager network-interface filter.</modulesummary>
<description>
<p>This module defines the behaviour of the manager network interface
@@ -100,7 +100,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
<funcs>
<func>
- <name>accept_recv(Domain, Addr) -> boolean()</name>
+ <name since="">accept_recv(Domain, Addr) -> boolean()</name>
<fsummary>Shall the received message be accepted</fsummary>
<type>
<v>Domain = transportDomain()</v>
@@ -116,7 +116,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
</func>
<func>
- <name>accept_send(Domain, Addr) -> boolean()</name>
+ <name since="">accept_send(Domain, Addr) -> boolean()</name>
<fsummary>Shall the message be sent</fsummary>
<type>
<v>Domain = transportDomain()</v>
@@ -132,7 +132,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
</func>
<func>
- <name>accept_recv_pdu(Domain, Addr, PduType) -> boolean()</name>
+ <name since="">accept_recv_pdu(Domain, Addr, PduType) -> boolean()</name>
<fsummary>Shall the received pdu be accepted</fsummary>
<type>
<v>Domain = transportDomain()</v>
@@ -150,7 +150,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
</func>
<func>
- <name>accept_send_pdu(Domain, Addr, PduType) -> boolean()</name>
+ <name since="">accept_send_pdu(Domain, Addr, PduType) -> boolean()</name>
<fsummary>Shall the pdu be sent</fsummary>
<type>
<v>Domain = transportDomain()</v>
diff --git a/lib/snmp/doc/src/snmpm_user.xml b/lib/snmp/doc/src/snmpm_user.xml
index 87ae1d224a..9abf596c83 100644
--- a/lib/snmp/doc/src/snmpm_user.xml
+++ b/lib/snmp/doc/src/snmpm_user.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>snmpm_user.xml</file>
</header>
- <module>snmpm_user</module>
+ <module since="">snmpm_user</module>
<modulesummary>Behaviour module for the SNMP manager user.</modulesummary>
<description>
<p>This module defines the behaviour of the manager user.
@@ -93,7 +93,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(),
<funcs>
<func>
- <name>handle_error(ReqId, Reason, UserData) -> void()</name>
+ <name since="">handle_error(ReqId, Reason, UserData) -> void()</name>
<fsummary>Handle error</fsummary>
<type>
<v>ReqId = integer()</v>
@@ -122,7 +122,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(),
</func>
<func>
- <name>handle_agent(Domain, Addr, Type, SnmpInfo, UserData) -> Reply</name>
+ <name since="">handle_agent(Domain, Addr, Type, SnmpInfo, UserData) -> Reply</name>
<fsummary>Handle agent</fsummary>
<type>
<v>Domain = transportDomainUdpIpv4 | transportDomainUdpIpv6</v>
@@ -181,7 +181,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(),
</func>
<func>
- <name>handle_pdu(TargetName, ReqId, SnmpPduInfo, UserData) -> void()</name>
+ <name since="">handle_pdu(TargetName, ReqId, SnmpPduInfo, UserData) -> void()</name>
<fsummary>Handle the reply to an asynchronous request</fsummary>
<type>
<v>TargetName = target_name()</v>
@@ -202,7 +202,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(),
</func>
<func>
- <name>handle_trap(TargetName, SnmpTrapInfo, UserData) -> Reply</name>
+ <name since="">handle_trap(TargetName, SnmpTrapInfo, UserData) -> Reply</name>
<fsummary>Handle a trap/notification message</fsummary>
<type>
<v>TargetName = TargetName2 = target_name()</v>
@@ -225,7 +225,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(),
</func>
<func>
- <name>handle_inform(TargetName, SnmpInformInfo, UserData) -> Reply</name>
+ <name since="">handle_inform(TargetName, SnmpInformInfo, UserData) -> Reply</name>
<fsummary>Handle a inform message</fsummary>
<type>
<v>TargetName = TargetName2 = target_name()</v>
@@ -253,7 +253,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(),
</func>
<func>
- <name>handle_report(TargetName, SnmpReportInfo, UserData) -> Reply</name>
+ <name since="">handle_report(TargetName, SnmpReportInfo, UserData) -> Reply</name>
<fsummary>Handle a report message</fsummary>
<type>
<v>TargetName = TargetName2 = target_name()</v>
@@ -278,7 +278,7 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(),
</func>
<func>
- <name>handle_invalid_result(IN, OUT) -> void()</name>
+ <name since="OTP R16B03">handle_invalid_result(IN, OUT) -> void()</name>
<fsummary>Handle a report message</fsummary>
<type>
<v>IN = {Func, Args}</v>
diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl
index ecf9498ca9..afed4482d2 100644
--- a/lib/snmp/src/agent/snmpa_net_if.erl
+++ b/lib/snmp/src/agent/snmpa_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -137,11 +137,10 @@ init(Prio, NoteStore, MasterAgent, Parent, Opts) ->
proc_lib:init_ack({ok, self()}),
try loop(State)
catch
- C:E when C =/= exit, E =/= shutdown ->
+ C:E:S when C =/= exit, E =/= shutdown ->
Fmt =
"loop/1 EXCEPTION ~w:~w~n"
" ~p",
- S = erlang:get_stacktrace(),
case C of
exit ->
%% Externally killed, root cause is elsewhere
@@ -647,10 +646,10 @@ maybe_handle_recv(
case
try FilterMod:accept_recv(From_1, From_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_recv(~p, ~p) crashed: ~w:~w~n ~p",
- [From_1,From_2,Class,Exception,erlang:get_stacktrace()]),
+ [From_1, From_2, Class, Exception, StackTrace]),
true
end
of
@@ -753,12 +752,11 @@ maybe_handle_recv_pdu(
case
try FilterMod:accept_recv_pdu(From_1, From_2, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_recv_pdu(~p, ~p, ~p) crashed: ~w:~w~n"
" ~p",
- [From_1,From_2,Type,Class,Exception,
- erlang:get_stacktrace()]),
+ [From_1, From_2, Type, Class, Exception, StackTrace]),
true
end
of
@@ -834,11 +832,10 @@ maybe_handle_reply_pdu(
try
FilterMod:accept_send_pdu(Addresses, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p",
- [Addresses, Type, Class, Exception,
- erlang:get_stacktrace()]),
+ [Addresses, Type, Class, Exception, StackTrace]),
true
end
of
@@ -872,7 +869,7 @@ handle_reply_pdu(
ACMData, LogF)) of
{ok, Packet} ->
?vinfo("time in agent: ~w mysec", [time_in_agent()]),
- try maybe_udp_send(S, Transport, To, Packet)
+ try maybe_udp_send_wo_log(S, Transport, To, Packet)
catch
{Reason, Sz} ->
error_msg("Cannot send message "
@@ -917,11 +914,10 @@ maybe_handle_send_pdu(
case
try FilterMod:accept_send_pdu(AddressesToFilter, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p",
- [AddressesToFilter,Type,
- Class,Exception,erlang:get_stacktrace()]),
+ [AddressesToFilter, Type, Class, Exception, StackTrace]),
true
end
of
@@ -1049,46 +1045,36 @@ do_handle_send_pdu(S, Type, Pdu, Addresses) ->
[Sz, Reason, Pdu])
end.
-do_handle_send_pdu1(
- #state{transports = Transports} = S,
- Type, Addresses) ->
+do_handle_send_pdu1(S, Type, Addresses) ->
lists:foreach(
- fun ({Domain, Address, Packet}) when is_binary(Packet) ->
- ?vdebug(
- "[~w] sending packet:~n"
- " size: ~p~n"
- " to: ~p", [Domain, sz(Packet), Address]),
- To = {Domain, Address},
- case select_transport_from_domain(Domain, Transports) of
- false ->
- error_msg(
- "Can not find transport~n"
- " size: ~p~n"
- " to: ~s",
- [sz(Packet), format_address(To)]);
- Transport ->
- maybe_udp_send(S, Transport, To, Packet)
- end;
- ({Domain, Address, {Packet, LogData}}) when is_binary(Packet) ->
- ?vdebug(
- "[~w] sending encrypted packet:~n"
- " size: ~p~n"
- " to: ~p", [Domain, sz(Packet), Address]),
- To = {Domain, Address},
- case select_transport_from_domain(Domain, Transports) of
- false ->
- error_msg(
- "Can not find transport~n"
- " size: ~p~n"
- " to: ~s",
- [sz(Packet), format_address(To)]);
- Transport ->
- maybe_udp_send(S, Transport, To, Packet, Type, LogData)
- end
+ fun ({Domain, Address, Pkg}) when is_binary(Pkg) ->
+ do_handle_send_pdu2(S, Type, Domain, Address,
+ Pkg, Pkg, "");
+ ({Domain, Address, {Pkg, LogPkg}}) when is_binary(Pkg) ->
+ do_handle_send_pdu2(S, Type, Domain, Address,
+ Pkg, LogPkg, " encrypted")
end,
Addresses).
-maybe_udp_send(
+do_handle_send_pdu2(#state{transports = Transports} = S,
+ Type, Domain, Address, Pkg, LogPkg, EncrStr) ->
+ ?vdebug("[~w] sending~s packet:"
+ "~n size: ~p"
+ "~n to: ~p", [Domain, EncrStr, sz(Pkg), Address]),
+ To = {Domain, Address},
+ case select_transport_from_domain(Domain, Transports) of
+ false ->
+ error_msg("Can not find transport: "
+ "~n size: ~p"
+ "~n to: ~s",
+ [sz(Pkg), format_address(To)]);
+ Transport ->
+ maybe_udp_send_w_log(S, Transport, To, Pkg, LogPkg, Type)
+ end.
+
+
+%% This function is used when logging has already been done!
+maybe_udp_send_wo_log(
#state{filter = FilterMod, transports = Transports},
#transport{socket = Socket},
To, Packet) ->
@@ -1096,10 +1082,10 @@ maybe_udp_send(
case
try FilterMod:accept_send(To_1, To_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send(~p, ~p) crashed: ~w:~w~n ~p",
- [To_1,To_2,Class,Exception,erlang:get_stacktrace()]),
+ [To_1, To_2, Class, Exception, StackTrace]),
true
end
of
@@ -1118,18 +1104,18 @@ maybe_udp_send(
udp_send(Socket, To, Packet)
end.
-maybe_udp_send(
+maybe_udp_send_w_log(
#state{log = Log, filter = FilterMod, transports = Transports},
#transport{socket = Socket},
- To, Packet, Type, _LogData) ->
+ To, Pkg, LogPkg, Type) ->
{To_1, To_2} = fix_filter_address(Transports, To),
case
try FilterMod:accept_send(To_1, To_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send(~p, ~p) crashed for: ~w:~w~n ~p",
- [To_1, To_2, Class, Exception, erlang:get_stacktrace()]),
+ [To_1, To_2, Class, Exception, StackTrace]),
true
end
of
@@ -1143,10 +1129,10 @@ maybe_udp_send(
_ ->
error_msg(
"FilterMod:accept_send(~p, ~p) returned: ~p",
- [To_1,To_2,Other])
+ [To_1, To_2, Other])
end,
- log(Log, Type, Packet, To),
- udp_send(Socket, To, Packet)
+ log(Log, Type, LogPkg, To),
+ udp_send(Socket, To, Pkg)
end.
udp_send(Socket, To, B) ->
@@ -1168,11 +1154,10 @@ udp_send(Socket, To, B) ->
ok ->
ok
catch
- error:ExitReason ->
+ error:ExitReason:StackTrace ->
error_msg("[exit] cannot send message "
"(destination: ~p:~p, size: ~p, reason: ~p, at: ~p)",
- [IpAddr, IpPort, sz(B), ExitReason,
- erlang:get_stacktrace()])
+ [IpAddr, IpPort, sz(B), ExitReason, StackTrace])
end.
sz(L) when is_list(L) -> length(L);
diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl
index 7f627d66d9..c810bfcd41 100644
--- a/lib/snmp/src/compile/snmpc.erl
+++ b/lib/snmp/src/compile/snmpc.erl
@@ -169,11 +169,7 @@ get_version() ->
MI = ?MODULE:module_info(),
Attr = get_info(attributes, MI),
Vsn = get_info(app_vsn, Attr),
- Comp = get_info(compile, MI),
- Time = get_info(time, Comp),
- {Year, Month, Day, Hour, Min, Sec} = Time,
- io_lib:format("~s [~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w]",
- [Vsn, Year, Month, Day, Hour, Min, Sec]).
+ Vsn.
maybe_display_options(Opts) ->
case lists:member(options, Opts) of
diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl
index 767d801eee..5713c14912 100644
--- a/lib/snmp/src/misc/snmp_log.erl
+++ b/lib/snmp/src/misc/snmp_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -649,13 +649,14 @@ do_log_to_file(Log, TextFile, Mibs, Start, Stop) ->
MiniMib = snmp_mini_mib:create(Mibs),
Write = fun(X) ->
case format_msg(X, MiniMib, Start, Stop) of
- {ok, S} ->
- io:format(Fd, "~s", [S]);
- _ ->
- ok
+ {Tag, S} when (Tag =:= ok) orelse (Tag =:= error) ->
+ io:format(Fd, "~s", [S]),
+ Tag;
+ Ignore ->
+ Ignore
end
end,
- Res = (catch loop(disk_log:chunk(Log, start), Log, Write)),
+ Res = (catch loop(Log, Write)),
snmp_mini_mib:delete(MiniMib),
file:close(Fd),
Res;
@@ -668,39 +669,63 @@ do_log_to_io(Log, Mibs, Start, Stop) ->
MiniMib = snmp_mini_mib:create(Mibs),
Write = fun(X) ->
case format_msg(X, MiniMib, Start, Stop) of
- {ok, S} ->
- io:format("~s", [S]);
- _ ->
- ok
+ {Tag, S} when (Tag =:= ok) orelse (Tag =:= error) ->
+ io:format("~s", [S]),
+ Tag;
+ X ->
+ X
end
end,
- (catch loop(disk_log:chunk(Log, start), Log, Write)),
+ Res = (catch loop(Log, Write)),
snmp_mini_mib:delete(MiniMib),
- ok.
+ Res.
+
+loop(Log, Write) ->
+ loop(disk_log:chunk(Log, start), Log, Write, 0, 0).
-loop(eof, _Log, _Write) ->
+loop(eof, _Log, _Write, _NumOK, 0 = _NumERR) ->
ok;
-loop({error, _} = Error, _Log, _Write) ->
+loop(eof, _Log, _Write, NumOK, NumERR) ->
+ {ok, {NumOK, NumERR}};
+loop({error, _} = Error, _Log, _Write, _NumOK, _NumERR) ->
Error;
-loop({Cont, Terms}, Log, Write) ->
- case (catch lists:foreach(Write, Terms)) of
- {'EXIT', Reason} ->
- {error, Reason};
- _ ->
- loop(disk_log:chunk(Log, Cont), Log, Write)
+loop({Cont, Terms}, Log, Write, NumOK, NumERR) ->
+ try loop_terms(Terms, Write) of
+ {ok, {AddedOK, AddedERR}} ->
+ loop(disk_log:chunk(Log, Cont), Log, Write,
+ NumOK+AddedOK, NumERR+AddedERR)
+ catch
+ C:E:S ->
+ {error, {C, E, S}}
end;
-loop({Cont, Terms, BadBytes}, Log, Write) ->
+loop({Cont, Terms, BadBytes}, Log, Write, NumOK, NumERR) ->
error_logger:error_msg("Skipping ~w bytes while converting ~p~n~n",
[BadBytes, Log]),
- case (catch lists:foreach(Write, Terms)) of
- {'EXIT', Reason} ->
- {error, Reason};
- _ ->
- loop(disk_log:chunk(Log, Cont), Log, Write)
- end;
-loop(Error, _Log, _Write) ->
- Error.
+ try loop_terms(Terms, Write) of
+ {ok, {AddedOK, AddedERR}} ->
+ loop(disk_log:chunk(Log, Cont), Log, Write,
+ NumOK+AddedOK, NumERR+AddedERR)
+ catch
+ C:E:S ->
+ {error, {C, E, S}}
+ end.
+
+
+loop_terms(Terms, Write) ->
+ loop_terms(Terms, Write, 0, 0).
+
+loop_terms([], _Write, NumOK, NumERR) ->
+ {ok, {NumOK, NumERR}};
+loop_terms([Term|Terms], Write, NumOK, NumERR) ->
+ case Write(Term) of
+ ok ->
+ loop_terms(Terms, Write, NumOK+1, NumERR);
+ error ->
+ loop_terms(Terms, Write, NumOK, NumERR+1);
+ _ ->
+ loop_terms(Terms, Write, NumOK, NumERR)
+ end.
format_msg(Entry, Mib, Start, Stop) ->
@@ -733,88 +758,149 @@ do_format_msg({Timestamp, SeqNo, Packet, Ip, Port}, Mib) ->
%% This is crap...
do_format_msg(_, _) ->
- format_tab("** unknown entry in log file\n\n", []).
+ {error, format_tab("** unknown entry in log file\n\n", [])}.
do_format_msg(TimeStamp, {V3Hdr, ScopedPdu}, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
+ try snmp_pdus:dec_scoped_pdu(ScopedPdu) of
ScopedPDU when is_record(ScopedPDU, scopedPdu) ->
Msg = #message{version = 'version-3',
vsn_hdr = V3Hdr,
data = ScopedPDU},
- f(ts2str(TimeStamp), "", Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file at ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), AddrStr, Reason])
+ try f(ts2str(TimeStamp), "", Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ format_error("format scoped pdu",
+ TimeStamp, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode scoped pdu",
+ TimeStamp, AddrStr, DecT, DecE)
end;
do_format_msg(TimeStamp, Packet, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
+ try snmp_pdus:dec_message(binary_to_list(Packet)) of
Msg when is_record(Msg, message) ->
- f(ts2str(TimeStamp), "", Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab("** error in log file ~p\n\n", [Reason])
+ try f(ts2str(TimeStamp), "", Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ %% Provide info about the message
+ Extra =
+ case Msg#message.version of
+ 'version-3' ->
+ #v3_hdr{msgID = ID,
+ msgFlags = Flags,
+ msgSecurityModel = SecModel} =
+ Msg#message.vsn_hdr,
+ SecLevel = snmp_misc:get_sec_level(Flags),
+ f("msg-id: ~w, sec-level: ~w, sec-model: ~w",
+ [ID, SecLevel, sm2atom(SecModel)]);
+ _ -> %% Community
+ f("community: ~s", [Msg#message.vsn_hdr])
+ end,
+ format_error(f("format ~p message; ~s",
+ [Msg#message.version, Extra]),
+ TimeStamp, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode message",
+ TimeStamp, AddrStr, DecT, DecE)
+
end.
-
+
+sm2atom(?SEC_ANY) -> any;
+sm2atom(?SEC_V1) -> v1;
+sm2atom(?SEC_V2C) -> v2c;
+sm2atom(?SEC_USM) -> usm;
+sm2atom(_) -> unknown.
+
do_format_msg(TimeStamp, SeqNo, {V3Hdr, ScopedPdu}, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
+ try snmp_pdus:dec_scoped_pdu(ScopedPdu) of
ScopedPDU when is_record(ScopedPDU, scopedPdu) ->
Msg = #message{version = 'version-3',
vsn_hdr = V3Hdr,
data = ScopedPDU},
- f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file at ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason])
+ try f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ format_error("format scoped pdu",
+ TimeStamp, SeqNo, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode scoped pdu",
+ TimeStamp, SeqNo, AddrStr, DecT, DecE)
end;
do_format_msg(TimeStamp, SeqNo, Packet, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
+ try snmp_pdus:dec_message(binary_to_list(Packet)) of
Msg when is_record(Msg, message) ->
- f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason])
+ try f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+
+ catch
+ FormatT:FormatE ->
+ %% Provide info about the message
+ Extra =
+ case Msg#message.version of
+ 'version-3' ->
+ #v3_hdr{msgID = ID,
+ msgFlags = Flags,
+ msgSecurityModel = SecModel} =
+ Msg#message.vsn_hdr,
+ SecLevel = snmp_misc:get_sec_level(Flags),
+ f("msg-id: ~w, sec-level: ~w, sec-model: ~w",
+ [ID, SecLevel, sm2atom(SecModel)]);
+ _ -> %% Community
+ f("community: ~s", [Msg#message.vsn_hdr])
+ end,
+ format_error(f("format ~p message; ~s",
+ [Msg#message.version, Extra]),
+ TimeStamp, SeqNo, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode message",
+ TimeStamp, SeqNo, AddrStr, DecT, DecE)
end.
-
-
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, {Addr, Port}},
-%% Mib, Start, Stop) ->
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port},
-%% Mib, Start, Stop);
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port},
-%% Mib, Start, Stop) ->
-%% case timestamp_filter(TimeStamp, Start, Stop) of
-%% true ->
-%% case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
-%% ScopedPDU when record(ScopedPDU, scopedPdu) ->
-%% Msg = #message{version = 'version-3',
-%% vsn_hdr = V3Hdr,
-%% data = ScopedPDU},
-%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib);
-%% {'EXIT', Reason} ->
-%% format_tab("** error in log file at ~s from ~p:~w ~p\n\n",
-%% [ts2str(TimeStamp), ip(Addr), Port, Reason])
-%% end;
-%% false ->
-%% ignore
-%% end;
-%% format_msg({TimeStamp, Packet, {Addr, Port}}, Mib, Start, Stop) ->
-%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop);
-%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop) ->
-%% case timestamp_filter(TimeStamp, Start, Stop) of
-%% true ->
-%% case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
-%% Msg when record(Msg, message) ->
-%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib);
-%% {'EXIT', Reason} ->
-%% format_tab("** error in log file ~p\n\n", [Reason])
-%% end;
-%% false ->
-%% ignore
-%% end;
-%% format_msg(_, _Mib, _Start, _Stop) ->
-%% format_tab("** unknown entry in log file\n\n", []).
+
+
+format_error(WhatStr, TimeStamp, AddrStr, throw, {error, Reason}) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s from ~s: "
+ "~n ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), AddrStr, Reason]),
+ {error, Str};
+format_error(WhatStr, TimeStamp, AddrStr, T, E) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s from ~s: "
+ "~n ~w: ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), AddrStr, T, E]),
+ {error, Str}.
+
+format_error(WhatStr, TimeStamp, SeqNo, AddrStr, throw, {error, Reason}) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s~s from ~s: "
+ "~n ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason]),
+ {error, Str};
+format_error(WhatStr, TimeStamp, SeqNo, AddrStr, T, E) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s~s from ~s: "
+ "~n ~w, ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), sn2str(SeqNo), AddrStr, T, E]),
+ {error, Str}.
+
f(TimeStamp, SeqNo,
#message{version = Vsn, vsn_hdr = VsnHdr, data = Data},
@@ -838,51 +924,21 @@ f(TimeStamp, SeqNo,
end,
format_tab(
"~w ~s - ~s [~s]~s ~w\n~s",
- [Class, AddrStr, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f(TimeStamp, SeqNo,
-%% #message{version = Vsn, vsn_hdr = VsnHdr, data = Data},
-%% Addr, Port, Mib) ->
-%% Str = format_pdu(Data, Mib),
-%% HdrStr = format_header(Vsn, VsnHdr),
-%% case get_type(Data) of
-%% trappdu ->
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'snmpv2-trap' ->
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'inform-request' ->
-%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'get-response' ->
-%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% report ->
-%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% _ ->
-%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port)
-%% end.
-
-%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("request ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("response ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("report ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
+ [Class, AddrStr, HdrStr, TimeStamp, SeqNo, Vsn, Str]);
+f(TimeStamp, SeqNo, Msg, AddrStr, _Mib) ->
+ io:format("<ERROR> Unexpected data: "
+ "~n TimeStamp: ~s~s"
+ "~n Msg: ~p"
+ "~n AddrStr: ~p"
+ "~n", [TimeStamp, SeqNo, Msg, AddrStr]),
+ throw({error, 'invalid-message'}).
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("trap ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
+f(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
-%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("inform ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
ipPort2Str(Ip, Port) ->
snmp_conf:mk_addr_string({Ip, Port}).
- %% io_lib:format("~s:~w", [ip(Ip), Port]).
%% Convert a timestamp 2-tupple to a printable string
%%
@@ -973,7 +1029,13 @@ format_pdu(#scopedPdu{contextName = Context, data = Pdu}, Mib) ->
io_lib:format("Context: \"~s\"\n~s",
[Context, snmp_misc:format_pdu(Pdu, Mib)]);
format_pdu(Pdu, Mib) ->
- snmp_misc:format_pdu(Pdu, Mib).
+ try snmp_misc:format_pdu(Pdu, Mib) of
+ Str ->
+ Str
+ catch
+ _:_ ->
+ throw({error, 'invalid-pdu'})
+ end.
get_type(#scopedPdu{data = Pdu}) ->
get_type(Pdu);
@@ -983,12 +1045,6 @@ get_type(#pdu{type = Type}) ->
Type.
-%% ip(Domain, Addr) ->
-%% snmp_conf:mk_addr_string(Domain, Addr).
-%% ip({A,B,C,D}) ->
-%% io_lib:format("~w.~w.~w.~w", [A,B,C,D]).
-
-
%% -------------------------------------------------------------------
%% Various utility functions
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 2ed2c4580c..f9c18af6ea 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
index 6a3466b6e4..b83c7461d1 100644
--- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
+++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 96123f02f5..4d5a0fbce8 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 5.2.11
+SNMP_VSN = 5.2.12
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index 425322f6ca..4e32dd9976 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -45,6 +45,7 @@ XML_REF3_FILES = \
ssh_connection.xml \
ssh_server_channel.xml \
ssh_server_key_api.xml \
+ ssh_file.xml \
ssh_sftp.xml \
ssh_sftpd.xml \
@@ -56,8 +57,8 @@ XML_CHAPTER_FILES = \
notes.xml \
introduction.xml \
using_ssh.xml \
+ terminology.xml \
configure_algos.xml
-# ssh_protocol.xml \
BOOK_FILES = book.xml
@@ -119,6 +120,7 @@ html: images $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECS_FILES)
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index c9aa877a7f..9503060140 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -30,8 +30,188 @@
<file>notes.xml</file>
</header>
-<section><title>Ssh 4.7</title>
+<section><title>Ssh 4.7.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ When an SSH server receives the very first message on a
+ new TCP connection, and that message is not the expected
+ one, the 64 first bytes of the received message are now
+ dumped in the INFO REPORT that reports the Protocol
+ Error.</p>
+ <p>
+ This facilitates the debugging of who sends the bad
+ message or of detecting a possible port scanning.</p>
+ <p>
+ Own Id: OTP-15772</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The callback <c>ssh_channel:init/1</c> was missing in
+ OTP-21</p>
+ <p>
+ Own Id: OTP-15762</p>
+ </item>
+ <item>
+ <p>
+ If a client was connected to an server on an already open
+ socket, the callback <c>fun(PeerName,FingerPrint)</c> in
+ the <c>accept_callback</c> option passed the local name
+ in the argument PeerName instead of the remote name.</p>
+ <p>
+ Own Id: OTP-15763</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SSH sftp daemon now accepts an SSH_FXP_STAT message
+ encoded according to the wrong sftp version. Some clients
+ sends such messages.</p>
+ <p>
+ Own Id: OTP-15498 Aux Id: ERL-822, PR-2077 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed port leakage if a ssh:daemon call failed.</p>
+ <p>
+ Own Id: OTP-15397 Aux Id: ERL-801 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Incompatibility with newer OpenSSH fixed. Previously
+ versions 7.8 and later could cause Erlang SSH to exit.</p>
+ <p>
+ Own Id: OTP-15413</p>
+ </item>
+ <item>
+ <p>
+ The '<c>exec</c>' option for ssh daemons had wrong format
+ in the documentation.</p>
+ <p>
+ Own Id: OTP-15416</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added public key methods ssh-ed25519 and ssh-ed448.</p>
+ <p>
+ Requires OpenSSL 1.1.1 or higher as cryptolib under the
+ OTP application <c>crypto</c>.</p>
+ <p>
+ Own Id: OTP-15094 Aux Id: OTP-15419 </p>
+ </item>
+ <item>
+ <p>
+ The SSH property tests are now adapted to the PropEr
+ testing tool.</p>
+ <p>
+ Own Id: OTP-15312</p>
+ </item>
+ <item>
+ <p>
+ The term "user" was not documented in the SSH app. A new
+ chapter with terminology is added to the User's Manual
+ where the term "user" is defined.</p>
+ <p>
+ A reference manual page about the module <c>ssh_file</c>
+ is also added. This is the default callback module for
+ user's keys, host keys etc.</p>
+ <p>
+ Own Id: OTP-15314</p>
+ </item>
+ <item>
+ <p>
+ Host and user key checking is made more robust.</p>
+ <p>
+ Own Id: OTP-15424</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+<section><title>Ssh 4.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Extended the undocumented <c>ssh_dbg</c> debug module
+ with an api for a circular trace buffer. This makes it
+ easy to record the last low-level events before an error
+ is detected. It is intended for solving difficult errors.</p>
+ <p>
+ Own Id: OTP-15020</p>
+ </item>
+ <item>
+ <p>
+ The key exchange methods
+ <c>'[email protected]'</c>,
+ <c>'curve25519-sha256'</c> and <c>'curve448-sha512'</c>
+ are implemented. The last two are defined in
+ https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves</p>
+ <p>
+ They all depends on that OpenSSL 1.1.1 or higher is used
+ as cryptolib.</p>
+ <p>
+ Own Id: OTP-15133 Aux Id: OTP-15240 </p>
+ </item>
+ <item>
+ <p>
+ The cipher '<c>[email protected]</c>' is now
+ supported if OpenSSL 1.1.1 or higher is used as
+ cryptolib.</p>
+ <p>
+ Own Id: OTP-15209 Aux Id: OTP-15164 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -190,6 +370,64 @@
</item>
</list>
</section>
+</section>
+
+<section><title>Ssh 4.6.9.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed port leakage if a ssh:daemon call failed.</p>
+ <p>
+ Own Id: OTP-15397 Aux Id: ERL-801 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.9.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Incompatibility with newer OpenSSH fixed. Previously
+ versions 7.8 and later could cause Erlang SSH to exit.</p>
+ <p>
+ Own Id: OTP-15413</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.9.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SFTP clients reported the error reason <c>""</c> if a
+ non-OTP sftp server was killed during a long file
+ transmission.</p>
+ <p>
+ Now the signal name (for example <c>"KILL"</c>) will be
+ the error reason if the server's reason is empty.</p>
+ <p>
+ The documentation also lacked type information about this
+ class of errors.</p>
+ <p>
+ Own Id: OTP-15148 Aux Id: ERIERL-194 </p>
+ </item>
+ <item>
+ <p>
+ Fix ssh_sftp decode error for sftp protocol version 4</p>
+ <p>
+ Own Id: OTP-15149 Aux Id: ERIERL-199 </p>
+ </item>
+ </list>
+ </section>
</section>
@@ -3804,4 +4042,3 @@
</section>
</chapter>
-
diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml
index df37b0244f..60572b985b 100644
--- a/lib/ssh/doc/src/ref_man.xml
+++ b/lib/ssh/doc/src/ref_man.xml
@@ -40,6 +40,7 @@
<xi:include href="ssh_connection.xml"/>
<xi:include href="ssh_client_key_api.xml"/>
<xi:include href="ssh_server_key_api.xml"/>
+ <xi:include href="ssh_file.xml"/>
<xi:include href="ssh_sftp.xml"/>
<xi:include href="ssh_sftpd.xml"/>
</application>
diff --git a/lib/ssh/doc/src/specs.xml b/lib/ssh/doc/src/specs.xml
index acdbe2ddfd..a6517f3660 100644
--- a/lib/ssh/doc/src/specs.xml
+++ b/lib/ssh/doc/src/specs.xml
@@ -6,6 +6,7 @@
<xi:include href="../specs/specs_ssh_connection.xml"/>
<xi:include href="../specs/specs_ssh_server_channel.xml"/>
<xi:include href="../specs/specs_ssh_server_key_api.xml"/>
+ <xi:include href="../specs/specs_ssh_file.xml"/>
<xi:include href="../specs/specs_ssh_sftp.xml"/>
<xi:include href="../specs/specs_ssh_sftpd.xml"/>
</specs>
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index f238bf2ca8..1a53a2ea98 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -28,7 +28,7 @@
<date>2007-10-06</date>
<rev></rev>
</header>
- <module>ssh</module>
+ <module since="">ssh</module>
<modulesummary>Main API of the ssh application</modulesummary>
<description>
<p>This is the interface module for the <c>SSH</c> application.
@@ -99,8 +99,8 @@
</p>
<p>The paths could easily be changed by options:
- <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso> and
- <seealso marker="#type-system_dir_daemon_option"><c>system_dir</c></seealso>.
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso> and
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>.
</p>
<p>A completly different storage could be interfaced by writing call-back modules
using the behaviours
@@ -123,12 +123,12 @@
<item><c>ssh_host_ecdsa_key</c> and <c>ssh_host_ecdsa_key.pub</c></item>
</list>
<p>The host keys directory could be changed with the option
- <seealso marker="#type-system_dir_daemon_option"><c>system_dir</c></seealso>.</p>
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>.</p>
</item>
<item>Optional: one or more <i>User's public key</i> in case of <c>publickey</c> authorization.
Default is to store them concatenated in the file <c>.ssh/authorized_keys</c> in the user's home directory.
<p>The user keys directory could be changed with the option
- <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>.</p>
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>.</p>
</item>
</list>
</section>
@@ -138,7 +138,7 @@
<p>The keys and some other data are by default stored in files in the directory <c>.ssh</c>
in the user's home directory.</p>
<p>The directory could be changed with the option
- <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>.
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>.
</p>
<list>
<item>Optional: a list of <i>Host public key(s)</i> for previously connected hosts. This list
@@ -183,31 +183,6 @@
</datatype>
<datatype>
- <name name="pref_public_key_algs_client_option"/>
- <desc>
- <p>List of user (client) public key algorithms to try to use.</p>
- <p>The default value is the <c>public_key</c> entry in the list returned by
- <seealso marker="#default_algorithms/0">ssh:default_algorithms/0</seealso>.
- </p>
- <p>If there is no public key of a specified type available, the corresponding entry is ignored.
- Note that the available set is dependent on the underlying cryptolib and current user's public keys.
- </p>
- <p>See also the option <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>
- for specifying the path to the user's keys.
- </p>
- </desc>
- </datatype>
-
- <datatype>
- <name name="pubkey_passphrase_client_options"/>
- <desc>
- <p>If the user's DSA, RSA or ECDSA key is protected by a passphrase, it can be
- supplied with thoose options.
- </p>
- </desc>
- </datatype>
-
- <datatype>
<name name="host_accepting_client_options"/>
<name name="accept_hosts"/>
<name name="fp_digest_alg"/>
@@ -220,7 +195,7 @@
<p>This option guides the <c>connect</c> function on how to act when the connected server presents a Host
Key that the client has not seen before. The default is to ask the user with a question on stdio of whether to
accept or reject the new Host Key.
- See the option <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>
+ See the option <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
for specifying the path to the file <c>known_hosts</c> where previously accepted Host Keys are recorded.
See also the option
<seealso marker="#type-key_cb_common_option">key_cb</seealso>
@@ -276,7 +251,7 @@
accept question the next time the same host is connected. If the option
<seealso marker="#type-key_cb_common_option"><c>key_cb</c></seealso>
is not present, the key is saved in the file "known_hosts". See option
- <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso> for
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso> for
the location of that file.
</p>
<p>If <c>false</c>, the key is not saved and the key will still be unknown
@@ -406,9 +381,20 @@
<datatype>
<name name="exec_daemon_option"/>
+ <name name="exec_spec"/>
+ <desc/>
+ </datatype>
+ <datatype>
+ <name name="exec_fun"/>
+ <desc/>
+ </datatype>
+ <datatype>
<name name="'exec_fun/1'"/>
<name name="'exec_fun/2'"/>
<name name="'exec_fun/3'"/>
+ <desc/>
+ </datatype>
+ <datatype>
<name name="exec_result"/>
<desc>
<p>This option changes how the daemon execute exec-requests from clients. The term in the return value
@@ -478,18 +464,6 @@
<name name="pwdfun_4"/>
<desc>
<taglist>
- <tag><marker id="type-system_dir_daemon_option"/><c>system_dir</c></tag>
- <item>
- <p>Sets the system directory, containing the host key files
- that identify the host keys for <c>ssh</c>. Defaults to
- <c>/etc/ssh</c>.</p>
- <p>For security reasons, this directory is normally accessible only to the root user.</p>
- <p>See also the option
- <seealso marker="#type-key_cb_common_option">key_cb</seealso>
- for the general way to handle keys.
- </p>
- </item>
-
<tag><c>auth_method_kb_interactive_data</c></tag>
<item>
<p>Sets the text strings that the daemon sends to the client for presentation to the user when
@@ -502,7 +476,7 @@
</p>
</item>
- <tag><c>user_passwords</c></tag>
+ <tag><marker id="option-user_passwords"/><c>user_passwords</c></tag>
<item>
<p>Provides passwords for password authentication. The passwords are used when someone tries
to connect to the server and public key user-authentication fails. The option provides
@@ -510,7 +484,7 @@
</p>
</item>
- <tag><c>password</c></tag>
+ <tag><marker id="option-password"/><c>password</c></tag>
<item>
<p>Provides a global password that authenticates any user.</p>
<warning>
@@ -519,7 +493,9 @@
</warning>
</item>
- <tag><c>pwdfun</c> with <c>pwdfun_4()</c></tag>
+ <tag><marker id="option-pwdfun"/><c>pwdfun</c> with
+ <seealso marker="#type-pwdfun_4"><c>pwdfun_4()</c></seealso>
+ </tag>
<item>
<p>Provides a function for password validation. This could used for calling an external system or handeling
passwords stored as hash values.
@@ -546,7 +522,9 @@
can be used for this. The return value <c>disconnect</c> is useful for this.</p>
</item>
- <tag><c>pwdfun</c> with <c>pwdfun_2()</c></tag>
+ <tag><c>pwdfun</c> with
+ <seealso marker="#type-pwdfun_2"><c>pwdfun_2()</c></seealso>
+ </tag>
<item>
<p>Provides a function for password validation. This function is called with user and password
as strings, and returns:</p>
@@ -725,21 +703,6 @@
</datatype>
<datatype>
- <name name="user_dir_common_option"/>
- <desc>
- <p>Sets the user directory. That is, the directory containing <c>ssh</c> configuration
- files for the user, such as
- <c>known_hosts</c>, <c>id_rsa</c>, <c>id_dsa</c>>, <c>id_ecdsa</c> and <c>authorized_key</c>.
- Defaults to the directory normally referred to as <c>~/.ssh</c>.
- </p>
- <p>See also the option
- <seealso marker="#type-key_cb_common_option">key_cb</seealso>
- for the general way to handle keys.
- </p>
- </desc>
- </datatype>
-
- <datatype>
<name name="profile_common_option"/>
<desc>
<p>Used together with <c>ip-address</c> and <c>port</c> to
@@ -795,7 +758,8 @@
</p>
<p>The <c>Opts</c> defaults to <c>[]</c> when only the <c>Module</c> is specified.
</p>
- <p>The default value of this option is <c>{ssh_file, []}</c>.
+ <p>The default value of this option is <c>{ssh_file, []}</c>. See also the manpage of
+ <seealso marker="ssh:ssh_file">ssh_file</seealso>.
</p>
<p>A call to the call-back function <c>F</c> will be</p>
<code>
@@ -804,13 +768,32 @@
<p>where <c>...</c> are arguments to <c>F</c> as in
<seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and/or
<seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
- The <c>UserOptions</c> are the options given to <c>ssh:connect</c>, <c>ssh:shell</c> or <c>ssh:daemon</c>.
+ The <c>UserOptions</c> are the options given to
+ <seealso marker="ssh:ssh#connect-3">ssh:connect</seealso>,
+ <seealso marker="ssh:ssh#shell-1">ssh:shell</seealso> or
+ <seealso marker="ssh:ssh#daemon-2">ssh:daemon</seealso>.
</p>
</desc>
</datatype>
<datatype>
+ <name name="pref_public_key_algs_common_option"/>
+ <desc>
+ <p>List of user (client) public key algorithms to try to use.</p>
+ <p>The default value is the <c>public_key</c> entry in the list returned by
+ <seealso marker="#default_algorithms/0">ssh:default_algorithms/0</seealso>.
+ </p>
+ <p>If there is no public key of a specified type available, the corresponding entry is ignored.
+ Note that the available set is dependent on the underlying cryptolib and current user's public keys.
+ </p>
+ <p>See also the option <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
+ for specifying the path to the user's keys.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
<name name="disconnectfun_common_option"/>
<desc>
<p>Provides a fun to implement your own logging when the peer disconnects.</p>
@@ -1076,17 +1059,17 @@
<!-- CLOSE/1 -->
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Closes an SSH connection.</fsummary>
<desc><p>Closes an SSH connection.</p></desc>
</func>
<!-- CONNECT/2 etc -->
<func>
- <name>connect(Host, Port, Options) -> Result </name>
- <name>connect(Host, Port, Options, NegotiationTimeout) -> Result </name>
- <name>connect(TcpSocket, Options) -> Result</name>
- <name>connect(TcpSocket, Options, NegotiationTimeout) -> Result</name>
+ <name since="">connect(Host, Port, Options) -> Result </name>
+ <name since="">connect(Host, Port, Options, NegotiationTimeout) -> Result </name>
+ <name since="OTP 19.0">connect(TcpSocket, Options) -> Result</name>
+ <name since="">connect(TcpSocket, Options, NegotiationTimeout) -> Result</name>
<fsummary>Connects to an SSH server.</fsummary>
<type>
<v>Host = <seealso marker="#type-host">host()</seealso></v>
@@ -1115,7 +1098,7 @@
<!-- CONNECTION_INFO/1, CONNECTION_INFO/2 -->
<func>
- <name name="connection_info" arity="2"/>
+ <name name="connection_info" arity="2" since=""/>
<fsummary>Retrieves information about a connection.</fsummary>
<desc>
<p>Retrieves information about a connection. The list <c>Keys</c> defines which information that
@@ -1125,9 +1108,9 @@
<!-- DEAMON/1,2,3 -->
<func>
- <name>daemon(Port | TcpSocket) -> Result</name>
- <name>daemon(Port | TcpSocket, Options) -> Result</name>
- <name>daemon(HostAddress, Port, Options) -> Result</name>
+ <name since="">daemon(Port | TcpSocket) -> Result</name>
+ <name since="">daemon(Port | TcpSocket, Options) -> Result</name>
+ <name since="">daemon(HostAddress, Port, Options) -> Result</name>
<fsummary>Starts a server listening for SSH connections.</fsummary>
<type>
<v>Port = integer()</v>
@@ -1171,7 +1154,7 @@
<!-- DAEMON_INFO/1 -->
<func>
- <name name="daemon_info" arity="1"/>
+ <name name="daemon_info" arity="1" since="OTP 19.0"/>
<fsummary>Get info about a daemon</fsummary>
<desc>
<p>Returns a key-value list with information about the daemon.</p>
@@ -1181,7 +1164,7 @@
<!-- DEFAULT_ALGORITHMS/0 -->
<func>
- <name name="default_algorithms" arity="0"/>
+ <name name="default_algorithms" arity="0" since="OTP 18.0"/>
<fsummary>Get a list declaring the supported algorithms</fsummary>
<desc>
<p>Returns a key-value list, where the keys are the different types of algorithms and the values are the
@@ -1193,9 +1176,9 @@
<!-- SHELL/1,2,3 -->
<func>
- <name>shell(Host | TcpSocket) -> Result </name>
- <name>shell(Host | TcpSocket, Options) -> Result </name>
- <name>shell(Host, Port, Options) -> Result </name>
+ <name since="">shell(Host | TcpSocket) -> Result </name>
+ <name since="">shell(Host | TcpSocket, Options) -> Result </name>
+ <name since="">shell(Host, Port, Options) -> Result </name>
<fsummary>Starts an interactive shell on a remote SSH server.</fsummary>
<type>
<v>Host = <seealso marker="#type-host">host()</seealso></v>
@@ -1220,8 +1203,8 @@
</func>
<func>
- <name name="start" arity="0"/>
- <name name="start" arity="1"/>
+ <name name="start" arity="0" since=""/>
+ <name name="start" arity="1" since=""/>
<fsummary>Starts the SSH application.</fsummary>
<desc>
<p>Utility function that starts the applications <c>crypto</c>, <c>public_key</c>,
@@ -1232,7 +1215,7 @@
</func>
<func>
- <name name="stop" arity="0"/>
+ <name name="stop" arity="0" since=""/>
<fsummary>Stops the <c>ssh</c> application.</fsummary>
<desc>
<p>Stops the <c>ssh</c> application.
@@ -1242,9 +1225,9 @@
</func>
<func>
- <name name="stop_daemon" arity="1"/>
- <name name="stop_daemon" arity="2"/>
- <name name="stop_daemon" arity="3"/>
+ <name name="stop_daemon" arity="1" since=""/>
+ <name name="stop_daemon" arity="2" since=""/>
+ <name name="stop_daemon" arity="3" since="OTP 21.0"/>
<fsummary>Stops the listener and all connections started by the listener.</fsummary>
<desc>
<p>Stops the listener and all connections started by the listener.</p>
@@ -1252,9 +1235,9 @@
</func>
<func>
- <name name="stop_listener" arity="1"/>
- <name name="stop_listener" arity="2"/>
- <name name="stop_listener" arity="3"/>
+ <name name="stop_listener" arity="1" since=""/>
+ <name name="stop_listener" arity="2" since=""/>
+ <name name="stop_listener" arity="3" since="OTP 21.0"/>
<fsummary>Stops the listener, but leaves existing connections started by the listener operational.</fsummary>
<desc>
<p>Stops the listener, but leaves existing connections started by the listener operational.</p>
diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml
index 9ec909d733..0c22a50c3f 100644
--- a/lib/ssh/doc/src/ssh_app.xml
+++ b/lib/ssh/doc/src/ssh_app.xml
@@ -74,13 +74,18 @@
<c>id_ecdsa_key</c>,
<c>known_hosts</c>, and <c>authorized_keys</c> in ~/.ssh,
and for the host key files in <c>/etc/ssh</c>. These locations can be changed
- by the options <c>user_dir</c> and <c>system_dir</c>.
+ by the options
+ <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso> and
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>.
</p>
<p>Public key handling can also be customized through a callback module that
implements the behaviors
<seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and
<seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
</p>
+ <p>See also the default callback module documentation in
+ <seealso marker="ssh_file">ssh_file</seealso>.
+ </p>
</section>
<section>
@@ -151,6 +156,9 @@
<item>diffie-hellman-group16-sha512</item>
<item>diffie-hellman-group18-sha512</item>
<item>diffie-hellman-group14-sha256</item>
+ <item>curve25519-sha256</item>
+ <item>[email protected]</item>
+ <item>curve448-sha512</item>
<item>diffie-hellman-group14-sha1</item>
<item>diffie-hellman-group-exchange-sha1</item>
<item>(diffie-hellman-group1-sha1, retired: It can be enabled with the
@@ -167,6 +175,8 @@
<item>ecdsa-sha2-nistp384</item>
<item>ecdsa-sha2-nistp521</item>
<item>ecdsa-sha2-nistp256</item>
+ <item>ssh-ed25519</item>
+ <item>ssh-ed448</item>
<item>ssh-rsa</item>
<item>rsa-sha2-256</item>
<item>rsa-sha2-512</item>
@@ -186,6 +196,7 @@
<tag>Encryption algorithms (ciphers)</tag>
<item>
<list type="bulleted">
+ <item>[email protected]</item>
<item>[email protected]</item>
<item>aes256-ctr</item>
<item>aes192-ctr</item>
@@ -365,7 +376,15 @@
</list>
<p/>
</item>
-
+
+ <item>
+ <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves">Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448 (work in progress)</url>
+ </item>
+
+ <item>
+ <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ed25519-ed448">Ed25519 and Ed448 public key algorithms for the Secure Shell (SSH) protocol (work in progress)</url>
+ </item>
+
</list>
</section>
diff --git a/lib/ssh/doc/src/ssh_client_channel.xml b/lib/ssh/doc/src/ssh_client_channel.xml
index 9be4007c68..cd28b95fd3 100644
--- a/lib/ssh/doc/src/ssh_client_channel.xml
+++ b/lib/ssh/doc/src/ssh_client_channel.xml
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_client_channel</module>
+ <module since="OTP 21.0">ssh_client_channel</module>
<modulesummary>-behaviour(ssh_client_channel). (Replaces ssh_channel)
</modulesummary>
<description>
@@ -68,8 +68,8 @@
<funcs>
<func>
- <name>call(ChannelRef, Msg) -></name>
- <name>call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}</name>
+ <name since="OTP 21.0">call(ChannelRef, Msg) -></name>
+ <name since="OTP 21.0">call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}</name>
<fsummary>Makes a synchronous call to a channel.</fsummary>
<type>
<v>ChannelRef = pid() </v>
@@ -92,7 +92,7 @@
</func>
<func>
- <name>cast(ChannelRef, Msg) -> ok </name>
+ <name since="OTP 21.0">cast(ChannelRef, Msg) -> ok </name>
<fsummary>Sends an asynchronous message to the channel
ChannelRef and returns ok.</fsummary>
<type>
@@ -111,7 +111,7 @@
</func>
<func>
- <name>enter_loop(State) -> _ </name>
+ <name since="OTP 21.0">enter_loop(State) -> _ </name>
<fsummary>Makes an existing process an ssh_client_channel (replaces ssh_channel) process.</fsummary>
<type>
<v>State = term()</v>
@@ -131,7 +131,7 @@
</func>
<func>
- <name>init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name>
+ <name since="OTP 21.0">init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name>
<fsummary>Initiates an <c>ssh_client_channel</c> process.</fsummary>
<type>
<v>Options = [{Option, Value}]</v>
@@ -173,7 +173,7 @@
</func>
<func>
- <name>reply(Client, Reply) -> _</name>
+ <name since="OTP 21.0">reply(Client, Reply) -> _</name>
<fsummary>Sends a reply to a client.</fsummary>
<type>
<v>Client = opaque()</v>
@@ -193,8 +193,8 @@
</func>
<func>
- <name>start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> </name>
- <name>start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
+ <name since="OTP 21.0">start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> </name>
+ <name since="OTP 21.0">start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
{ok, ChannelRef} | {error, Reason}</name>
<fsummary>Starts a process that handles an SSH channel.</fsummary>
<type>
@@ -244,7 +244,7 @@
<funcs>
<func>
- <name>Module:code_change(OldVsn, State, Extra) -> {ok,
+ <name since="OTP 21.0">Module:code_change(OldVsn, State, Extra) -> {ok,
NewState}</name>
<fsummary>Converts process state when code is changed.</fsummary>
<type>
@@ -287,7 +287,7 @@
</func>
<func>
- <name>Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ <name since="OTP 21.0">Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
{stop, Reason}</name>
<fsummary>Makes necessary initializations and returns the
initial channel state if the initializations succeed.</fsummary>
@@ -307,7 +307,7 @@
</func>
<func>
- <name>Module:handle_call(Msg, From, State) -> Result</name>
+ <name since="OTP 21.0">Module:handle_call(Msg, From, State) -> Result</name>
<fsummary>Handles messages sent by calling
<c>call/[2,3]</c>.</fsummary>
<type>
@@ -334,7 +334,7 @@
</func>
<func>
- <name>Module:handle_cast(Msg, State) -> Result</name>
+ <name since="OTP 21.0">Module:handle_cast(Msg, State) -> Result</name>
<fsummary>Handles messages sent by calling
<c>cast/2</c>.</fsummary>
<type>
@@ -355,7 +355,7 @@
</func>
<func>
- <name>Module:handle_msg(Msg, State) -> {ok, State} |
+ <name since="OTP 21.0">Module:handle_msg(Msg, State) -> {ok, State} |
{stop, ChannelId, State}</name>
<fsummary>Handles other messages than SSH connection protocol,
@@ -389,7 +389,7 @@
</func>
<func>
- <name>Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ <name since="OTP 21.0">Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
ChannelId, State}</name>
<fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
<type>
@@ -416,7 +416,7 @@
</func>
<func>
- <name>Module:terminate(Reason, State) -> _</name>
+ <name since="OTP 21.0">Module:terminate(Reason, State) -> _</name>
<fsummary>Does cleaning up before channel process termination.
</fsummary>
<type>
diff --git a/lib/ssh/doc/src/ssh_client_key_api.xml b/lib/ssh/doc/src/ssh_client_key_api.xml
index bc77756147..9f2f3013e5 100644
--- a/lib/ssh/doc/src/ssh_client_key_api.xml
+++ b/lib/ssh/doc/src/ssh_client_key_api.xml
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_client_key_api</module>
+ <module since="OTP R16B">ssh_client_key_api</module>
<modulesummary>
-behaviour(ssh_client_key_api).
</modulesummary>
@@ -86,7 +86,7 @@
<funcs>
<func>
- <name>Module:add_host_key(HostNames, PublicHostKey, ConnectOptions) -> ok | {error, Reason}</name>
+ <name since="OTP R16B">Module:add_host_key(HostNames, PublicHostKey, ConnectOptions) -> ok | {error, Reason}</name>
<fsummary>Adds a host key to the set of trusted host keys.</fsummary>
<type>
<v>HostNames = string()</v>
@@ -103,7 +103,7 @@
</func>
<func>
- <name>Module:is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result</name>
+ <name since="OTP R16B">Module:is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result</name>
<fsummary>Checks if a host key is trusted.</fsummary>
<type>
<v>Key = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
@@ -125,7 +125,7 @@
</func>
<func>
- <name>Module:user_key(Algorithm, ConnectOptions) ->
+ <name since="OTP R16B">Module:user_key(Algorithm, ConnectOptions) ->
{ok, PrivateKey} | {error, Reason}</name>
<fsummary>Fetches the users <em>public key</em> matching the <c>Algorithm</c>.</fsummary>
<type>
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
index 8e1cf156a8..2a701929f6 100644
--- a/lib/ssh/doc/src/ssh_connection.xml
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_connection</module>
+ <module since="">ssh_connection</module>
<modulesummary>
This module provides API functions to send SSH Connection Protocol
events to the other side of an SSH channel.
@@ -201,7 +201,7 @@
<funcs>
<func>
- <name>adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok</name>
+ <name since="">adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok</name>
<fsummary>Adjusts the SSH flow control window.</fsummary>
<type>
<v>ConnectionRef = connection_ref()</v>
@@ -221,7 +221,7 @@
</func>
<func>
- <name>close(ConnectionRef, ChannelId) -> ok</name>
+ <name since="">close(ConnectionRef, ChannelId) -> ok</name>
<fsummary>Sends a close message on the channel <c>ChannelId</c>.</fsummary>
<type>
<v>ConnectionRef = connection_ref()</v>
@@ -240,7 +240,7 @@
</func>
<func>
- <name>exec(ConnectionRef, ChannelId, Command, TimeOut) -> ssh_request_status() |
+ <name since="">exec(ConnectionRef, ChannelId, Command, TimeOut) -> ssh_request_status() |
{error, reason()}</name>
<fsummary>Requests that the server starts the execution of the given command.</fsummary>
<type>
@@ -284,7 +284,7 @@
</func>
<func>
- <name>exit_status(ConnectionRef, ChannelId, Status) -> ok</name>
+ <name since="">exit_status(ConnectionRef, ChannelId, Status) -> ok</name>
<fsummary>Sends the exit status of a command to the client.</fsummary>
<type>
<v>ConnectionRef = connection_ref() </v>
@@ -298,8 +298,8 @@
</func>
<func>
- <name>ptty_alloc(ConnectionRef, ChannelId, Options) -></name>
- <name>ptty_alloc(ConnectionRef, ChannelId, Options, Timeout) -> > ssh_request_status() |
+ <name since="OTP 17.5">ptty_alloc(ConnectionRef, ChannelId, Options) -></name>
+ <name since="OTP 17.4">ptty_alloc(ConnectionRef, ChannelId, Options, Timeout) -> > ssh_request_status() |
{error, reason()}</name>
<fsummary>Sends an SSH Connection Protocol <c>pty_req</c>,
to allocate a pseudo-terminal.</fsummary>
@@ -339,7 +339,7 @@
</func>
<func>
- <name>reply_request(ConnectionRef, WantReply, Status, ChannelId) -> ok</name>
+ <name since="">reply_request(ConnectionRef, WantReply, Status, ChannelId) -> ok</name>
<fsummary>Sends status replies to requests that want such replies.</fsummary>
<type>
<v>ConnectionRef = connection_ref()</v>
@@ -357,10 +357,10 @@
</func>
<func>
- <name>send(ConnectionRef, ChannelId, Data) -></name>
- <name>send(ConnectionRef, ChannelId, Data, Timeout) -></name>
- <name>send(ConnectionRef, ChannelId, Type, Data) -></name>
- <name>send(ConnectionRef, ChannelId, Type, Data, TimeOut) ->
+ <name since="">send(ConnectionRef, ChannelId, Data) -></name>
+ <name since="">send(ConnectionRef, ChannelId, Data, Timeout) -></name>
+ <name since="">send(ConnectionRef, ChannelId, Type, Data) -></name>
+ <name since="">send(ConnectionRef, ChannelId, Type, Data, TimeOut) ->
ok | {error, timeout} | {error, closed}</name>
<fsummary>Sends channel data.</fsummary>
<type>
@@ -380,7 +380,7 @@
</func>
<func>
- <name>send_eof(ConnectionRef, ChannelId) -> ok | {error, closed}</name>
+ <name since="">send_eof(ConnectionRef, ChannelId) -> ok | {error, closed}</name>
<fsummary>Sends EOF on channel <c>ChannelId</c>.</fsummary>
<type>
<v>ConnectionRef = connection_ref()</v>
@@ -392,8 +392,8 @@
</func>
<func>
- <name>session_channel(ConnectionRef, Timeout) -></name>
- <name>session_channel(ConnectionRef, InitialWindowSize,
+ <name since="">session_channel(ConnectionRef, Timeout) -></name>
+ <name since="">session_channel(ConnectionRef, InitialWindowSize,
MaxPacketSize, Timeout) -> {ok, channel_id()} | {error, reason()}</name>
<fsummary>Opens a channel for an SSH session.</fsummary>
<type>
@@ -410,7 +410,7 @@
</func>
<func>
- <name>setenv(ConnectionRef, ChannelId, Var, Value, TimeOut) -> ssh_request_status() |
+ <name since="">setenv(ConnectionRef, ChannelId, Var, Value, TimeOut) -> ssh_request_status() |
{error, reason()}</name>
<fsummary>Environment variables can be passed to the
shell/command to be started later.</fsummary>
@@ -428,7 +428,7 @@
</func>
<func>
- <name>shell(ConnectionRef, ChannelId) -> ok | failure | {error, closed}
+ <name since="">shell(ConnectionRef, ChannelId) -> ok | failure | {error, closed}
</name>
<fsummary>Requests that the user default shell (typically defined in
/etc/passwd in Unix systems) is to be executed at the server end.</fsummary>
@@ -448,7 +448,7 @@
</func>
<func>
- <name>subsystem(ConnectionRef, ChannelId, Subsystem, Timeout) -> ssh_request_status() |
+ <name since="">subsystem(ConnectionRef, ChannelId, Subsystem, Timeout) -> ssh_request_status() |
{error, reason()}</name>
<fsummary>Requests to execute a predefined subsystem on the server.</fsummary>
<type>
diff --git a/lib/ssh/doc/src/ssh_file.xml b/lib/ssh/doc/src/ssh_file.xml
new file mode 100644
index 0000000000..f1fef09083
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_file.xml
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>ssh_file</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module since="OTP 21.2">ssh_file</module>
+ <modulesummary>Default callback module for the client's and server's database operations in the ssh application</modulesummary>
+ <description>
+ <p>This module is the default callback handler for the client's and the server's user and host "database" operations.
+ All data, for instance key pairs, are stored in files in the normal file system. This page documents the files, where they
+ are stored and configuration options for this callback module.
+ </p>
+ <p>The intention is to be compatible with the
+ <url href="http://www.openssh.com">OpenSSH</url>
+ storage in files. Therefore it mimics directories and filenames of
+ <url href="http://www.openssh.com">OpenSSH</url>.
+ </p>
+
+ <p>Ssh_file implements the <seealso marker="ssh:ssh_server_key_api">ssh_server_key_api</seealso> and
+ the <seealso marker="ssh:ssh_client_key_api">ssh_client_key_api</seealso>.
+ This enables the user to make an own interface using for example a database handler.
+ </p>
+ <p>Such another callback module could be used by setting the option
+ <seealso marker="ssh:ssh#type-key_cb_common_option"><c>key_cb</c></seealso>
+ when starting a client or a server (with for example
+ <seealso marker="ssh:ssh#connect-3">ssh:connect</seealso>,
+ <seealso marker="ssh:ssh#daemon-2">ssh:daemon</seealso> of
+ <seealso marker="ssh:ssh#shell-1">ssh:shell</seealso>
+ ).
+ </p>
+
+ <note>
+ <p>The functions are <i>Callbacks</i> for the SSH app. They are not intended to be called from the user's code!
+ </p>
+ </note>
+ </description>
+
+ <section>
+ <title>Files, directories and who uses them</title>
+ <section>
+ <title>Daemons</title>
+ <p>Daemons uses all files stored in the <seealso marker="#SYSDIR">SYSDIR</seealso> directory.
+ </p>
+ <p>Optionaly, in case of <c>publickey</c> authorization, one or more of the remote user's public keys
+ in the <seealso marker="#USERDIR">USERDIR</seealso> directory are used.
+ See the files
+ <seealso marker="#USERDIR-authorized_keys"><c>USERDIR/authorized_keys</c></seealso> and
+ <seealso marker="#USERDIR-authorized_keys2"><c>USERDIR/authorized_keys2</c></seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Clients</title>
+ <p>Clients uses all files stored in the <seealso marker="#USERDIR">USERDIR</seealso> directory.
+ </p>
+ </section>
+
+ <section>
+ <title>Directory contents</title>
+ <taglist>
+ <tag><marker id="LOCALUSER"/>LOCALUSER</tag>
+ <item><p>The user name of the OS process running the Erlang virtual machine (emulator).</p>
+ </item>
+
+ <tag><marker id="SYSDIR"/>SYSDIR</tag>
+ <item><p>This is the directory holding the server's files:</p>
+ <list>
+ <item><marker id="SYSDIR-ssh_host_dsa_key"/><c>ssh_host_dsa_key</c> - private dss host key (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_rsa_key"/><c>ssh_host_rsa_key</c> - private rsa host key (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_ecdsa_key"/><c>ssh_host_ecdsa_key</c> - private ecdsa host key (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_ed25519_key"/><c>ssh_host_ed25519_key</c> - private eddsa host key for curve 25519 (optional)</item>
+ <item><marker id="SYSDIR-ssh_host_ed448_key"/><c>ssh_host_ed448_key</c> - private eddsa host key for curve 448 (optional)</item>
+ </list>
+ <p>At least one host key must be defined. The default value of SYSDIR is <marker id="#/etc/ssh"/><c>/etc/ssh</c>.
+ </p>
+ <p>For security reasons, this directory is normally accessible only to the root user.
+ </p>
+ <p>To change the SYSDIR, see the <seealso marker="#type-system_dir_daemon_option">system_dir</seealso> option.
+ </p>
+ </item>
+
+ <tag><marker id="USERDIR"/>USERDIR</tag>
+ <item><p>This is the directory holding the files:</p>
+ <list>
+ <item><marker id="USERDIR-authorized_keys"/><c>authorized_keys</c>
+ and, as second alternative
+ <marker id="USERDIR-authorized_keys2"/><c>authorized_keys2</c> -
+ the user's public keys are stored concatenated in one of those files.
+ </item>
+ <item><marker id="USERDIR-known_hosts"/><c>known_hosts</c> - host keys from hosts visited
+ concatenated. The file is created and used by the client.</item>
+ <item><marker id="USERDIR-id_dsa"/><c>id_dsa</c> - private dss user key (optional)</item>
+ <item><marker id="USERDIR-id_rsa"/><c>id_rsa</c> - private rsa user key (optional)</item>
+ <item><marker id="USERDIR-id_ecdsa"/><c>id_ecdsa</c> - private ecdsa user key (optional)</item>
+ <item><marker id="USERDIR-id_ed25519"/><c>id_ed25519</c> - private eddsa user key for curve 25519 (optional)</item>
+ <item><marker id="USERDIR-id_ed448"/><c>id_ed448</c> - private eddsa user key for curve 448 (optional)</item>
+ </list>
+ <p>The default value of USERDIR is <c>/home/</c><seealso marker="#LOCALUSER"><c>LOCALUSER</c></seealso><c>/.ssh</c>.
+ </p>
+ <p>To change the USERDIR, see the <seealso marker="#type-user_dir_common_option">user_dir</seealso> option
+ </p>
+ </item>
+ </taglist>
+ </section>
+ </section>
+
+ <datatypes>
+ <datatype_title>Options for the default ssh_file callback module</datatype_title>
+ <datatype>
+ <name name="user_dir_common_option"/>
+ <desc>
+ <p>Sets the <seealso marker="#USERDIR">user directory</seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="user_dir_fun_common_option"/>
+ <name name="user2dir"/>
+ <desc>
+ <p>Sets the <seealso marker="#USERDIR">user directory</seealso> dynamically
+ by evaluating the <c>user2dir</c> function.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="system_dir_daemon_option"/>
+ <desc>
+ <p>Sets the <seealso marker="#SYSDIR">system directory</seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pubkey_passphrase_client_options"/>
+ <desc>
+ <p>If the user's DSA, RSA or ECDSA key is protected by a passphrase, it can be
+ supplied with thoose options.
+ </p>
+ <p>Note that EdDSA passhrases (Curves 25519 and 448) are not implemented.</p>
+ </desc>
+ </datatype>
+
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name since="OTP 21.2">host_key(Algorithm, DaemonOptions) -> {ok, Key} | {error, Reason}</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_server_key_api#Module:host_key-2">ssh_server_key_api, Module:host_key/2</seealso>.
+ </p>
+ <p><strong>Options</strong></p>
+ <list>
+ <item><seealso marker="#type-system_dir_daemon_option">system_dir</seealso></item>
+ <!-- item>dsa_pass_phrase</item -->
+ <!-- item>rsa_pass_phrase</item -->
+ <!-- item>ecdsa_pass_phrase</item -->
+ </list>
+ <p><strong>Files</strong></p>
+ <list>
+ <item><seealso marker="#SYSDIR-ssh_host_rsa_key"><c>SYSDIR/ssh_host_rsa_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_dsa_key"><c>SYSDIR/ssh_host_dsa_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_ecdsa_key"><c>SYSDIR/ssh_host_ecdsa_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_ed25519_key"><c>SYSDIR/ssh_host_ed25519_key</c></seealso></item>
+ <item><seealso marker="#SYSDIR-ssh_host_ed448_key"><c>SYSDIR/ssh_host_ed448_key</c>c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">is_auth_key(PublicUserKey, User, DaemonOptions) -> Result</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_server_key_api#Module:is_auth_key-3">ssh_server_key_api: Module:is_auth_key/3</seealso>.
+ </p>
+ <p><strong>Options</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_fun_common_option">user_dir_fun</seealso></item>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ </list>
+ <p><strong>Files</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-authorized_keys"><c>USERDIR/authorized_keys</c></seealso></item>
+ <item><seealso marker="#USERDIR-authorized_keys2"><c>USERDIR/authorized_keys2</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">add_host_key(HostNames, PublicHostKey, ConnectOptions) -> ok | {error, Reason}</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_client_key_api#Module:add_host_key-3">ssh_client_key_api, Module:add_host_key/3</seealso>.
+ </p>
+ <p><strong>Option</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ </list>
+ <p><strong>File</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-known_hosts"><c>USERDIR/known_hosts</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_client_key_api#Module:is_host_key-4">ssh_client_key_api, Module:is_host_key/4</seealso>.
+ </p>
+ <p><strong>Option</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ </list>
+ <p><strong>File</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-known_hosts"><c>USERDIR/known_hosts</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 21.2">user_key(Algorithm, ConnectOptions) -> {ok, PrivateKey} | {error, Reason}</name>
+ <fsummary></fsummary>
+ <desc>
+ <p><strong>Types and description</strong></p>
+ <p>See the api description in
+ <seealso marker="ssh:ssh_client_key_api#Module:user_key-2">ssh_client_key_api, Module:user_key/2</seealso>.
+ </p>
+ <p><strong>Options</strong></p>
+ <list>
+ <item><seealso marker="#type-user_dir_common_option">user_dir</seealso></item>
+ <item><seealso marker="#type-pubkey_passphrase_client_options">dsa_pass_phrase</seealso></item>
+ <item><seealso marker="#type-pubkey_passphrase_client_options">rsa_pass_phrase</seealso></item>
+ <item><seealso marker="#type-pubkey_passphrase_client_options">ecdsa_pass_phrase</seealso></item>
+ </list>
+ <p>Note that EdDSA passhrases (Curves 25519 and 448) are not implemented.</p>
+ <p><strong>Files</strong></p>
+ <list>
+ <item><seealso marker="#USERDIR-id_dsa"><c>USERDIR/id_dsa</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_rsa"><c>USERDIR/id_rsa</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_ecdsa"><c>USERDIR/id_ecdsa</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_ed25519"><c>USERDIR/id_ed25519</c></seealso></item>
+ <item><seealso marker="#USERDIR-id_ed448"><c>USERDIR/id_ed448</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
diff --git a/lib/ssh/doc/src/ssh_server_channel.xml b/lib/ssh/doc/src/ssh_server_channel.xml
index 31ba9a3231..a4e18bbfbf 100644
--- a/lib/ssh/doc/src/ssh_server_channel.xml
+++ b/lib/ssh/doc/src/ssh_server_channel.xml
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_server_channel</module>
+ <module since="OTP 21.0">ssh_server_channel</module>
<modulesummary>-behaviour(ssh_server_channel). (Replaces ssh_daemon_channel)
</modulesummary>
<description>
@@ -70,7 +70,7 @@
<funcs>
<func>
- <name>Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ <name since="OTP 21.0">Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
{stop, Reason}</name>
<fsummary>Makes necessary initializations and returns the
initial channel state if the initializations succeed.</fsummary>
@@ -93,7 +93,7 @@
</func>
<func>
- <name>Module:handle_msg(Msg, State) -> {ok, State} |
+ <name since="OTP 21.0">Module:handle_msg(Msg, State) -> {ok, State} |
{stop, ChannelId, State}</name>
<fsummary>Handles other messages than SSH connection protocol,
@@ -125,7 +125,7 @@
</func>
<func>
- <name>Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ <name since="OTP 21.0">Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
ChannelId, State}</name>
<fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
<type>
@@ -152,7 +152,7 @@
</func>
<func>
- <name>Module:terminate(Reason, State) -> _</name>
+ <name since="OTP 21.0">Module:terminate(Reason, State) -> _</name>
<fsummary>Does cleaning up before channel process termination.
</fsummary>
<type>
diff --git a/lib/ssh/doc/src/ssh_server_key_api.xml b/lib/ssh/doc/src/ssh_server_key_api.xml
index e2a31bd5f5..013a788a4a 100644
--- a/lib/ssh/doc/src/ssh_server_key_api.xml
+++ b/lib/ssh/doc/src/ssh_server_key_api.xml
@@ -29,7 +29,7 @@
<date></date>
<rev></rev>
</header>
- <module>ssh_server_key_api</module>
+ <module since="OTP R16B">ssh_server_key_api</module>
<modulesummary>
-behaviour(ssh_server_key_api).
</modulesummary>
@@ -87,7 +87,7 @@
<funcs>
<func>
- <name>Module:host_key(Algorithm, DaemonOptions) ->
+ <name since="OTP R16B">Module:host_key(Algorithm, DaemonOptions) ->
{ok, Key} | {error, Reason}</name>
<fsummary>Fetches the host’s private key.</fsummary>
<type>
@@ -111,7 +111,7 @@
</func>
<func>
- <name>Module:is_auth_key(PublicUserKey, User, DaemonOptions) -> Result</name>
+ <name since="OTP R16B">Module:is_auth_key(PublicUserKey, User, DaemonOptions) -> Result</name>
<fsummary>Checks if the user key is authorized.</fsummary>
<type>
<v>PublicUserKey = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index 4d2337c30a..c89092798d 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -29,7 +29,7 @@
<rev></rev>
<file>ssh_sftp.sgml</file>
</header>
- <module>ssh_sftp</module>
+ <module since="">ssh_sftp</module>
<modulesummary>SFTP client.</modulesummary>
<description>
<p>This module implements an SSH FTP (SFTP) client. SFTP is a
@@ -46,9 +46,9 @@
<taglist>
<tag><c>reason()</c></tag>
<item>
- <p>= <c>atom()</c> A description of the reason why an operation failed.</p>
+ <p>= <c>atom() | string() | tuple() </c>A description of the reason why an operation failed.</p>
<p>
- The value is formed from the sftp error codes in the protocol-level responses as defined in
+ The <c>atom()</c> value is formed from the sftp error codes in the protocol-level responses as defined in
<url href="https://tools.ietf.org/id/draft-ietf-secsh-filexfer-13.txt">draft-ietf-secsh-filexfer-13.txt</url>
section 9.1.
</p>
@@ -57,6 +57,10 @@
E.g. the error code <c>SSH_FX_NO_SUCH_FILE</c>
will cause the <c>reason()</c> to be <c>no_such_file</c>.
</p>
+ <p>The <c>string()</c> reason is the error information from the server in case of an exit-signal. If that information is empty, the reason is the exit signal name.
+ </p>
+ <p>The <c>tuple()</c> reason are other errors like the <c>{exit_status,integer()}</c> if the exit status is not 0.
+ </p>
</item>
<tag><c>connection_ref() =</c></tag>
@@ -78,7 +82,7 @@
<funcs>
<func>
- <name>apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, reason()}</name>
+ <name since="">apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, reason()}</name>
<fsummary>Reads asynchronously from an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -94,7 +98,7 @@
</func>
<func>
- <name>apwrite(ChannelPid, Handle, Position, Data) -> {async, N} | {error, reason()}</name>
+ <name since="">apwrite(ChannelPid, Handle, Position, Data) -> {async, N} | {error, reason()}</name>
<fsummary>Writes asynchronously to an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -112,7 +116,7 @@
</func>
<func>
- <name>aread(ChannelPid, Handle, Len) -> {async, N} | {error, reason()}</name>
+ <name since="">aread(ChannelPid, Handle, Len) -> {async, N} | {error, reason()}</name>
<fsummary>Reads asynchronously from an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -133,7 +137,7 @@
</func>
<func>
- <name>awrite(ChannelPid, Handle, Data) -> {async, N} | {error, reason()}</name>
+ <name since="">awrite(ChannelPid, Handle, Data) -> {async, N} | {error, reason()}</name>
<fsummary>Writes asynchronously to an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -155,8 +159,8 @@
</func>
<func>
- <name>close(ChannelPid, Handle) -></name>
- <name>close(ChannelPid, Handle, Timeout) -> ok | {error, reason()}</name>
+ <name since="">close(ChannelPid, Handle) -></name>
+ <name since="">close(ChannelPid, Handle, Timeout) -> ok | {error, reason()}</name>
<fsummary>Closes an open handle.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -169,8 +173,8 @@
</func>
<func>
- <name>delete(ChannelPid, Name) -></name>
- <name>delete(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name since="">delete(ChannelPid, Name) -></name>
+ <name since="">delete(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
<fsummary>Deletes a file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -184,8 +188,8 @@
</func>
<func>
- <name>del_dir(ChannelPid, Name) -></name>
- <name>del_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name since="">del_dir(ChannelPid, Name) -></name>
+ <name since="">del_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
<fsummary>Deletes an empty directory.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -200,8 +204,8 @@
</func>
<func>
- <name>list_dir(ChannelPid, Path) -></name>
- <name>list_dir(ChannelPid, Path, Timeout) -> {ok, Filenames} | {error, reason()}</name>
+ <name since="">list_dir(ChannelPid, Path) -></name>
+ <name since="">list_dir(ChannelPid, Path, Timeout) -> {ok, Filenames} | {error, reason()}</name>
<fsummary>Lists the directory.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -217,8 +221,8 @@
</func>
<func>
- <name>make_dir(ChannelPid, Name) -></name>
- <name>make_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name since="">make_dir(ChannelPid, Name) -></name>
+ <name since="">make_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
<fsummary>Creates a directory.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -233,8 +237,8 @@
</func>
<func>
- <name>make_symlink(ChannelPid, Name, Target) -></name>
- <name>make_symlink(ChannelPid, Name, Target, Timeout) -> ok | {error, reason()}</name>
+ <name since="">make_symlink(ChannelPid, Name, Target) -></name>
+ <name since="">make_symlink(ChannelPid, Name, Target, Timeout) -> ok | {error, reason()}</name>
<fsummary>Creates a symbolic link.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -249,8 +253,8 @@
</func>
<func>
- <name>open(ChannelPid, File, Mode) -></name>
- <name>open(ChannelPid, File, Mode, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <name since="">open(ChannelPid, File, Mode) -></name>
+ <name since="">open(ChannelPid, File, Mode, Timeout) -> {ok, Handle} | {error, reason()}</name>
<fsummary>Opens a file and returns a handle.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -266,8 +270,8 @@
</desc>
</func>
<func>
- <name>opendir(ChannelPid, Path) -></name>
- <name>opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <name since="">opendir(ChannelPid, Path) -></name>
+ <name since="">opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | {error, reason()}</name>
<fsummary>Opens a directory and returns a handle.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -281,8 +285,8 @@
</func>
<func>
- <name>open_tar(ChannelPid, Path, Mode) -></name>
- <name>open_tar(ChannelPid, Path, Mode, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <name since="OTP 17.4">open_tar(ChannelPid, Path, Mode) -></name>
+ <name since="OTP 17.4">open_tar(ChannelPid, Path, Mode, Timeout) -> {ok, Handle} | {error, reason()}</name>
<fsummary>Opens a tar file on the server to which <c>ChannelPid</c>
is connected and returns a handle.</fsummary>
<type>
@@ -335,8 +339,8 @@
</func>
<func>
- <name>position(ChannelPid, Handle, Location) -></name>
- <name>position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition | {error, reason()}</name>
+ <name since="">position(ChannelPid, Handle, Location) -></name>
+ <name since="">position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition | {error, reason()}</name>
<fsummary>Sets the file position of a file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -380,8 +384,8 @@
</func>
<func>
- <name>pread(ChannelPid, Handle, Position, Len) -></name>
- <name>pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
+ <name since="">pread(ChannelPid, Handle, Position, Len) -></name>
+ <name since="">pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
<fsummary>Reads from an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -398,8 +402,8 @@
</func>
<func>
- <name>pwrite(ChannelPid, Handle, Position, Data) -> ok</name>
- <name>pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, reason()}</name>
+ <name since="">pwrite(ChannelPid, Handle, Position, Data) -> ok</name>
+ <name since="">pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, reason()}</name>
<fsummary>Writes to an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -415,13 +419,12 @@
</func>
<func>
- <name>read(ChannelPid, Handle, Len) -></name>
- <name>read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
+ <name since="">read(ChannelPid, Handle, Len) -></name>
+ <name since="">read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
<fsummary>Reads from an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
<v>Handle = term()</v>
- <v>Position = integer()</v>
<v>Len = integer()</v>
<v>Timeout = timeout()</v>
<v>Data = string() | binary()</v>
@@ -438,8 +441,8 @@
</func>
<func>
- <name>read_file(ChannelPid, File) -></name>
- <name>read_file(ChannelPid, File, Timeout) -> {ok, Data} | {error, reason()}</name>
+ <name since="">read_file(ChannelPid, File) -></name>
+ <name since="">read_file(ChannelPid, File, Timeout) -> {ok, Data} | {error, reason()}</name>
<fsummary>Reads a file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -453,8 +456,8 @@
</func>
<func>
- <name>read_file_info(ChannelPid, Name) -></name>
- <name>read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()}</name>
+ <name since="">read_file_info(ChannelPid, Name) -></name>
+ <name since="">read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()}</name>
<fsummary>Gets information about a file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -478,8 +481,8 @@
</func>
<func>
- <name>read_link(ChannelPid, Name) -></name>
- <name>read_link(ChannelPid, Name, Timeout) -> {ok, Target} | {error, reason()}</name>
+ <name since="">read_link(ChannelPid, Name) -></name>
+ <name since="">read_link(ChannelPid, Name, Timeout) -> {ok, Target} | {error, reason()}</name>
<fsummary>Reads symbolic link.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -493,8 +496,8 @@
</func>
<func>
- <name>read_link_info(ChannelPid, Name) -> {ok, FileInfo} | {error, reason()}</name>
- <name>read_link_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()}</name>
+ <name since="">read_link_info(ChannelPid, Name) -> {ok, FileInfo} | {error, reason()}</name>
+ <name since="">read_link_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()}</name>
<fsummary>Gets information about a symbolic link.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -514,8 +517,8 @@
</func>
<func>
- <name>rename(ChannelPid, OldName, NewName) -> </name>
- <name>rename(ChannelPid, OldName, NewName, Timeout) -> ok | {error, reason()}</name>
+ <name since="">rename(ChannelPid, OldName, NewName) -> </name>
+ <name since="">rename(ChannelPid, OldName, NewName, Timeout) -> ok | {error, reason()}</name>
<fsummary>Renames a file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -531,16 +534,16 @@
</func>
<func>
- <name>start_channel(ConnectionRef) -></name>
- <name>start_channel(ConnectionRef, Options) ->
+ <name since="">start_channel(ConnectionRef) -></name>
+ <name since="">start_channel(ConnectionRef, Options) ->
{ok, Pid} | {error, reason()|term()}</name>
- <name>start_channel(Host, Options) -></name>
- <name>start_channel(Host, Port, Options) ->
+ <name since="">start_channel(Host, Options) -></name>
+ <name since="">start_channel(Host, Port, Options) ->
{ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
- <name>start_channel(TcpSocket) -></name>
- <name>start_channel(TcpSocket, Options) ->
+ <name since="">start_channel(TcpSocket) -></name>
+ <name since="">start_channel(TcpSocket, Options) ->
{ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
<fsummary>Starts an SFTP client.</fsummary>
@@ -591,7 +594,7 @@
</func>
<func>
- <name>stop_channel(ChannelPid) -> ok</name>
+ <name since="">stop_channel(ChannelPid) -> ok</name>
<fsummary>Stops the SFTP client channel.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -603,8 +606,8 @@
</func>
<func>
- <name>write(ChannelPid, Handle, Data) -></name>
- <name>write(ChannelPid, Handle, Data, Timeout) -> ok | {error, reason()}</name>
+ <name since="">write(ChannelPid, Handle, Data) -></name>
+ <name since="">write(ChannelPid, Handle, Data, Timeout) -> ok | {error, reason()}</name>
<fsummary>Writes to an open file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -622,8 +625,8 @@
</func>
<func>
- <name>write_file(ChannelPid, File, Iolist) -></name>
- <name>write_file(ChannelPid, File, Iolist, Timeout) -> ok | {error, reason()}</name>
+ <name since="">write_file(ChannelPid, File, Iolist) -></name>
+ <name since="">write_file(ChannelPid, File, Iolist, Timeout) -> ok | {error, reason()}</name>
<fsummary>Writes a file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
@@ -638,8 +641,8 @@
</func>
<func>
- <name>write_file_info(ChannelPid, Name, Info) -></name>
- <name>write_file_info(ChannelPid, Name, Info, Timeout) -> ok | {error, reason()}</name>
+ <name since="">write_file_info(ChannelPid, Name, Info) -></name>
+ <name since="">write_file_info(ChannelPid, Name, Info, Timeout) -> ok | {error, reason()}</name>
<fsummary>Writes information for a file.</fsummary>
<type>
<v>ChannelPid = pid()</v>
diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml
index 3b34150e98..ee72784add 100644
--- a/lib/ssh/doc/src/ssh_sftpd.xml
+++ b/lib/ssh/doc/src/ssh_sftpd.xml
@@ -29,7 +29,7 @@
<rev></rev>
<file>ssh_sftpd.sgml</file>
</header>
- <module>ssh_sftpd</module>
+ <module since="">ssh_sftpd</module>
<modulesummary>Specifies the channel process to handle an SFTP subsystem.</modulesummary>
<description>
<p>Specifies a channel process to handle an SFTP subsystem.</p>
@@ -51,7 +51,7 @@
</section>
<funcs>
<func>
- <name>subsystem_spec(Options) -> subsystem_spec()</name>
+ <name since="">subsystem_spec(Options) -> subsystem_spec()</name>
<fsummary>Returns the subsystem specification that allows an SSH daemon to handle the subsystem "sftp".</fsummary>
<type>
<v>Options = [{Option, Value}]</v>
diff --git a/lib/ssh/doc/src/terminology.xml b/lib/ssh/doc/src/terminology.xml
new file mode 100644
index 0000000000..db1e08970d
--- /dev/null
+++ b/lib/ssh/doc/src/terminology.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2018</year>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Terminology</title>
+ <prepared></prepared>
+ <docno></docno>
+ <approved></approved>
+ <date></date>
+ <rev></rev>
+ <file>terminology.xml</file>
+ </header>
+
+ <section>
+ <title>General Information</title>
+ <p>In the following terms that may cause confusion are explained.
+ </p>
+ </section>
+
+ <section>
+ <title>The term "user"</title>
+ <p>A "user" is a term that everyone understands intuitively. However, the understandings may differ which can
+ cause confusion.
+ </p>
+ <p>The term is used differently in <url href="http://www.openssh.com">OpenSSH</url> and SSH in Erlang/OTP.
+ The reason is the different environments and use cases that are not immediatly obvious.
+ </p>
+ <p>This chapter aims at explaining the differences and giving a rationale for why Erlang/OTP handles "user" as
+ it does.
+ </p>
+
+ <section>
+ <title>In OpenSSH</title>
+ <p>Many have been in contact with the command 'ssh' on a Linux machine (or similar) to remotly log in on
+ another machine. One types
+ </p>
+ <code>ssh host</code>
+ <p>to log in on the machine named <c>host</c>. The command prompts for your password on the remote <c>host</c> and
+ then you can read, write and execute as your <i>user name</i> has rights on the remote <c>host</c>. There are
+ stronger variants with pre-distributed keys or certificates, but that are for now just details in the
+ authentication process.
+ </p>
+ <p>You could log in as the user <c>anotheruser</c> with
+ </p>
+ <code>ssh anotheruser@host</code>
+ <p>and you will then be enabled to act as <c>anotheruser</c> on the <c>host</c> if authorized correctly.
+ </p>
+ <p>So what does <i>"your user name has rights"</i> mean? In a UNIX/Linux/etc context it is exactly as that context:
+ The <i>user</i> could read, write and execute programs according to the OS rules.
+ In addition, the user has a home directory (<c>$HOME</c>) and there is a <c>$HOME/.ssh/</c> directory
+ with ssh-specific files.
+ </p>
+ <section>
+ <title>SSH password authentication</title>
+ <p>When SSH tries to log in to a host, the ssh protocol communicates the user name (as a string) and a password.
+ The remote ssh server checks that there is such a user defined and that the provided password is acceptable.
+ </p>
+ <p>If so, the user is authorized.
+ </p>
+ </section>
+ <section>
+ <title>SSH public key authentication</title>
+ <p>This is a stronger method where the ssh protocol brings the user name, the user's public key and some
+ cryptographic information which we could ignore here.
+ </p>
+ <p>The ssh server on the remote host checks:
+ </p>
+ <list>
+ <item>That the <i>user</i> has a home directory,</item>
+ <item>that home directory contains a .ssh/ directory and</item>
+ <item>the .ssh/ directory contains the public key just received in the <c>authorized_keys</c> file</item>
+ </list>
+ <p>if so, the user is authorized.
+ </p>
+ </section>
+ <section>
+ <title>The SSH server on UNIX/Linux/etc after a succesful authentication</title>
+ <p>After a succesful incoming authentication, a new process runs as the just authenticated user.</p>
+ <p>Next step is to start a service according to the ssh request. In case of a request of a shell,
+ a new one is started which handles the OS-commands that arrives from the client (that's "you").
+ </p>
+ <p>In case of a sftp request, an sftp server is started in with the user's rights. So it could read, write or delete
+ files if allowed for that user.
+ </p>
+ </section>
+ </section>
+
+ <section>
+ <title>In Erlang/OTP SSH</title>
+ <p>For the Erlang/OTP SSH server the situation is different. The server executes in an Erlang process
+ in the Erlang emulator which in turn executes in an OS process. The emulator does not try to change its
+ user when authenticated over the SSH protocol.
+ So the remote user name is only for authentication purposes in the Erlang/OTP SSH application.
+ </p>
+ <section>
+ <title>Password authentication in Erlang SSH</title>
+ <p>The Erlang/OTP SSH server checks the user name and password in the following order:
+ </p>
+ <list type="ordered">
+ <item>If a
+ <seealso marker="ssh:ssh#option-pwdfun"><c>pwdfun</c></seealso>
+ is defined, that one is called and the returned boolean is the authentication result.
+ </item>
+ <item>Else, if the
+ <seealso marker="ssh:ssh#option-user_passwords"><c>user_passwords</c></seealso>
+ option is defined and the username and the password matches, the authentication is a success.
+ </item>
+ <item>Else, if the option
+ <seealso marker="ssh:ssh#option-password"><c>password</c></seealso>
+ is defined and matches the password the authentication is a success.
+ Note that the use of this option is not recommended in non-test code.
+ </item>
+ </list>
+ </section>
+ <section>
+ <title>Public key authentication in Erlang SSH</title>
+ <p>The user name, public key and cryptographic data (a signature) that is sent by the client, are used as follows
+ (some steps left out for clearity):
+ </p>
+ <list type="ordered">
+ <item>A callback module is selected using the options
+ <seealso marker="ssh:ssh#type-key_cb_common_option"><c>key_cb</c></seealso>.
+ </item>
+ <item>The callback module is used to check that the provided public key is one of the user's pre-stored.
+ In case of the default callback module, the files <c>authorized_keys</c> and <c>authorized_keys2</c>
+ are searched in a directory found in the following order:
+ <list>
+ <item>If the option
+ <seealso marker="ssh:ssh_file#type-user_dir_fun_common_option"><c>user_dir_fun</c></seealso>
+ is defined, that fun is called and the returned directory is used,
+ </item>
+ <item>Else, If the option
+ <seealso marker="ssh:ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
+ is defined, that directory is used,
+ </item>
+ <item>Else the subdirectory <c>.ssh</c> in the home directory of the user executing
+ the OS process of the Erlang emulator is used.
+ </item>
+ </list>
+ If the provided public key is not found, the authentication fails.
+ </item>
+ <item>Finally, if the provided public key is found, the signature provided by the client is checked with
+ the public key.
+ </item>
+ </list>
+ </section>
+ <section>
+ <title>The Erlang/OTP SSH server after a succesful authentication</title>
+ <p>After a successful authentication an <i>Erlang process</i> is handling the service request from the remote
+ ssh client. The rights of that process are those of the user of the OS process running the Erlang emulator.
+ </p>
+ <p>If a shell service request arrives to the server, an <i>Erlang shell</i> is opened in the server's emulator.
+ The rights in that shell is independent of the just authenticated user.
+ </p>
+ <p>In case of an sftp request, an sftp server is started with the rights of the user of the Erlang emulator's OS
+ process. So with sftp the authenticated user does not influence the rights.
+ </p>
+ <p>So after an authentication, the user name is not used anymore and has no influence.
+ </p>
+ </section>
+ </section>
+ </section>
+</chapter>
+
diff --git a/lib/ssh/doc/src/usersguide.xml b/lib/ssh/doc/src/usersguide.xml
index 38ffa48cde..8a4df208d8 100644
--- a/lib/ssh/doc/src/usersguide.xml
+++ b/lib/ssh/doc/src/usersguide.xml
@@ -36,5 +36,6 @@
</description>
<xi:include href="introduction.xml"/>
<xi:include href="using_ssh.xml"/>
+ <xi:include href="terminology.xml"/>
<xi:include href="configure_algos.xml"/>
</part>
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index 80662e9a70..4455d5ecc5 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -74,16 +74,17 @@
<marker id="Running an Erlang ssh Daemon"></marker>
<title>Running an Erlang ssh Daemon</title>
- <p>The <c>system_dir</c> option must be a directory containing a host
- key file and it defaults to <c>/etc/ssh</c>. For details, see Section
- Configuration Files in <seealso
- marker="SSH_app">ssh(6)</seealso>.
+ <p>The
+ <seealso marker="ssh_file#type-system_dir_daemon_option"><c>system_dir</c></seealso>
+ option must be a directory containing a host key file and it defaults to <c>/etc/ssh</c>.
+ For details, see Section Configuration Files in <seealso marker="SSH_app">ssh(6)</seealso>.
</p>
<note><p>Normally, the <c>/etc/ssh</c> directory is only readable by root.</p>
</note>
- <p>The option <c>user_dir</c> defaults to directory <c>users ~/.ssh</c>.</p>
+ <p>The option <seealso marker="ssh_file#type-user_dir_common_option"><c>user_dir</c></seealso>
+ defaults to directory <c>users ~/.ssh</c>.</p>
<p><em>Step 1.</em> To run the example without root privileges,
generate new keys and host keys:</p>
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 086fa6e5f8..ff5aee14d7 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -127,7 +127,7 @@ connect(Socket, UserOptions, NegotiationTimeout) when is_port(Socket),
Options ->
case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of
ok ->
- {ok, {Host,_Port}} = inet:sockname(Socket),
+ {ok, {Host,_Port}} = inet:peername(Socket),
Opts = ?PUT_INTERNAL_OPT([{user_pid,self()}, {host,Host}], Options),
ssh_connection_handler:start_connection(client, Socket, Opts, NegotiationTimeout);
{error,SockError} ->
@@ -270,25 +270,38 @@ daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535,
try
{Host1, UserOptions} = handle_daemon_args(Host0, UserOptions0),
#{} = Options0 = ssh_options:handle_options(server, UserOptions),
-
- {{Host,Port}, ListenSocket} =
- open_listen_socket(Host1, Port0, Options0),
-
- %% Now Host,Port is what to use for the supervisor to register its name,
- %% and ListenSocket is for listening on connections. But it is still owned
- %% by self()...
-
- finalize_start(Host, Port, ?GET_OPT(profile, Options0),
- ?PUT_INTERNAL_OPT({lsocket,{ListenSocket,self()}}, Options0),
- fun(Opts, Result) ->
- {_, Callback, _} = ?GET_OPT(transport, Opts),
- receive
- {request_control, ListenSocket, ReqPid} ->
- ok = Callback:controlling_process(ListenSocket, ReqPid),
- ReqPid ! {its_yours,ListenSocket},
- Result
- end
- end)
+ {open_listen_socket(Host1, Port0, Options0), Options0}
+ of
+ {{{Host,Port}, ListenSocket}, Options1} ->
+ try
+ %% Now Host,Port is what to use for the supervisor to register its name,
+ %% and ListenSocket is for listening on connections. But it is still owned
+ %% by self()...
+ finalize_start(Host, Port, ?GET_OPT(profile, Options1),
+ ?PUT_INTERNAL_OPT({lsocket,{ListenSocket,self()}}, Options1),
+ fun(Opts, Result) ->
+ {_, Callback, _} = ?GET_OPT(transport, Opts),
+ receive
+ {request_control, ListenSocket, ReqPid} ->
+ ok = Callback:controlling_process(ListenSocket, ReqPid),
+ ReqPid ! {its_yours,ListenSocket},
+ Result
+ end
+ end)
+ of
+ {error,Err} ->
+ close_listen_socket(ListenSocket, Options1),
+ {error,Err};
+ OK ->
+ OK
+ catch
+ error:Error ->
+ close_listen_socket(ListenSocket, Options1),
+ error(Error);
+ exit:Exit ->
+ close_listen_socket(ListenSocket, Options1),
+ exit(Exit)
+ end
catch
throw:bad_fd ->
{error,bad_fd};
@@ -524,6 +537,15 @@ open_listen_socket(_Host0, Port0, Options0) ->
{{LHost,LPort}, LSock}.
%%%----------------------------------------------------------------
+close_listen_socket(ListenSocket, Options) ->
+ try
+ {_, Callback, _} = ?GET_OPT(transport, Options),
+ Callback:close(ListenSocket)
+ catch
+ _C:_E -> ok
+ end.
+
+%%%----------------------------------------------------------------
finalize_start(Host, Port, Profile, Options0, F) ->
try
%% throws error:Error if no usable hostkey is found
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 9631427749..923e9309f4 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -118,6 +118,9 @@
'diffie-hellman-group14-sha256' |
'diffie-hellman-group16-sha512' |
'diffie-hellman-group18-sha512' |
+ 'curve25519-sha256' |
+ 'curve448-sha512' |
'ecdh-sha2-nistp256' |
'ecdh-sha2-nistp384' |
'ecdh-sha2-nistp521'
@@ -126,6 +129,8 @@
-type pubkey_alg() :: 'ecdsa-sha2-nistp256' |
'ecdsa-sha2-nistp384' |
'ecdsa-sha2-nistp521' |
+ 'ssh-ed25519' |
+ 'ssh-ed448' |
'rsa-sha2-256' |
'rsa-sha2-512' |
'ssh-dss' |
@@ -140,7 +145,8 @@
'aes192-ctr' |
'aes256-ctr' |
.
-type mac_alg() :: 'AEAD_AES_128_GCM' |
@@ -169,7 +175,7 @@
-type common_options() :: [ common_option() ].
-type common_option() ::
- user_dir_common_option()
+ ssh_file:user_dir_common_option()
| profile_common_option()
| max_idle_time_common_option()
| key_cb_common_option()
@@ -178,6 +184,7 @@
| ssh_msg_debug_fun_common_option()
| rekey_limit_common_option()
| id_string_common_option()
+ | pref_public_key_algs_common_option()
| preferred_algorithms_common_option()
| modify_algorithms_common_option()
| auth_methods_common_option()
@@ -187,8 +194,6 @@
-define(COMMON_OPTION, common_option()).
-
--type user_dir_common_option() :: {user_dir, false | string()}.
-type profile_common_option() :: {profile, atom() }.
-type max_idle_time_common_option() :: {idle_time, timeout()}.
-type rekey_limit_common_option() :: {rekey_limit, Bytes::limit_bytes() |
@@ -207,6 +212,7 @@
{ssh_msg_debug_fun, fun((ssh:connection_ref(),AlwaysDisplay::boolean(),Msg::binary(),LanguageTag::binary()) -> any()) } .
-type id_string_common_option() :: {id_string, string() | random | {random,Nmin::pos_integer(),Nmax::pos_integer()} }.
+-type pref_public_key_algs_common_option() :: {pref_public_key_algs, [pubkey_alg()] } .
-type preferred_algorithms_common_option():: {preferred_algorithms, algs_list()}.
-type modify_algorithms_common_option() :: {modify_algorithms, modify_algs_list()}.
-type auth_methods_common_option() :: {auth_methods, string() }.
@@ -219,14 +225,13 @@
{transport, {atom(),atom(),atom()} }
| {vsn, {non_neg_integer(),non_neg_integer()} }
| {tstflg, list(term())}
- | {user_dir_fun, fun()}
+ | ssh_file:user_dir_fun_common_option()
| {max_random_length_padding, non_neg_integer()} .
-type client_option() ::
- pref_public_key_algs_client_option()
- | pubkey_passphrase_client_options()
+ ssh_file:pubkey_passphrase_client_options()
| host_accepting_client_options()
| authentication_client_options()
| diffie_hellman_group_exchange_client_option()
@@ -237,15 +242,14 @@
| ?COMMON_OPTION .
-type opaque_client_options() ::
- {keyboard_interact_fun, fun((term(),term(),term()) -> term())}
+ {keyboard_interact_fun, fun((Name::iodata(),
+ Instruction::iodata(),
+ Prompts::[{Prompt::iodata(),Echo::boolean()}]
+ ) ->
+ [Response::iodata()]
+ )}
| opaque_common_options().
--type pref_public_key_algs_client_option() :: {pref_public_key_algs, [pubkey_alg()] } .
-
--type pubkey_passphrase_client_options() :: {dsa_pass_phrase, string()}
- | {rsa_pass_phrase, string()}
- | {ecdsa_pass_phrase, string()} .
-
-type host_accepting_client_options() ::
{silently_accept_hosts, accept_hosts()}
| {user_interaction, boolean()}
@@ -256,13 +260,7 @@
| accept_callback()
| {HashAlgoSpec::fp_digest_alg(), accept_callback()}.
--type fp_digest_alg() :: 'md5' |
- 'sha' |
- 'sha224' |
- 'sha256' |
- 'sha384' |
- 'sha512'
- .
+-type fp_digest_alg() :: 'md5' | crypto:sha1() | crypto:sha2() .
-type accept_callback() :: fun((PeerName::string(), fingerprint() ) -> boolean()) .
-type fingerprint() :: string() | [string()].
@@ -301,8 +299,9 @@
-type 'shell_fun/1'() :: fun((User::string()) -> pid()) .
-type 'shell_fun/2'() :: fun((User::string(), PeerAddr::inet:ip_address()) -> pid()).
--type exec_daemon_option() :: {exec, 'exec_fun/1'() | 'exec_fun/2'() | 'exec_fun/3'() }.
-
+-type exec_daemon_option() :: {exec, exec_spec()} .
+-type exec_spec() :: {direct, exec_fun()} .
+-type exec_fun() :: 'exec_fun/1'() | 'exec_fun/2'() | 'exec_fun/3'().
-type 'exec_fun/1'() :: fun((Cmd::string()) -> exec_result()) .
-type 'exec_fun/2'() :: fun((Cmd::string(), User::string()) -> exec_result()) .
-type 'exec_fun/3'() :: fun((Cmd::string(), User::string(), ClientAddr::ip_port()) -> exec_result()) .
@@ -313,7 +312,7 @@
-type send_ext_info_daemon_option() :: {send_ext_info, boolean()} .
-type authentication_daemon_options() ::
- {system_dir, string()}
+ ssh_file:system_dir_daemon_option()
| {auth_method_kb_interactive_data, prompt_texts() }
| {user_passwords, [{UserName::string(),Pwd::string()}]}
| {password, string()}
@@ -388,9 +387,6 @@
algorithms, %% #alg{}
- key_cb, %% Private/Public key callback module
- io_cb, %% Interaction callback module
-
send_mac = none, %% send MAC algorithm
send_mac_key, %% key used in send MAC algorithm
send_mac_size = 0,
@@ -492,4 +488,29 @@
-define(wr_record(N), ?wr_record(N, [])).
+%% Circular trace buffer macros
+
+-record(circ_buf_entry,
+ {
+ module,
+ line,
+ function,
+ pid = self(),
+ value
+ }).
+
+-define(CIRC_BUF_IN(VALUE),
+ ssh_dbg:cbuf_in(
+ #circ_buf_entry{module = ?MODULE,
+ line = ?LINE,
+ function = {?FUNCTION_NAME,?FUNCTION_ARITY},
+ pid = self(),
+ value = (VALUE)
+ })
+ ).
+
+-define(CIRC_BUF_IN_ONCE(VALUE),
+ ((fun(V) -> ?CIRC_BUF_IN(V), V end)(VALUE))
+ ).
+
-endif. % SSH_HRL defined
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 4e4aa440de..9632168e65 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -91,8 +91,10 @@ unique(L) ->
%%%---- userauth_request_msg "callbacks"
-password_msg([#ssh{opts = Opts, io_cb = IoCb,
- user = User, service = Service} = Ssh0]) ->
+password_msg([#ssh{opts = Opts,
+ user = User,
+ service = Service} = Ssh0]) ->
+ IoCb = ?GET_INTERNAL_OPT(io_cb, Opts),
{Password,Ssh} =
case ?GET_OPT(password, Opts) of
undefined when IoCb == ssh_no_io ->
@@ -137,9 +139,7 @@ keyboard_interactive_msg([#ssh{user = User,
get_public_key(SigAlg, #ssh{opts = Opts}) ->
KeyAlg = key_alg(SigAlg),
- {KeyCb,KeyCbOpts} = ?GET_OPT(key_cb, Opts),
- UserOpts = ?GET_OPT(user_options, Opts),
- case KeyCb:user_key(KeyAlg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
+ case ssh_transport:call_KeyCb(user_key, [KeyAlg], Opts) of
{ok, PrivKey} ->
try
%% Check the key - the KeyCb may be a buggy plugin
@@ -387,11 +387,9 @@ handle_userauth_info_request(#ssh_msg_userauth_info_request{name = Name,
instruction = Instr,
num_prompts = NumPrompts,
data = Data},
- #ssh{opts = Opts,
- io_cb = IoCb
- } = Ssh) ->
+ #ssh{opts=Opts} = Ssh) ->
PromptInfos = decode_keyboard_interactive_prompts(NumPrompts,Data),
- case keyboard_interact_get_responses(IoCb, Opts, Name, Instr, PromptInfos) of
+ case keyboard_interact_get_responses(Opts, Name, Instr, PromptInfos) of
not_ok ->
not_ok;
Responses ->
@@ -498,9 +496,7 @@ get_password_option(Opts, User) ->
pre_verify_sig(User, KeyBlob, Opts) ->
try
Key = public_key:ssh_decode(KeyBlob, ssh2_pubkey), % or exception
- {KeyCb,KeyCbOpts} = ?GET_OPT(key_cb, Opts),
- UserOpts = ?GET_OPT(user_options, Opts),
- KeyCb:is_auth_key(Key, User, [{key_cb_private,KeyCbOpts}|UserOpts])
+ ssh_transport:call_KeyCb(is_auth_key, [Key, User], Opts)
catch
_:_ ->
false
@@ -509,10 +505,8 @@ pre_verify_sig(User, KeyBlob, Opts) ->
verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, #ssh{opts = Opts} = Ssh) ->
try
Alg = binary_to_list(AlgBin),
- {KeyCb,KeyCbOpts} = ?GET_OPT(key_cb, Opts),
- UserOpts = ?GET_OPT(user_options, Opts),
Key = public_key:ssh_decode(KeyBlob, ssh2_pubkey), % or exception
- true = KeyCb:is_auth_key(Key, User, [{key_cb_private,KeyCbOpts}|UserOpts]),
+ true = ssh_transport:call_KeyCb(is_auth_key, [Key, User], Opts),
PlainText = build_sig_data(SessionId, User, Service, KeyBlob, Alg),
<<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
<<?UINT32(AlgLen), _Alg:AlgLen/binary,
@@ -536,56 +530,78 @@ build_sig_data(SessionId, User, Service, KeyBlob, Alg) ->
+key_alg('rsa-sha2-256') -> 'ssh-rsa';
+key_alg('rsa-sha2-512') -> 'ssh-rsa';
+key_alg(Alg) -> Alg.
+
+%%%================================================================
+%%%
+%%% Keyboard-interactive
+%%%
+
decode_keyboard_interactive_prompts(_NumPrompts, Data) ->
ssh_message:decode_keyboard_interactive_prompts(Data, []).
-keyboard_interact_get_responses(IoCb, Opts, Name, Instr, PromptInfos) ->
- NumPrompts = length(PromptInfos),
+keyboard_interact_get_responses(Opts, Name, Instr, PromptInfos) ->
keyboard_interact_get_responses(?GET_OPT(user_interaction, Opts),
?GET_OPT(keyboard_interact_fun, Opts),
- ?GET_OPT(password, Opts), IoCb, Name,
- Instr, PromptInfos, Opts, NumPrompts).
+ ?GET_OPT(password, Opts),
+ Name,
+ Instr,
+ PromptInfos,
+ Opts).
-keyboard_interact_get_responses(_, _, not_ok, _, _, _, _, _, _) ->
+%% Don't re-try an already rejected password. This could happen if both keyboard-interactive
+%% and password methods are tried:
+keyboard_interact_get_responses(_, _, not_ok, _, _, _, _) ->
not_ok;
-keyboard_interact_get_responses(_, undefined, Password, _, _, _, _, _,
- 1) when Password =/= undefined ->
- [Password]; %% Password auth implemented with keyboard-interaction and passwd is known
-keyboard_interact_get_responses(_, _, _, _, _, _, _, _, 0) ->
+
+%% Only one password requestedm and we have got one via the 'password' option for the daemon:
+keyboard_interact_get_responses(_, undefined, Pwd, _, _, [_], _) when Pwd =/= undefined ->
+ [Pwd]; %% Password auth implemented with keyboard-interaction and passwd is known
+
+%% No password requested (keyboard-interactive):
+keyboard_interact_get_responses(_, _, _, _, _, [], _) ->
[];
-keyboard_interact_get_responses(false, undefined, undefined, _, _, _, [Prompt|_], Opts, _) ->
- ssh_no_io:read_line(Prompt, Opts); %% Throws error as keyboard interaction is not allowed
-keyboard_interact_get_responses(true, undefined, _,IoCb, Name, Instr, PromptInfos, Opts, _) ->
- keyboard_interact(IoCb, Name, Instr, PromptInfos, Opts);
-keyboard_interact_get_responses(true, Fun, _Pwd, _IoCb, Name, Instr, PromptInfos, _Opts, NumPrompts) ->
- keyboard_interact_fun(Fun, Name, Instr, PromptInfos, NumPrompts).
-
-keyboard_interact(IoCb, Name, Instr, Prompts, Opts) ->
+
+%% user_interaction is forbidden (by option user_interaction) and we have to ask
+%% the user for one or more.
+%% Throw an error:
+keyboard_interact_get_responses(false, undefined, undefined, _, _, [Prompt|_], Opts) ->
+ ssh_no_io:read_line(Prompt, Opts);
+
+%% One or more passwords are requested, we may prompt the user and no fun is used
+%% to get the responses:
+keyboard_interact_get_responses(true, undefined, _, Name, Instr, PromptInfos, Opts) ->
+ prompt_user_for_passwords(Name, Instr, PromptInfos, Opts);
+
+%% The passwords are provided with a fun. Use that one!
+keyboard_interact_get_responses(true, Fun, _Pwd, Name, Instr, PromptInfos, _Opts) ->
+ keyboard_interact_fun(Fun, Name, Instr, PromptInfos).
+
+
+
+prompt_user_for_passwords(Name, Instr, PromptInfos, Opts) ->
+ IoCb = ?GET_INTERNAL_OPT(io_cb, Opts),
write_if_nonempty(IoCb, Name),
write_if_nonempty(IoCb, Instr),
lists:map(fun({Prompt, true}) -> IoCb:read_line(Prompt, Opts);
({Prompt, false}) -> IoCb:read_password(Prompt, Opts)
end,
- Prompts).
+ PromptInfos).
-write_if_nonempty(_, "") -> ok;
-write_if_nonempty(_, <<>>) -> ok;
-write_if_nonempty(IoCb, Text) -> IoCb:format("~s~n",[Text]).
-
-
-keyboard_interact_fun(KbdInteractFun, Name, Instr, PromptInfos, NumPrompts) ->
- Prompts = lists:map(fun({Prompt, _Echo}) -> Prompt end,
- PromptInfos),
- case KbdInteractFun(Name, Instr, Prompts) of
- Rs when length(Rs) == NumPrompts ->
- Rs;
- _Rs ->
+keyboard_interact_fun(KbdInteractFun, Name, Instr, PromptInfos) ->
+ case KbdInteractFun(Name, Instr, PromptInfos) of
+ Responses when is_list(Responses),
+ length(Responses) == length(PromptInfos) ->
+ Responses;
+ _ ->
nok
end.
-key_alg('rsa-sha2-256') -> 'ssh-rsa';
-key_alg('rsa-sha2-512') -> 'ssh-rsa';
-key_alg(Alg) -> Alg.
+write_if_nonempty(_, "") -> ok;
+write_if_nonempty(_, <<>>) -> ok;
+write_if_nonempty(IoCb, Text) -> IoCb:format("~s~n",[Text]).
diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl
index 443bd05086..1d977e3bc9 100644
--- a/lib/ssh/src/ssh_channel.erl
+++ b/lib/ssh/src/ssh_channel.erl
@@ -58,6 +58,7 @@
State::term()}.
%%% API
-export([start/4, start/5, start_link/4, start_link/5, call/2, call/3,
+ init/1,
cast/2, reply/2, enter_loop/1]).
%%====================================================================
@@ -76,6 +77,9 @@ cast(ChannelPid, Msg) ->
reply(From, Msg) ->
ssh_client_channel:reply(From, Msg).
+init(Args) ->
+ ssh_client_channel:init(Args).
+
start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
ssh_client_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs).
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 8e4831a601..8f32966a12 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -356,6 +356,8 @@ alg(ConnectionHandler) ->
| undefined,
encrypted_data_buffer = <<>> :: binary()
| undefined,
+ aead_data = <<>> :: binary()
+ | undefined,
undecrypted_packet_length :: undefined | non_neg_integer(),
key_exchange_init_msg :: #ssh_msg_kexinit{}
| undefined,
@@ -445,7 +447,6 @@ init_ssh_record(Role, Socket, Opts) ->
init_ssh_record(Role, Socket, PeerAddr, Opts) ->
AuthMethods = ?GET_OPT(auth_methods, Opts),
S0 = #ssh{role = Role,
- key_cb = ?GET_OPT(key_cb, Opts),
opts = Opts,
userauth_supported_methods = AuthMethods,
available_host_keys = available_hkey_algorithms(Role, Opts),
@@ -470,10 +471,11 @@ init_ssh_record(Role, Socket, PeerAddr, Opts) ->
S1 =
S0#ssh{c_vsn = Vsn,
c_version = Version,
- io_cb = case ?GET_OPT(user_interaction, Opts) of
- true -> ssh_io;
- false -> ssh_no_io
- end,
+ opts = ?PUT_INTERNAL_OPT({io_cb, case ?GET_OPT(user_interaction, Opts) of
+ true -> ssh_io;
+ false -> ssh_no_io
+ end},
+ Opts),
userauth_quiet_mode = ?GET_OPT(quiet_mode, Opts),
peer = {PeerName, PeerAddr},
local = LocalName
@@ -486,7 +488,6 @@ init_ssh_record(Role, Socket, PeerAddr, Opts) ->
server ->
S0#ssh{s_vsn = Vsn,
s_version = Version,
- io_cb = ?GET_INTERNAL_OPT(io_cb, Opts, ssh_io),
userauth_methods = string:tokens(AuthMethods, ","),
kb_tries_left = 3,
peer = {undefined, PeerAddr},
@@ -593,7 +594,7 @@ handle_event(_, socket_control, {hello,_}=StateName, D) ->
{stop, {shutdown,{unexpected_getopts_return, Other}}}
end;
-handle_event(_, {info_line,_Line}, {hello,Role}=StateName, D) ->
+handle_event(_, {info_line,Line}, {hello,Role}=StateName, D) ->
case Role of
client ->
%% The server may send info lines to the client before the version_exchange
@@ -604,9 +605,9 @@ handle_event(_, {info_line,_Line}, {hello,Role}=StateName, D) ->
%% But the client may NOT send them to the server. Openssh answers with cleartext,
%% and so do we
send_bytes("Protocol mismatch.", D),
- ?call_disconnectfun_and_log_cond("Protocol mismatch.",
- "Protocol mismatch in version exchange. Client sent info lines.",
- StateName, D),
+ Msg = io_lib:format("Protocol mismatch in version exchange. Client sent info lines.~n~s",
+ [ssh_dbg:hex_dump(Line, 64)]),
+ ?call_disconnectfun_and_log_cond("Protocol mismatch.", Msg, StateName, D),
{stop, {shutdown,"Protocol mismatch in version exchange. Client sent info lines."}}
end;
@@ -981,6 +982,10 @@ handle_event(_, #ssh_msg_userauth_info_request{}, {userauth_keyboard_interactive
%%% ######## {connected, client|server} ####
+%% Skip ext_info messages in connected state (for example from OpenSSH >= 7.7)
+handle_event(_, #ssh_msg_ext_info{}, {connected,_Role}, D) ->
+ {keep_state, D};
+
handle_event(_, {#ssh_msg_kexinit{},_}, {connected,Role}, D0) ->
{KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(D0#data.ssh_params),
D = D0#data{ssh_params = Ssh,
@@ -1308,14 +1313,16 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
try ssh_transport:handle_packet_part(
D0#data.decrypted_data_buffer,
<<(D0#data.encrypted_data_buffer)/binary, NewData/binary>>,
- D0#data.undecrypted_packet_length,
+ D0#data.aead_data,
+ D0#data.undecrypted_packet_length,
D0#data.ssh_params)
of
{packet_decrypted, DecryptedBytes, EncryptedDataRest, Ssh1} ->
D1 = D0#data{ssh_params =
Ssh1#ssh{recv_sequence = ssh_transport:next_seqnum(Ssh1#ssh.recv_sequence)},
decrypted_data_buffer = <<>>,
- undecrypted_packet_length = undefined,
+ undecrypted_packet_length = undefined,
+ aead_data = <<>>,
encrypted_data_buffer = EncryptedDataRest},
try
ssh_message:decode(set_kex_overload_prefix(DecryptedBytes,D1))
@@ -1353,14 +1360,15 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
StateName, D1),
{stop, Shutdown, D}
end;
-
- {get_more, DecryptedBytes, EncryptedDataRest, RemainingSshPacketLen, Ssh1} ->
+
+ {get_more, DecryptedBytes, EncryptedDataRest, AeadData, RemainingSshPacketLen, Ssh1} ->
%% Here we know that there are not enough bytes in
%% EncryptedDataRest to use. We must wait for more.
inet:setopts(Sock, [{active, once}]),
{keep_state, D0#data{encrypted_data_buffer = EncryptedDataRest,
decrypted_data_buffer = DecryptedBytes,
- undecrypted_packet_length = RemainingSshPacketLen,
+ undecrypted_packet_length = RemainingSshPacketLen,
+ aead_data = AeadData,
ssh_params = Ssh1}};
{bad_mac, Ssh1} ->
@@ -1677,18 +1685,19 @@ peer_role(client) -> server;
peer_role(server) -> client.
%%--------------------------------------------------------------------
-available_hkey_algorithms(Role, Options) ->
- KeyCb = ?GET_OPT(key_cb, Options),
- case [A || A <- available_hkey_algos(Options),
- (Role==client) orelse available_host_key(KeyCb, A, Options)
- ] of
-
- [] when Role==client ->
- error({shutdown, "No public key algs"});
-
- [] when Role==server ->
- error({shutdown, "No host key available"});
+available_hkey_algorithms(client, Options) ->
+ case available_hkey_algos(Options) of
+ [] ->
+ error({shutdown, "No public key algs"});
+ Algs ->
+ [atom_to_list(A) || A<-Algs]
+ end;
+available_hkey_algorithms(server, Options) ->
+ case [A || A <- available_hkey_algos(Options),
+ is_usable_host_key(A, Options)] of
+ [] ->
+ error({shutdown, "No host key available"});
Algs ->
[atom_to_list(A) || A<-Algs]
end.
@@ -1704,18 +1713,6 @@ available_hkey_algos(Options) ->
AvailableAndSupported.
-%% Alg :: atom()
-available_host_key({KeyCb,KeyCbOpts}, Alg, Opts) ->
- UserOpts = ?GET_OPT(user_options, Opts),
- case KeyCb:host_key(Alg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
- {ok,Key} ->
- %% Check the key - the KeyCb may be a buggy plugin
- ssh_transport:valid_key_sha_alg(Key, Alg);
- _ ->
- false
- end.
-
-
send_msg(Msg, State=#data{ssh_params=Ssh0}) when is_tuple(Msg) ->
{Bytes, Ssh} = ssh_transport:ssh_packet(Msg, Ssh0),
send_bytes(Bytes, State),
@@ -1835,10 +1832,21 @@ ext_info(_, D0) ->
D0.
%%%----------------------------------------------------------------
-is_usable_user_pubkey(A, Ssh) ->
- case ssh_auth:get_public_key(A, Ssh) of
+is_usable_user_pubkey(Alg, Ssh) ->
+ try ssh_auth:get_public_key(Alg, Ssh) of
{ok,_} -> true;
_ -> false
+ catch
+ _:_ -> false
+ end.
+
+%%%----------------------------------------------------------------
+is_usable_host_key(Alg, Opts) ->
+ try ssh_transport:get_host_key(Alg, Opts)
+ of
+ _PrivHostKey -> true
+ catch
+ _:_ -> false
end.
%%%----------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index b53c09b17d..43ac4c0ccf 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -54,7 +54,14 @@
start_tracer/0, start_tracer/1,
on/1, on/0,
off/1, off/0,
- go_on/0
+ go_on/0,
+ %% Circular buffer
+ cbuf_start/0, cbuf_start/1,
+ cbuf_stop_clear/0,
+ cbuf_in/1,
+ cbuf_list/0,
+ hex_dump/1, hex_dump/2,
+ fmt_cbuf_items/0, fmt_cbuf_item/1
]).
-export([shrink_bin/1,
@@ -71,6 +78,8 @@
-behaviour(gen_server).
-define(SERVER, ?MODULE).
+-define(CALL_TIMEOUT, 15000). % 3x the default
+
%%%================================================================
-define(ALL_DBG_TYPES, get_all_dbg_types()).
@@ -107,7 +116,7 @@ start_tracer(WriteFun) when is_function(WriteFun,3) ->
start_tracer(WriteFun, InitAcc) when is_function(WriteFun, 3) ->
Handler =
fun(Arg, Acc0) ->
- try_all_types_in_all_modules(gen_server:call(?SERVER, get_on),
+ try_all_types_in_all_modules(gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT),
Arg, WriteFun,
Acc0)
end,
@@ -122,7 +131,7 @@ off() -> off(?ALL_DBG_TYPES). % A bit overkill...
off(Type) -> switch(off, Type).
go_on() ->
- IsOn = gen_server:call(?SERVER, get_on),
+ IsOn = gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT),
on(IsOn).
%%%----------------------------------------------------------------
@@ -253,7 +262,7 @@ switch(X, Types) when is_list(Types) ->
end,
case lists:usort(Types) -- ?ALL_DBG_TYPES of
[] ->
- gen_server:call(?SERVER, {switch,X,Types});
+ gen_server:call(?SERVER, {switch,X,Types}, ?CALL_TIMEOUT);
L ->
{error, {unknown, L}}
end.
@@ -331,3 +340,175 @@ ts({_,_,Usec}=Now) when is_integer(Usec) ->
io_lib:format("~.2.0w:~.2.0w:~.2.0w.~.6.0w",[HH,MM,SS,Usec]);
ts(_) ->
"-".
+
+%%%================================================================
+-define(CIRC_BUF, circ_buf).
+
+cbuf_start() ->
+ cbuf_start(20).
+
+cbuf_start(CbufMaxLen) ->
+ put(?CIRC_BUF, {CbufMaxLen,queue:new()}),
+ ok.
+
+
+cbuf_stop_clear() ->
+ case erase(?CIRC_BUF) of
+ undefined ->
+ [];
+ {_CbufMaxLen,Queue} ->
+ queue:to_list(Queue)
+ end.
+
+
+cbuf_in(Value) ->
+ case get(?CIRC_BUF) of
+ undefined ->
+ disabled;
+ {CbufMaxLen,Queue} ->
+ UpdatedQueue =
+ try queue:head(Queue) of
+ {Value, TS0, Cnt0} ->
+ %% Same Value as last saved in the queue
+ queue:in_r({Value, TS0, Cnt0+1},
+ queue:drop(Queue)
+ );
+ _ ->
+ queue:in_r({Value, erlang:timestamp(), 1},
+ truncate_cbuf(Queue, CbufMaxLen)
+ )
+ catch
+ error:empty ->
+ queue:in_r({Value, erlang:timestamp(), 1}, Queue)
+ end,
+ put(?CIRC_BUF, {CbufMaxLen,UpdatedQueue}),
+ ok
+ end.
+
+
+cbuf_list() ->
+ case get(?CIRC_BUF) of
+ undefined ->
+ [];
+ {_CbufMaxLen,Queue} ->
+ queue:to_list(Queue)
+ end.
+
+
+truncate_cbuf(Q, CbufMaxLen) ->
+ case queue:len(Q) of
+ N when N>=CbufMaxLen ->
+ truncate_cbuf(element(2,queue:out_r(Q)), CbufMaxLen);
+ _ ->
+ Q
+ end.
+
+fmt_cbuf_items() ->
+ lists:flatten(
+ io_lib:format("Circular trace buffer. Latest item first.~n~s~n",
+ [case get(?CIRC_BUF) of
+ {Max,_} ->
+ L = cbuf_list(),
+ [io_lib:format("==== ~.*w: ~s~n",[num_digits(Max),N,fmt_cbuf_item(X)]) ||
+ {N,X} <- lists:zip(lists:seq(1,length(L)), L)
+ ];
+ _ ->
+ io_lib:format("Not started.~n",[])
+ end])).
+
+
+num_digits(0) -> 1;
+num_digits(N) when N>0 -> 1+trunc(math:log10(N)).
+
+
+fmt_cbuf_item({Value, TimeStamp, N}) ->
+ io_lib:format("~s~s~n~s~n",
+ [fmt_ts(TimeStamp),
+ [io_lib:format(" (Repeated ~p times)",[N]) || N>1],
+ fmt_value(Value)]).
+
+
+fmt_ts(TS = {_,_,Us}) ->
+ {{YY,MM,DD},{H,M,S}} = calendar:now_to_universal_time(TS),
+ io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~.6.0w UTC",[YY,MM,DD,H,M,S,Us]).
+
+fmt_value(#circ_buf_entry{module = M,
+ line = L,
+ function = {F,A},
+ pid = Pid,
+ value = V}) ->
+ io_lib:format("~p:~p ~p/~p ~p~n~s",[M,L,F,A,Pid,fmt_value(V)]);
+fmt_value(Value) ->
+ io_lib:format("~p",[Value]).
+
+%%%================================================================
+
+-record(h, {max_bytes = 65536,
+ bytes_per_line = 16,
+ address_len = 4
+ }).
+
+
+hex_dump(Data) -> hex_dump1(Data, hd_opts([])).
+
+hex_dump(X, Max) when is_integer(Max) ->
+ hex_dump(X, [{max_bytes,Max}]);
+hex_dump(X, OptList) when is_list(OptList) ->
+ hex_dump1(X, hd_opts(OptList)).
+
+hex_dump1(B, Opts) when is_binary(B) -> hex_dump1(binary_to_list(B), Opts);
+hex_dump1(L, Opts) when is_list(L), length(L) > Opts#h.max_bytes ->
+ io_lib:format("~s---- skip ~w bytes----~n", [hex_dump1(lists:sublist(L,Opts#h.max_bytes), Opts),
+ length(L) - Opts#h.max_bytes
+ ]);
+hex_dump1(L, Opts0) when is_list(L) ->
+ Opts = Opts0#h{address_len = num_hex_digits(Opts0#h.max_bytes)},
+ Result = hex_dump(L, [{0,[],[]}], Opts),
+ [io_lib:format("~*.s | ~*s | ~s~n"
+ "~*.c-+-~*c-+-~*c~n",
+ [Opts#h.address_len, lists:sublist("Address",Opts#h.address_len),
+ -3*Opts#h.bytes_per_line, lists:sublist("Hexdump",3*Opts#h.bytes_per_line),
+ "ASCII",
+ Opts#h.address_len, $-,
+ 3*Opts#h.bytes_per_line, $-,
+ Opts#h.bytes_per_line, $-
+ ]) |
+ [io_lib:format("~*.16.0b | ~s~*c | ~s~n",[Opts#h.address_len, N*Opts#h.bytes_per_line,
+ lists:reverse(Hexs),
+ 3*(Opts#h.bytes_per_line-length(Hexs)), $ ,
+ lists:reverse(Chars)])
+ || {N,Hexs,Chars} <- lists:reverse(Result)
+ ]
+ ].
+
+
+hd_opts(L) -> lists:foldl(fun hd_opt/2, #h{}, L).
+
+hd_opt({max_bytes,M}, O) -> O#h{max_bytes=M};
+hd_opt({bytes_per_line,M}, O) -> O#h{bytes_per_line=M}.
+
+
+num_hex_digits(N) when N<16 -> 1;
+num_hex_digits(N) -> trunc(math:ceil(math:log2(N)/4)).
+
+
+hex_dump([L|Cs], Result0, Opts) when is_list(L) ->
+ Result = hex_dump(L,Result0, Opts),
+ hex_dump(Cs, Result, Opts);
+
+hex_dump(Cs, [{N0,_,Chars}|_]=Lines, Opts) when length(Chars) == Opts#h.bytes_per_line ->
+ hex_dump(Cs, [{N0+1,[],[]}|Lines], Opts);
+
+hex_dump([C|Cs], [{N,Hexs,Chars}|Lines], Opts) ->
+ Asc = if
+ 16#20 =< C,C =< 16#7E -> C;
+ true -> $.
+ end,
+ Hex = io_lib:format("~2.16.0b ", [C]),
+ hex_dump(Cs, [{N, [Hex|Hexs], [Asc|Chars]} | Lines], Opts);
+
+hex_dump([], Result, _) ->
+ Result.
+
+
+
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 832952ed52..510269bbb1 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -39,6 +39,24 @@
is_auth_key/3]).
+-export_type([system_dir_daemon_option/0,
+ user_dir_common_option/0,
+ user_dir_fun_common_option/0,
+ pubkey_passphrase_client_options/0
+ ]).
+
+-type system_dir_daemon_option() :: {system_dir, string()}.
+-type user_dir_common_option() :: {user_dir, string()}.
+-type user_dir_fun_common_option() :: {user_dir_fun, user2dir()}.
+-type user2dir() :: fun((RemoteUserName::string()) -> UserDir :: string()) .
+
+-type pubkey_passphrase_client_options() :: {dsa_pass_phrase, string()}
+ | {rsa_pass_phrase, string()}
+%% Not yet implemented: | {ed25519_pass_phrase, string()}
+%% Not yet implemented: | {ed448_pass_phrase, string()}
+ | {ecdsa_pass_phrase, string()} .
+
+
-define(PERM_700, 8#700).
-define(PERM_644, 8#644).
@@ -103,6 +121,8 @@ file_base_name('ssh-dss' ) -> "ssh_host_dsa_key";
file_base_name('ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key";
file_base_name('ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key";
file_base_name('ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key";
+file_base_name('ssh-ed25519' ) -> "ssh_host_ed25519_key";
+file_base_name('ssh-ed448' ) -> "ssh_host_ed448_key";
file_base_name(_ ) -> "ssh_host_key".
decode(File, Password) ->
@@ -240,6 +260,8 @@ identity_key_filename('ssh-rsa' ) -> "id_rsa";
identity_key_filename('rsa-sha2-256' ) -> "id_rsa";
identity_key_filename('rsa-sha2-384' ) -> "id_rsa";
identity_key_filename('rsa-sha2-512' ) -> "id_rsa";
+identity_key_filename('ssh-ed25519' ) -> "id_ed25519";
+identity_key_filename('ssh-ed448' ) -> "id_ed448";
identity_key_filename('ecdsa-sha2-nistp256') -> "id_ecdsa";
identity_key_filename('ecdsa-sha2-nistp384') -> "id_ecdsa";
identity_key_filename('ecdsa-sha2-nistp521') -> "id_ecdsa".
@@ -249,9 +271,12 @@ identity_pass_phrase("ssh-rsa" ) -> rsa_pass_phrase;
identity_pass_phrase("rsa-sha2-256" ) -> rsa_pass_phrase;
identity_pass_phrase("rsa-sha2-384" ) -> rsa_pass_phrase;
identity_pass_phrase("rsa-sha2-512" ) -> rsa_pass_phrase;
+%% Not yet implemented: identity_pass_phrase("ssh-ed25519" ) -> ed25519_pass_phrase;
+%% Not yet implemented: identity_pass_phrase("ssh-ed448" ) -> ed448_pass_phrase;
identity_pass_phrase("ecdsa-sha2-"++_) -> ecdsa_pass_phrase;
identity_pass_phrase(P) when is_atom(P) ->
- identity_pass_phrase(atom_to_list(P)).
+ identity_pass_phrase(atom_to_list(P));
+identity_pass_phrase(_) -> undefined.
lookup_host_key_fd(Fd, KeyToMatch, Host, KeyType) ->
case io:get_line(Fd, '') of
@@ -301,6 +326,10 @@ key_match({#'ECPoint'{},{namedCurve,Curve}}, Alg) ->
_ ->
false
end;
+key_match({ed_pub,ed25519,_}, 'ssh-ed25519') ->
+ true;
+key_match({ed_pub,ed448,_}, 'ssh-ed448') ->
+ true;
key_match(_, _) ->
false.
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index 55c0548c9b..d95e58c1bb 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -289,12 +289,12 @@ encode(#ssh_msg_kex_dh_gex_reply{
<<?Ebyte(?SSH_MSG_KEX_DH_GEX_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>;
encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) ->
- <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Empint(Q_c)>>;
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Ebinary(Q_c)>>;
encode(#ssh_msg_kex_ecdh_reply{public_host_key = {Key,SigAlg}, q_s = Q_s, h_sig = Sign}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
EncSign = encode_signature(Key, SigAlg, Sign),
- <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Empint(Q_s), ?Ebinary(EncSign)>>;
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Ebinary(Q_s), ?Ebinary(EncSign)>>;
encode(#ssh_msg_ignore{data = Data}) ->
<<?Ebyte(?SSH_MSG_IGNORE), ?Estring_utf8(Data)>>;
@@ -504,13 +504,13 @@ decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1),
h_sig = decode_signature(Hashsign)
};
-decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_MPINT(Q_c,__0)>>) ->
+decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_BIN(Q_c,__0)>>) ->
#ssh_msg_kex_ecdh_init{
q_c = Q_c
};
decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY),
- ?DEC_BIN(Key,__1), ?DEC_MPINT(Q_s,__2), ?DEC_BIN(Sig,__3)>>) ->
+ ?DEC_BIN(Key,__1), ?DEC_BIN(Q_s,__2), ?DEC_BIN(Sig,__3)>>) ->
#ssh_msg_kex_ecdh_reply{
public_host_key = public_key:ssh_decode(Key, ssh2_pubkey),
q_s = Q_s,
@@ -611,7 +611,13 @@ encode_signature({_, #'Dss-Parms'{}}, _SigAlg, Signature) ->
<<?Ebinary(<<"ssh-dss">>), ?Ebinary(Signature)>>;
encode_signature({#'ECPoint'{}, {namedCurve,OID}}, _SigAlg, Signature) ->
CurveName = public_key:oid2ssh_curvename(OID),
- <<?Ebinary(<<"ecdsa-sha2-",CurveName/binary>>), ?Ebinary(Signature)>>.
+ <<?Ebinary(<<"ecdsa-sha2-",CurveName/binary>>), ?Ebinary(Signature)>>;
+encode_signature({ed_pub, ed25519,_}, _SigAlg, Signature) ->
+ <<?Ebinary(<<"ssh-ed25519">>), ?Ebinary(Signature)>>;
+encode_signature({ed_pub, ed448,_}, _SigAlg, Signature) ->
+ <<?Ebinary(<<"ssh-ed448">>), ?Ebinary(Signature)>>.
+
+
%%%################################################################
%%%#
diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl
index bc9f2156bc..1010c9be55 100644
--- a/lib/ssh/src/ssh_options.erl
+++ b/lib/ssh/src/ssh_options.erl
@@ -434,6 +434,18 @@ default(client) ->
class => user_options
},
+%%% Not yet implemented {ed25519_pass_phrase, def} =>
+%%% Not yet implemented #{default => undefined,
+%%% Not yet implemented chk => fun check_string/1,
+%%% Not yet implemented class => user_options
+%%% Not yet implemented },
+%%% Not yet implemented
+%%% Not yet implemented {ed448_pass_phrase, def} =>
+%%% Not yet implemented #{default => undefined,
+%%% Not yet implemented chk => fun check_string/1,
+%%% Not yet implemented class => user_options
+%%% Not yet implemented },
+%%% Not yet implemented
{silently_accept_hosts, def} =>
#{default => false,
chk => fun check_silently_accept_hosts/1,
@@ -452,12 +464,6 @@ default(client) ->
class => user_options
},
- {pref_public_key_algs, def} =>
- #{default => ssh_transport:default_algorithms(public_key),
- chk => fun check_pref_public_key_algs/1,
- class => user_options
- },
-
{dh_gex_limits, def} =>
#{default => {1024, 6144, 8192}, % FIXME: Is this true nowadays?
chk => fun({Min,I,Max}) ->
@@ -523,6 +529,12 @@ default(common) ->
class => user_options
},
+ {pref_public_key_algs, def} =>
+ #{default => ssh_transport:default_algorithms(public_key),
+ chk => fun check_pref_public_key_algs/1,
+ class => user_options
+ },
+
{preferred_algorithms, def} =>
#{default => ssh:default_algorithms(),
chk => fun check_preferred_algorithms/1,
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index 6e720a47b7..1b2ba5a50b 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -798,13 +798,22 @@ handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}},
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, Signal, Error0, _}},
State0) ->
+ Error =
+ case Error0 of
+ "" -> Signal;
+ _ -> Error0
+ end,
State = reply_all(State0, {error, Error}),
{stop, ChannelId, State};
handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State0) ->
- State = reply_all(State0, {error, {exit_status, Status}}),
+ State =
+ case State0 of
+ 0 -> State0;
+ _ -> reply_all(State0, {error, {exit_status, Status}})
+ end,
{stop, ChannelId, State}.
%%--------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 7ee762dcee..aa9ba0f9bb 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -125,9 +125,9 @@ handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}}, State) ->
- Report = io_lib:format("Connection closed by peer ~n Error ~p~n",
- [Error]),
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, Signal, Error, _}}, State) ->
+ Report = io_lib:format("Connection closed by peer signal ~p~n Error ~p~n",
+ [Signal,Error]),
error_logger:error_report(Report),
{stop, ChannelId, State};
@@ -508,11 +508,8 @@ close_our_file({_,Fd}, FileMod, FS0) ->
FS1.
%%% stat: do the stat
-stat(Vsn, ReqId, Data, State, F) when Vsn =< 3->
- <<?UINT32(BLen), BPath:BLen/binary>> = Data,
- stat(ReqId, unicode:characters_to_list(BPath), State, F);
-stat(Vsn, ReqId, Data, State, F) when Vsn >= 4->
- <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(_Flags)>> = Data,
+stat(Vsn, ReqId, Data, State, F) ->
+ <<?UINT32(BLen), BPath:BLen/binary, _/binary>> = Data,
stat(ReqId, unicode:characters_to_list(BPath), State, F).
fstat(Vsn, ReqId, Data, State) when Vsn =< 3->
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 9ec16b420d..9ff20454cd 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -36,7 +36,7 @@
default_algorithms/0, default_algorithms/1,
algo_classes/0, algo_class/1,
algo_two_spec_classes/0, algo_two_spec_class/1,
- handle_packet_part/4,
+ handle_packet_part/5,
handle_hello_version/1,
key_exchange_init_msg/1,
key_init/3, new_keys_message/1,
@@ -51,7 +51,9 @@
extract_public_key/1,
ssh_packet/2, pack/2,
valid_key_sha_alg/2,
- sha/1, sign/3, verify/5]).
+ sha/1, sign/3, verify/5,
+ get_host_key/2,
+ call_KeyCb/3]).
-export([dbg_trace/3]).
@@ -104,17 +106,14 @@ algo_two_spec_class(_) -> false.
default_algorithms(kex) ->
supported_algorithms(kex, [
- %% Under devolpment:
- 'curve25519-sha256',
- 'curve448-sha512',
%% Gone in OpenSSH 7.3.p1:
'diffie-hellman-group1-sha1'
]);
default_algorithms(cipher) ->
supported_algorithms(cipher, same(['AEAD_AES_128_GCM',
- 'AEAD_AES_256_GCM']));
+ 'AEAD_AES_256_GCM'
+ ]));
default_algorithms(mac) ->
supported_algorithms(mac, same(['AEAD_AES_128_GCM',
'AEAD_AES_256_GCM']));
@@ -128,18 +127,18 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()].
supported_algorithms(kex) ->
select_crypto_supported(
[
- {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]},
- {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]},
- {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]},
- %% https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves
- %% Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
- {'curve25519-sha256', [{public_keys,eddh}, {curves,x25519}, {hashs,sha256}]},
- {'[email protected]', [{public_keys,eddh}, {curves,x25519}, {hashs,sha256}]},
- {'curve448-sha512', [{public_keys,eddh}, {curves,x448}, {hashs,sha512}]},
+ {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {curves,secp384r1}, {hashs,sha384}]},
+ {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {curves,secp521r1}, {hashs,sha512}]},
+ {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {curves,secp256r1}, {hashs,sha256}]},
{'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]},
{'diffie-hellman-group16-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
{'diffie-hellman-group18-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
{'diffie-hellman-group14-sha256', [{public_keys,dh}, {hashs,sha256}]}, % In OpenSSH 7.3.p1
+ %% https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves
+ %% Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
+ {'curve25519-sha256', [{public_keys,ecdh}, {curves,x25519}, {hashs,sha256}]},
+ {'[email protected]', [{public_keys,ecdh}, {curves,x25519}, {hashs,sha256}]},
+ {'curve448-sha512', [{public_keys,ecdh}, {curves,x448}, {hashs,sha512}]},
{'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]},
{'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]},
{'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]}
@@ -147,9 +146,11 @@ supported_algorithms(kex) ->
supported_algorithms(public_key) ->
select_crypto_supported(
[
- {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {ec_curve,secp384r1}]},
- {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {ec_curve,secp521r1}]},
- {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]},
+ {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {curves,secp384r1}]},
+ {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {curves,secp521r1}]},
+ {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {curves,secp256r1}]},
+ {'ssh-ed25519', [{public_keys,eddsa}, {curves,ed25519} ]},
+ {'ssh-ed448', [{public_keys,eddsa}, {curves,ed448} ]},
{'ssh-rsa', [{public_keys,rsa}, {hashs,sha} ]},
{'rsa-sha2-256', [{public_keys,rsa}, {hashs,sha256} ]},
{'rsa-sha2-512', [{public_keys,rsa}, {hashs,sha512} ]},
@@ -160,6 +161,7 @@ supported_algorithms(cipher) ->
same(
select_crypto_supported(
[
+ {'[email protected]', [{ciphers,chacha20}, {macs,poly1305}]},
{'[email protected]', [{ciphers,{aes_gcm,256}}]},
{'aes256-ctr', [{ciphers,{aes_ctr,256}}]},
{'aes192-ctr', [{ciphers,{aes_ctr,192}}]},
@@ -174,9 +176,9 @@ supported_algorithms(cipher) ->
supported_algorithms(mac) ->
same(
select_crypto_supported(
- [{'hmac-sha2-256', [{hashs,sha256}]},
- {'hmac-sha2-512', [{hashs,sha512}]},
- {'hmac-sha1', [{hashs,sha}]},
+ [{'hmac-sha2-256', [{macs,hmac}, {hashs,sha256}]},
+ {'hmac-sha2-512', [{macs,hmac}, {hashs,sha512}]},
+ {'hmac-sha1', [{macs,hmac}, {hashs,sha}]},
{'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]},
{'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]}
]
@@ -433,7 +435,8 @@ key_exchange_first_msg(Kex, Ssh0) when Kex == 'ecdh-sha2-nistp256' ;
%%%
handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
Ssh0 = #ssh{algorithms = #alg{kex=Kex,
- hkey=SignAlg} = Algs}) ->
+ hkey=SignAlg} = Algs,
+ opts = Opts}) ->
%% server
{G, P} = dh_group(Kex),
if
@@ -441,7 +444,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
Sz = dh_bits(Algs),
{Public, Private} = generate_key(dh, [P,G,2*Sz]),
K = compute_key(dh, E, Private, [P,G]),
- MyPrivHostKey = get_host_key(Ssh0, SignAlg),
+ MyPrivHostKey = get_host_key(SignAlg, Opts),
MyPubHostKey = extract_public_key(MyPrivHostKey),
H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {E,Public,K}),
H_SIG = sign(H, sha(SignAlg), MyPrivHostKey),
@@ -580,14 +583,15 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E},
#ssh{keyex_key = {{Private, Public}, {G, P}},
keyex_info = {Min, Max, NBits},
algorithms = #alg{kex=Kex,
- hkey=SignAlg}} = Ssh0) ->
+ hkey=SignAlg},
+ opts = Opts} = Ssh0) ->
%% server
if
1=<E, E=<(P-1) ->
K = compute_key(dh, E, Private, [P,G]),
if
1<K, K<(P-1) ->
- MyPrivHostKey = get_host_key(Ssh0, SignAlg),
+ MyPrivHostKey = get_host_key(SignAlg, Opts),
MyPubHostKey = extract_public_key(MyPrivHostKey),
H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {Min,NBits,Max,P,G,E,Public,K}),
H_SIG = sign(H, sha(SignAlg), MyPrivHostKey),
@@ -655,7 +659,8 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = PeerPubHostK
%%%
handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
Ssh0 = #ssh{algorithms = #alg{kex=Kex,
- hkey=SignAlg}}) ->
+ hkey=SignAlg},
+ opts = Opts}) ->
%% at server
Curve = ecdh_curve(Kex),
{MyPublic, MyPrivate} = generate_key(ecdh, Curve),
@@ -663,7 +668,7 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
compute_key(ecdh, PeerPublic, MyPrivate, Curve)
of
K ->
- MyPrivHostKey = get_host_key(Ssh0, SignAlg),
+ MyPrivHostKey = get_host_key(SignAlg, Opts),
MyPubHostKey = extract_public_key(MyPrivHostKey),
H = kex_hash(Ssh0, MyPubHostKey, sha(Curve), {PeerPublic, MyPublic, K}),
H_SIG = sign(H, sha(SignAlg), MyPrivHostKey),
@@ -761,8 +766,7 @@ ext_info_message(#ssh{role=server,
send_ext_info=true,
opts = Opts} = Ssh0) ->
AlgsList = lists:map(fun erlang:atom_to_list/1,
- proplists:get_value(public_key,
- ?GET_OPT(preferred_algorithms, Opts))),
+ ?GET_OPT(pref_public_key_algs, Opts)),
Msg = #ssh_msg_ext_info{nr_extensions = 1,
data = [{"server-sig-algs", string:join(AlgsList,",")}]
},
@@ -780,10 +784,8 @@ sid(#ssh{session_id = Id}, _) -> Id.
%%
%% The host key should be read from storage
%%
-get_host_key(SSH, SignAlg) ->
- #ssh{key_cb = {KeyCb,KeyCbOpts}, opts = Opts} = SSH,
- UserOpts = ?GET_OPT(user_options, Opts),
- case KeyCb:host_key(SignAlg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
+get_host_key(SignAlg, Opts) ->
+ case call_KeyCb(host_key, [SignAlg], Opts) of
{ok, PrivHostKey} ->
%% Check the key - the KeyCb may be a buggy plugin
case valid_key_sha_alg(PrivHostKey, SignAlg) of
@@ -794,6 +796,11 @@ get_host_key(SSH, SignAlg) ->
exit({error, {Result, unsupported_key_type}})
end.
+call_KeyCb(F, Args, Opts) ->
+ {KeyCb,KeyCbOpts} = ?GET_OPT(key_cb, Opts),
+ UserOpts = ?GET_OPT(user_options, Opts),
+ apply(KeyCb, F, Args ++ [[{key_cb_private,KeyCbOpts}|UserOpts]]).
+
extract_public_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) ->
#'RSAPublicKey'{modulus = N, publicExponent = E};
extract_public_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) ->
@@ -801,6 +808,8 @@ extract_public_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) ->
extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID},
publicKey = Q}) ->
{#'ECPoint'{point=Q}, {namedCurve,OID}};
+extract_public_key({ed_pri, Alg, Pub, _Priv}) ->
+ {ed_pub, Alg, Pub};
extract_public_key(#{engine:=_, key_id:=_, algorithm:=Alg} = M) ->
case {Alg, crypto:privkey_to_pubkey(Alg, M)} of
{rsa, [E,N]} ->
@@ -860,29 +869,30 @@ accepted_host(Ssh, PeerName, Public, Opts) ->
end.
-yes_no(Ssh, Prompt) ->
- (Ssh#ssh.io_cb):yes_no(Prompt, Ssh#ssh.opts).
+yes_no(#ssh{opts=Opts}, Prompt) ->
+ IoCb = ?GET_INTERNAL_OPT(io_cb, Opts, ssh_io),
+ IoCb:yes_no(Prompt, Opts).
fmt_hostkey('ssh-rsa') -> "RSA";
fmt_hostkey('ssh-dss') -> "DSA";
+fmt_hostkey('ssh-ed25519') -> "ED25519";
+fmt_hostkey('ssh-ed448') -> "ED448";
fmt_hostkey(A) when is_atom(A) -> fmt_hostkey(atom_to_list(A));
fmt_hostkey("ecdsa"++_) -> "ECDSA";
fmt_hostkey(X) -> X.
-known_host_key(#ssh{opts = Opts, key_cb = {KeyCb,KeyCbOpts}, peer = {PeerName,_}} = Ssh,
+known_host_key(#ssh{opts = Opts, peer = {PeerName,_}} = Ssh,
Public, Alg) ->
- UserOpts = ?GET_OPT(user_options, Opts),
- case is_host_key(KeyCb, Public, PeerName, Alg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
- {_,true} ->
+ case call_KeyCb(is_host_key, [Public, PeerName, Alg], Opts) of
+ true ->
ok;
- {_,false} ->
+ false ->
DoAdd = ?GET_OPT(save_accepted_host, Opts),
case accepted_host(Ssh, PeerName, Public, Opts) of
true when DoAdd == true ->
- {_,R} = add_host_key(KeyCb, PeerName, Public, [{key_cb_private,KeyCbOpts}|UserOpts]),
- R;
+ call_KeyCb(add_host_key, [PeerName, Public], Opts);
true when DoAdd == false ->
ok;
false ->
@@ -892,13 +902,6 @@ known_host_key(#ssh{opts = Opts, key_cb = {KeyCb,KeyCbOpts}, peer = {PeerName,_}
end
end.
-is_host_key(KeyCb, Public, PeerName, Alg, Data) ->
- {KeyCb, KeyCb:is_host_key(Public, PeerName, Alg, Data)}.
-
-add_host_key(KeyCb, PeerName, Public, Data) ->
- {KeyCb, KeyCb:add_host_key(PeerName, Public, Data)}.
-
-
%% Each of the algorithm strings MUST be a comma-separated list of
%% algorithm names (see ''Algorithm Naming'' in [SSH-ARCH]). Each
%% supported (allowed) algorithm MUST be listed in order of preference.
@@ -982,13 +985,14 @@ select_algorithm(Role, Client, Server, Opts) ->
%%% the exchanged MAC algorithms are ignored and there doesn't have to be
%%% a matching MAC.
-aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan('AEAD_AES_128_GCM', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan('AEAD_AES_256_GCM', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan(_, 'AEAD_AES_128_GCM') -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan(_, 'AEAD_AES_256_GCM') -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}.
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
+aead_gcm_simultan('AEAD_AES_128_GCM'=C, _) -> {C, C};
+aead_gcm_simultan('AEAD_AES_256_GCM'=C, _) -> {C, C};
+aead_gcm_simultan(_, 'AEAD_AES_128_GCM'=C) -> {C, C};
+aead_gcm_simultan(_, 'AEAD_AES_256_GCM'=C) -> {C, C};
+aead_gcm_simultan('[email protected]'=C, _)-> {C, C};
+aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}.
select_encrypt_decrypt(client, Client, Server) ->
@@ -1136,7 +1140,7 @@ pack(PlainText,
encrypt = CryptoAlg} = Ssh0, PacketLenDeviationForTests) when is_binary(PlainText) ->
{Ssh1, CompressedPlainText} = compress(Ssh0, PlainText),
- {EcryptedPacket, MAC, Ssh3} =
+ {FinalPacket, Ssh3} =
case pkt_type(CryptoAlg) of
common ->
PaddingLen = padding_length(4+1+size(CompressedPlainText), Ssh0),
@@ -1145,16 +1149,15 @@ pack(PlainText,
PlainPacketData = <<?UINT32(PlainPacketLen),?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
{Ssh2, EcryptedPacket0} = encrypt(Ssh1, PlainPacketData),
MAC0 = mac(MacAlg, MacKey, SeqNum, PlainPacketData),
- {EcryptedPacket0, MAC0, Ssh2};
+ {<<EcryptedPacket0/binary,MAC0/binary>>, Ssh2};
aead ->
PaddingLen = padding_length(1+size(CompressedPlainText), Ssh0),
Padding = ssh_bits:random(PaddingLen),
PlainPacketLen = 1 + PaddingLen + size(CompressedPlainText) + PacketLenDeviationForTests,
PlainPacketData = <<?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
- {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, {<<?UINT32(PlainPacketLen)>>,PlainPacketData}),
- {<<?UINT32(PlainPacketLen),EcryptedPacket0/binary>>, MAC0, Ssh2}
+ {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, <<?UINT32(PlainPacketLen),PlainPacketData/binary>>),
+ {<<EcryptedPacket0/binary,MAC0/binary>>, Ssh2}
end,
- FinalPacket = [EcryptedPacket, MAC],
Ssh = Ssh3#ssh{send_sequence = (SeqNum+1) band 16#ffffffff},
{FinalPacket, Ssh}.
@@ -1174,31 +1177,31 @@ padding_length(Size, #ssh{encrypt_block_size = BlockSize,
-handle_packet_part(<<>>, Encrypted0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) ->
+handle_packet_part(<<>>, Encrypted0, AEAD0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) ->
%% New ssh packet
case get_length(pkt_type(CryptoAlg), Encrypted0, Ssh0) of
get_more ->
%% too short to get the length
- {get_more, <<>>, Encrypted0, undefined, Ssh0};
+ {get_more, <<>>, Encrypted0, AEAD0, undefined, Ssh0};
- {ok, PacketLen, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE ->
+ {ok, PacketLen, _, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE ->
%% far too long message than expected
{error, {exceeds_max_size,PacketLen}};
- {ok, PacketLen, Decrypted, Encrypted1,
+ {ok, PacketLen, Decrypted, Encrypted1, AEAD,
#ssh{recv_mac_size = MacSize} = Ssh1} ->
%% enough bytes so we got the length and can calculate how many
%% more bytes to expect for a full packet
TotalNeeded = (4 + PacketLen + MacSize),
- handle_packet_part(Decrypted, Encrypted1, TotalNeeded, Ssh1)
+ handle_packet_part(Decrypted, Encrypted1, AEAD, TotalNeeded, Ssh1)
end;
-handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0)
+handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0)
when (size(DecryptedPfx)+size(EncryptedBuffer)) < TotalNeeded ->
%% need more bytes to finalize the packet
- {get_more, DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0};
+ {get_more, DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0};
-handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded,
+handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded,
#ssh{recv_mac_size = MacSize,
decrypt = CryptoAlg} = Ssh0) ->
%% enough bytes to decode the packet.
@@ -1216,8 +1219,7 @@ handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded,
{packet_decrypted, DecompressedPayload, NextPacketBytes, Ssh}
end;
aead ->
- PacketLenBin = DecryptedPfx,
- case decrypt(Ssh0, {PacketLenBin,EncryptedSfx,Mac}) of
+ case decrypt(Ssh0, {AEAD,EncryptedSfx,Mac}) of
{Ssh1, error} ->
{bad_mac, Ssh1};
{Ssh1, DecryptedSfx} ->
@@ -1234,21 +1236,29 @@ get_length(common, EncryptedBuffer, #ssh{decrypt_block_size = BlockSize} = Ssh0)
<<EncBlock:BlockSize/binary, EncryptedRest/binary>> = EncryptedBuffer,
{Ssh,
<<?UINT32(PacketLen),_/binary>> = Decrypted} = decrypt(Ssh0, EncBlock),
- {ok, PacketLen, Decrypted, EncryptedRest, Ssh};
+ {ok, PacketLen, Decrypted, EncryptedRest, <<>>, Ssh};
false ->
get_more
end;
+
get_length(aead, EncryptedBuffer, Ssh) ->
- case size(EncryptedBuffer) >= 4 of
- true ->
+ case {size(EncryptedBuffer) >= 4, Ssh#ssh.decrypt} of
+ {true, '[email protected]'} ->
+ <<EncryptedLen:4/binary, EncryptedRest/binary>> = EncryptedBuffer,
+ {Ssh1, PacketLenBin} = decrypt(Ssh, {length,EncryptedLen}),
+ <<?UINT32(PacketLen)>> = PacketLenBin,
+ {ok, PacketLen, PacketLenBin, EncryptedRest, EncryptedLen, Ssh1};
+ {true, _} ->
<<?UINT32(PacketLen), EncryptedRest/binary>> = EncryptedBuffer,
- {ok, PacketLen, <<?UINT32(PacketLen)>>, EncryptedRest, Ssh};
- false ->
+ {ok, PacketLen, <<?UINT32(PacketLen)>>, EncryptedRest, <<?UINT32(PacketLen)>>, Ssh};
+ {false, _} ->
get_more
end.
+
pkt_type('AEAD_AES_128_GCM') -> aead;
pkt_type('AEAD_AES_256_GCM') -> aead;
+pkt_type('[email protected]') -> aead;
pkt_type(_) -> common.
payload(<<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>) ->
@@ -1353,11 +1363,32 @@ cipher('aes192-ctr') ->
cipher('aes256-ctr') ->
#cipher_data{key_bytes = 32,
iv_bytes = 16,
- block_bytes = 16}.
+ block_bytes = 16};
+
+cipher('[email protected]') -> % FIXME: Verify!!
+ #cipher_data{key_bytes = 32,
+ iv_bytes = 12,
+ block_bytes = 8}.
+
encrypt_init(#ssh{encrypt = none} = Ssh) ->
{ok, Ssh};
+encrypt_init(#ssh{encrypt = '[email protected]', role = client} = Ssh) ->
+ %% [email protected] uses two independent crypto streams, one (chacha20)
+ %% for the length used in stream mode, and the other (chacha20-poly1305) as AEAD for
+ %% the payload and to MAC the length||payload.
+ %% See draft-josefsson-ssh-chacha20-poly1305-openssh-00
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "C", 512),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2}
+ % encrypt_block_size = 16, %default = 8. What to set it to? 64 (openssl chacha.h)
+ % ctx and iv is setup for each packet
+ }};
+encrypt_init(#ssh{encrypt = '[email protected]', role = server} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "D", 512),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2}
+ % encrypt_block_size = 16, %default = 8. What to set it to?
+ }};
encrypt_init(#ssh{encrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
IV = hash(Ssh, "A", 12*8),
<<K:16/binary>> = hash(Ssh, "C", 128),
@@ -1458,18 +1489,40 @@ encrypt_final(Ssh) ->
encrypt(#ssh{encrypt = none} = Ssh, Data) ->
{Ssh, Data};
+encrypt(#ssh{encrypt = '[email protected]',
+ encrypt_keys = {K1,K2},
+ send_sequence = Seq} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ %% Encrypt length
+ IV1 = <<0:8/unit:8, Seq:8/unit:8>>,
+ {_,EncLen} = crypto:stream_encrypt(crypto:stream_init(chacha20, K1, IV1),
+ LenData),
+ %% Encrypt payload
+ IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
+ {_,EncPayloadData} = crypto:stream_encrypt(crypto:stream_init(chacha20, K2, IV2),
+ PayloadData),
+
+ %% MAC tag
+ {_,PolyKey} = crypto:stream_encrypt(crypto:stream_init(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>),
+ <<0:32/unit:8>>),
+ EncBytes = <<EncLen/binary,EncPayloadData/binary>>,
+ Ctag = crypto:poly1305(PolyKey, EncBytes),
+ %% Result
+ {Ssh, {EncBytes,Ctag}};
encrypt(#ssh{encrypt = 'AEAD_AES_128_GCM',
encrypt_keys = K,
- encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
- Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ encrypt_ctx = IV0} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ {Ctext,Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, {LenData,PayloadData}),
IV = next_gcm_iv(IV0),
- {Ssh#ssh{encrypt_ctx = IV}, Enc};
+ {Ssh#ssh{encrypt_ctx = IV}, {<<LenData/binary,Ctext/binary>>,Ctag}};
encrypt(#ssh{encrypt = 'AEAD_AES_256_GCM',
encrypt_keys = K,
- encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
- Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ encrypt_ctx = IV0} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ {Ctext,Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, {LenData,PayloadData}),
IV = next_gcm_iv(IV0),
- {Ssh#ssh{encrypt_ctx = IV}, Enc};
+ {Ssh#ssh{encrypt_ctx = IV}, {<<LenData/binary,Ctext/binary>>,Ctag}};
encrypt(#ssh{encrypt = '3des-cbc',
encrypt_keys = {K1,K2,K3},
encrypt_ctx = IV0} = Ssh, Data) ->
@@ -1502,6 +1555,14 @@ encrypt(#ssh{encrypt = 'aes256-ctr',
decrypt_init(#ssh{decrypt = none} = Ssh) ->
{ok, Ssh};
+decrypt_init(#ssh{decrypt = '[email protected]', role = client} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "D", 512),
+ {ok, Ssh#ssh{decrypt_keys = {K1,K2}
+ }};
+decrypt_init(#ssh{decrypt = '[email protected]', role = server} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "C", 512),
+ {ok, Ssh#ssh{decrypt_keys = {K1,K2}
+ }};
decrypt_init(#ssh{decrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
IV = hash(Ssh, "B", 12*8),
<<K:16/binary>> = hash(Ssh, "D", 128),
@@ -1602,6 +1663,31 @@ decrypt_final(Ssh) ->
decrypt(Ssh, <<>>) ->
{Ssh, <<>>};
+decrypt(#ssh{decrypt = '[email protected]',
+ decrypt_keys = {K1,_K2},
+ recv_sequence = Seq} = Ssh, {length,EncryptedLen}) ->
+ {_State,PacketLenBin} =
+ crypto:stream_decrypt(crypto:stream_init(chacha20, K1, <<0:8/unit:8, Seq:8/unit:8>>),
+ EncryptedLen),
+ {Ssh, PacketLenBin};
+decrypt(#ssh{decrypt = '[email protected]',
+ decrypt_keys = {_K1,K2},
+ recv_sequence = Seq} = Ssh, {AAD,Ctext,Ctag}) ->
+ %% The length is already decoded and used to divide the input
+ %% Check the mac (important that it is timing-safe):
+ {_,PolyKey} =
+ crypto:stream_encrypt(crypto:stream_init(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>),
+ <<0:32/unit:8>>),
+ case equal_const_time(Ctag, crypto:poly1305(PolyKey, <<AAD/binary,Ctext/binary>>)) of
+ true ->
+ %% MAC is ok, decode
+ IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
+ {_,PlainText} =
+ crypto:stream_decrypt(crypto:stream_init(chacha20,K2,IV2), Ctext),
+ {Ssh, PlainText};
+ false ->
+ {Ssh,error}
+ end;
decrypt(#ssh{decrypt = none} = Ssh, Data) ->
{Ssh, Data};
decrypt(#ssh{decrypt = 'AEAD_AES_128_GCM',
@@ -1744,7 +1830,7 @@ send_mac_init(SSH) ->
Key = hash(SSH, "F", KeySize),
{ok, SSH#ssh { send_mac_key = Key }}
end;
- aead ->
+ _ ->
%% Not applicable
{ok, SSH}
end.
@@ -1765,7 +1851,7 @@ recv_mac_init(SSH) ->
Key = hash(SSH, "E", 8*mac_key_bytes(SSH#ssh.recv_mac)),
{ok, SSH#ssh { recv_mac_key = Key }}
end;
- aead ->
+ _ ->
%% Not applicable
{ok, SSH}
end.
@@ -1812,6 +1898,7 @@ hash(K, H, Ki, N, HashAlg) ->
kex_hash(SSH, Key, HashAlg, Args) ->
crypto:hash(HashAlg, kex_plaintext(SSH,Key,Args)).
+
kex_plaintext(SSH, Key, Args) ->
EncodedKey = public_key:ssh_encode(Key, ssh2_pubkey),
<<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
@@ -1819,8 +1906,13 @@ kex_plaintext(SSH, Key, Args) ->
?Ebinary(EncodedKey),
(kex_alg_dependent(Args))/binary>>.
+
+kex_alg_dependent({Q_c, Q_s, K}) when is_binary(Q_c), is_binary(Q_s) ->
+ %% ecdh
+ <<?Ebinary(Q_c), ?Ebinary(Q_s), ?Empint(K)>>;
+
kex_alg_dependent({E, F, K}) ->
- %% diffie-hellman and ec diffie-hellman (with E = Q_c, F = Q_s)
+ %% diffie-hellman
<<?Empint(E), ?Empint(F), ?Empint(K)>>;
kex_alg_dependent({-1, NBits, -1, Prime, Gen, E, F, K}) ->
@@ -1850,6 +1942,11 @@ valid_key_sha_alg(#'RSAPrivateKey'{}, 'ssh-rsa' ) -> true;
valid_key_sha_alg({_, #'Dss-Parms'{}}, 'ssh-dss') -> true;
valid_key_sha_alg(#'DSAPrivateKey'{}, 'ssh-dss') -> true;
+valid_key_sha_alg({ed_pub, ed25519,_}, 'ssh-ed25519') -> true;
+valid_key_sha_alg({ed_pri, ed25519,_,_},'ssh-ed25519') -> true;
+valid_key_sha_alg({ed_pub, ed448,_}, 'ssh-ed448') -> true;
+valid_key_sha_alg({ed_pri, ed448,_,_}, 'ssh-ed448') -> true;
+
valid_key_sha_alg({#'ECPoint'{},{namedCurve,OID}}, Alg) -> valid_key_sha_alg_ec(OID, Alg);
valid_key_sha_alg(#'ECPrivateKey'{parameters = {namedCurve,OID}}, Alg) -> valid_key_sha_alg_ec(OID, Alg);
valid_key_sha_alg(_, _) -> false.
@@ -1859,12 +1956,17 @@ valid_key_sha_alg_ec(OID, Alg) ->
Alg == list_to_atom("ecdsa-sha2-" ++ binary_to_list(Curve)).
+-dialyzer({no_match, public_algo/1}).
+
public_algo(#'RSAPublicKey'{}) -> 'ssh-rsa'; % FIXME: Not right with draft-curdle-rsa-sha2
public_algo({_, #'Dss-Parms'{}}) -> 'ssh-dss';
+public_algo({ed_pub, ed25519,_}) -> 'ssh-ed25519';
+public_algo({ed_pub, ed448,_}) -> 'ssh-ed448';
public_algo({#'ECPoint'{},{namedCurve,OID}}) ->
Curve = public_key:oid2ssh_curvename(OID),
list_to_atom("ecdsa-sha2-" ++ binary_to_list(Curve)).
+
sha('ssh-rsa') -> sha;
sha('rsa-sha2-256') -> sha256;
sha('rsa-sha2-384') -> sha384;
@@ -1873,6 +1975,8 @@ sha('ssh-dss') -> sha;
sha('ecdsa-sha2-nistp256') -> sha(secp256r1);
sha('ecdsa-sha2-nistp384') -> sha(secp384r1);
sha('ecdsa-sha2-nistp521') -> sha(secp521r1);
+sha('ssh-ed25519') -> undefined; % Included in the spec of ed25519
+sha('ssh-ed448') -> undefined; % Included in the spec of ed448
sha(secp256r1) -> sha256;
sha(secp384r1) -> sha384;
sha(secp521r1) -> sha512;
@@ -1905,6 +2009,7 @@ mac_key_bytes('hmac-sha2-256')-> 32;
mac_key_bytes('hmac-sha2-512')-> 64;
mac_key_bytes('AEAD_AES_128_GCM') -> 0;
mac_key_bytes('AEAD_AES_256_GCM') -> 0;
+mac_key_bytes('[email protected]') -> 0;
mac_key_bytes(none) -> 0.
mac_digest_size('hmac-sha1') -> 20;
@@ -1915,6 +2020,7 @@ mac_digest_size('hmac-sha2-256') -> 32;
mac_digest_size('hmac-sha2-512') -> 64;
mac_digest_size('AEAD_AES_128_GCM') -> 16;
mac_digest_size('AEAD_AES_256_GCM') -> 16;
+mac_digest_size('[email protected]') -> 16;
mac_digest_size(none) -> 0.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1937,11 +2043,13 @@ parallell_gen_key(Ssh = #ssh{keyex_key = {x, {G, P}},
Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}}.
+generate_key(ecdh = Algorithm, Args) ->
+ crypto:generate_key(Algorithm, Args);
generate_key(Algorithm, Args) ->
{Public,Private} = crypto:generate_key(Algorithm, Args),
{crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}.
-
+
compute_key(Algorithm, OthersPublic, MyPrivate, Args) ->
Shared = crypto:compute_key(Algorithm, OthersPublic, MyPrivate, Args),
crypto:bytes_to_integer(Shared).
@@ -1963,7 +2071,6 @@ ecdh_curve('curve448-sha512' ) -> x448;
ecdh_curve('curve25519-sha256' ) -> x25519;
ecdh_curve('[email protected]' ) -> x25519.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Utils for default_algorithms/1 and supported_algorithms/1
@@ -1978,15 +2085,10 @@ supported_algorithms(Key, BlackList) ->
select_crypto_supported(L) ->
- Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()],
+ Sup = crypto:supports(),
[Name || {Name,CryptoRequires} <- L,
crypto_supported(CryptoRequires, Sup)].
-crypto_supported_curves() ->
- try crypto:ec_curves()
- catch _:_ -> []
- end.
-
crypto_supported(Conditions, Supported) ->
lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) ->
crypto_name_supported(Tag,CryptoName,Supported);
@@ -1996,7 +2098,11 @@ crypto_supported(Conditions, Supported) ->
end, Conditions).
crypto_name_supported(Tag, CryptoName, Supported) ->
- lists:member(CryptoName, proplists:get_value(Tag,Supported,[])).
+ Vs = case proplists:get_value(Tag,Supported,[]) of
+ [] when Tag == curves -> crypto:ec_curves();
+ L -> L
+ end,
+ lists:member(CryptoName, Vs).
len_supported(Name, Len) ->
try
@@ -2027,6 +2133,20 @@ same(Algs) -> [{client2server,Algs}, {server2client,Algs}].
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Compare two binaries in a timing safe maner.
+%%% The time spent in comparing should not be different depending on where in the binaries they differ.
+%%% This is to avoid a certain side-channel attac.
+equal_const_time(X1, X2) -> equal_const_time(X1, X2, true).
+
+equal_const_time(<<B1,R1/binary>>, <<B2,R2/binary>>, Truth) ->
+ equal_const_time(R1, R2, Truth and (B1 == B2));
+equal_const_time(<<>>, <<>>, Truth) ->
+ Truth;
+equal_const_time(_, _, _) ->
+ false.
+
+%%%-------- Remove CR, LF and following characters from a line
+
trim_tail(Str) ->
lists:takewhile(fun(C) ->
C=/=$\r andalso C=/=$\n
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index e1680c120e..1d77ccb311 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -734,7 +734,7 @@ decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
{Type,Tail2} =
if Vsn =< 3 ->
{?SSH_FILEXFER_TYPE_UNKNOWN, Tail};
- Vsn >= 5 ->
+ true ->
<<?BYTE(T), TL/binary>> = Tail,
{T, TL}
end,
diff --git a/lib/ssh/test/.gitignore b/lib/ssh/test/.gitignore
new file mode 100644
index 0000000000..c9d5f086b3
--- /dev/null
+++ b/lib/ssh/test/.gitignore
@@ -0,0 +1,5 @@
+
+
+property_test/ssh_eqc_client_server_dirs/system
+property_test/ssh_eqc_client_server_dirs/user
+
diff --git a/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl b/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl
index 6d0d8f5d99..f4b521356f 100644
--- a/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl
+++ b/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl
@@ -58,6 +58,7 @@
%%% Properties:
prop_seq(Config) ->
+ error_logger:tty(false),
{ok,Pid} = ssh_eqc_event_handler:add_report_handler(),
{_, _, Port} = init_daemon(Config),
numtests(1000,
@@ -66,16 +67,25 @@ prop_seq(Config) ->
send_bad_sequence(Port, Delay, Pid),
not any_relevant_error_report(Pid)
catch
- C:E -> io:format('~p:~p~n',[C,E]),
+ C:E:S -> ct:log("~p:~p~n~p",[C,E,S]),
false
end
)).
send_bad_sequence(Port, Delay, Pid) ->
- {ok,S} = gen_tcp:connect("localhost",Port,[]),
- gen_tcp:send(S,"Illegal info-string\r\n"),
- ssh_test_lib:sleep_microsec(Delay),
- gen_tcp:close(S).
+ send_bad_sequence(Port, Delay, Pid, 10).
+
+send_bad_sequence(Port, Delay, Pid, N) ->
+ case gen_tcp:connect("localhost",Port,[]) of
+ {ok,S} ->
+ gen_tcp:send(S,"Illegal info-string\r\n"),
+ ssh_test_lib:sleep_microsec(Delay),
+ gen_tcp:close(S);
+
+ {error,econnreset} when N>0 ->
+ timer:sleep(1),
+ send_bad_sequence(Port, Delay, Pid, N-1)
+ end.
any_relevant_error_report(Pid) ->
{ok, Reports} = ssh_eqc_event_handler:get_reports(Pid),
diff --git a/lib/ssh/test/property_test/ssh_eqc_client_server.erl b/lib/ssh/test/property_test/ssh_eqc_client_server.erl
index 39d0b4e410..acb0faa0c7 100644
--- a/lib/ssh/test/property_test/ssh_eqc_client_server.erl
+++ b/lib/ssh/test/property_test/ssh_eqc_client_server.erl
@@ -22,25 +22,27 @@
-module(ssh_eqc_client_server).
-compile(export_all).
+
+-proptest([proper]).
--include_lib("common_test/include/ct.hrl").
-
--ifdef(PROPER).
-%% Proper is not supported.
--else.
--ifdef(TRIQ).
-%% Proper is not supported.
+-ifndef(PROPER).
-else.
+%% Only use proper
+%%
+%% Previously only EQC was supported, but the changes to support PROPER is not
+%% just a wrapper. Since we do not have access to eqc we can't test the changes
+%% so therefore eqc is disabeled.
+%% However, with access to eqc it ought to be quite easy to re-enable eqc by
+%% studying the diff.
+-include_lib("proper/include/proper.hrl").
+-define(MOD_eqc,proper).
+
+-include_lib("common_test/include/ct.hrl").
%% Limit the testing time on CI server... this needs to be improved in % from total budget.
-define(TESTINGTIME(Prop), eqc:testing_time(30,Prop)).
-
--include_lib("eqc/include/eqc.hrl").
--include_lib("eqc/include/eqc_statem.hrl").
--eqc_group_commands(true).
-
-define(SSH_DIR,"ssh_eqc_client_server_dirs").
-define(sec, *1000).
@@ -51,10 +53,6 @@
port
}).
--record(conn,{ref,
- srvr_ref
- }).
-
-record(chan, {ref,
conn_ref,
subsystem,
@@ -65,7 +63,7 @@
initialized = false,
servers = [], % [#srvr{}]
clients = [],
- connections = [], % [#conn{}]
+ connections = [],
channels = [], % [#chan{}]
data_dir
}).
@@ -80,9 +78,8 @@
-define(SUBSYSTEMS, ["echo1", "echo2", "echo3", "echo4"]).
--define(SERVER_ADDRESS, { {127,1,0,choose(1,254)}, % IP
- choose(1024,65535) % Port
- }).
+-define(SERVER_ADDRESS, {127,0,0,1}). % Server listening IP. Darwin, Solaris & FreeBSD
+ % dislikes all other in 127.0.0.0/24
-define(SERVER_EXTRA_OPTIONS, [{parallel_login,bool()}] ).
@@ -104,10 +101,12 @@
%% To be called as eqc:quickcheck( ssh_eqc_client_server:prop_seq() ).
prop_seq() ->
- ?TESTINGTIME(do_prop_seq(?SSH_DIR)).
+ error_logger:tty(false),
+ ?TESTINGTIME(do_prop_seq(?SSH_DIR)).
%% To be called from a common_test test suite
prop_seq(CT_Config) ->
+ error_logger:tty(false),
do_prop_seq(full_path(?SSH_DIR, CT_Config)).
@@ -124,10 +123,12 @@ full_path(SSHdir, CT_Config) ->
SSHdir).
%%%----
prop_parallel() ->
+ error_logger:tty(false),
?TESTINGTIME(do_prop_parallel(?SSH_DIR)).
%% To be called from a common_test test suite
prop_parallel(CT_Config) ->
+ error_logger:tty(false),
do_prop_parallel(full_path(?SSH_DIR, CT_Config)).
do_prop_parallel(DataDir) ->
@@ -139,22 +140,22 @@ do_prop_parallel(DataDir) ->
end).
%%%----
-prop_parallel_multi() ->
- ?TESTINGTIME(do_prop_parallel_multi(?SSH_DIR)).
-
-%% To be called from a common_test test suite
-prop_parallel_multi(CT_Config) ->
- do_prop_parallel_multi(full_path(?SSH_DIR, CT_Config)).
-
-do_prop_parallel_multi(DataDir) ->
- setup_rsa(DataDir),
- ?FORALL(Repetitions,?SHRINK(1,[10]),
- ?FORALL(Cmds,parallel_commands(?MODULE),
- ?ALWAYS(Repetitions,
- begin
- {H,Sf,Result} = run_parallel_commands(?MODULE,Cmds,[{data_dir,DataDir}]),
- present_result(?MODULE, Cmds, {H,Sf,Result}, Result==ok)
- end))).
+%% prop_parallel_multi() ->
+%% ?TESTINGTIME(do_prop_parallel_multi(?SSH_DIR)).
+
+%% %% To be called from a common_test test suite
+%% prop_parallel_multi(CT_Config) ->
+%% do_prop_parallel_multi(full_path(?SSH_DIR, CT_Config)).
+
+%% do_prop_parallel_multi(DataDir) ->
+%% setup_rsa(DataDir),
+%% ?FORALL(Repetitions,?SHRINK(1,[10]),
+%% ?FORALL(Cmds,parallel_commands(?MODULE),
+%% ?ALWAYS(Repetitions,
+%% begin
+%% {H,Sf,Result} = run_parallel_commands(?MODULE,Cmds,[{data_dir,DataDir}]),
+%% present_result(?MODULE, Cmds, {H,Sf,Result}, Result==ok)
+%% end))).
%%%================================================================
%%% State machine spec
@@ -169,13 +170,50 @@ initial_state(DataDir) ->
ssh:start().
%%%----------------
-weight(S, ssh_send) -> 5*length([C || C<-S#state.channels, has_subsyst(C)]);
-weight(S, ssh_start_subsyst) -> 3*length([C || C<-S#state.channels, no_subsyst(C)]);
+weight(S, ssh_send) -> 20*length([C || C<-S#state.channels, has_subsyst(C)]);
+weight(S, ssh_start_subsyst) -> 10*length([C || C<-S#state.channels, no_subsyst(C)]);
weight(S, ssh_close_channel) -> 2*length([C || C<-S#state.channels, has_subsyst(C)]);
-weight(S, ssh_open_channel) -> length(S#state.connections);
+weight(S, ssh_open_channel) -> 2*length(S#state.connections);
weight(_S, _) -> 1.
%%%----------------
+fns() -> [initial_state,
+ ssh_server,
+ ssh_client,
+ ssh_open_connection,
+ ssh_close_connection,
+ ssh_open_channel,
+ ssh_close_channel,
+ ssh_start_subsyst,
+ ssh_send
+ ].
+
+call_f(Name, Sfx) ->
+ case get({Name,Sfx}) of
+ undefined -> F = list_to_atom(lists:concat([Name,"_",Sfx])),
+ put({Name,Sfx}, F),
+ F;
+ F when is_atom(F) -> F
+ end.
+
+-define(call(Name, What, Args), apply(?MODULE, call_f(Name,What), Args)).
+
+symbolic_call(S,Name) -> {call, ?MODULE, Name, ?call(Name,args,[S])}.
+
+may_generate(S, F) -> ?call(F,pre,[S]).
+
+command(S) ->
+ frequency([{weight(S,F), symbolic_call(S,F)} || F <- fns(),
+ may_generate(S, F)]
+ ).
+
+precondition(S, {call,_M,F,As}) -> try ?call(F, pre, [S,As])
+ catch _:undef -> try ?call(F,pre,[S]) catch _:undef -> true end
+ end.
+next_state(S, Res, {call,_M,F,As}) -> try ?call(F, next, [S,Res,As]) catch _:undef -> S end.
+postcondition(S, {call,_M,F,As}, Res) -> try ?call(F, post, [S,As,Res]) catch _:undef -> true end.
+
+%%%----------------
%%% Initialize
initial_state_pre(S) -> not S#state.initialized.
@@ -200,24 +238,34 @@ ssh_server_pre(S) -> S#state.initialized andalso
ssh_server_args(_) -> [?SERVER_ADDRESS, {var,data_dir}, ?SERVER_EXTRA_OPTIONS].
-ssh_server({IP,Port}, DataDir, ExtraOptions) ->
- ok(ssh:daemon(IP, Port,
- [
- {system_dir, system_dir(DataDir)},
- {user_dir, user_dir(DataDir)},
- {subsystems, [{SS, {ssh_eqc_subsys, [SS]}} || SS <- ?SUBSYSTEMS]}
- | ExtraOptions
- ])).
-
-ssh_server_post(_S, _Args, {error,eaddrinuse}) -> true;
-ssh_server_post(_S, _Args, Result) -> is_ok(Result).
-
-ssh_server_next(S, {error,eaddrinuse}, _) -> S;
-ssh_server_next(S, Result, [{IP,Port},_,_]) ->
- S#state{servers=[#srvr{ref = Result,
- address = IP,
- port = Port}
- | S#state.servers]}.
+ssh_server(IP0, DataDir, ExtraOptions) ->
+ case ssh:daemon(IP0, 0,
+ [
+ {system_dir, system_dir(DataDir)},
+ {user_dir, user_dir(DataDir)},
+ {subsystems, [{SS, {ssh_eqc_subsys, [SS]}} || SS <- ?SUBSYSTEMS]}
+ | ExtraOptions
+ ]) of
+ {ok,DaemonRef} ->
+ case ssh:daemon_info(DaemonRef) of
+ {ok, Props} ->
+ Port = proplists:get_value(port,Props),
+ IP = proplists:get_value(ip,Props),
+ #srvr{ref = DaemonRef,
+ address = IP,
+ port = Port};
+ Other ->
+ Other
+ end;
+ Other ->
+ Other
+ end.
+
+ssh_server_post(_S, _Args, #srvr{port=Port}) -> (0 < Port) andalso (Port < 65536);
+ssh_server_post(_S, _Args, _) -> false.
+
+ssh_server_next(S, Srvr, _) ->
+ S#state{servers=[Srvr | S#state.servers]}.
%%%----------------
%%% Start a new client
@@ -271,8 +319,7 @@ ssh_open_connection(#srvr{address=Ip, port=Port}, DataDir) ->
ssh_open_connection_post(_S, _Args, Result) -> is_ok(Result).
-ssh_open_connection_next(S, ConnRef, [#srvr{ref=SrvrRef},_]) ->
- S#state{connections=[#conn{ref=ConnRef, srvr_ref=SrvrRef}|S#state.connections]}.
+ssh_open_connection_next(S, ConnRef, [_,_]) -> S#state{connections=[ConnRef|S#state.connections]}.
%%%----------------
%%% Stop a new connection
@@ -282,12 +329,12 @@ ssh_close_connection_pre(S) -> S#state.connections /= [].
ssh_close_connection_args(S) -> [oneof(S#state.connections)].
-ssh_close_connection(#conn{ref=ConnectionRef}) -> ssh:close(ConnectionRef).
+ssh_close_connection(ConnectionRef) -> ssh:close(ConnectionRef).
-ssh_close_connection_next(S, _, [Conn=#conn{ref=ConnRef}]) ->
- S#state{connections = S#state.connections--[Conn],
- channels = [C || C <- S#state.channels,
- C#chan.conn_ref /= ConnRef]
+ssh_close_connection_next(S, _, [ConnRef]) ->
+ S#state{connections = S#state.connections--[ConnRef],
+ channels = [C || C <- S#state.channels,
+ C#chan.conn_ref /= ConnRef]
}.
%%%----------------
@@ -299,14 +346,14 @@ ssh_open_channel_pre(S) -> S#state.connections /= [].
ssh_open_channel_args(S) -> [oneof(S#state.connections)].
%%% For re-arrangement in parallel tests.
-ssh_open_channel_pre(S,[C]) -> lists:member(C,S#state.connections).
+ssh_open_channel_pre(S,[C]) when is_record(S,state) -> lists:member(C,S#state.connections).
-ssh_open_channel(#conn{ref=ConnectionRef}) ->
+ssh_open_channel(ConnectionRef) ->
ok(ssh_connection:session_channel(ConnectionRef, 20?sec)).
ssh_open_channel_post(_S, _Args, Result) -> is_ok(Result).
-ssh_open_channel_next(S, ChannelRef, [#conn{ref=ConnRef}]) ->
+ssh_open_channel_next(S, ChannelRef, [ConnRef]) ->
S#state{channels=[#chan{ref=ChannelRef,
conn_ref=ConnRef}
| S#state.channels]}.
@@ -326,9 +373,7 @@ ssh_close_channel_next(S, _, [C]) ->
S#state{channels = [Ci || Ci <- S#state.channels,
sig(C) /= sig(Ci)]}.
-
sig(C) -> {C#chan.ref, C#chan.conn_ref}.
-
%%%----------------
%%% Start a sub system on a channel
@@ -361,9 +406,10 @@ ssh_start_subsyst_next(S, _Result, [C,SS,Pid|_]) ->
ssh_send_pre(S) -> lists:any(fun has_subsyst/1, S#state.channels).
-ssh_send_args(S) -> [oneof(lists:filter(fun has_subsyst/1, S#state.channels)),
- choose(0,1),
- message()].
+ssh_send_args(S) ->
+ [oneof(lists:filter(fun has_subsyst/1, S#state.channels)),
+ choose(0,1),
+ message()].
%% For re-arrangement in parallel tests.
ssh_send_pre(S, [C|_]) -> lists:member(C, S#state.channels).
@@ -388,17 +434,17 @@ ssh_send(C=#chan{conn_ref=ConnectionRef, ref=ChannelRef, client_pid=Pid}, Type,
end).
ssh_send_blocking(_S, _Args) ->
- true.
+ true.
ssh_send_post(_S, [C,_,Msg], Response) when is_binary(Response) ->
- Expected = ssh_eqc_subsys:response(modify_msg(C,Msg), C#chan.subsystem),
+ Expected = ssh_eqc_subsys:response(modify_msg(C,Msg), C#chan.subsystem),
case Response of
Expected -> true;
_ -> {send_failed, size(Response), size(Expected)}
end;
ssh_send_post(_S, _Args, Response) ->
- {error,Response}.
+ {error,Response}.
modify_msg(_, <<>>) -> <<>>;
@@ -440,7 +486,11 @@ present_result(_Module, Cmds, _Triple, true) ->
true)))));
present_result(Module, Cmds, Triple, false) ->
- pretty_commands(Module, Cmds, Triple, [{show_states,true}], false).
+ pretty_comands(Module, Cmds, Triple, [{show_states,true}], false),
+ false. % Proper dislikes non-boolean results while eqc treats non-true as false.
+
+pretty_comands(Module, Cmds, Triple, Opts, Bool) ->
+ ct:log("Module = ~p,~n Cmds = ~p,~n Triple = ~p,~n Opts = ~p,~n Bool = ~p",[Module, Cmds, Triple, Opts, Bool]).
@@ -476,23 +526,35 @@ traverse_commands(Fseq, Fpar, {Seq, ParLs}) -> lists:append([Fseq(Seq)|Fpar(ParL
print_frequencies() -> print_frequencies(10).
print_frequencies(Ngroups) -> fun([]) -> io:format('Empty list!~n',[]);
- (L ) -> print_frequencies(L,Ngroups,0,element(1,lists:last(L)))
+ (L ) ->
+ try
+ M = lists:last(L),
+ Max = if is_integer(M) -> M;
+ is_tuple(M) -> element(1,L)
+ end,
+ print_frequencies(L,Ngroups,0,Max)
+ catch
+ C:E:S ->
+ ct:pal("~p:~p ~p:~p~n~p~n~p",[?MODULE,?LINE,C,E,S,L])
+ end
end.
+
print_frequencies(Ngroups, MaxValue) -> fun(L) -> print_frequencies(L,Ngroups,0,MaxValue) end.
print_frequencies(L, N, Min, Max) when N>Max -> print_frequencies(L++[{N,0}], N, Min, N);
-print_frequencies(L, N, Min, Max) ->
-%%io:format('L=~p~n',[L]),
+print_frequencies(L, N, Min, Max0) ->
try
+ Interval = round((Max0-Min)/N),
+ Max = Max0 + (Max0 rem Interval),
IntervalUpperLimits =
lists:reverse(
- [Max | tl(lists:reverse(lists:seq(Min,Max,round((Max-Min)/N))))]
+ [Max | tl(lists:reverse(lists:seq(Min,Max,Interval)))]
),
{Acc0,_} = lists:mapfoldl(fun(Upper,Lower) ->
{{{Lower,Upper},0}, Upper+1}
end, hd(IntervalUpperLimits), tl(IntervalUpperLimits)),
- Fs0 = get_frequencies(L, Acc0),
+ Fs0 = get_frequencies(L, Acc0),
SumVal = lists:sum([V||{_,V}<-Fs0]),
Fs = with_percentage(Fs0, SumVal),
Mean = mean(L),
@@ -517,7 +579,6 @@ print_frequencies(L, N, Min, Max) ->
|| {Interval={Rlow,Rhigh},Val,Percent} <- Fs],
io:format('~*c ~*c~n',[2*Npos_range,32,Npos_value+2,$-]),
io:format('~*c ~*w~n',[2*Npos_range,32,Npos_value,SumVal])
- %%,io:format('L=~p~n',[L])
catch
C:E ->
io:format('*** Faild printing (~p:~p) for~n~p~n',[C,E,L])
@@ -527,6 +588,8 @@ get_frequencies([{I,Num}|T], [{{Lower,Upper},Cnt}|Acc]) when Lower=<I,I=<Upper -
get_frequencies(T, [{{Lower,Upper},Cnt+Num}|Acc]);
get_frequencies(L=[{I,_Num}|_], [Ah={{_Lower,Upper},_Cnt}|Acc]) when I>Upper ->
[Ah | get_frequencies(L,Acc)];
+get_frequencies([I|T], Acc) when is_integer(I) ->
+ get_frequencies([{I,1}|T], Acc);
get_frequencies([], Acc) ->
Acc.
@@ -616,4 +679,3 @@ erase_dir(Dir) ->
file:del_dir(Dir).
-endif.
--endif.
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl
index 5e589e585f..02e5f40c38 100644
--- a/lib/ssh/test/ssh_algorithms_SUITE.erl
+++ b/lib/ssh/test/ssh_algorithms_SUITE.erl
@@ -184,12 +184,15 @@ init_per_testcase(TC, {public_key,Alg}, Config) ->
| ExtraOpts],
[{extra_daemon,true}|Config]);
{{ok,_}, {error,Err}} ->
+ ct:log("Alg = ~p~nOpts = ~p",[Alg,Opts]),
{skip, io_lib:format("No host key: ~p",[Err])};
{{error,Err}, {ok,_}} ->
+ ct:log("Alg = ~p~nOpts = ~p",[Alg,Opts]),
{skip, io_lib:format("No user key: ~p",[Err])};
_ ->
+ ct:log("Alg = ~p~nOpts = ~p",[Alg,Opts]),
{skip, "Neither host nor user key"}
end;
@@ -470,7 +473,9 @@ setup_pubkey(Alg, Config) ->
'rsa-sha2-512' -> ssh_test_lib:setup_rsa(DataDir, UserDir);
'ecdsa-sha2-nistp256' -> ssh_test_lib:setup_ecdsa("256", DataDir, UserDir);
'ecdsa-sha2-nistp384' -> ssh_test_lib:setup_ecdsa("384", DataDir, UserDir);
- 'ecdsa-sha2-nistp521' -> ssh_test_lib:setup_ecdsa("521", DataDir, UserDir)
+ 'ecdsa-sha2-nistp521' -> ssh_test_lib:setup_ecdsa("521", DataDir, UserDir);
+ 'ssh-ed25519' -> ssh_test_lib:setup_eddsa(ed25519, DataDir, UserDir);
+ 'ssh-ed448' -> ssh_test_lib:setup_eddsa(ed448, DataDir, UserDir)
end,
Config.
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed25519 b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed25519
new file mode 100644
index 0000000000..401a3e4a9a
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed25519
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDm9P8/gC0IOKmwHLSvkmEtS2Xx0RRqUDqC6wY6UgDVnwAAAJg3+6xpN/us
+aQAAAAtzc2gtZWQyNTUxOQAAACDm9P8/gC0IOKmwHLSvkmEtS2Xx0RRqUDqC6wY6UgDVnw
+AAAEBzC/Z2WGJhZ3l3tIBnUc6DCbp+lXY2yc2RRpWQTdf8sub0/z+ALQg4qbActK+SYS1L
+ZfHRFGpQOoLrBjpSANWfAAAAE3VhYmhuaWxAZWx4YWRsajNxMzIBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed25519.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed25519.pub
new file mode 100644
index 0000000000..a5c03b19c1
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed25519.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb0/z+ALQg4qbActK+SYS1LZfHRFGpQOoLrBjpSANWf uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed448 b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed448
new file mode 100644
index 0000000000..8ecfd710dc
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed448
@@ -0,0 +1,10 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAAAlz
+c2gtZWQ0NDgAAAA53OqeePNaG/NJmoMbELhskKrAHNhLZ6AQm1WjbpMoseNl/OFh
+1xznExpUPqTLX36fHYsAaWRHABQAAAAA0AAAEREAABERAAAACXNzaC1lZDQ0OAAA
+ADnc6p5481ob80magxsQuGyQqsAc2EtnoBCbVaNukyix42X84WHXHOcTGlQ+pMtf
+fp8diwBpZEcAFAAAAAByzSPST3FCdOdENDI3uTKQ9RH2Ql+Y5kRZ/yA+iYUIP/32
+BQBVOrwOBc0CGEvbicTM1n4YeVEmfrMo3OqeePNaG/NJmoMbELhskKrAHNhLZ6AQ
+m1WjbpMoseNl/OFh1xznExpUPqTLX36fHYsAaWRHABQAAAAAAAECAwQ=
+-----END OPENSSH PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed448.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed448.pub
new file mode 100644
index 0000000000..cec0765a5d
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/id_ed448.pub
@@ -0,0 +1 @@
+ssh-ed448 AAAACXNzaC1lZDQ0OAAAADnc6p5481ob80magxsQuGyQqsAc2EtnoBCbVaNukyix42X84WHXHOcTGlQ+pMtffp8diwBpZEcAFAA= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key
new file mode 100644
index 0000000000..13a8fcf491
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACBJSOuiYGWaO9lye8Bgafod1kw8P6cV3Xb2qJgCB6yJfQAAAJi+h4O7voeD
+uwAAAAtzc2gtZWQyNTUxOQAAACBJSOuiYGWaO9lye8Bgafod1kw8P6cV3Xb2qJgCB6yJfQ
+AAAEBaOcJfGPNemKc1wPHTCmM4Kwvh6dZ0CqY14UT361UnN0lI66JgZZo72XJ7wGBp+h3W
+TDw/pxXddvaomAIHrIl9AAAAE3VhYmhuaWxAZWx4YWRsajNxMzIBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key.pub
new file mode 100644
index 0000000000..156ef4045c
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed25519_key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIElI66JgZZo72XJ7wGBp+h3WTDw/pxXddvaomAIHrIl9 uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key
new file mode 100644
index 0000000000..31a7e4e8c3
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key
@@ -0,0 +1,10 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAAAlz
+c2gtZWQ0NDgAAAA5X9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2
+m0bHBhvWeD3x5Q9s0foavq/oJWGAAAAA0AAAEREAABERAAAACXNzaC1lZDQ0OAAA
+ADlf10SbWbRh/Sznh+xhatRqHaE0JIWnDh+KDqddgOlneO3xJHabRscGG9Z4PfHl
+D2zR+hq+r+glYYAAAABybIKlYsuAjRDWMr6JyFE+v2ySnzTd+oyfY8mWDvbjSKNS
+jIo/zC8ETjmj/FuUSS+PAy51SaIAmPlbX9dEm1m0Yf0s54fsYWrUah2hNCSFpw4f
+ig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq/oJWGAAAAAAAECAwQ=
+-----END OPENSSH PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key.pub b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key.pub
new file mode 100644
index 0000000000..8c390dcb58
--- /dev/null
+++ b/lib/ssh/test/ssh_algorithms_SUITE_data/ssh_host_ed448_key.pub
@@ -0,0 +1 @@
+ssh-ed448 AAAACXNzaC1lZDQ0OAAAADlf10SbWbRh/Sznh+xhatRqHaE0JIWnDh+KDqddgOlneO3xJHabRscGG9Z4PfHlD2zR+hq+r+glYYA=
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 778ae1e7b6..5de6d52092 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -43,7 +43,9 @@ suite() ->
{timetrap,{seconds,40}}].
all() ->
- [{group, all_tests}].
+ [{group, all_tests},
+ daemon_already_started
+ ].
groups() ->
[{all_tests, [parallel], [{group, ssh_renegotiate_SUITE},
@@ -56,6 +58,8 @@ groups() ->
{group, ecdsa_sha2_nistp256_key},
{group, ecdsa_sha2_nistp384_key},
{group, ecdsa_sha2_nistp521_key},
+ {group, ed25519_key},
+ {group, ed448_key},
{group, dsa_pass_key},
{group, rsa_pass_key},
{group, ecdsa_sha2_nistp256_pass_key},
@@ -94,6 +98,8 @@ groups() ->
{ecdsa_sha2_nistp256_key, [], [{group, basic}]},
{ecdsa_sha2_nistp384_key, [], [{group, basic}]},
{ecdsa_sha2_nistp521_key, [], [{group, basic}]},
+ {ed25519_key, [], [{group, basic}]},
+ {ed448_key, [], [{group, basic}]},
{rsa_host_key_is_actualy_ecdsa, [], [fail_daemon_start]},
{host_user_key_differs, [parallel], [exec_key_differs1,
exec_key_differs2,
@@ -222,6 +228,28 @@ init_per_group(ecdsa_sha2_nistp521_key, Config) ->
false ->
{skip, unsupported_pub_key}
end;
+init_per_group(ed25519_key, Config) ->
+ case lists:member('ssh-ed25519',
+ ssh_transport:default_algorithms(public_key)) of
+ true ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ssh_test_lib:setup_eddsa(ed25519, DataDir, PrivDir),
+ Config;
+ false ->
+ {skip, unsupported_pub_key}
+ end;
+init_per_group(ed448_key, Config) ->
+ case lists:member('ssh-ed448',
+ ssh_transport:default_algorithms(public_key)) of
+ true ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ssh_test_lib:setup_eddsa(ed448, DataDir, PrivDir),
+ Config;
+ false ->
+ {skip, unsupported_pub_key}
+ end;
init_per_group(rsa_pass_key, Config) ->
case lists:member('ssh-rsa',
ssh_transport:default_algorithms(public_key)) of
@@ -775,6 +803,24 @@ daemon_already_started(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
+%%% Test that a failed daemon start does not leave the port open
+daemon_error_closes_port(Config) ->
+ GoodSystemDir = proplists:get_value(data_dir, Config),
+ Port = ssh_test_lib:inet_port(),
+ {error,_} = ssh_test_lib:daemon(Port, []), % No system dir
+ case ssh_test_lib:daemon(Port, [{system_dir, GoodSystemDir}]) of
+ {error,eaddrinuse} ->
+ {fail, "Port leakage"};
+ {error,Error} ->
+ ct:log("Strange error: ~p",[Error]),
+ {fail, "Strange error"};
+ {Pid, _Host, Port} ->
+ %% Ok
+ ssh:stop_daemon(Pid)
+ end.
+
+
+%%--------------------------------------------------------------------
%%% check that known_hosts is updated correctly
known_hosts(Config) when is_list(Config) ->
SystemDir = proplists:get_value(data_dir, Config),
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ed25519 b/lib/ssh/test/ssh_basic_SUITE_data/id_ed25519
new file mode 100644
index 0000000000..401a3e4a9a
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ed25519
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDm9P8/gC0IOKmwHLSvkmEtS2Xx0RRqUDqC6wY6UgDVnwAAAJg3+6xpN/us
+aQAAAAtzc2gtZWQyNTUxOQAAACDm9P8/gC0IOKmwHLSvkmEtS2Xx0RRqUDqC6wY6UgDVnw
+AAAEBzC/Z2WGJhZ3l3tIBnUc6DCbp+lXY2yc2RRpWQTdf8sub0/z+ALQg4qbActK+SYS1L
+ZfHRFGpQOoLrBjpSANWfAAAAE3VhYmhuaWxAZWx4YWRsajNxMzIBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ed25519.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ed25519.pub
new file mode 100644
index 0000000000..a5c03b19c1
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ed25519.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb0/z+ALQg4qbActK+SYS1LZfHRFGpQOoLrBjpSANWf uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ed448 b/lib/ssh/test/ssh_basic_SUITE_data/id_ed448
new file mode 100644
index 0000000000..8ecfd710dc
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ed448
@@ -0,0 +1,10 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAAAlz
+c2gtZWQ0NDgAAAA53OqeePNaG/NJmoMbELhskKrAHNhLZ6AQm1WjbpMoseNl/OFh
+1xznExpUPqTLX36fHYsAaWRHABQAAAAA0AAAEREAABERAAAACXNzaC1lZDQ0OAAA
+ADnc6p5481ob80magxsQuGyQqsAc2EtnoBCbVaNukyix42X84WHXHOcTGlQ+pMtf
+fp8diwBpZEcAFAAAAAByzSPST3FCdOdENDI3uTKQ9RH2Ql+Y5kRZ/yA+iYUIP/32
+BQBVOrwOBc0CGEvbicTM1n4YeVEmfrMo3OqeePNaG/NJmoMbELhskKrAHNhLZ6AQ
+m1WjbpMoseNl/OFh1xznExpUPqTLX36fHYsAaWRHABQAAAAAAAECAwQ=
+-----END OPENSSH PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_ed448.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_ed448.pub
new file mode 100644
index 0000000000..cec0765a5d
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_ed448.pub
@@ -0,0 +1 @@
+ssh-ed448 AAAACXNzaC1lZDQ0OAAAADnc6p5481ob80magxsQuGyQqsAc2EtnoBCbVaNukyix42X84WHXHOcTGlQ+pMtffp8diwBpZEcAFAA= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key
new file mode 100644
index 0000000000..13a8fcf491
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACBJSOuiYGWaO9lye8Bgafod1kw8P6cV3Xb2qJgCB6yJfQAAAJi+h4O7voeD
+uwAAAAtzc2gtZWQyNTUxOQAAACBJSOuiYGWaO9lye8Bgafod1kw8P6cV3Xb2qJgCB6yJfQ
+AAAEBaOcJfGPNemKc1wPHTCmM4Kwvh6dZ0CqY14UT361UnN0lI66JgZZo72XJ7wGBp+h3W
+TDw/pxXddvaomAIHrIl9AAAAE3VhYmhuaWxAZWx4YWRsajNxMzIBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key.pub
new file mode 100644
index 0000000000..156ef4045c
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed25519_key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIElI66JgZZo72XJ7wGBp+h3WTDw/pxXddvaomAIHrIl9 uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key
new file mode 100644
index 0000000000..31a7e4e8c3
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key
@@ -0,0 +1,10 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAAAlz
+c2gtZWQ0NDgAAAA5X9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2
+m0bHBhvWeD3x5Q9s0foavq/oJWGAAAAA0AAAEREAABERAAAACXNzaC1lZDQ0OAAA
+ADlf10SbWbRh/Sznh+xhatRqHaE0JIWnDh+KDqddgOlneO3xJHabRscGG9Z4PfHl
+D2zR+hq+r+glYYAAAABybIKlYsuAjRDWMr6JyFE+v2ySnzTd+oyfY8mWDvbjSKNS
+jIo/zC8ETjmj/FuUSS+PAy51SaIAmPlbX9dEm1m0Yf0s54fsYWrUah2hNCSFpw4f
+ig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq/oJWGAAAAAAAECAwQ=
+-----END OPENSSH PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key.pub
new file mode 100644
index 0000000000..8c390dcb58
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_ed448_key.pub
@@ -0,0 +1 @@
+ssh-ed448 AAAACXNzaC1lZDQ0OAAAADlf10SbWbRh/Sznh+xhatRqHaE0JIWnDh+KDqddgOlneO3xJHabRscGG9Z4PfHlD2zR+hq+r+glYYA=
diff --git a/lib/ssh/test/ssh_bench_SUITE.erl b/lib/ssh/test/ssh_bench_SUITE.erl
index b6c6147646..2ac4e5636a 100644
--- a/lib/ssh/test/ssh_bench_SUITE.erl
+++ b/lib/ssh/test/ssh_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,10 +65,10 @@ init_per_suite(Config) ->
{preferred_algorithms, Algs},
{modify_algorithms,[{prepend,[{cipher,[none]},
{mac,[none]}
- ]},
- {rm, [{cipher,['[email protected]',
- ]}
+ ]}
+ %% ,{rm, [{cipher,['[email protected]',
+ %% ]}
]},
{max_random_length_padding, 0},
{subsystems, [{"/dev/null", {ssh_bench_dev_null,[DataSize]}}]}
@@ -109,11 +109,10 @@ connect(Config) ->
lists:foreach(
fun(KexAlg) ->
PrefAlgs = preferred_algorithms(KexAlg),
- report([{value, measure_connect(Config,
- [{preferred_algorithms,PrefAlgs}])},
- {suite, ?MODULE},
- {name, mk_name(["Connect erlc erld ",KexAlg," [µs]"])}
- ])
+ TimeMicroSec = measure_connect(Config,
+ [{preferred_algorithms,PrefAlgs}]),
+ report(["Connect erlc erld ",KexAlg," [connects per sec]"],
+ 1000000 / TimeMicroSec)
end, KexAlgs).
@@ -130,7 +129,7 @@ measure_connect(Config, Opts) ->
[begin
{Time, {ok,Pid}} = timer:tc(ssh,connect,["localhost", Port, ConnectOptions]),
ssh:close(Pid),
- Time
+ Time % in µs
end || _ <- lists:seq(1,?Nruns)]).
%%%----------------------------------------------------------------
@@ -152,7 +151,8 @@ transfer_text(Config) ->
|| {Crypto,Mac} <- [{ none, none},
{'aes128-ctr', 'hmac-sha1'},
{'aes256-ctr', 'hmac-sha1'},
-%% {'[email protected]', 'hmac-sha1'},
+{'[email protected]', 'hmac-sha1'},
+{'[email protected]', 'hmac-sha1'},
{'aes128-cbc', 'hmac-sha1'},
{'3des-cbc', 'hmac-sha1'},
{'aes128-ctr', 'hmac-sha2-256'},
@@ -177,34 +177,32 @@ gen_data(DataSz) ->
<<Data0/binary, Data1/binary>>.
-%% connect_measure(Port, Cipher, Mac, Data, Options) ->
-%% report([{value, 1},
-%% {suite, ?MODULE},
-%% {name, mk_name(["Transfer 1M bytes ",Cipher,"/",Mac," [µs]"])}]);
connect_measure(Port, Cipher, Mac, Data, Options) ->
- AES_GCM = {cipher,['[email protected]',
+ AES_GCM = {cipher,
+ []},
AlgOpt = case {Cipher,Mac} of
{none,none} ->
[{modify_algorithms,[{prepend, [{cipher,[Cipher]},
- {mac,[Mac]}]},
- {rm,[AES_GCM]}
+ {mac,[Mac]}]}
+%%% ,{rm,[AES_GCM]}
]}];
{none,_} ->
- [{modify_algorithms,[{prepend, [{cipher,[Cipher]}]},
- {rm,[AES_GCM]}
+ [{modify_algorithms,[{prepend, [{cipher,[Cipher]}]}
+%%% ,{rm,[AES_GCM]}
]},
{preferred_algorithms, [{mac,[Mac]}]}];
{_,none} ->
- [{modify_algorithms,[{prepend, [{mac,[Mac]}]},
- {rm,[AES_GCM]}
+ [{modify_algorithms,[{prepend, [{mac,[Mac]}]}
+%%% ,{rm,[AES_GCM]}
]},
{preferred_algorithms, [{cipher,[Cipher]}]}];
_ ->
[{preferred_algorithms, [{cipher,[Cipher]},
- {mac,[Mac]}]},
- {modify_algorithms, [{rm,[AES_GCM]}]}
+ {mac,[Mac]}]}
+%%% ,{modify_algorithms, [{rm,[AES_GCM]}]}
]
end,
Times =
@@ -217,10 +215,8 @@ connect_measure(Port, Cipher, Mac, Data, Options) ->
ssh:close(C),
Time
end || _ <- lists:seq(1,?Nruns)],
-
- report([{value, median(Times)},
- {suite, ?MODULE},
- {name, mk_name(["Transfer 1M bytes ",Cipher,"/",Mac," [µs]"])}]).
+ report(["Transfer ",Cipher,"/",Mac," [Mbyte per sec]"],
+ 1000000 / median(Times)).
send_wait_acc(C, Ch, Data) ->
ssh_connection:send(C, Ch, Data),
@@ -235,12 +231,6 @@ send_wait_acc(C, Ch, Data) ->
%%%
%%%----------------------------------------------------------------
-mk_name(Name) -> [char(C) || C <- lists:concat(Name)].
-
-char($-) -> $_;
-char(C) -> C.
-
-%%%----------------------------------------------------------------
preferred_algorithms(KexAlg) ->
[{kex, [KexAlg]},
{public_key, ['ssh-rsa']},
@@ -262,11 +252,22 @@ median(Data) when is_list(Data) ->
1 ->
lists:nth(N div 2 + 1, SortedData)
end,
- ct:log("median(~p) = ~p",[SortedData,Median]),
+ ct:pal("median(~p) = ~p",[SortedData,Median]),
Median.
+%%%----------------------------------------------------------------
+report(LabelList, Value) ->
+ Label = report_chars(lists:concat(LabelList)),
+ ct:pal("ct_event:notify ~p: ~p", [Label, Value]),
+ ct_event:notify(
+ #event{name = benchmark_data,
+ data = [{suite, ?MODULE},
+ {name, Label},
+ {value, Value}]}).
+
+report_chars(Cs) ->
+ [case C of
+ $- -> $_;
+ _ -> C
+ end || C <- Cs].
-report(Data) ->
- ct:log("EventData = ~p",[Data]),
- ct_event:notify(#event{name = benchmark_data,
- data = Data}).
diff --git a/lib/ssh/test/ssh_compat_SUITE.erl b/lib/ssh/test/ssh_compat_SUITE.erl
index 1c607bebe8..8e82527c6e 100644
--- a/lib/ssh/test/ssh_compat_SUITE.erl
+++ b/lib/ssh/test/ssh_compat_SUITE.erl
@@ -648,6 +648,7 @@ setup_remote_priv_and_local_auth_keys(KeyAlg, IP, Port, UserDir, Config) ->
{silently_accept_hosts,true},
{user_interaction,false}
]),
+ rm_id_in_remote_dir(Ch, ".ssh"),
_ = ssh_sftp:make_dir(Ch, ".ssh"),
DstFile = filename:join(".ssh", dst_filename(user,KeyAlg)),
ok = ssh_sftp:write_file(Ch, DstFile, Priv),
@@ -658,6 +659,18 @@ setup_remote_priv_and_local_auth_keys(KeyAlg, IP, Port, UserDir, Config) ->
ok = ssh:close(Cc),
UserDir.
+rm_id_in_remote_dir(Ch, Dir) ->
+ case ssh_sftp:list_dir(Ch, Dir) of
+ {error,_Error} ->
+ ok;
+ {ok,FileNames} ->
+ lists:foreach(fun("id_"++_ = F) ->
+ ok = ssh_sftp:delete(Ch, filename:join(Dir,F));
+ (_) ->
+ leave
+ end, FileNames)
+ end.
+
user_priv_pub_keys(Config, KeyAlg) -> priv_pub_keys("users_keys", user, Config, KeyAlg).
host_priv_pub_keys(Config, KeyAlg) -> priv_pub_keys("host_keys", host, Config, KeyAlg).
@@ -673,6 +686,8 @@ src_filename(user, 'ssh-rsa' ) -> "id_rsa";
src_filename(user, 'rsa-sha2-256' ) -> "id_rsa";
src_filename(user, 'rsa-sha2-512' ) -> "id_rsa";
src_filename(user, 'ssh-dss' ) -> "id_dsa";
+src_filename(user, 'ssh-ed25519' ) -> "id_ed25519";
+src_filename(user, 'ssh-ed448' ) -> "id_ed448";
src_filename(user, 'ecdsa-sha2-nistp256') -> "id_ecdsa256";
src_filename(user, 'ecdsa-sha2-nistp384') -> "id_ecdsa384";
src_filename(user, 'ecdsa-sha2-nistp521') -> "id_ecdsa521";
@@ -680,6 +695,8 @@ src_filename(host, 'ssh-rsa' ) -> "ssh_host_rsa_key";
src_filename(host, 'rsa-sha2-256' ) -> "ssh_host_rsa_key";
src_filename(host, 'rsa-sha2-512' ) -> "ssh_host_rsa_key";
src_filename(host, 'ssh-dss' ) -> "ssh_host_dsa_key";
+src_filename(host, 'ssh-ed25519' ) -> "ssh_host_ed25519_key";
+src_filename(host, 'ssh-ed448' ) -> "ssh_host_ed448_key";
src_filename(host, 'ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key256";
src_filename(host, 'ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key384";
src_filename(host, 'ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key521".
@@ -688,6 +705,8 @@ dst_filename(user, 'ssh-rsa' ) -> "id_rsa";
dst_filename(user, 'rsa-sha2-256' ) -> "id_rsa";
dst_filename(user, 'rsa-sha2-512' ) -> "id_rsa";
dst_filename(user, 'ssh-dss' ) -> "id_dsa";
+dst_filename(user, 'ssh-ed25519' ) -> "id_ed25519";
+dst_filename(user, 'ssh-ed448' ) -> "id_ed448";
dst_filename(user, 'ecdsa-sha2-nistp256') -> "id_ecdsa";
dst_filename(user, 'ecdsa-sha2-nistp384') -> "id_ecdsa";
dst_filename(user, 'ecdsa-sha2-nistp521') -> "id_ecdsa";
@@ -695,6 +714,8 @@ dst_filename(host, 'ssh-rsa' ) -> "ssh_host_rsa_key";
dst_filename(host, 'rsa-sha2-256' ) -> "ssh_host_rsa_key";
dst_filename(host, 'rsa-sha2-512' ) -> "ssh_host_rsa_key";
dst_filename(host, 'ssh-dss' ) -> "ssh_host_dsa_key";
+dst_filename(host, 'ssh-ed25519' ) -> "ssh_host_ed25519_key";
+dst_filename(host, 'ssh-ed448' ) -> "ssh_host_ed448_key";
dst_filename(host, 'ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key";
dst_filename(host, 'ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key";
dst_filename(host, 'ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key".
@@ -1105,7 +1126,24 @@ prepare_local_directory(ServerRootDir) ->
"chmod 222 unreadable_file",
"exit"].
+
check_local_directory(ServerRootDir) ->
+ TimesToTry = 3, % sleep 0.5, 1, 2 and then 4 secs (7.5s in total)
+ check_local_directory(ServerRootDir, 500, TimesToTry-1).
+
+check_local_directory(ServerRootDir, SleepTime, N) ->
+ case do_check_local_directory(ServerRootDir) of
+ {error,Error} when N>0 ->
+ %% Could be that the erlang side is faster and the docker's operations
+ %% are not yet finalized.
+ %% Sleep for a while and retry a few times:
+ timer:sleep(SleepTime),
+ check_local_directory(ServerRootDir, 2*SleepTime, N-1);
+ Other ->
+ Other
+ end.
+
+do_check_local_directory(ServerRootDir) ->
case lists:sort(ok(file:list_dir(ServerRootDir)) -- [".",".."]) of
["ex_tst1","mydir","tst2"] ->
{ok,Expect} = file:read_file(filename:join(ServerRootDir,"ex_tst1")),
@@ -1140,6 +1178,7 @@ check_local_directory(ServerRootDir) ->
{error,{bad_dir_contents,"/"}}
end.
+
call_sftp_in_docker(Config, ServerIP, ServerPort, Cmnds, UserDir) ->
{DockerIP,DockerPort} = ip_port(Config),
{ok,C} = ssh:connect(DockerIP, DockerPort,
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all
index 0dcf8cb570..c2e77fcc79 100755
--- a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all
+++ b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all
@@ -18,6 +18,12 @@ SSH_SSL_VERSIONS=(\
openssh 7.6p1 openssl 1.0.2n \
\
openssh 7.6p1 libressl 2.6.4 \
+ \
+ openssh 7.7p1 openssl 1.0.2p \
+ openssh 7.8p1 openssl 1.0.2p \
+ openssh 7.9p1 openssl 1.0.2p \
+ \
+ openssh 7.9p1 libressl 2.6.4 \
)
if [ "x$1" == "x-b" ]
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key
new file mode 100644
index 0000000000..13a8fcf491
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACBJSOuiYGWaO9lye8Bgafod1kw8P6cV3Xb2qJgCB6yJfQAAAJi+h4O7voeD
+uwAAAAtzc2gtZWQyNTUxOQAAACBJSOuiYGWaO9lye8Bgafod1kw8P6cV3Xb2qJgCB6yJfQ
+AAAEBaOcJfGPNemKc1wPHTCmM4Kwvh6dZ0CqY14UT361UnN0lI66JgZZo72XJ7wGBp+h3W
+TDw/pxXddvaomAIHrIl9AAAAE3VhYmhuaWxAZWx4YWRsajNxMzIBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key.pub b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key.pub
new file mode 100644
index 0000000000..156ef4045c
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed25519_key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIElI66JgZZo72XJ7wGBp+h3WTDw/pxXddvaomAIHrIl9 uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key
new file mode 100644
index 0000000000..31a7e4e8c3
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key
@@ -0,0 +1,10 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAAAlz
+c2gtZWQ0NDgAAAA5X9dEm1m0Yf0s54fsYWrUah2hNCSFpw4fig6nXYDpZ3jt8SR2
+m0bHBhvWeD3x5Q9s0foavq/oJWGAAAAA0AAAEREAABERAAAACXNzaC1lZDQ0OAAA
+ADlf10SbWbRh/Sznh+xhatRqHaE0JIWnDh+KDqddgOlneO3xJHabRscGG9Z4PfHl
+D2zR+hq+r+glYYAAAABybIKlYsuAjRDWMr6JyFE+v2ySnzTd+oyfY8mWDvbjSKNS
+jIo/zC8ETjmj/FuUSS+PAy51SaIAmPlbX9dEm1m0Yf0s54fsYWrUah2hNCSFpw4f
+ig6nXYDpZ3jt8SR2m0bHBhvWeD3x5Q9s0foavq/oJWGAAAAAAAECAwQ=
+-----END OPENSSH PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key.pub b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key.pub
new file mode 100644
index 0000000000..8c390dcb58
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ed448_key.pub
@@ -0,0 +1 @@
+ssh-ed448 AAAACXNzaC1lZDQ0OAAAADlf10SbWbRh/Sznh+xhatRqHaE0JIWnDh+KDqddgOlneO3xJHabRscGG9Z4PfHlD2zR+hq+r+glYYA=
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed25519 b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed25519
new file mode 100644
index 0000000000..401a3e4a9a
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed25519
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDm9P8/gC0IOKmwHLSvkmEtS2Xx0RRqUDqC6wY6UgDVnwAAAJg3+6xpN/us
+aQAAAAtzc2gtZWQyNTUxOQAAACDm9P8/gC0IOKmwHLSvkmEtS2Xx0RRqUDqC6wY6UgDVnw
+AAAEBzC/Z2WGJhZ3l3tIBnUc6DCbp+lXY2yc2RRpWQTdf8sub0/z+ALQg4qbActK+SYS1L
+ZfHRFGpQOoLrBjpSANWfAAAAE3VhYmhuaWxAZWx4YWRsajNxMzIBAg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed25519.pub b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed25519.pub
new file mode 100644
index 0000000000..a5c03b19c1
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed25519.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOb0/z+ALQg4qbActK+SYS1LZfHRFGpQOoLrBjpSANWf uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed448 b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed448
new file mode 100644
index 0000000000..8ecfd710dc
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed448
@@ -0,0 +1,10 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAAAlz
+c2gtZWQ0NDgAAAA53OqeePNaG/NJmoMbELhskKrAHNhLZ6AQm1WjbpMoseNl/OFh
+1xznExpUPqTLX36fHYsAaWRHABQAAAAA0AAAEREAABERAAAACXNzaC1lZDQ0OAAA
+ADnc6p5481ob80magxsQuGyQqsAc2EtnoBCbVaNukyix42X84WHXHOcTGlQ+pMtf
+fp8diwBpZEcAFAAAAAByzSPST3FCdOdENDI3uTKQ9RH2Ql+Y5kRZ/yA+iYUIP/32
+BQBVOrwOBc0CGEvbicTM1n4YeVEmfrMo3OqeePNaG/NJmoMbELhskKrAHNhLZ6AQ
+m1WjbpMoseNl/OFh1xznExpUPqTLX36fHYsAaWRHABQAAAAAAAECAwQ=
+-----END OPENSSH PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed448.pub b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed448.pub
new file mode 100644
index 0000000000..cec0765a5d
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ed448.pub
@@ -0,0 +1 @@
+ssh-ed448 AAAACXNzaC1lZDQ0OAAAADnc6p5481ob80magxsQuGyQqsAc2EtnoBCbVaNukyix42X84WHXHOcTGlQ+pMtffp8diwBpZEcAFAA= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_dbg_SUITE.erl b/lib/ssh/test/ssh_dbg_SUITE.erl
index 5439817d10..ab7918fa90 100644
--- a/lib/ssh/test/ssh_dbg_SUITE.erl
+++ b/lib/ssh/test/ssh_dbg_SUITE.erl
@@ -38,11 +38,20 @@ suite() ->
{timetrap,{seconds,60}}].
all() ->
- [basic,
- dbg_alg_terminate,
- dbg_ssh_messages,
- dbg_connections,
- dbg_channels
+ [{group, dbg},
+ {group, circ_buf}
+ ].
+
+groups() ->
+ [{dbg, [], [dbg_basic,
+ dbg_alg_terminate,
+ dbg_ssh_messages,
+ dbg_connections,
+ dbg_channels]},
+ {circ_buf, [], [cb_basic,
+ cb_print,
+ cb_macros_print
+ ]}
].
%%--------------------------------------------------------------------
@@ -82,7 +91,7 @@ end_per_testcase(_TC, Config) ->
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-basic(_Config) ->
+dbg_basic(_Config) ->
L0 = ssh_dbg:start(),
true = is_pid(whereis(ssh_dbg)),
true = is_list(L0),
@@ -342,6 +351,53 @@ dbg_channels(Config) ->
stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid).
%%--------------------------------------------------------------------
+cb_basic(_Config) ->
+ %% Check that the circular buffer is disabled at start:
+ [] = ssh_dbg:cbuf_list(),
+ disabled = ssh_dbg:cbuf_in(anything),
+ [] = ssh_dbg:cbuf_list(),
+ %% Start it and enter three values, first is duplicated;
+ ok = ssh_dbg:cbuf_start(3),
+ ok = ssh_dbg:cbuf_in(v1),
+ ok = ssh_dbg:cbuf_in(v1),
+ ok = ssh_dbg:cbuf_in(v2),
+ ok = ssh_dbg:cbuf_in(v3),
+ [{v3,_,1}, {v2,_,1}, {v1,_,2}] = ssh_dbg:cbuf_list(),
+ %% Check that a fourth value erase the first entered:
+ ok = ssh_dbg:cbuf_in(v4),
+ [{v4,_,1}, {v3,_,1}, {v2,_,1}] = ssh_dbg:cbuf_list(),
+ %% Check that entering a value that is in the tail but not in the head is treated as a new value:
+ ok = ssh_dbg:cbuf_in(v2),
+ [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_list(),
+ %% Stop and check that the buffer is returned:
+ [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_stop_clear(),
+ %% Stopping a stopped buffer returns empty:
+ [] = ssh_dbg:cbuf_stop_clear(),
+ %% Check that a value can't be entered in a stopped buffer:
+ disabled = ssh_dbg:cbuf_in(v2).
+
+%%--------------------------------------------------------------------
+cb_print(_Config) ->
+ ssh_dbg:cbuf_start(),
+ [begin
+ ssh_dbg:cbuf_in(V),
+ ct:log("Enter ~p",[V])
+ end || V <- lists:seq(1,10)],
+ ct:log("~s",[ssh_dbg:fmt_cbuf_items()]),
+ ssh_dbg:cbuf_stop_clear().
+
+%%--------------------------------------------------------------------
+cb_macros_print(_Config) ->
+ ssh_dbg:cbuf_start(),
+ [begin
+ V = {test,V0},
+ ?CIRC_BUF_IN(V),
+ ct:log("Enter ~p",[V])
+ end || V0 <- lists:seq(1,5)],
+ ct:log("~s",[ssh_dbg:fmt_cbuf_items()]),
+ ssh_dbg:cbuf_stop_clear().
+
+%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_engine_SUITE.erl b/lib/ssh/test/ssh_engine_SUITE.erl
index c2e6ac1fee..3adb23acdb 100644
--- a/lib/ssh/test/ssh_engine_SUITE.erl
+++ b/lib/ssh/test/ssh_engine_SUITE.erl
@@ -126,10 +126,17 @@ simple_connect(Config) ->
load_engine() ->
case crypto:get_test_engine() of
{ok, Engine} ->
- try crypto:engine_load(<<"dynamic">>,
+ try
+ %% The test engine has it's own fake rsa sign/verify that
+ %% you don't want to use, so exclude it from methods to load:
+ Methods =
+ crypto:engine_get_all_methods() -- [engine_method_rsa],
+ crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
<<"LOAD">>],
- [])
+ [],
+ Methods
+ )
catch
error:notsup ->
{error, notsup}
diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl
index daf62483cd..60d0da2a39 100644
--- a/lib/ssh/test/ssh_options_SUITE.erl
+++ b/lib/ssh/test/ssh_options_SUITE.erl
@@ -49,7 +49,7 @@
server_userpassword_option/1,
server_pwdfun_option/1,
server_pwdfun_4_option/1,
- server_pwdfun_4_option_repeat/1,
+ server_keyboard_interactive/1,
ssh_connect_arg4_timeout/1,
ssh_connect_negtimeout_parallel/1,
ssh_connect_negtimeout_sequential/1,
@@ -99,7 +99,7 @@ all() ->
server_userpassword_option,
server_pwdfun_option,
server_pwdfun_4_option,
- server_pwdfun_4_option_repeat,
+ server_keyboard_interactive,
{group, dir_options},
ssh_connect_timeout,
ssh_connect_arg4_timeout,
@@ -381,7 +381,7 @@ server_pwdfun_4_option(Config) ->
%%--------------------------------------------------------------------
-server_pwdfun_4_option_repeat(Config) ->
+server_keyboard_interactive(Config) ->
UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
%% Test that the state works
@@ -396,19 +396,28 @@ server_pwdfun_4_option_repeat(Config) ->
{pwdfun,PWDFUN}]),
%% Try with passwords "incorrect", "Bad again" and finally "bar"
- KIFFUN = fun(_,_,_) ->
+ KIFFUN = fun(_Name, _Instr, _PromptInfos) ->
K={k,self()},
- case get(K) of
- undefined ->
- put(K,1),
- ["incorrect"];
- 2 ->
- put(K,3),
- ["bar"];
- S->
- put(K,S+1),
- ["Bad again"]
- end
+ Answer =
+ case get(K) of
+ undefined ->
+ put(K,1),
+ ["incorrect"];
+ 2 ->
+ put(K,3),
+ ["bar"];
+ S->
+ put(K,S+1),
+ ["Bad again"]
+ end,
+ ct:log("keyboard_interact_fun:~n"
+ " Name = ~p~n"
+ " Instruction = ~p~n"
+ " Prompts = ~p~n"
+ "~nAnswer:~n ~p~n",
+ [_Name, _Instr, _PromptInfos, Answer]),
+
+ Answer
end,
ConnectionRef2 =
diff --git a/lib/ssh/test/ssh_property_test_SUITE.erl b/lib/ssh/test/ssh_property_test_SUITE.erl
index 3318b86d39..9aaac898a0 100644
--- a/lib/ssh/test/ssh_property_test_SUITE.erl
+++ b/lib/ssh/test/ssh_property_test_SUITE.erl
@@ -46,8 +46,9 @@ groups() ->
[{messages, [], [decode,
decode_encode]},
{client_server, [], [client_server_sequential,
- client_server_parallel,
- client_server_parallel_multi]}
+ client_server_parallel
+ %% client_server_parallel_multi
+ ]}
].
@@ -62,7 +63,7 @@ end_per_suite(Config) ->
%%% if we run proper.
init_per_group(client_server, Config) ->
case proplists:get_value(property_test_tool,Config) of
- eqc -> Config;
+ proper -> Config;
X -> {skip, lists:concat([X," is not supported"])}
end;
init_per_group(_, Config) ->
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index 416cc301db..a1a7eebcde 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -408,6 +408,21 @@ ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file
setup_ecdsa_known_host(Size, System, UserDir),
setup_ecdsa_auth_keys(Size, DataDir, UserDir).
+setup_eddsa(Alg, DataDir, UserDir) ->
+ {IdPriv, IdPub, HostPriv, HostPub} =
+ case Alg of
+ ed25519 -> {"id_ed25519", "id_ed25519.pub", "ssh_host_ed25519_key", "ssh_host_ed25519_key.pub"};
+ ed448 -> {"id_ed448", "id_ed448.pub", "ssh_host_ed448_key", "ssh_host_ed448_key.pub"}
+ end,
+ file:copy(filename:join(DataDir, IdPriv), filename:join(UserDir, IdPriv)),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, HostPriv), filename:join(System, HostPriv)),
+ file:copy(filename:join(DataDir, HostPub), filename:join(System, HostPub)),
+ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
+ setup_eddsa_known_host(HostPub, DataDir, UserDir),
+ setup_eddsa_auth_keys(IdPriv, DataDir, UserDir).
+
clean_dsa(UserDir) ->
del_dirs(filename:join(UserDir, "system")),
file:delete(filename:join(UserDir,"id_dsa")),
@@ -487,6 +502,11 @@ setup_ecdsa_known_host(_Size, SystemDir, UserDir) ->
[{Key, _}] = public_key:ssh_decode(SshBin, public_key),
setup_known_hosts(Key, UserDir).
+setup_eddsa_known_host(HostPub, SystemDir, UserDir) ->
+ {ok, SshBin} = file:read_file(filename:join(SystemDir, HostPub)),
+ [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
+ setup_known_hosts(Key, UserDir).
+
setup_known_hosts(Key, UserDir) ->
{ok, Hostname} = inet:gethostname(),
{ok, {A, B, C, D}} = inet:getaddr(Hostname, inet),
@@ -529,6 +549,11 @@ setup_ecdsa_auth_keys(Size, Dir, UserDir) ->
PKey = #'ECPoint'{point = Q},
setup_auth_keys([{ {PKey,Param}, [{comment, "Test"}]}], UserDir).
+setup_eddsa_auth_keys(IdPriv, Dir, UserDir) ->
+ {ok, Pem} = file:read_file(filename:join(Dir, IdPriv)),
+ {ed_pri, Alg, Pub, _} = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
+ setup_auth_keys([{{ed_pub,Alg,Pub}, [{comment, "Test"}]}], UserDir).
+
setup_auth_keys(Keys, Dir) ->
AuthKeys = public_key:ssh_encode(Keys, auth_keys),
AuthKeysFile = filename:join(Dir, "authorized_keys"),
diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl
index 8de550af15..f2c9892f95 100644
--- a/lib/ssh/test/ssh_trpt_test_lib.erl
+++ b/lib/ssh/test/ssh_trpt_test_lib.erl
@@ -41,15 +41,20 @@
opts = [],
timeout = 5000, % ms
seen_hello = false,
- enc = <<>>,
ssh = #ssh{}, % #ssh{}
alg_neg = {undefined,undefined}, % {own_kexinit, peer_kexinit}
alg, % #alg{}
vars = dict:new(),
reply = [], % Some repy msgs are generated hidden in ssh_transport :[
prints = [],
- return_value
- }).
+ return_value,
+
+ %% Packet retrival and decryption
+ decrypted_data_buffer = <<>>,
+ encrypted_data_buffer = <<>>,
+ aead_data = <<>>,
+ undecrypted_packet_length
+ }).
-define(role(S), ((S#s.ssh)#ssh.role) ).
@@ -475,11 +480,11 @@ recv(S0 = #s{}) ->
%%%================================================================
try_find_crlf(Seen, S0) ->
- case erlang:decode_packet(line,S0#s.enc,[]) of
+ case erlang:decode_packet(line,S0#s.encrypted_data_buffer,[]) of
{more,_} ->
- Line = <<Seen/binary,(S0#s.enc)/binary>>,
+ Line = <<Seen/binary,(S0#s.encrypted_data_buffer)/binary>>,
S0#s{seen_hello = {more,Line},
- enc = <<>>, % didn't find a complete line
+ encrypted_data_buffer = <<>>, % didn't find a complete line
% -> no more characters to test
return_value = {more,Line}
};
@@ -490,13 +495,13 @@ try_find_crlf(Seen, S0) ->
S = opt(print_messages, S0,
fun(X) when X==true;X==detail -> {"Recv info~n~p~n",[Line]} end),
S#s{seen_hello = false,
- enc = Rest,
+ encrypted_data_buffer = Rest,
return_value = {info,Line}};
S1=#s{} ->
S = opt(print_messages, S1,
fun(X) when X==true;X==detail -> {"Recv hello~n~p~n",[Line]} end),
S#s{seen_hello = true,
- enc = Rest,
+ encrypted_data_buffer = Rest,
return_value = {hello,Line}}
end
end.
@@ -511,19 +516,73 @@ handle_hello(Bin, S=#s{ssh=C}) ->
{{Vp,Vs}, server} -> S#s{ssh = C#ssh{c_vsn=Vp, c_version=Vs}}
end.
-receive_binary_msg(S0=#s{ssh=C0=#ssh{decrypt_block_size = BlockSize,
+receive_binary_msg(S0=#s{}) ->
+ case ssh_transport:handle_packet_part(
+ S0#s.decrypted_data_buffer,
+ S0#s.encrypted_data_buffer,
+ S0#s.aead_data,
+ S0#s.undecrypted_packet_length,
+ S0#s.ssh)
+ of
+ {packet_decrypted, DecryptedBytes, EncryptedDataRest, Ssh1} ->
+ S1 = S0#s{ssh = Ssh1#ssh{recv_sequence = ssh_transport:next_seqnum(Ssh1#ssh.recv_sequence)},
+ decrypted_data_buffer = <<>>,
+ undecrypted_packet_length = undefined,
+ aead_data = <<>>,
+ encrypted_data_buffer = EncryptedDataRest},
+ case
+ catch ssh_message:decode(set_prefix_if_trouble(DecryptedBytes,S1))
+ of
+ {'EXIT',_} -> fail(decode_failed,S1);
+
+ Msg ->
+ Ssh2 = case Msg of
+ #ssh_msg_kexinit{} ->
+ ssh_transport:key_init(opposite_role(Ssh1), Ssh1, DecryptedBytes);
+ _ ->
+ Ssh1
+ end,
+ S2 = opt(print_messages, S1,
+ fun(X) when X==true;X==detail -> {"Recv~n~s~n",[format_msg(Msg)]} end),
+ S3 = opt(print_messages, S2,
+ fun(detail) -> {"decrypted bytes ~p~n",[DecryptedBytes]} end),
+ S3#s{ssh = inc_recv_seq_num(Ssh2),
+ return_value = Msg
+ }
+ end;
+
+ {get_more, DecryptedBytes, EncryptedDataRest, AeadData, TotalNeeded, Ssh1} ->
+ %% Here we know that there are not enough bytes in
+ %% EncryptedDataRest to use. We must wait for more.
+ Remaining = case TotalNeeded of
+ undefined -> 8;
+ _ -> TotalNeeded - size(DecryptedBytes) - size(EncryptedDataRest)
+ end,
+ receive_binary_msg(
+ receive_wait(Remaining,
+ S0#s{encrypted_data_buffer = EncryptedDataRest,
+ decrypted_data_buffer = DecryptedBytes,
+ undecrypted_packet_length = TotalNeeded,
+ aead_data = AeadData,
+ ssh = Ssh1}
+ ))
+ end.
+
+
+
+old_receive_binary_msg(S0=#s{ssh=C0=#ssh{decrypt_block_size = BlockSize,
recv_mac_size = MacSize
}
}) ->
- case size(S0#s.enc) >= max(8,BlockSize) of
+ case size(S0#s.encrypted_data_buffer) >= max(8,BlockSize) of
false ->
%% Need more bytes to decode the packet_length field
- Remaining = max(8,BlockSize) - size(S0#s.enc),
+ Remaining = max(8,BlockSize) - size(S0#s.encrypted_data_buffer),
receive_binary_msg( receive_wait(Remaining, S0) );
true ->
%% Has enough bytes to decode the packet_length field
{_, <<?UINT32(PacketLen), _/binary>>, _} =
- ssh_transport:decrypt_blocks(S0#s.enc, BlockSize, C0), % FIXME: BlockSize should be at least 4
+ ssh_transport:decrypt_blocks(S0#s.encrypted_data_buffer, BlockSize, C0), % FIXME: BlockSize should be at least 4
%% FIXME: Check that ((4+PacketLen) rem BlockSize) == 0 ?
@@ -534,19 +593,19 @@ receive_binary_msg(S0=#s{ssh=C0=#ssh{decrypt_block_size = BlockSize,
((4+PacketLen) rem BlockSize) =/= 0 ->
fail(bad_packet_length_modulo, S0); % FIXME: disconnect
- size(S0#s.enc) >= (4 + PacketLen + MacSize) ->
+ size(S0#s.encrypted_data_buffer) >= (4 + PacketLen + MacSize) ->
%% has the whole packet
S0;
true ->
%% need more bytes to get have the whole packet
- Remaining = (4 + PacketLen + MacSize) - size(S0#s.enc),
+ Remaining = (4 + PacketLen + MacSize) - size(S0#s.encrypted_data_buffer),
receive_wait(Remaining, S0)
end,
%% Decrypt all, including the packet_length part (re-use the initial #ssh{})
{C1, SshPacket = <<?UINT32(_),?BYTE(PadLen),Tail/binary>>, EncRest} =
- ssh_transport:decrypt_blocks(S1#s.enc, PacketLen+4, C0),
+ ssh_transport:decrypt_blocks(S1#s.encrypted_data_buffer, PacketLen+4, C0),
PayloadLen = PacketLen - 1 - PadLen,
<<CompressedPayload:PayloadLen/binary, _Padding:PadLen/binary>> = Tail,
@@ -573,7 +632,7 @@ receive_binary_msg(S0=#s{ssh=C0=#ssh{decrypt_block_size = BlockSize,
S3 = opt(print_messages, S2,
fun(detail) -> {"decrypted bytes ~p~n",[SshPacket]} end),
S3#s{ssh = inc_recv_seq_num(C3),
- enc = Rest,
+ encrypted_data_buffer = Rest,
return_value = Msg
}
end
@@ -602,7 +661,7 @@ receive_poll(S=#s{socket=Sock}) ->
inet:setopts(Sock, [{active,once}]),
receive
{tcp,Sock,Data} ->
- receive_poll( S#s{enc = <<(S#s.enc)/binary,Data/binary>>} );
+ receive_poll( S#s{encrypted_data_buffer = <<(S#s.encrypted_data_buffer)/binary,Data/binary>>} );
{tcp_closed,Sock} ->
throw({tcp,tcp_closed});
{tcp_error, Sock, Reason} ->
@@ -616,7 +675,7 @@ receive_wait(S=#s{socket=Sock,
inet:setopts(Sock, [{active,once}]),
receive
{tcp,Sock,Data} ->
- S#s{enc = <<(S#s.enc)/binary,Data/binary>>};
+ S#s{encrypted_data_buffer = <<(S#s.encrypted_data_buffer)/binary,Data/binary>>};
{tcp_closed,Sock} ->
throw({tcp,tcp_closed});
{tcp_error, Sock, Reason} ->
@@ -627,11 +686,11 @@ receive_wait(S=#s{socket=Sock,
receive_wait(N, S=#s{socket=Sock,
timeout=Timeout,
- enc=Enc0}) when N>0 ->
+ encrypted_data_buffer=Enc0}) when N>0 ->
inet:setopts(Sock, [{active,once}]),
receive
{tcp,Sock,Data} ->
- receive_wait(N-size(Data), S#s{enc = <<Enc0/binary,Data/binary>>});
+ receive_wait(N-size(Data), S#s{encrypted_data_buffer = <<Enc0/binary,Data/binary>>});
{tcp_closed,Sock} ->
throw({tcp,tcp_closed});
{tcp_error, Sock, Reason} ->
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 6060e50d31..837da27ab0 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,4 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 4.7
-
+SSH_VSN = 4.7.6
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/specs/.gitignore b/lib/ssl/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/ssl/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/ssl/doc/src/Makefile b/lib/ssl/doc/src/Makefile
index f9128e8e45..7cf251d8f9 100644
--- a/lib/ssl/doc/src/Makefile
+++ b/lib/ssl/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2017. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -80,11 +80,16 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
DVIPS_FLAGS +=
+SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../..
# ----------------------------------------------------
# Targets
@@ -92,7 +97,7 @@ DVIPS_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-docs: pdf html man
+docs: html pdf man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -102,8 +107,10 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
man: $(MAN3_FILES) $(MAN6_FILES)
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 917df03b5b..d46b4abf5c 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,477 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 9.2.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct solution for retaining tcp flow control OTP-15802
+ (ERL-934) as to not break ssl:recv as reported in
+ (ERL-938)</p>
+ <p>
+ Own Id: OTP-15823 Aux Id: ERL-934, ERL-938 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Missing check of size of user_data_buffer made internal
+ socket behave as an active socket instead of active N.
+ This could cause memory problems.</p>
+ <p>
+ Own Id: OTP-15802 Aux Id: ERL-934 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Back port of bug fix ERL-893 from OTP-22 and document
+ enhancements that will solve dialyzer warnings for users
+ of the ssl application.</p>
+ <p>
+ This change also affects public_key, eldap (and inet
+ doc).</p>
+ <p>
+ Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With the default BEAST Mitigation strategy for TLS 1.0 an
+ empty TLS fragment could be sent after a one-byte
+ fragment. This glitch has been fixed.</p>
+ <p>
+ Own Id: OTP-15054 Aux Id: ERIERL-346 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The timeout for a passive receive was sometimes not
+ cancelled and later caused a server crash. This bug has
+ now been corrected.</p>
+ <p>
+ Own Id: OTP-14701 Aux Id: ERL-883, ERL-884 </p>
+ </item>
+ <item>
+ <p>
+ Add tag for passive message (active N) in cb_info to
+ retain transport transparency.</p>
+ <p>
+ Own Id: OTP-15679 Aux Id: ERL-861 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug that an incorrect return value for gen_statem
+ could be created when alert was a result of handling
+ renegotiation info extension</p>
+ <p>
+ Own Id: OTP-15502</p>
+ </item>
+ <item>
+ <p>
+ Correct check for 3des_ede_cbc, could cause ssl to claim
+ to support 3des_ede_cbc when cryptolib does not.</p>
+ <p>
+ Own Id: OTP-15539</p>
+ </item>
+ <item>
+ <p>
+ Improved DTLS error handling, avoids unexpected
+ connection failure in rare cases.</p>
+ <p>
+ Own Id: OTP-15561</p>
+ </item>
+ <item>
+ <p>
+ Corrected active once emulation bug that could cause the
+ ssl_closed meassage to not be sent. Bug introduced by
+ OTP-15449</p>
+ <p>
+ Own Id: OTP-15666 Aux Id: ERIERL-316, </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add client option {reuse_session, SessionID::binary()}
+ that can be used together with new option value
+ {reuse_sessions, save}. This makes it possible to reuse a
+ session from a specific connection establishment.</p>
+ <p>
+ Own Id: OTP-15369</p>
+ </item>
+ <item>
+ <p>
+ The Reason part of of the error return from the functions
+ connect and handshake has a better and documented format.
+ This will sometimes differ from previous returned
+ reasons, however those where only documented as term()
+ and should for that reason not be relied on.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15423</p>
+ </item>
+ <item>
+ <p>
+ Refactor of state handling to improve TLS application
+ data throughput and reduce CPU overhead</p>
+ <p>
+ Own Id: OTP-15445</p>
+ </item>
+ <item>
+ <p>
+ The SSL code has been optimized in many small ways to
+ reduce CPU load for encryption/decryption, especially for
+ Erlang's distribution protocol over TLS.</p>
+ <p>
+ Own Id: OTP-15529</p>
+ </item>
+ <item>
+ <p>
+ Add support for active N</p>
+ <p>
+ Own Id: OTP-15665 Aux Id: ERL-811, PR-2072 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix encoding of the SRP extension length field in ssl.
+ The old encoding of the SRP extension length could cause
+ interoperability problems with third party SSL
+ implementations when SRP was used.</p>
+ <p>
+ Own Id: OTP-15477 Aux Id: ERL-790 </p>
+ </item>
+ <item>
+ <p>
+ Guarantee active once data delivery, handling TCP stream
+ properly.</p>
+ <p>
+ Own Id: OTP-15504 Aux Id: ERL-371 </p>
+ </item>
+ <item>
+ <p>
+ Correct gen_statem returns for some error cases</p>
+ <p>
+ Own Id: OTP-15505</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed renegotiation bug. Client did not handle server
+ initiated renegotiation correctly after rewrite to two
+ connection processes, due to ERL-622 commit
+ d87ac1c55188f5ba5cdf72384125d94d42118c18. This could
+ manifest it self as a " bad_record_mac" alert.</p>
+ <p>
+ Also included are some optimizations</p>
+ <p>
+ Own Id: OTP-15489 Aux Id: ERL-308 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ PEM cache was not evicting expired entries due to due to
+ timezone confusion.</p>
+ <p>
+ Own Id: OTP-15368</p>
+ </item>
+ <item>
+ <p>
+ Make sure an error is returned if a "transport_accept
+ socket" is used in some other call than ssl:handshake* or
+ ssl:controlling_process</p>
+ <p>
+ Own Id: OTP-15384 Aux Id: ERL-756 </p>
+ </item>
+ <item>
+ <p>
+ Fix timestamp handling in the PEM-cache could cause
+ entries to not be invalidated at the correct time.</p>
+ <p>
+ Own Id: OTP-15402</p>
+ </item>
+ <item>
+ <p>
+ Extend check for undelivered data at closing, could under
+ some circumstances fail to deliver all data that was
+ actually received.</p>
+ <p>
+ Own Id: OTP-15412 Aux Id: ERL-731 </p>
+ </item>
+ <item>
+ <p>
+ Correct signature check for TLS-1.2 that allows different
+ algorithms for signature of peer cert and peer cert key.
+ Not all allowed combinations where accepted.</p>
+ <p>
+ Own Id: OTP-15415 Aux Id: ERL-763 </p>
+ </item>
+ <item>
+ <p>
+ Correct gen_statem return value, could cause
+ renegotiation to fail.</p>
+ <p>
+ Own Id: OTP-15418 Aux Id: ERL-770 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add engine support for RSA key exchange</p>
+ <p>
+ Own Id: OTP-15420 Aux Id: ERIERL-268 </p>
+ </item>
+ <item>
+ <p>
+ ssl now uses active n internally to boost performance.
+ Old active once behavior can be restored by setting
+ application variable see manual page for ssl application
+ (man 6).</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15449</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct alert handling with new TLS sender process, from
+ ssl-9.0.2. CLOSE ALERTS could under some circumstances be
+ encoded using an incorrect cipher state. This would cause
+ the peer to regard them as unknown messages.</p>
+ <p>
+ Own Id: OTP-15337 Aux Id: ERL-738 </p>
+ </item>
+ <item>
+ <p>
+ Correct handling of socket packet option with new TLS
+ sender process, from ssl-9.0.2. When changing the socket
+ option {packet, 1|2|3|4} with ssl:setopts/2 the option
+ must internally be propagated to the sender process as
+ well as the reader process as this particular option also
+ affects the data to be sent.</p>
+ <p>
+ Own Id: OTP-15348 Aux Id: ERL-747 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Use separate processes for sending and receiving
+ application data for TLS connections to avoid potential
+ deadlock that was most likely to occur when using TLS for
+ Erlang distribution. Note does not change the API.</p>
+ <p>
+ Own Id: OTP-15122</p>
+ </item>
+ <item>
+ <p>
+ Correct handling of empty server SNI extension</p>
+ <p>
+ Own Id: OTP-15168</p>
+ </item>
+ <item>
+ <p>
+ Correct PSK cipher suite handling and add
+ selected_cipher_suite to connection information</p>
+ <p>
+ Own Id: OTP-15172</p>
+ </item>
+ <item>
+ <p>
+ Adopt to the fact that cipher suite sign restriction are
+ relaxed in TLS-1.2</p>
+ <p>
+ Own Id: OTP-15173</p>
+ </item>
+ <item>
+ <p>
+ Enhance error handling of non existing PEM files</p>
+ <p>
+ Own Id: OTP-15174</p>
+ </item>
+ <item>
+ <p>
+ Correct close handling of transport accepted sockets in
+ the error state</p>
+ <p>
+ Own Id: OTP-15216</p>
+ </item>
+ <item>
+ <p>
+ Correct PEM cache to not add references to empty entries
+ when PEM file does not exist.</p>
+ <p>
+ Own Id: OTP-15224</p>
+ </item>
+ <item>
+ <p>
+ Correct handling of all PSK cipher suites</p>
+ <p>
+ Before only some PSK suites would be correctly negotiated
+ and most PSK ciphers suites would fail the connection.</p>
+ <p>
+ Own Id: OTP-15285</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ TLS will now try to order certificate chains if they
+ appear to be unordered. That is prior to TLS 1.3,
+ “certificate_list” ordering was required to be
+ strict, however some implementations already allowed for
+ some flexibility. For maximum compatibility, all
+ implementations SHOULD be prepared to handle potentially
+ extraneous certificates and arbitrary orderings from any
+ TLS version.</p>
+ <p>
+ Own Id: OTP-12983</p>
+ </item>
+ <item>
+ <p>
+ TLS will now try to reconstructed an incomplete
+ certificate chains from its local CA-database and use
+ that data for the certificate path validation. This
+ especially makes sense for partial chains as then the
+ peer might not send an intermediate CA as it is
+ considered the trusted root in that case.</p>
+ <p>
+ Own Id: OTP-15060</p>
+ </item>
+ <item>
+ <p>
+ Option keyfile defaults to certfile and should be trumped
+ with key. This failed for engine keys.</p>
+ <p>
+ Own Id: OTP-15193</p>
+ </item>
+ <item>
+ <p>
+ Error message improvement when own certificate has
+ decoding issues, see also issue ERL-668.</p>
+ <p>
+ Own Id: OTP-15234</p>
+ </item>
+ <item>
+ <p>
+ Correct dialyzer spec for key option</p>
+ <p>
+ Own Id: OTP-15281</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct cipher suite handling for ECDHE_*, the incorrect
+ handling could cause an incorrrect suite to be selected
+ and most likly fail the handshake.</p>
+ <p>
+ Own Id: OTP-15203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 9.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -170,6 +641,90 @@
</section>
+<section><title>SSL 8.2.6.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Add engine support for RSA key exchange</p>
+ <p>
+ Own Id: OTP-15420</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Extend check for undelivered data at closing, could under
+ some circumstances fail to deliverd all data that was
+ acctualy recivied.</p>
+ <p>
+ Own Id: OTP-15412</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct handling of empty server SNI extension</p>
+ <p>
+ Own Id: OTP-15168</p>
+ </item>
+ <item>
+ <p>
+ Correct cipher suite handling for ECDHE_*, the incorrect
+ handling could cause an incorrrect suite to be selected
+ and most likly fail the handshake.</p>
+ <p>
+ Own Id: OTP-15203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improve cipher suite handling correcting ECC and TLS-1.2
+ requierments. Backport of solution for ERL-641</p>
+ <p>
+ Own Id: OTP-15178</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Option keyfile defaults to certfile and should be trumped
+ with key. This failed for engine keys.</p>
+ <p>
+ Own Id: OTP-15193</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 8.2.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2948,5 +3503,3 @@
</section>
</section>
</chapter>
-
-
diff --git a/lib/ssl/doc/src/specs.xml b/lib/ssl/doc/src/specs.xml
new file mode 100644
index 0000000000..50e9428fec
--- /dev/null
+++ b/lib/ssl/doc/src/specs.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_ssl_crl_cache_api.xml"/>
+ <xi:include href="../specs/specs_ssl_crl_cache.xml"/>
+ <xi:include href="../specs/specs_ssl_session_cache_api.xml"/>
+ <xi:include href="../specs/specs_ssl.xml"/>
+</specs>
+
+
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index e3deb1c8a4..c448d345de 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -28,7 +28,7 @@
<rev></rev>
<file>ssl.xml</file>
</header>
- <module>ssl</module>
+ <module since="">ssl</module>
<modulesummary>Interface Functions for Secure Socket Layer</modulesummary>
<description>
<p>
@@ -37,277 +37,335 @@
<seealso marker="ssl_app">ssl(6)</seealso>.
</p>
</description>
-
- <section>
- <title>DATA TYPES</title>
- <p>The following data types are used in the functions for SSL/TLS/DTLS:</p>
-
- <taglist>
-
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false</c></p></item>
-
- <tag><c>option() =</c></tag>
- <item><p><c>socketoption() | ssl_option() | transport_option()</c></p>
- </item>
-
- <tag><c>socketoption() =</c></tag>
- <item><p><c>proplists:property()</c></p>
- <p>The default socket options are
- <c>[{mode,list},{packet, 0},{header, 0},{active, true}]</c>.</p>
- <p>For valid options, see the
- <seealso marker="kernel:inet">inet(3)</seealso>,
- <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> and
- <seealso marker="kernel:gen_tcp">gen_udp(3)</seealso>
- manual pages
- in Kernel. Note that stream oriented options such as packet are only relevant for SSL/TLS and not DTLS</p></item>
-
- <tag><marker id="type-ssloption"/><c>ssl_option() =</c></tag>
- <item>
- <p><c>{verify, verify_type()}</c></p>
- <p><c>| {verify_fun, {fun(), term()}}</c></p>
- <p><c>| {fail_if_no_peer_cert, boolean()}</c></p>
- <p><c>| {depth, integer()}</c></p>
- <p><c>| {cert, public_key:der_encoded()}</c></p>
- <p><c>| {certfile, path()}</c></p>
- <p><c>| {key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey'
- | 'PrivateKeyInfo', public_key:der_encoded()} |
- #{algorithm := rsa | dss | ecdsa,
- engine := crypto:engine_ref(), key_id := crypto:key_id(), password => crypto:password()}</c></p>
- <p><c>| {keyfile, path()}</c></p>
- <p><c>| {password, string()}</c></p>
- <p><c>| {cacerts, [public_key:der_encoded()]}</c></p>
- <p><c>| {cacertfile, path()}</c></p>
- <p><c>| {dh, public_key:der_encoded()}</c></p>
- <p><c>| {dhfile, path()}</c></p>
- <p><c>| {ciphers, ciphers()}</c></p>
- <p><c>| {user_lookup_fun, {fun(), term()}}, {psk_identity, string()},
- {srp_identity, {string(), string()}}</c></p>
- <p><c>| {reuse_sessions, boolean()}</c></p>
- <p><c>| {reuse_session, fun()} {next_protocols_advertised, [binary()]}</c></p>
- <p><c>| {client_preferred_next_protocols, {client | server,
- [binary()]} | {client | server, [binary()], binary()}}</c></p>
- <p><c>| {log_alert, boolean()}</c></p>
- <p><c>| {server_name_indication, hostname() | disable}</c></p>
- <p><c>| {customize_hostname_check, list()}</c></p>
- <p><c>| {sni_hosts, [{hostname(), [ssl_option()]}]}</c></p>
- <p><c>| {sni_fun, SNIfun::fun()}</c></p>
- </item>
-
- <tag><c>transport_option() =</c></tag>
- <item><p><c>{cb_info, {CallbackModule::atom(), DataTag::atom(),
-
- ClosedTag::atom(), ErrTag:atom()}}</c></p>
- <p>Defaults to <c>{gen_tcp, tcp, tcp_closed, tcp_error}</c> for TLS
- and <c>{gen_udp, udp, udp_closed, udp_error}</c> for DTLS. Can be used
- to customize the transport layer. For TLS the callback module must implement a
- reliable transport protocol, behave as <c>gen_tcp</c>, and have functions
- corresponding to <c>inet:setopts/2</c>, <c>inet:getopts/2</c>,
- <c>inet:peername/1</c>, <c>inet:sockname/1</c>, and <c>inet:port/1</c>.
- The callback <c>gen_tcp</c> is treated specially and calls <c>inet</c>
- directly. For DTLS this feature must be considered exprimental.</p>
- <taglist>
- <tag><c>CallbackModule =</c></tag>
- <item><p><c>atom()</c></p></item>
- <tag><c>DataTag =</c></tag>
- <item><p><c>atom()</c></p>
- <p>Used in socket data message.</p></item>
- <tag><c>ClosedTag =</c></tag>
- <item><p><c>atom()</c></p>
- <p>Used in socket close message.</p></item>
- </taglist>
- </item>
-
- <tag><c>verify_type() =</c></tag>
- <item><p><c>verify_none | verify_peer</c></p></item>
-
- <tag><c>path() =</c></tag>
- <item><p><c>string()</c></p>
- <p>Represents a file path.</p></item>
- <tag><c>public_key:der_encoded() =</c></tag>
- <item><p><c>binary()</c></p>
- <p>ASN.1 DER-encoded entity as an Erlang binary.</p></item>
+ <!--
+ ================================================================
+ = Data types =
+ ================================================================
+ -->
- <tag><c>host() =</c></tag>
- <item><p><c>hostname() | ipaddress()</c></p></item>
+ <datatypes>
+ <datatype_title>Types used in SSL/TLS/DTLS</datatype_title>
- <tag><c>hostname() =</c></tag>
- <item><p><c>string() - DNS hostname</c></p></item>
-
- <tag><c>ip_address() =</c></tag>
- <item><p><c>{N1,N2,N3,N4} % IPv4 | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6
- </c></p></item>
+
+ <datatype>
+ <name name="socket"/>
+ </datatype>
+
+ <datatype>
+ <name name="sslsocket"/>
+ <desc>
+ <p>An opaque reference to the TLS/DTLS connection, may be used for equality matching.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="tls_option"/>
+ </datatype>
+
+ <datatype>
+ <name name="tls_client_option"/>
+ </datatype>
+
+ <datatype>
+ <name name="tls_server_option"/>
+ </datatype>
+
+
+ <datatype>
+ <name name="socket_option"/>
+ <desc>
+ <p>The default socket options are
+ <c>[{mode,list},{packet, 0},{header, 0},{active, true}]</c>.</p>
+ <p>For valid options, see the
+ <seealso marker="kernel:inet">inet(3)</seealso>,
+ <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> and
+ <seealso marker="kernel:gen_tcp">gen_udp(3)</seealso>
+ manual pages in Kernel. Note that stream oriented options such as packet
+ are only relevant for SSL/TLS and not DTLS</p>
+ </desc>
+ </datatype>
- <tag><c>sslsocket() =</c></tag>
- <item><p>opaque()</p></item>
-
- <tag><marker id="type-protocol"/><c> protocol_version() =</c></tag>
- <item><p><c> ssl_tls_protocol() | dtls_protocol() </c></p></item>
-
- <item><p><c>sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2'</c></p></item>
-
- <tag><marker id="type-protocol"/><c> dtls_protocol() =</c></tag>
- <item><p><c>'dtlsv1' | 'dtlsv1.2'</c></p></item>
-
- <tag><c>ciphers() =</c></tag>
- <item><p><c>= [ciphersuite()]</c></p>
- <p>Tuples and string formats accepted by versions
- before ssl-8.2.4 will be converted for backwards compatibility</p></item>
-
- <tag><c>ciphersuite() =</c></tag>
- <item><p><c>
- #{key_exchange := key_exchange(),
- cipher := cipher(),
- mac := MAC::hash() | aead,
- prf := PRF::hash() | default_prf} </c></p></item>
-
- <tag><c>key_exchange()=</c></tag>
- <item><p><c>rsa | dhe_dss | dhe_rsa | dh_anon | psk | dhe_psk
- | rsa_psk | srp_anon | srp_dss | srp_rsa | ecdh_anon | ecdh_ecdsa
- | ecdhe_ecdsa | ecdh_rsa | ecdhe_rsa</c></p></item>
-
- <tag><c>cipher() =</c></tag>
- <item><p><c>rc4_128 | des_cbc | '3des_ede_cbc'
- | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305</c></p></item>
-
- <tag><c>hash() =</c></tag>
- <item><p><c>md5 | sha | sha224 | sha256 | sha348 | sha512</c></p></item>
-
- <tag><c>prf_random() =</c></tag>
- <item><p><c>client_random | server_random</c></p></item>
-
- <tag><c>cipher_filters() =</c></tag>
- <item><p><c> [{key_exchange | cipher | mac | prf, algo_filter()}])</c></p></item>
-
- <tag><c>algo_filter() =</c></tag>
- <item><p>fun(key_exchange() | cipher() | hash() | aead | default_prf) -> true | false </p></item>
-
- <tag><c>srp_param_type() =</c></tag>
- <item><p><c>srp_1024 | srp_1536 | srp_2048 | srp_3072
- | srp_4096 | srp_6144 | srp_8192</c></p></item>
-
- <tag><c>SNIfun::fun()</c></tag>
- <item><p><c>= fun(ServerName :: string()) -> [ssl_option()]</c></p></item>
-
- <tag><c>named_curve() =</c></tag>
- <item><p><c>sect571r1 | sect571k1 | secp521r1 | brainpoolP512r1
- | sect409k1 | sect409r1 | brainpoolP384r1 | secp384r1
- | sect283k1 | sect283r1 | brainpoolP256r1 | secp256k1 | secp256r1
- | sect239k1 | sect233k1 | sect233r1 | secp224k1 | secp224r1
- | sect193r1 | sect193r2 | secp192k1 | secp192r1 | sect163k1
- | sect163r1 | sect163r2 | secp160k1 | secp160r1 | secp160r2</c></p></item>
-
- <tag><c>hello_extensions() =</c></tag>
- <item><p><c>#{renegotiation_info =>
- signature_algs => [{hash(), ecsda| rsa| dsa}] | undefined
- alpn => binary() | undefined,
- next_protocol_negotiation,
- srp => string() | undefined,
- ec_point_formats ,
- elliptic_curves = [oid] | undefined
- sni = string()}
- }</c></p></item>
+ <datatype>
+ <name name="active_msgs"/>
+ <desc>
+ <p>When a TLS/DTLS socket is in active mode (the default), data from the
+ socket is delivered to the owner of the socket in the form of
+ messages as described above.</p>
+ <p>The <c>ssl_passive</c> message is sent only when the socket is in
+ <c>{active, N}</c> mode and the counter dropped to 0. It indicates
+ that the socket has transitioned to passive (<c>{active, false}</c>) mode.</p>
+ </desc>
+ </datatype>
-
- </taglist>
- </section>
-
- <section>
- <title>TLS/DTLS OPTION DESCRIPTIONS - COMMON for SERVER and CLIENT</title>
-
- <p>The following options have the same meaning in the client and
- the server:</p>
+ <datatype>
+ <name name="transport_option"/>
+ <desc>
+ <p>Defaults to <c>{gen_tcp, tcp, tcp_closed, tcp_error,
+ tcp_passive}</c> for TLS (for backward compatibility a four
+ tuple will be converted to a five tuple with the last element
+ "second_element"_passive) and <c>{gen_udp, udp, udp_closed,
+ udp_error}</c> for DTLS (might also be changed to five tuple in
+ the future). Can be used to customize the transport layer. The
+ tag values should be the values used by the underlying
+ transport in its active mode messages. For TLS the callback
+ module must implement a reliable transport protocol, behave as
+ <c>gen_tcp</c>, and have functions corresponding to
+ <c>inet:setopts/2</c>, <c>inet:getopts/2</c>,
+ <c>inet:peername/1</c>, <c>inet:sockname/1</c>, and
+ <c>inet:port/1</c>. The callback <c>gen_tcp</c> is treated
+ specially and calls <c>inet</c> directly. For DTLS this
+ feature must be considered exprimental.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="host"/>
+ </datatype>
+
+ <datatype>
+ <name name="hostname"/>
+ </datatype>
+
+ <datatype>
+ <name name="ip_address"/>
+ </datatype>
+
+ <datatype>
+ <name name="protocol_version"/>
+ </datatype>
+
+ <datatype>
+ <name name="tls_version"/>
+ </datatype>
+
+ <datatype>
+ <name name="dtls_version"/>
+ </datatype>
+
+ <datatype>
+ <name name="legacy_version"/>
+ </datatype>
+
+ <datatype>
+ <name name="prf_random"/>
+ </datatype>
+
+ <datatype>
+ <name name="verify_type"/>
+ </datatype>
+
+ <datatype>
+ <name name="ciphers"/>
+ </datatype>
+
+ <datatype>
+ <name name="erl_cipher_suite"/>
+ </datatype>
+
+ <datatype>
+ <name name="cipher"/>
+ </datatype>
- <taglist>
-
- <tag><c>{protocol, tls | dtls}</c></tag>
- <item><p>Choose TLS or DTLS protocol for the transport layer security.
- Defaults to <c>tls</c> Introduced in OTP 20, DTLS support is considered
- experimental in this release. Other transports than UDP are not yet supported.</p></item>
-
- <tag><c>{handshake, hello | full}</c></tag>
- <item><p> Defaults to <c>full</c>. If hello is specified the handshake will
- pause after the hello message and give the user a possibility make decisions
- based on hello extensions before continuing or aborting the handshake by calling
- <seealso marker="#handshake_continue-3"> handshake_continue/3</seealso> or
- <seealso marker="#handshake_cancel-1"> handshake_cancel/1</seealso>
- </p></item>
-
- <tag><c>{cert, public_key:der_encoded()}</c></tag>
- <item><p>The DER-encoded users certificate. If this option
- is supplied, it overrides option <c>certfile</c>.</p></item>
-
- <tag><c>{certfile, path()}</c></tag>
- <item><p>Path to a file containing the user certificate.</p></item>
-
- <tag>
- <marker id="key_option_def"/>
- <c>{key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey'
- |'PrivateKeyInfo', public_key:der_encoded()} | #{algorithm := rsa | dss | ecdsa,
- engine := crypto:engine_ref(), key_id := crypto:key_id(), password => crypto:password()}</c></tag>
- <item><p>The DER-encoded user's private key or a map refering to a crypto
- engine and its key reference that optionally can be password protected,
- seealso <seealso marker="crypto:crypto#engine_load-4"> crypto:engine_load/4
- </seealso> and <seealso marker="crypto:engine_load"> Crypto's Users Guide</seealso>. If this option
- is supplied, it overrides option <c>keyfile</c>.</p></item>
-
- <tag><c>{keyfile, path()}</c></tag>
- <item><p>Path to the file containing the user's
- private PEM-encoded key. As PEM-files can contain several
- entries, this option defaults to the same file as given by
- option <c>certfile</c>.</p></item>
-
- <tag><c>{password, string()}</c></tag>
- <item><p>String containing the user's password. Only used if the
- private keyfile is password-protected.</p></item>
-
- <tag><c>{ciphers, ciphers()}</c></tag>
- <item><p>Supported cipher suites. The function
- <c>cipher_suites/0</c> can be used to find all ciphers that are
- supported by default. <c>cipher_suites(all)</c> can be called
- to find all available cipher suites. Pre-Shared Key
- (<url href="http://www.ietf.org/rfc/rfc4279.txt">RFC 4279</url> and
- <url href="http://www.ietf.org/rfc/rfc5487.txt">RFC 5487</url>),
- Secure Remote Password
- (<url href="http://www.ietf.org/rfc/rfc5054.txt">RFC 5054</url>), RC4 cipher suites,
- and anonymous cipher suites only work if explicitly enabled by
- this option; they are supported/enabled by the peer also.
- Anonymous cipher suites are supported for testing purposes
- only and are not be used when security matters.</p></item>
-
- <tag><c>{eccs, [named_curve()]}</c></tag>
- <item><p> Allows to specify the order of preference for named curves
- and to restrict their usage when using a cipher suite supporting them.
- </p></item>
-
- <tag><c>{secure_renegotiate, boolean()}</c></tag>
- <item><p>Specifies if to reject renegotiation attempt that does
- not live up to
- <url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.
- By default <c>secure_renegotiate</c> is set to <c>true</c>,
- that is, secure renegotiation is enforced. If set to <c>false</c> secure renegotiation
- will still be used if possible,
- but it falls back to insecure renegotiation if the peer
- does not support
- <url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.</p>
- </item>
-
- <tag><c>{depth, integer()}</c></tag>
- <item><p>Maximum number of non-self-issued
+ <datatype>
+ <name name="legacy_cipher"/>
+ </datatype>
+
+ <datatype>
+ <name name="cipher_filters"/>
+ </datatype>
+
+ <datatype>
+ <name name="hash"/>
+ </datatype>
+
+ <datatype>
+ <name name="sha2"/>
+ </datatype>
+
+ <datatype>
+ <name name="legacy_hash"/>
+ </datatype>
+
+ <datatype>
+ <name name="old_cipher_suite"/>
+ </datatype>
+
+ <datatype>
+ <name name="signature_algs"/>
+ </datatype>
+
+ <datatype>
+ <name name="sign_algo"/>
+ </datatype>
+
+ <datatype>
+ <name name="kex_algo"/>
+ </datatype>
+
+ <datatype>
+ <name name="algo_filter"/>
+ </datatype>
+
+ <datatype>
+ <name name="named_curve"/>
+ </datatype>
+
+ <datatype>
+ <name name="psk_identity"/>
+ </datatype>
+
+ <datatype>
+ <name name="srp_identity"/>
+ </datatype>
+
+ <datatype>
+ <name name="srp_param_type"/>
+ </datatype>
+
+ <datatype>
+ <name name="app_level_protocol"/>
+ </datatype>
+
+ <datatype>
+ <name name="protocol_extensions"/>
+ </datatype>
+
+ <datatype>
+ <name name="error_alert"/>
+ </datatype>
+
+ <datatype>
+ <name name="tls_alert"/>
+ </datatype>
+
+ <datatype>
+ <name name="reason"/>
+ </datatype>
+
+ <datatype_title>TLS/DTLS OPTION DESCRIPTIONS - COMMON for SERVER and CLIENT</datatype_title>
+
+ <datatype>
+ <name name="common_option"/>
+ </datatype>
+
+ <datatype>
+ <name since="OTP 20" name="protocol"/>
+ <desc>
+ <p>Choose TLS or DTLS protocol for the transport layer security.
+ Defaults to <c>tls</c>. For DTLS other transports than UDP are not yet supported.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="handshake_completion"/>
+ <desc>
+ <p>Defaults to <c>full</c>. If hello is specified the handshake will
+ pause after the hello message and give the user a possibility make decisions
+ based on hello extensions before continuing or aborting the handshake by calling
+ <seealso marker="#handshake_continue-3"> handshake_continue/3</seealso> or
+ <seealso marker="#handshake_cancel-1"> handshake_cancel/1</seealso></p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="cert"/>
+ <desc>
+ <p>The DER-encoded users certificate. If this option
+ is supplied, it overrides option <c>certfile</c>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="cert_pem"/>
+ <desc>
+ <p>Path to a file containing the user certificate on PEM format.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key"/>
+ <desc>
+ <p>The DER-encoded user's private key or a map refering to a crypto
+ engine and its key reference that optionally can be password protected,
+ seealso <seealso marker="crypto:crypto#engine_load-4"> crypto:engine_load/4
+ </seealso> and <seealso marker="crypto:engine_load"> Crypto's Users Guide</seealso>. If this option
+ is supplied, it overrides option <c>keyfile</c>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key_pem"/>
+ <desc>
+ <p>Path to the file containing the user's
+ private PEM-encoded key. As PEM-files can contain several
+ entries, this option defaults to the same file as given by
+ option <c>certfile</c>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key_password"/>
+ <desc>
+ <p>String containing the user's password. Only used if the
+ private keyfile is password-protected.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="cipher_suites"/>
+ <desc>
+ <p>Supported cipher suites. The function
+ <c>cipher_suites/2</c> can be used to find all ciphers that
+ are supported by default. <c>cipher_suites(all, 'tlsv1.2')</c> can be
+ called to find all available cipher suites. Pre-Shared Key
+ (<url href="http://www.ietf.org/rfc/rfc4279.txt">RFC
+ 4279</url> and <url
+ href="http://www.ietf.org/rfc/rfc5487.txt">RFC 5487</url>),
+ Secure Remote Password (<url
+ href="http://www.ietf.org/rfc/rfc5054.txt">RFC 5054</url>),
+ RC4, 3DES, DES cipher suites, and anonymous cipher suites only work if
+ explicitly enabled by this option; they are supported/enabled
+ by the peer also. Anonymous cipher suites are supported for
+ testing purposes only and are not be used when security
+ matters.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="secure_renegotiation"/>
+ <desc><p>Specifies if to reject renegotiation attempt that does
+ not live up to <url
+ href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>. By
+ default <c>secure_renegotiate</c> is set to <c>true</c>, that
+ is, secure renegotiation is enforced. If set to <c>false</c>
+ secure renegotiation will still be used if possible, but it
+ falls back to insecure renegotiation if the peer does not
+ support <url href="http://www.ietf.org/rfc/rfc5746.txt">RFC
+ 5746</url>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="allowed_cert_chain_length"/>
+ <desc><p>Maximum number of non-self-issued
intermediate certificates that can follow the peer certificate
in a valid certification path. So, if depth is 0 the PEER must
be signed by the trusted ROOT-CA directly; if 1 the path can
be PEER, CA, ROOT-CA; if 2 the path can be PEER, CA, CA,
- ROOT-CA, and so on. The default value is 1.</p></item>
-
- <tag><marker id="verify_fun"/><c>{verify_fun, {Verifyfun :: fun(), InitialUserState ::
- term()}}</c></tag>
- <item><p>The verification fun is to be defined as follows:</p>
+ ROOT-CA, and so on. The default value is 1.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="custom_verify"/>
+ <desc>
+ <p>The verification fun is to be defined as follows:</p>
<code>
-fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom() | {revoked,
-atom()}} |
+fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom() |
+ {revoked, atom()}} |
{extension, #'Extension'{}}, InitialUserState :: term()) ->
{valid, UserState :: term()} | {valid_peer, UserState :: term()} |
{fail, Reason :: term()} | {unknown, UserState :: term()}.
@@ -315,20 +373,21 @@ atom()}} |
<p>The verification fun is called during the X509-path
validation when an error or an extension unknown to the SSL
- application is encountered. It is also called
- when a certificate is considered valid by the path validation
- to allow access to each certificate in the path to the user
- application. It differentiates between the peer
- certificate and the CA certificates by using <c>valid_peer</c> or
- <c>valid</c> as second argument to the verification fun. See the
- <seealso marker="public_key:public_key_records">public_key User's
- Guide</seealso> for definition of <c>#'OTPCertificate'{}</c> and
- <c>#'Extension'{}</c>.</p>
+ application is encountered. It is also called when a
+ certificate is considered valid by the path validation to
+ allow access to each certificate in the path to the user
+ application. It differentiates between the peer certificate
+ and the CA certificates by using <c>valid_peer</c> or
+ <c>valid</c> as second argument to the verification fun. See
+ the <seealso marker="public_key:public_key_records">public_key
+ User's Guide</seealso> for definition of
+ <c>#'OTPCertificate'{}</c> and <c>#'Extension'{}</c>.</p>
<list type="bulleted">
- <item><p>If the verify callback fun returns <c>{fail, Reason}</c>,
- the verification process is immediately stopped, an alert is
- sent to the peer, and the TLS/DTLS handshake terminates.</p></item>
+ <item><p>If the verify callback fun returns <c>{fail,
+ Reason}</c>, the verification process is immediately
+ stopped, an alert is sent to the peer, and the TLS/DTLS
+ handshake terminates.</p></item>
<item><p>If the verify callback fun returns <c>{valid, UserState}</c>,
the verification process continues.</p></item>
<item><p>If the verify callback fun always returns
@@ -378,10 +437,12 @@ atom()}} |
<taglist>
<tag><c>unknown_ca</c></tag>
- <item><p>No trusted CA was found in the trusted store. The trusted CA is
- normally a so called ROOT CA, which is a self-signed certificate. Trust can
- be claimed for an intermediate CA (trusted anchor does not have to be
- self-signed according to X-509) by using option <c>partial_chain</c>.</p>
+ <item><p>No trusted CA was found in the trusted store. The
+ trusted CA is normally a so called ROOT CA, which is a
+ self-signed certificate. Trust can be claimed for an
+ intermediate CA (trusted anchor does not have to be
+ self-signed according to X-509) by using option
+ <c>partial_chain</c>.</p>
</item>
<tag><c>selfsigned_peer</c></tag>
@@ -392,15 +453,17 @@ atom()}} |
marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_validation/3</seealso>
</p></item>
</taglist>
- </item>
-
- <tag><c>{crl_check, boolean() | peer | best_effort }</c></tag>
- <item>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="crl_check"/>
+ <desc>
<p>Perform CRL (Certificate Revocation List) verification
<seealso marker="public_key:public_key#pkix_crls_validate-3">
- (public_key:pkix_crls_validate/3)</seealso> on all the certificates during the path validation
- <seealso
- marker="public_key:public_key#pkix_path_validation-3">(public_key:pkix_path_validation/3)
+ (public_key:pkix_crls_validate/3)</seealso> on all the
+ certificates during the path validation <seealso
+ marker="public_key:public_key#pkix_path_validation-3">(public_key:pkix_path_validation/3)
</seealso>
of the certificate chain. Defaults to <c>false</c>.</p>
@@ -412,112 +475,111 @@ marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_valid
<item>if certificate revocation status can not be determined
it will be accepted as valid.</item>
</taglist>
-
+
<p>The CA certificates specified for the connection will be used to
construct the certificate chain validating the CRLs.</p>
<p>The CRLs will be fetched from a local or external cache. See
<seealso marker="ssl:ssl_crl_cache_api">ssl_crl_cache_api(3)</seealso>.</p>
- </item>
-
- <tag><c>{crl_cache, {Module :: atom(), {DbHandle :: internal | term(), Args :: list()}}}</c></tag>
- <item>
- <p>Specify how to perform lookup and caching of certificate revocation lists.
- <c>Module</c> defaults to <seealso marker="ssl:ssl_crl_cache">ssl_crl_cache</seealso>
- with <c> DbHandle </c> being <c>internal</c> and an
- empty argument list.</p>
-
- <p>There are two implementations available:</p>
-
- <taglist>
- <tag><c>ssl_crl_cache</c></tag>
- <item>
- <p>This module maintains a cache of CRLs. CRLs can be
- added to the cache using the function <seealso
- marker="ssl:ssl_crl_cache#insert-1">ssl_crl_cache:insert/1</seealso>,
- and optionally automatically fetched through HTTP if the
- following argument is specified:</p>
-
- <taglist>
- <tag><c>{http, timeout()}</c></tag>
- <item><p>
- Enables fetching of CRLs specified as http URIs in<seealso
- marker="public_key:public_key_records">X509 certificate extensions</seealso>.
- Requires the OTP inets application.</p>
- </item>
- </taglist>
- </item>
-
- <tag><c>ssl_crl_hash_dir</c></tag>
- <item>
- <p>This module makes use of a directory where CRLs are
- stored in files named by the hash of the issuer name.</p>
-
- <p>The file names consist of eight hexadecimal digits
- followed by <c>.rN</c>, where <c>N</c> is an integer,
- e.g. <c>1a2b3c4d.r0</c>. For the first version of the
- CRL, <c>N</c> starts at zero, and for each new version,
- <c>N</c> is incremented by one. The OpenSSL utility
- <c>c_rehash</c> creates symlinks according to this
- pattern.</p>
-
- <p>For a given hash value, this module finds all
- consecutive <c>.r*</c> files starting from zero, and those
- files taken together make up the revocation list. CRL
- files whose <c>nextUpdate</c> fields are in the past, or
- that are issued by a different CA that happens to have the
- same name hash, are excluded.</p>
-
- <p>The following argument is required:</p>
-
- <taglist>
- <tag><c>{dir, string()}</c></tag>
- <item><p>Specifies the directory in which the CRLs can be found.</p></item>
- </taglist>
-
- </item>
-
- <tag><c>max_handshake_size</c></tag>
- <item>
- <p>Integer (24 bits unsigned). Used to limit the size of
- valid TLS handshake packets to avoid DoS attacks.
- Defaults to 256*1024.</p>
- </item>
-
- </taglist>
-
- </item>
+ </desc>
+ </datatype>
- <tag><c>{partial_chain, fun(Chain::[DerCert]) -> {trusted_ca, DerCert} |
- unknown_ca }</c></tag>
- <item><p>Claim an intermediate CA in the chain as trusted. TLS then
- performs <seealso
- marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_validation/3</seealso>
- with the selected CA as trusted anchor and the rest of the chain.</p></item>
+ <datatype>
+ <name name="crl_cache_opts"/>
+ <desc>
+ <p>Specify how to perform lookup and caching of certificate revocation lists.
+ <c>Module</c> defaults to <seealso marker="ssl:ssl_crl_cache">ssl_crl_cache</seealso>
+ with <c> DbHandle </c> being <c>internal</c> and an
+ empty argument list.</p>
+
+ <p>There are two implementations available:</p>
+
+ <taglist>
+ <tag><c>ssl_crl_cache</c></tag>
+ <item>
+ <p>This module maintains a cache of CRLs. CRLs can be
+ added to the cache using the function <seealso
+ marker="ssl:ssl_crl_cache#insert-1">ssl_crl_cache:insert/1</seealso>,
+ and optionally automatically fetched through HTTP if the
+ following argument is specified:</p>
+
+ <taglist>
+ <tag><c>{http, timeout()}</c></tag>
+ <item><p>
+ Enables fetching of CRLs specified as http URIs in<seealso
+ marker="public_key:public_key_records">X509 certificate extensions</seealso>.
+ Requires the OTP inets application.</p>
+ </item>
+ </taglist>
+ </item>
+
+ <tag><c>ssl_crl_hash_dir</c></tag>
+ <item>
+ <p>This module makes use of a directory where CRLs are
+ stored in files named by the hash of the issuer name.</p>
+
+ <p>The file names consist of eight hexadecimal digits
+ followed by <c>.rN</c>, where <c>N</c> is an integer,
+ e.g. <c>1a2b3c4d.r0</c>. For the first version of the
+ CRL, <c>N</c> starts at zero, and for each new version,
+ <c>N</c> is incremented by one. The OpenSSL utility
+ <c>c_rehash</c> creates symlinks according to this
+ pattern.</p>
+
+ <p>For a given hash value, this module finds all
+ consecutive <c>.r*</c> files starting from zero, and those
+ files taken together make up the revocation list. CRL
+ files whose <c>nextUpdate</c> fields are in the past, or
+ that are issued by a different CA that happens to have the
+ same name hash, are excluded.</p>
+
+ <p>The following argument is required:</p>
+
+ <taglist>
+ <tag><c>{dir, string()}</c></tag>
+ <item><p>Specifies the directory in which the CRLs can be found.</p></item>
+ </taglist>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="root_fun"/>
+ <desc>
+ <code>
+fun(Chain::[public_key:der_encoded()]) ->
+ {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca}
+ </code>
+ <p>Claim an intermediate CA in the chain as trusted. TLS then
+ performs <seealso
+ marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_validation/3</seealso>
+ with the selected CA as trusted anchor and the rest of the chain.</p>
+ </desc>
+ </datatype>
- <tag><c>{versions, [protocol_version()]}</c></tag>
- <item><p>TLS protocol versions supported by started clients and servers.
+ <datatype>
+ <name name="protocol_versions"/>
+ <desc><p>TLS protocol versions supported by started clients and servers.
This option overrides the application environment option
<c>protocol_version</c> and <c>dtls_protocol_version</c>. If the environment option is not set, it defaults
to all versions, except SSL-3.0, supported by the SSL application.
- See also <seealso marker="ssl:ssl_app">ssl(6).</seealso></p></item>
+ See also <seealso marker="ssl:ssl_app">ssl(6).</seealso></p>
+ </desc>
+ </datatype>
- <tag><c>{hibernate_after, integer()|undefined}</c></tag>
- <item><p>When an integer-value is specified, <c>TLS/DTLS-connection</c>
- goes into hibernation after the specified number of milliseconds
- of inactivity, thus reducing its memory footprint. When
- <c>undefined</c> is specified (this is the default), the process
- never goes into hibernation.</p></item>
- <tag><c>{user_lookup_fun, {Lookupfun :: fun(), UserState :: term()}}</c></tag>
- <item><p>The lookup fun is to defined as follows:</p>
+ <datatype>
+ <name name="custom_user_lookup"/>
+ <desc><p>The lookup fun is to defined as follows:</p>
<code>
fun(psk, PSKIdentity ::string(), UserState :: term()) ->
{ok, SharedSecret :: binary()} | error;
fun(srp, Username :: string(), UserState :: term()) ->
- {ok, {SRPParams :: srp_param_type(), Salt :: binary(), DerivedKey :: binary()}} | error.
+ {ok, {SRPParams :: srp_param_type(), Salt :: binary(),
+ DerivedKey :: binary()}} | error.
</code>
<p>For Pre-Shared Key (PSK) cipher suites, the lookup fun is
@@ -533,20 +595,54 @@ fun(srp, Username :: string(), UserState :: term()) ->
<url href="http://tools.ietf.org/html/rfc5054#section-2.4"> RFC 5054</url>:
<c>crypto:sha([Salt, crypto:sha([Username, &lt;&lt;$:&gt;&gt;, Password])])</c>
</p>
- </item>
+ </desc>
+ </datatype>
- <tag><c>{padding_check, boolean()}</c></tag>
- <item><p>Affects TLS-1.0 connections only.
+ <datatype>
+ <name name="session_id"/>
+ <desc>
+ <p>Identifies a TLS session.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="log_alert"/>
+ <desc><p>If set to <c>false</c>, error reports are not displayed.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="hibernate_after"/>
+ <desc><p>When an integer-value is specified, <c>TLS/DTLS-connection</c>
+ goes into hibernation after the specified number of milliseconds
+ of inactivity, thus reducing its memory footprint. When
+ <c>undefined</c> is specified (this is the default), the process
+ never goes into hibernation.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="handshake_size"/>
+ <desc>
+ <p>Integer (24 bits unsigned). Used to limit the size of
+ valid TLS handshake packets to avoid DoS attacks.
+ Defaults to 256*1024.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="padding_check"/>
+ <desc><p>Affects TLS-1.0 connections only.
If set to <c>false</c>, it disables the block cipher padding check
to be able to interoperate with legacy software.</p>
<warning><p>Using <c>{padding_check, boolean()}</c> makes TLS
vulnerable to the Poodle attack.</p></warning>
- </item>
-
-
+ </desc>
+ </datatype>
- <tag><c>{beast_mitigation, one_n_minus_one | zero_n | disabled}</c></tag>
- <item><p>Affects SSL-3.0 and TLS-1.0 connections only. Used to change the BEAST
+ <datatype>
+ <name name="beast_mitigation"/>
+ <desc><p>Affects SSL-3.0 and TLS-1.0 connections only. Used to change the BEAST
mitigation strategy to interoperate with legacy software.
Defaults to <c>one_n_minus_one</c>.</p>
@@ -556,127 +652,170 @@ fun(srp, Username :: string(), UserState :: term()) ->
<p><c>disabled</c> - Disable BEAST mitigation.</p>
- <warning><p>Using <c>{beast_mitigation, disabled}</c> makes SSL or TLS
+ <warning><p>Using <c>{beast_mitigation, disabled}</c> makes SSL-3.0 or TLS-1.0
vulnerable to the BEAST attack.</p></warning>
- </item>
- </taglist>
-
- </section>
-
- <section>
- <title>TLS/DTLS OPTION DESCRIPTIONS - CLIENT SIDE</title>
-
- <p>The following options are client-specific or have a slightly different
- meaning in the client than in the server:</p>
-
- <taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ssl_imp"/>
+ <desc><p>Deprecated since OTP-17, has no affect.</p></desc>
+ </datatype>
+
+ <datatype_title>TLS/DTLS OPTION DESCRIPTIONS - CLIENT</datatype_title>
+
+ <datatype>
+ <name name="client_option"/>
+ </datatype>
+
+ <datatype>
+ <name name="client_verify_type"/>
+ <desc><p>In mode <c>verify_none</c> the default behavior is to allow
+ all x509-path validation errors. See also option <seealso marker="#type-custom_verify">verify_fun</seealso>.</p>
+ </desc>
+ </datatype>
- <tag><c>{verify, verify_type()}</c></tag>
- <item><p>In mode <c>verify_none</c> the default behavior is to allow
- all x509-path validation errors. See also option <c>verify_fun</c>.</p>
- </item>
+ <datatype>
+ <name name="client_reuse_session"/>
+ <desc>
+ <p>Reuses a specific session earlier saved with the option
+ <c>{reuse_sessions, save} since OTP-21.3 </c>
+ </p>
+ </desc>
+ </datatype>
- <tag><c>{reuse_sessions, boolean()}</c></tag>
- <item><p>Specifies if the client is to try to reuse sessions
- when possible.</p></item>
+ <datatype>
+ <name name="client_reuse_sessions"/>
+ <desc>
+ <p>When <c>save</c> is specified a new connection will be negotiated
+ and saved for later reuse. The session ID can be fetched with
+ <seealso marker="#connection_information-2">connection_information/2</seealso>
+ and used with the client option <seealso marker="#type-client_reuse_session">reuse_session</seealso>
+ The boolean value true specifies that if possible, automatized session reuse will
+ be performed. If a new session is created, and is unique in regard
+ to previous stored sessions, it will be saved for possible later reuse. Since OTP-21.3</p>
+ </desc>
+ </datatype>
- <tag><c>{cacerts, [public_key:der_encoded()]}</c></tag>
- <item><p>The DER-encoded trusted certificates. If this option
- is supplied it overrides option <c>cacertfile</c>.</p></item>
-
- <tag><c>{cacertfile, path()}</c></tag>
- <item><p>Path to a file containing PEM-encoded CA certificates. The CA
+ <datatype>
+ <name name="client_cacerts"/>
+ <desc>
+ <p>The DER-encoded trusted certificates. If this option
+ is supplied it overrides option <c>cacertfile</c>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client_cafile"/>
+ <desc>
+ <p>Path to a file containing PEM-encoded CA certificates. The CA
certificates are used during server authentication and when building the
client certificate chain.</p>
- </item>
-
- <tag><c>{alpn_advertised_protocols, [binary()]}</c></tag>
- <item>
- <p>The list of protocols supported by the client to be sent to the
- server to be used for an Application-Layer Protocol Negotiation (ALPN).
- If the server supports ALPN then it will choose a protocol from this
- list; otherwise it will fail the connection with a "no_application_protocol"
- alert. A server that does not support ALPN will ignore this value.</p>
-
- <p>The list of protocols must not contain an empty binary.</p>
-
- <p>The negotiated protocol can be retrieved using the <c>negotiated_protocol/1</c> function.</p>
- </item>
-
- <tag><c>{client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()]}}</c><br/>
- <c>{client_preferred_next_protocols, {Precedence :: server | client, ClientPrefs :: [binary()], Default :: binary()}}</c></tag>
- <item>
- <p>Indicates that the client is to try to perform Next Protocol
- Negotiation.</p>
-
- <p>If precedence is server, the negotiated protocol is the
- first protocol to be shown on the server advertised list, which is
- also on the client preference list.</p>
-
- <p>If precedence is client, the negotiated protocol is the
- first protocol to be shown on the client preference list, which is
- also on the server advertised list.</p>
-
- <p>If the client does not support any of the server advertised
- protocols or the server does not advertise any protocols, the
- client falls back to the first protocol in its list or to the
- default protocol (if a default is supplied). If the
- server does not support Next Protocol Negotiation, the
- connection terminates if no default protocol is supplied.</p>
- </item>
-
- <tag><c>{psk_identity, string()}</c></tag>
- <item><p>Specifies the identity the client presents to the server.
- The matching secret is found by calling <c>user_lookup_fun</c>.</p>
- </item>
-
- <tag><c>{srp_identity, {Username :: string(), Password :: string()}
- </c></tag>
- <item><p>Specifies the username and password to use to authenticate
- to the server.</p></item>
-
- <tag><c>{server_name_indication, HostName :: hostname()}</c></tag>
- <item><p>Specify the hostname to be used in TLS Server Name Indication extension.
- If not specified it will default to the <c>Host</c> argument of <seealso marker="#connect-3">connect/[3,4]</seealso>
- unless it is of type inet:ipaddress().</p>
- <p>
- The <c>HostName</c> will also be used in the hostname verification of the peer certificate using
- <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>.
- </p>
- </item>
- <tag><c>{server_name_indication, disable}</c></tag>
- <item>
- <p> Prevents the Server Name Indication extension from being sent and
- disables the hostname verification check
- <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso> </p>
- </item>
-
- <tag><c>{customize_hostname_check, Options::list()}</c></tag>
- <item>
- <p> Customizes the hostname verification of the peer certificate, as different protocols that use
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client_alpn"/>
+ <desc>
+ <p>The list of protocols supported by the client to be sent to the
+ server to be used for an Application-Layer Protocol Negotiation (ALPN).
+ If the server supports ALPN then it will choose a protocol from this
+ list; otherwise it will fail the connection with a "no_application_protocol"
+ alert. A server that does not support ALPN will ignore this value.</p>
+
+ <p>The list of protocols must not contain an empty binary.</p>
+
+ <p>The negotiated protocol can be retrieved using the <c>negotiated_protocol/1</c> function.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client_preferred_next_protocols"/>
+ <desc>
+ <p>Indicates that the client is to try to perform Next Protocol
+ Negotiation.</p>
+
+ <p>If precedence is server, the negotiated protocol is the
+ first protocol to be shown on the server advertised list, which is
+ also on the client preference list.</p>
+
+ <p>If precedence is client, the negotiated protocol is the
+ first protocol to be shown on the client preference list, which is
+ also on the server advertised list.</p>
+
+ <p>If the client does not support any of the server advertised
+ protocols or the server does not advertise any protocols, the
+ client falls back to the first protocol in its list or to the
+ default protocol (if a default is supplied). If the
+ server does not support Next Protocol Negotiation, the
+ connection terminates if no default protocol is supplied.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client_psk_identity"/>
+ <desc>
+ <p>Specifies the identity the client presents to the server.
+ The matching secret is found by calling <c>user_lookup_fun</c></p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client_srp_identity"/>
+ <desc>
+ <p>Specifies the username and password to use to authenticate
+ to the server.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="sni"/>
+ <desc>
+ <p>Specify the hostname to be used in TLS Server Name Indication extension.
+ If not specified it will default to the <c>Host</c> argument of <seealso marker="#connect-3">connect/[3,4]</seealso>
+ unless it is of type inet:ipaddress().</p>
+ <p>
+ The <c>HostName</c> will also be used in the hostname verification of the peer certificate using
+ <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>.
+ </p>
+ <p> The special value <c>disable</c> prevents the Server Name Indication extension from being sent and
+ disables the hostname verification check
+ <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso> </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="customize_hostname_check"/>
+ <desc>
+ <p> Customizes the hostname verification of the peer certificate, as different protocols that use
TLS such as HTTP or LDAP may want to do it differently, for possible options see
<seealso marker="public_key:public_key#pkix_verify_hostname-3">public_key:pkix_verify_hostname/3</seealso> </p>
- </item>
-
- <tag><c>{fallback, boolean()}</c></tag>
- <item>
- <p> Send special cipher suite TLS_FALLBACK_SCSV to avoid undesired TLS version downgrade.
- Defaults to false</p>
- <warning><p>Note this option is not needed in normal TLS usage and should not be used
- to implement new clients. But legacy clients that retries connections in the following manner</p>
-
- <p><c> ssl:connect(Host, Port, [...{versions, ['tlsv2', 'tlsv1.1', 'tlsv1', 'sslv3']}])</c></p>
- <p><c> ssl:connect(Host, Port, [...{versions, [tlsv1.1', 'tlsv1', 'sslv3']}, {fallback, true}])</c></p>
- <p><c> ssl:connect(Host, Port, [...{versions, ['tlsv1', 'sslv3']}, {fallback, true}]) </c></p>
- <p><c> ssl:connect(Host, Port, [...{versions, ['sslv3']}, {fallback, true}]) </c></p>
-
- <p>may use it to avoid undesired TLS version downgrade. Note that TLS_FALLBACK_SCSV must also
- be supported by the server for the prevention to work.
- </p></warning>
- </item>
- <tag><marker id="client_signature_algs"/><c>{signature_algs, [{hash(), ecdsa | rsa | dsa}]}</c></tag>
- <item>
- <p>In addition to the algorithms negotiated by the cipher
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="fallback"/>
+ <desc>
+ <p> Send special cipher suite TLS_FALLBACK_SCSV to avoid undesired TLS version downgrade.
+ Defaults to false</p>
+ <warning><p>Note this option is not needed in normal TLS usage and should not be used
+ to implement new clients. But legacy clients that retries connections in the following manner</p>
+
+ <p><c> ssl:connect(Host, Port, [...{versions, ['tlsv2', 'tlsv1.1', 'tlsv1', 'sslv3']}])</c></p>
+ <p><c> ssl:connect(Host, Port, [...{versions, [tlsv1.1', 'tlsv1', 'sslv3']}, {fallback, true}])</c></p>
+ <p><c> ssl:connect(Host, Port, [...{versions, ['tlsv1', 'sslv3']}, {fallback, true}]) </c></p>
+ <p><c> ssl:connect(Host, Port, [...{versions, ['sslv3']}, {fallback, true}]) </c></p>
+
+ <p>may use it to avoid undesired TLS version downgrade. Note that TLS_FALLBACK_SCSV must also
+ be supported by the server for the prevention to work.
+ </p></warning>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client_signature_algs"/>
+ <desc>
+ <p>In addition to the algorithms negotiated by the cipher
suite used for key exchange, payload encryption, message
authentication and pseudo random calculation, the TLS signature
algorithm extension <url
@@ -707,178 +846,226 @@ fun(srp, Username :: string(), UserState :: term()) ->
Selected signature algorithm can restrict which hash functions
that may be selected. Default support for {md5, rsa} removed in ssl-8.0
</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>TLS/DTLS OPTION DESCRIPTIONS - SERVER SIDE</title>
+ </desc>
+ </datatype>
+
- <p>The following options are server-specific or have a slightly different
- meaning in the server than in the client:</p>
+ <datatype_title>TLS/DTLS OPTION DESCRIPTIONS - SERVER </datatype_title>
- <taglist>
- <tag><c>{cacerts, [public_key:der_encoded()]}</c></tag>
- <item><p>The DER-encoded trusted certificates. If this option
- is supplied it overrides option <c>cacertfile</c>.</p></item>
+ <datatype>
+ <name name="server_option"/>
+ </datatype>
+
+ <datatype>
+ <name name="server_cacerts"/>
+ <desc><p>The DER-encoded trusted certificates. If this option
+ is supplied it overrides option <c>cacertfile</c>.</p>
+ </desc>
+ </datatype>
- <tag><c>{cacertfile, path()}</c></tag>
- <item><p>Path to a file containing PEM-encoded CA
- certificates. The CA certificates are used to build the server
- certificate chain and for client authentication. The CAs are
- also used in the list of acceptable client CAs passed to the
- client when a certificate is requested. Can be omitted if there
- is no need to verify the client and if there are no
- intermediate CAs for the server certificate.</p></item>
-
- <tag><c>{dh, public_key:der_encoded()}</c></tag>
- <item><p>The DER-encoded Diffie-Hellman parameters. If specified,
- it overrides option <c>dhfile</c>.</p></item>
-
- <tag><c>{dhfile, path()}</c></tag>
- <item><p>Path to a file containing PEM-encoded Diffie Hellman parameters
- to be used by the server if a cipher suite using Diffie Hellman key
- exchange is negotiated. If not specified, default parameters are used.
- </p></item>
-
- <tag><c>{verify, verify_type()}</c></tag>
- <item><p>A server only does x509-path validation in mode <c>verify_peer</c>,
- as it then sends a certificate request to the client
- (this message is not sent if the verify option is <c>verify_none</c>).
- You can then also want to specify option <c>fail_if_no_peer_cert</c>.
- </p></item>
-
- <tag><c>{fail_if_no_peer_cert, boolean()}</c></tag>
- <item><p>Used together with <c>{verify, verify_peer}</c> by an TLS/DTLS server.
- If set to <c>true</c>, the server fails if the client does not have
- a certificate to send, that is, sends an empty certificate. If set to
- <c>false</c>, it fails only if the client sends an invalid
- certificate (an empty certificate is considered valid). Defaults to false.</p>
- </item>
-
- <tag><c>{reuse_sessions, boolean()}</c></tag>
- <item><p>Specifies if the server is to agree to reuse sessions
- when requested by the clients. See also option <c>reuse_session</c>.
- </p></item>
-
- <tag><c>{reuse_session, fun(SuggestedSessionId,
- PeerCert, Compression, CipherSuite) -> boolean()}</c></tag>
- <item><p>Enables the TLS/DTLS server to have a local policy
- for deciding if a session is to be reused or not.
- Meaningful only if <c>reuse_sessions</c> is set to <c>true</c>.
- <c>SuggestedSessionId</c> is a <c>binary()</c>, <c>PeerCert</c> is
- a DER-encoded certificate, <c>Compression</c> is an enumeration integer,
- and <c>CipherSuite</c> is of type <c>ciphersuite()</c>.</p></item>
-
- <tag><c>{alpn_preferred_protocols, [binary()]}</c></tag>
- <item>
- <p>Indicates the server will try to perform Application-Layer
- Protocol Negotiation (ALPN).</p>
-
- <p>The list of protocols is in order of preference. The protocol
- negotiated will be the first in the list that matches one of the
- protocols advertised by the client. If no protocol matches, the
- server will fail the connection with a "no_application_protocol" alert.</p>
-
- <p>The negotiated protocol can be retrieved using the <c>negotiated_protocol/1</c> function.</p>
- </item>
-
- <tag><c>{next_protocols_advertised, Protocols :: [binary()]}</c></tag>
- <item><p>List of protocols to send to the client if the client indicates that
- it supports the Next Protocol extension. The client can select a protocol
- that is not on this list. The list of protocols must not contain an empty
- binary. If the server negotiates a Next Protocol, it can be accessed
- using the <c>negotiated_next_protocol/1</c> method.</p></item>
-
- <tag><c>{psk_identity, string()}</c></tag>
- <item><p>Specifies the server identity hint, which the server presents to
- the client.</p></item>
-
- <tag><c>{log_alert, boolean()}</c></tag>
- <item><p>If set to <c>false</c>, error reports are not displayed.</p></item>
-
- <tag><c>{honor_cipher_order, boolean()}</c></tag>
- <item><p>If set to <c>true</c>, use the server preference for cipher
- selection. If set to <c>false</c> (the default), use the client
- preference.</p></item>
-
- <tag><c>{sni_hosts, [{hostname(), [ssl_option()]}]}</c></tag>
- <item><p>If the server receives a SNI (Server Name Indication) from the client
- matching a host listed in the <c>sni_hosts</c> option, the specific options for
- that host will override previously specified options.
-
- The option <c>sni_fun</c>, and <c>sni_hosts</c> are mutually exclusive.</p></item>
-
- <tag><c>{sni_fun, SNIfun::fun()}</c></tag>
- <item><p>If the server receives a SNI (Server Name Indication) from the client,
- the given function will be called to retrieve <c>[ssl_option()]</c> for the indicated server.
- These options will be merged into predefined <c>[ssl_option()]</c>.
-
- The function should be defined as:
- <c>fun(ServerName :: string()) -> [ssl_option()]</c>
- and can be specified as a fun or as named <c>fun module:function/1</c>
-
- The option <c>sni_fun</c>, and <c>sni_hosts</c> are mutually exclusive.</p></item>
-
- <tag><c>{client_renegotiation, boolean()}</c></tag>
- <item>In protocols that support client-initiated renegotiation, the cost
- of resources of such an operation is higher for the server than the
- client. This can act as a vector for denial of service attacks. The SSL
- application already takes measures to counter-act such attempts,
- but client-initiated renegotiation can be strictly disabled by setting
- this option to <c>false</c>. The default value is <c>true</c>.
- Note that disabling renegotiation can result in long-lived connections
- becoming unusable due to limits on the number of messages the underlying
- cipher suite can encipher.
- </item>
-
- <tag><c>{honor_cipher_order, boolean()}</c></tag>
- <item>If true, use the server's preference for cipher selection. If false
- (the default), use the client's preference.
- </item>
- <tag><c>{honor_ecc_order, boolean()}</c></tag>
- <item>If true, use the server's preference for ECC curve selection. If false
- (the default), use the client's preference.
- </item>
-
- <tag><c>{signature_algs, [{hash(), ecdsa | rsa | dsa}]}</c></tag>
- <item><p> The algorithms specified by
- this option will be the ones accepted by the server in a signature algorithm
- negotiation, introduced in TLS-1.2. The algorithms will also be offered to the client if a
- client certificate is requested. For more details see the <seealso marker="#client_signature_algs">corresponding client option</seealso>.
- </p> </item>
-
- </taglist>
- </section>
-
- <section>
- <title>General</title>
+ <datatype>
+ <name name="server_cafile"/>
+ <desc><p>Path to a file containing PEM-encoded CA
+ certificates. The CA certificates are used to build the server
+ certificate chain and for client authentication. The CAs are
+ also used in the list of acceptable client CAs passed to the
+ client when a certificate is requested. Can be omitted if
+ there is no need to verify the client and if there are no
+ intermediate CAs for the server certificate.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="dh_der"/>
+ <desc><p>The DER-encoded Diffie-Hellman parameters. If
+ specified, it overrides option <c>dhfile</c>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="dh_file"/>
+ <desc><p>Path to a file containing PEM-encoded Diffie Hellman
+ parameters to be used by the server if a cipher suite using
+ Diffie Hellman key exchange is negotiated. If not specified,
+ default parameters are used.</p>
+ </desc>
+ </datatype>
- <p>When an TLS/DTLS socket is in active mode (the default), data from the
- socket is delivered to the owner of the socket in the form of
- messages:</p>
- <list type="bulleted">
- <item><p><c>{ssl, Socket, Data}</c></p></item>
- <item><p><c>{ssl_closed, Socket}</c></p></item>
- <item><p><c>{ssl_error, Socket, Reason}</c></p></item>
- </list>
+ <datatype>
+ <name name="server_verify_type"/>
+ <desc><p>A server only does x509-path validation in mode
+ <c>verify_peer</c>, as it then sends a certificate request to
+ the client (this message is not sent if the verify option is
+ <c>verify_none</c>). You can then also want to specify option
+ <c>fail_if_no_peer_cert</c>. </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="fail_if_no_peer_cert"/>
+ <desc><p>Used together with <c>{verify, verify_peer}</c> by an
+ TLS/DTLS server. If set to <c>true</c>, the server fails if
+ the client does not have a certificate to send, that is, sends
+ an empty certificate. If set to <c>false</c>, it fails only if
+ the client sends an invalid certificate (an empty certificate
+ is considered valid). Defaults to false.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="server_reuse_sessions"/>
+ <desc><p>The boolean value true specifies that the server will
+ agree to reuse sessions. Setting it to false will result in an empty
+ session table, that is no sessions will be reused.
+ See also option <seealso marker="#type-server_reuse_session">reuse_session</seealso>
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="server_reuse_session"/>
+ <desc><p>Enables the TLS/DTLS server to have a local policy
+ for deciding if a session is to be reused or not. Meaningful
+ only if <c>reuse_sessions</c> is set to <c>true</c>.
+ <c>SuggestedSessionId</c> is a <c>binary()</c>,
+ <c>PeerCert</c> is a DER-encoded certificate,
+ <c>Compression</c> is an enumeration integer, and
+ <c>CipherSuite</c> is of type <c>ciphersuite()</c>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="server_alpn"/>
+ <desc>
+ <p>Indicates the server will try to perform
+ Application-Layer Protocol Negotiation (ALPN).</p>
+
+ <p>The list of protocols is in order of preference. The
+ protocol negotiated will be the first in the list that
+ matches one of the protocols advertised by the client. If no
+ protocol matches, the server will fail the connection with a
+ "no_application_protocol" alert.</p>
+
+ <p>The negotiated protocol can be retrieved using the
+ <c>negotiated_protocol/1</c> function.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="server_next_protocol"/>
+ <desc><p>List of protocols to send to the client if the client
+ indicates that it supports the Next Protocol extension. The
+ client can select a protocol that is not on this list. The
+ list of protocols must not contain an empty binary. If the
+ server negotiates a Next Protocol, it can be accessed using
+ the <c>negotiated_next_protocol/1</c> method.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="server_psk_identity"/>
+ <desc>
+ <p>Specifies the server identity hint, which the server presents to
+ the client.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="honor_cipher_order"/>
+ <desc>
+ <p>If set to <c>true</c>, use the server preference for cipher
+ selection. If set to <c>false</c> (the default), use the client
+ preference.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="sni_hosts"/>
+ <desc><p>If the server receives a SNI (Server Name Indication) from the client
+ matching a host listed in the <c>sni_hosts</c> option, the specific options for
+ that host will override previously specified options.
+
+ The option <c>sni_fun</c>, and <c>sni_hosts</c> are mutually exclusive.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="sni_fun"/>
+ <desc>
+ <p>If the server receives a SNI (Server Name Indication)
+ from the client, the given function will be called to
+ retrieve <seealso marker="#type-server_option">[server_option()] </seealso> for the indicated server.
+ These options will be merged into predefined
+ <seealso marker="#type-server_option">[server_option()] </seealso> list.
+
+ The function should be defined as:
+ fun(ServerName :: string()) -> <seealso marker="#type-server_option">[server_option()] </seealso>
+ and can be specified as a fun or as named <c>fun module:function/1</c>
+
+ The option <c>sni_fun</c>, and <c>sni_hosts</c> are mutually exclusive.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="client_renegotiation"/>
+ <desc><p>In protocols that support client-initiated
+ renegotiation, the cost of resources of such an operation is
+ higher for the server than the client. This can act as a
+ vector for denial of service attacks. The SSL application
+ already takes measures to counter-act such attempts, but
+ client-initiated renegotiation can be strictly disabled by
+ setting this option to <c>false</c>. The default value is
+ <c>true</c>. Note that disabling renegotiation can result in
+ long-lived connections becoming unusable due to limits on the
+ number of messages the underlying cipher suite can
+ encipher.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="honor_cipher_order"/>
+ <desc><p>If true, use the server's preference for cipher
+ selection. If false (the default), use the client's
+ preference.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="honor_ecc_order"/>
+ <desc><p>If true, use the server's preference for ECC curve
+ selection. If false (the default), use the client's
+ preference.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="server_signature_algs"/>
+ <desc><p> The algorithms specified by this option will be the
+ ones accepted by the server in a signature algorithm
+ negotiation, introduced in TLS-1.2. The algorithms will also
+ be offered to the client if a client certificate is
+ requested. For more details see the <seealso
+ marker="#type-client_signature_algs">corresponding client
+ option</seealso>.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+<!--
+ ================================================================
+ = Function definitions =
+ ================================================================
+-->
- <p>A <c>Timeout</c> argument specifies a time-out in milliseconds. The
- default value for argument <c>Timeout</c> is <c>infinity</c>.</p>
- </section>
-
<funcs>
<func>
- <name>append_cipher_suites(Deferred, Suites) -> ciphers() </name>
+ <name name="append_cipher_suites" arity="2" since="OTP 20.3"/>
<fsummary></fsummary>
- <type>
- <v>Deferred = ciphers() | cipher_filters() </v>
- <v>Suites = ciphers() </v>
- </type>
<desc><p>Make <c>Deferred</c> suites become the least preferred
suites, that is put them at the end of the cipher suite list
<c>Suites</c> after removing them from <c>Suites</c> if
@@ -889,25 +1076,18 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>cipher_suites() -></name>
- <name>cipher_suites(Type) -> old_ciphers()</name>
+ <name name="cipher_suites" arity="0" since="OTP R14B"/>
+ <name name="cipher_suites" arity="1" since="OTP R14B"/>
<fsummary>Returns a list of supported cipher suites.</fsummary>
- <type>
- <v>Type = erlang | openssl | all</v>
- </type>
<desc>
<p>Deprecated in OTP 21, use <seealso marker="#cipher_suites-2">cipher_suites/2</seealso> instead.</p>
</desc>
</func>
<func>
- <name>cipher_suites(Supported, Version) -> ciphers()</name>
+ <name name="cipher_suites" arity="2" since="OTP 20.3"/>
<fsummary>Returns a list of all default or
all supported cipher suites.</fsummary>
- <type>
- <v> Supported = default | all | anonymous </v>
- <v> Version = protocol_version() </v>
- </type>
<desc><p>Returns all default or all supported (except anonymous),
or all anonymous cipher suites for a
TLS version</p>
@@ -915,10 +1095,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>eccs() -></name>
- <name>eccs(protocol_version()) -> [named_curve()]</name>
+ <name name="eccs" arity="0" since="OTP 19.2"/>
+ <name name="eccs" arity="1" since="OTP 19.2"/>
<fsummary>Returns a list of supported ECCs.</fsummary>
-
<desc><p>Returns a list of supported ECCs. <c>eccs()</c>
is equivalent to calling <c>eccs(Protocol)</c> with all
supported protocols and then deduplicating the output.</p>
@@ -926,9 +1105,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>clear_pem_cache() -> ok </name>
+ <name name="clear_pem_cache" arity="0" since="OTP 17.5"/>
<fsummary> Clears the pem cache</fsummary>
-
<desc><p>PEM files, used by ssl API-functions, are cached. The
cache is regularly checked to see if any cache entries should be
invalidated, however this function provides a way to
@@ -938,61 +1116,50 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>connect(Socket, SslOptions) -> </name>
- <name>connect(Socket, SslOptions, Timeout) -> {ok, SslSocket} | {ok, SslSocket, Ext}
- | {error, Reason}</name>
+ <name name="connect" arity="2" since="OTP R14B"/>
+ <name name="connect" arity="3" clause_i="1" since=""/>
<fsummary>Upgrades a <c>gen_tcp</c>, or
equivalent, connected socket to an TLS socket.</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>SslOptions = [{handshake, hello| full} | ssl_option()]</v>
- <v>Timeout = integer() | infinity</v>
- <v>SslSocket = sslsocket()</v>
- <v>Ext = hello_extensions()</v>
- <v>Reason = term()</v>
- </type>
<desc><p>Upgrades a <c>gen_tcp</c>, or equivalent,
connected socket to an TLS socket, that is, performs the
client-side TLS handshake.</p>
- <note><p>If the option <c>verify</c> is set to <c>verify_peer</c>
- the option <c>server_name_indication</c> shall also be specified,
- if it is not no Server Name Indication extension will be sent,
- and <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>
- will be called with the IP-address of the connection as <c>ReferenceID</c>, which is proably not what you want.</p>
+ <note><p>If the option <c>verify</c> is set to
+ <c>verify_peer</c> the option <c>server_name_indication</c>
+ shall also be specified, if it is not no Server Name
+ Indication extension will be sent, and <seealso
+ marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>
+ will be called with the IP-address of the connection as
+ <c>ReferenceID</c>, which is proably not what you want.</p>
</note>
<p> If the option <c>{handshake, hello}</c> is used the
handshake is paused after receiving the server hello message
and the success response is <c>{ok, SslSocket, Ext}</c>
- instead of <c>{ok, SslSocket}</c>. Thereafter the handshake is continued or
- canceled by calling <seealso marker="#handshake_continue-3">
+ instead of <c>{ok, SslSocket}</c>. Thereafter the handshake
+ is continued or canceled by calling <seealso
+ marker="#handshake_continue-3">
<c>handshake_continue/3</c></seealso> or <seealso
- marker="#handshake_cancel-1"><c>handshake_cancel/1</c></seealso>.
+ marker="#handshake_cancel-1"><c>handshake_cancel/1</c></seealso>.
</p>
+ <p> If the option <c>active</c> is set to <c>once</c>, <c>true</c> or an integer value,
+ the process owning the sslsocket will receive messages of type
+ <seealso marker="#type-active_msgs"> active_msgs() </seealso>
+ </p>
</desc>
</func>
<func>
- <name>connect(Host, Port, Options) -></name>
- <name>connect(Host, Port, Options, Timeout) ->
- {ok, SslSocket}| {ok, SslSocket, Ext} | {error, Reason}</name>
+ <name since="" name="connect" arity="3" clause_i="2"/>
+ <name since="" name="connect" arity="4"/>
<fsummary>Opens an TLS/DTLS connection to <c>Host</c>, <c>Port</c>.</fsummary>
- <type>
- <v>Host = host()</v>
- <v>Port = integer()</v>
- <v>Options = [option()]</v>
- <v>Timeout = integer() | infinity</v>
- <v>SslSocket = sslsocket()</v>
- <v>Reason = term()</v>
- </type>
<desc><p>Opens an TLS/DTLS connection to <c>Host</c>, <c>Port</c>.</p>
<p> When the option <c>verify</c> is set to <c>verify_peer</c> the check
<seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>
will be performed in addition to the usual x509-path validation checks. If the check fails the error {bad_cert, hostname_check_failed} will
- be propagated to the path validation fun <seealso marker="#verify_fun">verify_fun</seealso>, where it is possible to do customized
+ be propagated to the path validation fun <seealso marker="#type-custom_verify">verify_fun</seealso>, where it is possible to do customized
checks by using the full possibilities of the <seealso marker="public_key:public_key#pkix_verify_hostname-3">public_key:pkix_verify_hostname/3</seealso> API.
When the option <c>server_name_indication</c> is provided, its value (the DNS name) will be used as <c>ReferenceID</c>
@@ -1014,28 +1181,24 @@ fun(srp, Username :: string(), UserState :: term()) ->
<c>handshake_continue/3</c></seealso> or <seealso
marker="#handshake_cancel-1"><c>handshake_cancel/1</c></seealso>.
</p>
+
+ <p> If the option <c>active</c> is set to <c>once</c>, <c>true</c> or an integer value,
+ the process owning the sslsocket will receive messages of type
+ <seealso marker="#type-active_msgs"> active_msgs() </seealso>
+ </p>
</desc>
</func>
<func>
- <name>close(SslSocket) -> ok | {error, Reason}</name>
+ <name since="" name="close" arity="1" />
<fsummary>Closes an TLS/DTLS connection.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Reason = term()</v>
- </type>
<desc><p>Closes an TLS/DTLS connection.</p>
</desc>
</func>
<func>
- <name>close(SslSocket, How) -> ok | {ok, port()} | {error, Reason}</name>
+ <name since="OTP 18.1" name="close" arity="2"/>
<fsummary>Closes an TLS connection.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>How = timeout() | {NewController::pid(), timeout()} </v>
- <v>Reason = term()</v>
- </type>
<desc><p>Closes or downgrades an TLS connection. In the latter case the transport
connection will be handed over to the <c>NewController</c> process after receiving
the TLS close alert from the peer. The returned transport socket will have
@@ -1044,15 +1207,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>controlling_process(SslSocket, NewOwner) ->
- ok | {error, Reason}</name>
+ <name since="" name="controlling_process" arity="2" />
<fsummary>Assigns a new controlling process to the
TLS/DTLS socket.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>NewOwner = pid()</v>
- <v>Reason = term()</v>
- </type>
<desc><p>Assigns a new controlling process to the SSL socket. A
controlling process is the owner of an SSL socket, and receives
all messages from the socket.</p>
@@ -1060,52 +1217,36 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>connection_information(SslSocket) ->
- {ok, Result} | {error, Reason} </name>
+ <name since="OTP 18.0" name="connection_information" arity="1"/>
<fsummary>Returns all the connection information.
</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Item = protocol | cipher_suite | sni_hostname | ecc | session_id | atom()</v>
- <d>Meaningful atoms, not specified above, are the ssl option names.</d>
- <v>Result = [{Item::atom(), Value::term()}]</v>
- <v>Reason = term()</v>
- </type>
<desc><p>Returns the most relevant information about the connection, ssl options that
are undefined will be filtered out. Note that values that affect the security of the
connection will only be returned if explicitly requested by connection_information/2.</p>
+ <note><p>The legacy <c>Item = cipher_suite</c> is still supported
+ and returns the cipher suite on its (undocumented) legacy format.
+ It should be replaced by <c>selected_cipher_suite</c>.</p></note>
</desc>
</func>
<func>
- <name>connection_information(SslSocket, Items) ->
- {ok, Result} | {error, Reason} </name>
+ <name since="OTP 18.0" name="connection_information" arity="2"/>
<fsummary>Returns the requested connection information.
</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Items = [Item]</v>
- <v>Item = protocol | cipher_suite | sni_hostname | ecc | session_id | client_random
- | server_random | master_secret | atom()</v>
- <d>Note that client_random, server_random and master_secret are values
- that affect the security of connection. Meaningful atoms, not specified above, are the ssl option names.</d>
- <v>Result = [{Item::atom(), Value::term()}]</v>
- <v>Reason = term()</v>
- </type>
<desc><p>Returns the requested information items about the connection,
if they are defined.</p>
+ <p>Note that client_random, server_random and master_secret are values
+ that affect the security of connection. Meaningful atoms, not specified
+ above, are the ssl option names.</p>
+
<note><p>If only undefined options are requested the
resulting list can be empty.</p></note>
</desc>
</func>
<func>
- <name>filter_cipher_suites(Suites, Filters) -> ciphers()</name>
+ <name since="OTP 20.3" name="filter_cipher_suites" arity="2" />
<fsummary></fsummary>
- <type>
- <v> Suites = ciphers()</v>
- <v> Filters = cipher_filters()</v>
- </type>
<desc><p>Removes cipher suites if any of the filter functions
returns false for any part of the cipher suite. This function
also calls default filter functions to make sure the cipher
@@ -1115,24 +1256,16 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>format_error(Reason) -> string()</name>
+ <name since="" name="format_error" arity="1" />
<fsummary>Returns an error string.</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Presents the error returned by an SSL function as a printable string.</p>
</desc>
</func>
<func>
- <name>getopts(SslSocket, OptionNames) ->
- {ok, [socketoption()]} | {error, Reason}</name>
+ <name since="" name="getopts" arity="2" />
<fsummary>Gets the values of the specified options.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>OptionNames = [atom()]</v>
- </type>
<desc>
<p>Gets the values of the specified socket options.
</p>
@@ -1140,16 +1273,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>getstat(SslSocket) ->
- {ok, OptionValues} | {error, inet:posix()}</name>
- <name>getstat(SslSocket, OptionNames) ->
- {ok, OptionValues} | {error, inet:posix()}</name>
+ <name since="OTP 19.0" name="getstat" arity="1" />
+ <name since="OTP 19.0" name="getstat" arity="2" />
<fsummary>Get one or more statistic options for a socket</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>OptionNames = [atom()]</v>
- <v>OptionValues = [{inet:stat_option(), integer()}]</v>
- </type>
<desc>
<p>Gets one or more statistic options for the underlying TCP socket.</p>
<p>See inet:getstat/2 for statistic options description.</p>
@@ -1157,32 +1283,24 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>handshake(HsSocket) -> </name>
- <name>handshake(HsSocket, Timeout) -> {ok, SslSocket} | {error, Reason}</name>
+ <name since="OTP 21.0" name="handshake" arity="1" />
+ <name since="OTP 21.0" name="handshake" arity="2" clause_i="1" />
<fsummary>Performs server-side SSL/TLS handshake.</fsummary>
- <type>
- <v>HsSocket = SslSocket = sslsocket()</v>
- <v>Timeout = integer()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Performs the SSL/TLS/DTLS server-side handshake.</p>
<p>Returns a new TLS/DTLS socket if the handshake is successful.</p>
+
+ <p> If the option <c>active</c> is set to <c>once</c>, <c>true</c> or an integer value,
+ the process owning the sslsocket will receive messages of type
+ <seealso marker="#type-active_msgs"> active_msgs() </seealso>
+ </p>
</desc>
</func>
<func>
- <name>handshake(Socket, SslOptions) -> </name>
- <name>handshake(Socket, SslOptions, Timeout) -> {ok, SslSocket} | {ok, SslSocket, Ext} | {error, Reason}</name>
+ <name since="OTP 21.0" name="handshake" arity="2" clause_i="2" />
+ <name since="OTP 21.0" name="handshake" arity="3" />
<fsummary>Performs server-side SSL/TLS/DTLS handshake.</fsummary>
- <type>
- <v>Socket = socket() | sslsocket() </v>
- <v>SslSocket = sslsocket() </v>
- <v>Ext = hello_extensions()</v>
- <v>SslOptions = [{handshake, hello| full} | ssl_option()]</v>
- <v>Timeout = integer()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>If <c>Socket</c> is a ordinary <c>socket()</c>: upgrades a <c>gen_tcp</c>,
or equivalent, socket to an SSL socket, that is, performs
@@ -1193,7 +1311,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
is undefined.
</p></warning>
- <p>If <c>Socket</c> is an <c>sslsocket()</c>: provides extra SSL/TLS/DTLS
+ <p>If <c>Socket</c> is an
+ <seealso marker="#type-sslsocket"> sslsocket() </seealso>: provides extra SSL/TLS/DTLS
options to those specified in
<seealso marker="#listen-2">listen/2 </seealso> and then performs
the SSL/TLS/DTLS handshake. Returns a new TLS/DTLS socket if the handshake is successful.</p>
@@ -1207,56 +1326,43 @@ fun(srp, Username :: string(), UserState :: term()) ->
<c>handshake_continue/3</c></seealso> or <seealso
marker="#handshake_cancel-1"><c>handshake_cancel/1</c></seealso>.
</p>
+
+ <p> If the option <c>active</c> is set to <c>once</c>, <c>true</c> or an integer value,
+ the process owning the sslsocket will receive messages of type
+ <seealso marker="#type-active_msgs"> active_msgs() </seealso>
+ </p>
+
</desc>
</func>
<func>
- <name>handshake_cancel(SslSocket) -> ok </name>
+ <name since="OTP 21.0" name="handshake_cancel" arity="1" />
<fsummary>Cancel handshake with a fatal alert</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- </type>
<desc>
<p>Cancel the handshake with a fatal <c>USER_CANCELED</c> alert.</p>
</desc>
</func>
<func>
- <name>handshake_continue(HsSocket, SSLOptions) -> {ok, SslSocket} | {error, Reason}</name>
- <name>handshake_continue(HsSocket, SSLOptions, Timeout) -> {ok, SslSocket} | {error, Reason}</name>
+ <name since="OTP 21.0" name="handshake_continue" arity="2" />
+ <name since="OTP 21.0" name="handshake_continue" arity="3" />
<fsummary>Continue the SSL/TLS handshake.</fsummary>
- <type>
- <v>HsSocket = SslSocket = sslsocket()</v>
- <v>SslOptions = [ssl_option()]</v>
- <v>Timeout = integer()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Continue the SSL/TLS handshake possiby with new, additional or changed options.</p>
</desc>
</func>
<func>
- <name>listen(Port, Options) ->
- {ok, ListenSocket} | {error, Reason}</name>
+ <name since="" name="listen" arity="2" />
<fsummary>Creates an SSL listen socket.</fsummary>
- <type>
- <v>Port = integer()</v>
- <v>Options = options()</v>
- <v>ListenSocket = sslsocket()</v>
- </type>
<desc>
<p>Creates an SSL listen socket.</p>
</desc>
</func>
<func>
- <name>negotiated_protocol(SslSocket) -> {ok, Protocol} | {error, protocol_not_negotiated}</name>
+ <name since="OTP 18.0" name="negotiated_protocol" arity="1" />
<fsummary>Returns the protocol negotiated through ALPN or NPN extensions.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Protocol = binary()</v>
- </type>
<desc>
<p>
Returns the protocol negotiated through ALPN or NPN extensions.
@@ -1265,12 +1371,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>peercert(SslSocket) -> {ok, Cert} | {error, Reason}</name>
+ <name since="" name="peercert" arity="1" />
<fsummary>Returns the peer certificate.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Cert = binary()</v>
- </type>
<desc>
<p>The peer certificate is returned as a DER-encoded binary.
The certificate can be decoded with
@@ -1280,26 +1382,16 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>peername(SslSocket) -> {ok, {Address, Port}} |
- {error, Reason}</name>
+ <name since="" name="peername" arity="1" />
<fsummary>Returns the peer address and port.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Address = ipaddress()</v>
- <v>Port = integer()</v>
- </type>
<desc>
<p>Returns the address and port number of the peer.</p>
</desc>
</func>
<func>
- <name>prepend_cipher_suites(Preferred, Suites) -> ciphers()</name>
+ <name since="OTP 20.3" name="prepend_cipher_suites" arity="2" />
<fsummary></fsummary>
- <type>
- <v>Preferred = ciphers() | cipher_filters() </v>
- <v>Suites = ciphers() </v>
- </type>
<desc><p>Make <c>Preferred</c> suites become the most preferred
suites that is put them at the head of the cipher suite list
<c>Suites</c> after removing them from <c>Suites</c> if
@@ -1310,15 +1402,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>prf(Socket, Secret, Label, Seed, WantedLength) -> {ok, binary()} | {error, reason()}</name>
+ <name since="OTP R15B01" name="prf" arity="5" />
<fsummary>Uses a session Pseudo-Random Function to generate key material.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Secret = binary() | master_secret</v>
- <v>Label = binary()</v>
- <v>Seed = [binary() | prf_random()]</v>
- <v>WantedLength = non_neg_integer()</v>
- </type>
<desc>
<p>Uses the Pseudo-Random Function (PRF) of a TLS session to generate
extra key material. It either takes user-generated values for
@@ -1330,16 +1415,14 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>recv(SslSocket, Length) -> </name>
- <name>recv(SslSocket, Length, Timeout) -> {ok, Data} | {error,
- Reason}</name>
+ <name since="" name="recv" arity="2" />
+ <name since="" name="recv" arity="3" />
<fsummary>Receives data on a socket.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Length = integer()</v>
- <v>Timeout = integer()</v>
- <v>Data = [char()] | binary()</v>
- </type>
+ <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 ERTS.
+ </type_desc>
<desc>
<p>Receives a packet from a socket in passive
mode. A closed socket is indicated by return value
@@ -1357,11 +1440,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>renegotiate(SslSocket) -> ok | {error, Reason}</name>
+ <name since="OTP R14B" name="renegotiate" arity="1" />
<fsummary>Initiates a new handshake.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- </type>
<desc><p>Initiates a new handshake. A notable return value is
<c>{error, renegotiation_rejected}</c> indicating that the peer
refused to go through with the renegotiation, but the connection
@@ -1370,40 +1450,27 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>send(SslSocket, Data) -> ok | {error, Reason}</name>
+ <name since="" name="send" arity="2" />
<fsummary>Writes data to a socket.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Data = iodata()</v>
- </type>
<desc>
- <p>Writes <c>Data</c> to <c>Socket</c>.</p>
+ <p>Writes <c>Data</c> to <c>SslSocket</c>.</p>
<p>A notable return value is <c>{error, closed}</c> indicating that
the socket is closed.</p>
</desc>
</func>
<func>
- <name>setopts(SslSocket, Options) -> ok | {error, Reason}</name>
+ <name since="" name="setopts" arity="2" />
<fsummary>Sets socket options.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Options = [socketoption]()</v>
- </type>
<desc>
<p>Sets options according to <c>Options</c> for socket
- <c>Socket</c>.</p>
+ <c>SslSocket</c>.</p>
</desc>
</func>
<func>
- <name>shutdown(SslSocket, How) -> ok | {error, Reason}</name>
+ <name since="OTP R14B" name="shutdown" arity="2" />
<fsummary>Immediately closes a socket.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>How = read | write | read_write</v>
- <v>Reason = reason()</v>
- </type>
<desc>
<p>Immediately closes a socket in one or two directions.</p>
<p><c>How == write</c> means closing the socket for writing,
@@ -1415,14 +1482,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>ssl_accept(SslSocket) -> </name>
- <name>ssl_accept(SslSocket, Timeout) -> ok | {error, Reason}</name>
+ <name since="" name="ssl_accept" arity="1" />
+ <name since="" name="ssl_accept" arity="2" />
<fsummary>Performs server-side SSL/TLS handshake.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Timeout = integer()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Deprecated in OTP 21, use <seealso marker="#handshake-1">handshake/[1,2]</seealso> instead.</p>
<note><p>handshake/[1,2] always returns a new socket.</p></note>
@@ -1430,15 +1492,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>ssl_accept(Socket, SslOptions) -> </name>
- <name>ssl_accept(Socket, SslOptions, Timeout) -> {ok, Socket} | ok | {error, Reason}</name>
+ <name since="OTP R14B" name="ssl_accept" arity="3" />
<fsummary>Performs server-side SSL/TLS/DTLS handshake.</fsummary>
- <type>
- <v>Socket = socket() | sslsocket() </v>
- <v>SslOptions = [ssl_option()]</v>
- <v>Timeout = integer()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Deprecated in OTP 21, use <seealso marker="#handshake-3">handshake/[2,3]</seealso> instead.</p>
<note><p>handshake/[2,3] always returns a new socket.</p></note>
@@ -1446,27 +1501,18 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>sockname(SslSocket) -> {ok, {Address, Port}} |
- {error, Reason}</name>
+ <name since="" name="sockname" arity="1" />
<fsummary>Returns the local address and port.</fsummary>
- <type>
- <v>SslSocket = sslsocket()</v>
- <v>Address = ipaddress()</v>
- <v>Port = integer()</v>
- </type>
<desc>
<p>Returns the local address and port number of socket
- <c>Socket</c>.</p>
+ <c>SslSocket</c>.</p>
</desc>
</func>
<func>
- <name>start() -> </name>
- <name>start(Type) -> ok | {error, Reason}</name>
+ <name since="OTP R14B" name="start" arity="0" />
+ <name since="OTP R14B">start(Type) -> ok | {error, Reason}</name>
<fsummary>Starts the SSL application.</fsummary>
- <type>
- <v>Type = permanent | transient | temporary</v>
- </type>
<desc>
<p>Starts the SSL application. Default type
is <c>temporary</c>.</p>
@@ -1474,7 +1520,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>stop() -> ok </name>
+ <name since="OTP R14B" name="stop" arity="0" />
<fsummary>Stops the SSL application.</fsummary>
<desc>
<p>Stops the SSL application.</p>
@@ -1482,28 +1528,18 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>suite_to_str(CipherSuite) -> String</name>
+ <name since="OTP 21.0" name="suite_to_str" arity="1" clause_i="1" />
<fsummary>Returns the string representation of a cipher suite.</fsummary>
- <type>
- <v>CipherSuite = erl_cipher_suite()</v>
- <v>String = string()</v>
- </type>
<desc>
<p>Returns the string representation of a cipher suite.</p>
</desc>
</func>
<func>
- <name>transport_accept(ListenSocket) -></name>
- <name>transport_accept(ListenSocket, Timeout) ->
- {ok, SslSocket} | {error, Reason}</name>
+ <name since="" name="transport_accept" arity="1" />
+ <name since="" name="transport_accept" arity="2" />
<fsummary>Accepts an incoming connection and
prepares for <c>ssl_accept</c>.</fsummary>
- <type>
- <v>ListenSocket = SslSocket = sslsocket()</v>
- <v>Timeout = integer()</v>
- <v>Reason = reason()</v>
- </type>
<desc>
<p>Accepts an incoming connection request on a listen socket.
<c>ListenSocket</c> must be a socket returned from
@@ -1513,9 +1549,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
to complete handshaking, that is,
establishing the SSL/TLS/DTLS connection.</p>
<warning>
- <p>The socket returned can only be used with
- <seealso marker="#handshake-2"> handshake/[2,3]</seealso>.
- No traffic can be sent or received before that call.</p>
+ <p>Most API functions require that the TLS/DTLS
+ connection is established to work as expected.
+ </p>
</warning>
<p>The accepted socket inherits the options set for
<c>ListenSocket</c> in
@@ -1529,13 +1565,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>versions() -> [versions_info()]</name>
+ <name since="OTP R14B" name="versions" arity="0" />
<fsummary>Returns version information relevant for the
SSL application.</fsummary>
- <type>
- <v>versions_info() = {app_vsn, string()} | {supported | available, [ssl_tls_protocol()]} |
- {supported_dtls | available_dtls, [dtls_protocol()]} </v>
- </type>
<desc>
<p>Returns version information relevant for the SSL
application.</p>
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml
index f6d9021d4a..893919aeb4 100644
--- a/lib/ssl/doc/src/ssl_app.xml
+++ b/lib/ssl/doc/src/ssl_app.xml
@@ -171,6 +171,20 @@
shutdown gracefully. Defaults to 5000 milliseconds.
</p>
</item>
+
+ <tag><c><![CDATA[internal_active_n = integer() <optional>]]></c></tag>
+ <item>
+ <p>
+ For TLS connections this value is used to handle the
+ internal socket. As the implementation was changed from an
+ active once to an active N behavior (N = 100), for
+ performance reasons, this option exist for possible tweaking
+ or restoring of the old behavior (internal_active_n = 1) in
+ unforeseen scenarios. The option will not affect erlang
+ distribution over TLS that will always run in active N mode.
+ Added in ssl-9.1 (OTP-21.2).
+ </p>
+ </item>
</taglist>
</section>
diff --git a/lib/ssl/doc/src/ssl_crl_cache.xml b/lib/ssl/doc/src/ssl_crl_cache.xml
index 71c6d5e49e..a33aec62a7 100644
--- a/lib/ssl/doc/src/ssl_crl_cache.xml
+++ b/lib/ssl/doc/src/ssl_crl_cache.xml
@@ -24,7 +24,7 @@
<file>ssl_crl_cache.xml</file>
</header>
- <module>ssl_crl_cache</module>
+ <module since="OTP 18.0">ssl_crl_cache</module>
<modulesummary>CRL cache </modulesummary>
<description>
<p>
@@ -34,32 +34,43 @@
the following functions are available.
</p>
</description>
+
+ <datatypes>
+ <datatype_title>DATA TYPES</datatype_title>
+
+ <datatype>
+ <name name="crl_src"/>
+ </datatype>
+
+ <datatype>
+ <name name="uri"/>
+ </datatype>
+
+ </datatypes>
<funcs>
<func>
- <name>delete(Entries) -> ok | {error, Reason} </name>
+ <name since="OTP 18.0">delete(Entries) -> ok | {error, Reason} </name>
<fsummary> </fsummary>
<type>
- <v> Entries = <seealso marker="stdlib:uri_string">uri_string:uri_string()</seealso> | {file, string()} | {der, [<seealso
- marker="public_key:public_key"> public_key:der_encoded() </seealso>]}</v>
- <v> Reason = term()</v>
+ <v> Entries = <seealso marker="#type-crl_src">crl_src()</seealso>]}</v>
+ <v> Reason = crl_reason()</v>
</type>
<desc>
<p>Delete CRLs from the ssl applications local cache. </p>
</desc>
</func>
<func>
- <name>insert(CRLSrc) -> ok | {error, Reason}</name>
- <name>insert(URI, CRLSrc) -> ok | {error, Reason}</name>
+ <name since="OTP 18.0">insert(CRLSrc) -> ok | {error, Reason}</name>
+ <name since="OTP 18.0">insert(URI, CRLSrc) -> ok | {error, Reason}</name>
<fsummary> </fsummary>
<type>
- <v> CRLSrc = {file, string()} | {der, [ <seealso
- marker="public_key:public_key"> public_key:der_encoded() </seealso> ]}</v>
- <v> URI = <seealso marker="stdlib:uri_string">uri_string:uri_string() </seealso> </v>
+ <v> CRLSrc = <seealso marker="#type-crl_src">crl_src()</seealso>]}</v>
+ <v> URI = <seealso marker="#type-uri">uri()</seealso> </v>
<v> Reason = term()</v>
</type>
<desc>
- <p>Insert CRLs into the ssl applications local cache. </p>
+ <p>Insert CRLs, available to fetch on DER format from <c>URI</c>, into the ssl applications local cache. </p>
</desc>
</func>
</funcs>
diff --git a/lib/ssl/doc/src/ssl_crl_cache_api.xml b/lib/ssl/doc/src/ssl_crl_cache_api.xml
index c6774b4df6..4cba4e1de1 100644
--- a/lib/ssl/doc/src/ssl_crl_cache_api.xml
+++ b/lib/ssl/doc/src/ssl_crl_cache_api.xml
@@ -24,7 +24,7 @@
<file>ssl_crl_cache_api.xml</file>
</header>
- <module>ssl_crl_cache_api</module>
+ <module since="OTP 18.0">ssl_crl_cache_api</module>
<modulesummary>API for a SSL/TLS CRL (Certificate Revocation List) cache.</modulesummary>
<description>
<p>
@@ -39,35 +39,44 @@
a CRL cache.
</p>
</description>
-
- <section>
- <title>DATA TYPES</title>
-
- <p>The following data types are used in the functions below:
- </p>
-
- <taglist>
-
- <tag><c>cache_ref() =</c></tag>
- <item>opaque()</item>
- <tag><c>dist_point() =</c></tag>
- <item><p>#'DistributionPoint'{} see <seealso
- marker="public_key:public_key_records"> X509 certificates records</seealso></p></item>
-
- </taglist>
+
+
+ <!--
+ ================================================================
+ = Data types =
+ ================================================================
+ -->
+
+ <datatypes>
- </section>
+ <datatype>
+ <name name="crl_cache_ref"/>
+ <desc>
+ <p>Reference to the CRL cache.</p>
+ </desc>
+ </datatype>
+
+
+ <datatype>
+ <name name="dist_point"/>
+ <desc>
+ <p>For description see <seealso
+ marker="public_key:public_key_records"> X509 certificates records</seealso></p>
+ </desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>fresh_crl(DistributionPoint, CRL) -> FreshCRL</name>
+ <name since="OTP 18.0">fresh_crl(DistributionPoint, CRL) -> FreshCRL</name>
<fsummary> <c>fun fresh_crl/2 </c> will be used as input option <c>update_crl</c> to
public_key:pkix_crls_validate/3 </fsummary>
<type>
- <v> DistributionPoint = dist_point() </v>
+ <v> DistributionPoint = <seealso marker="#type-dist_point"> dist_point() </seealso> </v>
<v> CRL = [<seealso
- marker="public_key:public_key">public_key:der_encoded()</seealso>] </v>
+ marker="public_key:public_key#type-der_encoded">public_key:der_encoded()</seealso>] </v>
<v> FreshCRL = [<seealso
- marker="public_key:public_key">public_key:der_encoded()</seealso>] </v>
+ marker="public_key:public_key#type-der_encoded">public_key:der_encoded()</seealso>] </v>
</type>
<desc>
<p> <c>fun fresh_crl/2 </c> will be used as input option <c>update_crl</c> to
@@ -76,16 +85,16 @@
</func>
<func>
- <name>lookup(DistributionPoint, Issuer, DbHandle) -> not_available | CRLs </name>
- <name>lookup(DistributionPoint, DbHandle) -> not_available | CRLs </name>
+ <name since="OTP 19.0">lookup(DistributionPoint, Issuer, DbHandle) -> not_available | CRLs </name>
+ <name since="OTP 18.0">lookup(DistributionPoint, DbHandle) -> not_available | CRLs </name>
<fsummary> </fsummary>
<type>
- <v> DistributionPoint = dist_point() </v>
+ <v> DistributionPoint = <seealso marker="#type-dist_point"> dist_point() </seealso> </v>
<v> Issuer = <seealso
- marker="public_key:public_key">public_key:issuer_name()</seealso> </v>
- <v> DbHandle = cache_ref() </v>
+ marker="public_key:public_key#type-issuer_name">public_key:issuer_name()</seealso> </v>
+ <v> DbHandle = <seealso marker="#type-crl_cache_ref"> crl_cache_ref() </seealso></v>
<v> CRLs = [<seealso
- marker="public_key:public_key">public_key:der_encoded()</seealso>] </v>
+ marker="public_key:public_key#type-der_encoded">public_key:der_encoded()</seealso>] </v>
</type>
<desc> <p>Lookup the CRLs belonging to the distribution point <c> Distributionpoint</c>.
This function may choose to only look in the cache or to follow distribution point
@@ -106,12 +115,12 @@
</func>
<func>
- <name>select(Issuer, DbHandle) -> CRLs </name>
+ <name since="OTP 18.0">select(Issuer, DbHandle) -> CRLs </name>
<fsummary>Select the CRLs in the cache that are issued by <c>Issuer</c></fsummary>
<type>
<v> Issuer = <seealso
- marker="public_key:public_key">public_key:issuer_name()</seealso></v>
- <v> DbHandle = cache_ref() </v>
+ marker="public_key:public_key#type-issuer_name">public_key:issuer_name()</seealso></v>
+ <v> DbHandle = <seealso marker="#type-crl_cache_ref"> cache_ref() </seealso></v>
</type>
<desc>
<p>Select the CRLs in the cache that are issued by <c>Issuer</c> </p>
diff --git a/lib/ssl/doc/src/ssl_session_cache_api.xml b/lib/ssl/doc/src/ssl_session_cache_api.xml
index a84a3dfce9..e841729e57 100644
--- a/lib/ssl/doc/src/ssl_session_cache_api.xml
+++ b/lib/ssl/doc/src/ssl_session_cache_api.xml
@@ -28,7 +28,7 @@
<rev></rev>
<file>ssl_session_cache_api.xml</file>
</header>
- <module>ssl_session_cache_api</module>
+ <module since="OTP R14B">ssl_session_cache_api</module>
<modulesummary>TLS session cache API</modulesummary>
<description>
@@ -38,39 +38,50 @@
defining a new callback module implementing this API.
</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <p>The following data types are used in the functions for
- <c>ssl_session_cache_api</c>:</p>
-
- <taglist>
- <tag><c>cache_ref() =</c></tag>
- <item><p><c>opaque()</c></p></item>
-
- <tag><c>key() =</c></tag>
- <item><p><c>{partialkey(), session_id()}</c></p></item>
-
- <tag><c>partialkey() =</c></tag>
- <item><p><c>opaque()</c></p></item>
-
- <tag><c>session_id() =</c></tag>
- <item><p><c>binary()</c></p></item>
-
- <tag><c>session()</c> =</tag>
- <item><p><c>opaque()</c></p></item>
- </taglist>
-
- </section>
+ <!--
+ ================================================================
+ = Data types =
+ ================================================================
+ -->
+
+ <datatypes>
+
+ <datatype>
+ <name name="session_cache_ref"/>
+ </datatype>
+
+ <datatype>
+ <name name="session_cache_key"/>
+ <desc>
+ <p>A key to an entry in the session cache.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="partial_key"/>
+ <desc>
+ <p>The opaque part of the key. Does not need to be handled
+ by the callback.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="session"/>
+ <desc>
+ <p>The session data that is stored for each session.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>delete(Cache, Key) -> _</name>
+ <name since="OTP R14B">delete(Cache, Key) -> _</name>
<fsummary>Deletes a cache entry.</fsummary>
<type>
- <v>Cache = cache_ref()</v>
- <v>Key = key()</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
+ <v>Key = <seealso marker="#type-session_cache_key">session_cache_key() </seealso> </v>
</type>
<desc>
<p>Deletes a cache entry. Is only called from the cache
@@ -80,10 +91,12 @@
</func>
<func>
- <name>foldl(Fun, Acc0, Cache) -> Acc</name>
+ <name since="OTP R14B">foldl(Fun, Acc0, Cache) -> Acc</name>
<fsummary></fsummary>
<type>
- <v></v>
+ <v>Fun = fun()</v>
+ <v>Acc0 = Acc = term()</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
</type>
<desc>
<p>Calls <c>Fun(Elem, AccIn)</c> on successive elements of the
@@ -96,10 +109,11 @@
</func>
<func>
- <name>init(Args) -> opaque() </name>
+ <name since="OTP 18.0">init(Args) -> Cache </name>
<fsummary>Returns cache reference.</fsummary>
<type>
- <v>Args = proplists:proplist()</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
+ <v>Args = <seealso marker="stdlib:proplists#type-proplist">proplists:proplist()</seealso></v>
</type>
<desc>
<p>Includes property <c>{role, client | server}</c>.
@@ -121,12 +135,12 @@
</func>
<func>
- <name>lookup(Cache, Key) -> Entry</name>
+ <name since="OTP R14B">lookup(Cache, Key) -> Entry</name>
<fsummary>Looks up a cache entry.</fsummary>
<type>
- <v>Cache = cache_ref()</v>
- <v>Key = key()</v>
- <v>Entry = session() | undefined</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
+ <v>Key = <seealso marker="#type-session_cache_key">session_cache_key()</seealso> </v>
+ <v>Session = <seealso marker="#type-session">session()</seealso> | undefined</v>
</type>
<desc>
<p>Looks up a cache entry. Is to be callable from any
@@ -136,12 +150,12 @@
</func>
<func>
- <name>select_session(Cache, PartialKey) -> [session()]</name>
+ <name since="OTP R14B">select_session(Cache, PartialKey) -> [Session]</name>
<fsummary>Selects sessions that can be reused.</fsummary>
<type>
- <v>Cache = cache_ref()</v>
- <v>PartialKey = partialkey()</v>
- <v>Session = session()</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
+ <v>PartialKey = <seealso marker="#type-partial_key"> partial_key() </seealso></v>
+ <v>Session = <seealso marker="#type-session">session()</seealso></v>
</type>
<desc>
<p>Selects sessions that can be reused. Is to be callable
@@ -151,10 +165,10 @@
</func>
<func>
- <name>size(Cache) -> integer()</name>
+ <name since="OTP 19.3">size(Cache) -> integer()</name>
<fsummary>Returns the number of sessions in the cache.</fsummary>
<type>
- <v>Cache = cache_ref()</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
</type>
<desc>
<p>Returns the number of sessions in the cache. If size
@@ -166,11 +180,12 @@
</func>
<func>
- <name>terminate(Cache) -> _</name>
+ <name since="OTP R14B">terminate(Cache) -> _</name>
<fsummary>Called by the process that handles the cache when it
is about to terminate.</fsummary>
<type>
- <v>Cache = term() - as returned by init/0</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
+ <d>As returned by init/0</d>
</type>
<desc>
<p>Takes care of possible cleanup that is needed when the
@@ -180,12 +195,12 @@
</func>
<func>
- <name>update(Cache, Key, Session) -> _</name>
+ <name since="OTP R14B">update(Cache, Key, Session) -> _</name>
<fsummary>Caches a new session or updates an already cached one.</fsummary>
<type>
- <v>Cache = cache_ref()</v>
- <v>Key = key()</v>
- <v>Session = session()</v>
+ <v>Cache = <seealso marker="#type-session_cache_ref"> session_cache_ref() </seealso></v>
+ <v>Key = <seealso marker="#type-session_cache_key">session_cache_key()</seealso> </v>
+ <v>Session = <seealso marker="#type-session">session()</seealso></v>
</type>
<desc>
<p>Caches a new session or updates an already cached one. Is
diff --git a/lib/ssl/examples/src/client_server.erl b/lib/ssl/examples/src/client_server.erl
index c150f43bff..8d68da12d5 100644
--- a/lib/ssl/examples/src/client_server.erl
+++ b/lib/ssl/examples/src/client_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,15 +39,15 @@ start() ->
%% Accept
{ok, ASock} = ssl:transport_accept(LSock),
- ok = ssl:ssl_accept(ASock),
+ {ok, SslSocket} = ssl:handshake(ASock),
io:fwrite("Accept: accepted.~n"),
- {ok, Cert} = ssl:peercert(ASock),
+ {ok, Cert} = ssl:peercert(SslSocket),
io:fwrite("Accept: peer cert:~n~p~n", [public_key:pkix_decode_cert(Cert, otp)]),
io:fwrite("Accept: sending \"hello\".~n"),
- ssl:send(ASock, "hello"),
- {error, closed} = ssl:recv(ASock, 0),
+ ssl:send(SslSocket, "hello"),
+ {error, closed} = ssl:recv(SslSocket, 0),
io:fwrite("Accept: detected closed.~n"),
- ssl:close(ASock),
+ ssl:close(SslSocket),
io:fwrite("Listen: closing and terminating.~n"),
ssl:close(LSock),
@@ -75,7 +75,7 @@ mk_opts(Role) ->
[{active, false},
{verify, 2},
{depth, 2},
+ {server_name_indication, disable},
{cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
{certfile, filename:join([Dir, Role, "cert.pem"])},
{keyfile, filename:join([Dir, Role, "key.pem"])}].
-
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index ebcb511653..8d1341f594 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -44,8 +44,6 @@ BEHAVIOUR_MODULES= \
MODULES= \
ssl \
- tls \
- dtls \
ssl_alert \
ssl_app \
ssl_sup \
@@ -64,9 +62,11 @@ MODULES= \
ssl_certificate\
ssl_pkix_db\
ssl_cipher \
+ ssl_cipher_format \
ssl_srp_primes \
tls_connection \
dtls_connection \
+ tls_sender\
ssl_config \
ssl_connection \
tls_handshake \
diff --git a/lib/ssl/src/dtls.erl b/lib/ssl/src/dtls.erl
deleted file mode 100644
index cd705152a8..0000000000
--- a/lib/ssl/src/dtls.erl
+++ /dev/null
@@ -1,113 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : Reflect DTLS specific API options (fairly simple wrapper at the moment)
-%% First implementation will support DTLS connections only in a "TLS/TCP like way"
-
--module(dtls).
-
--include("ssl_api.hrl").
--include("ssl_internal.hrl").
-
--export([connect/2, connect/3, listen/2, accept/1, accept/2,
- handshake/1, handshake/2, handshake/3]).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Connect to a DTLS server.
-%%--------------------------------------------------------------------
-
--spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
- {error, reason()}.
-
-connect(Socket, Options) when is_port(Socket) ->
- connect(Socket, Options, infinity).
-
--spec connect(host() | port(), [connect_option()] | inet:port_number(),
- timeout() | list()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Socket, SslOptions, Timeout) when is_port(Socket) ->
- DTLSOpts = [{protocol, dtls} | SslOptions],
- ssl:connect(Socket, DTLSOpts, Timeout);
-connect(Host, Port, Options) ->
- connect(Host, Port, Options, infinity).
-
--spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Host, Port, Options, Timeout) ->
- DTLSOpts = [{protocol, dtls} | Options],
- ssl:connect(Host, Port, DTLSOpts, Timeout).
-
-%%--------------------------------------------------------------------
--spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
-
-%%
-%% Description: Creates an ssl listen socket.
-%%--------------------------------------------------------------------
-listen(Port, Options) ->
- DTLSOpts = [{protocol, dtls} | Options],
- ssl:listen(Port, DTLSOpts).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs transport accept on an ssl listen socket
-%%--------------------------------------------------------------------
--spec accept(#sslsocket{}) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(ListenSocket) ->
- accept(ListenSocket, infinity).
-
--spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(Socket, Timeout) ->
- ssl:transport_accept(Socket, Timeout).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs accept on an ssl listen socket. e.i. performs
-%% ssl handshake.
-%%--------------------------------------------------------------------
-
--spec handshake(#sslsocket{}) -> ok | {error, reason()}.
-
-handshake(ListenSocket) ->
- handshake(ListenSocket, infinity).
-
-
--spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(#sslsocket{} = Socket, Timeout) ->
- ssl:ssl_accept(Socket, Timeout);
-
-handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- handshake(ListenSocket, SslOptions, infinity).
-
-
--spec handshake(port(), [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(Socket, SslOptions, Timeout) when is_port(Socket) ->
- ssl:ssl_accept(Socket, SslOptions, Timeout).
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index 53b46542e7..721689da8b 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,22 +36,21 @@
%% Internal application API
%% Setup
--export([start_fsm/8, start_link/7, init/1]).
+-export([start_fsm/8, start_link/7, init/1, pids/1]).
%% State transition handling
--export([next_record/1, next_event/3, next_event/4, handle_common_event/4]).
+-export([next_event/3, next_event/4, handle_protocol_record/3]).
%% Handshake handling
-export([renegotiate/2, send_handshake/2,
queue_handshake/2, queue_change_cipher/2,
- reinit_handshake_data/1, select_sni_extension/1, empty_connection_state/2]).
+ reinit/1, reinit_handshake_data/1, select_sni_extension/1, empty_connection_state/2]).
%% Alert and close handling
--export([encode_alert/3,send_alert/2, close/5, protocol_name/0]).
+-export([encode_alert/3, send_alert/2, send_alert_in_connection/2, close/5, protocol_name/0]).
%% Data handling
--export([encode_data/3, passive_receive/2, next_record_if_active/1,
- send/3, socket/5, setopts/3, getopts/3]).
+-export([socket/4, setopts/3, getopts/3]).
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
@@ -72,7 +71,7 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker}
try
{ok, Pid} = dtls_connection_sup:start_child([Role, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid], CbModule, Tracker),
ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
@@ -80,7 +79,7 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker}
end.
%%--------------------------------------------------------------------
--spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
+-spec start_link(atom(), ssl:host(), inet:port_number(), port(), list(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, reason()}.
%%
%% Description: Creates a gen_statem process which calls Module:init/1 to
@@ -91,20 +90,27 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
process_flag(trap_exit, true),
- State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
try
State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
gen_statem:enter_loop(?MODULE, [], init, State)
catch
throw:Error ->
- gen_statem:enter_loop(?MODULE, [], error, {Error,State0})
+ EState = State0#state{protocol_specific = Map#{error => Error}},
+ gen_statem:enter_loop(?MODULE, [], error, EState)
end.
+
+pids(_) ->
+ [self()].
+
%%====================================================================
%% State transition handling
%%====================================================================
-next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
- {no_record, State#state{unprocessed_handshake_events = N-1}};
-
+next_record(#state{handshake_env =
+ #handshake_env{unprocessed_handshake_events = N} = HsEnv}
+ = State) when N > 0 ->
+ {no_record, State#state{handshake_env =
+ HsEnv#handshake_env{unprocessed_handshake_events = N-1}}};
next_record(#state{protocol_buffers =
#protocol_buffers{dtls_cipher_texts = [#ssl_tls{epoch = Epoch} = CT | Rest]}
= Buffers,
@@ -136,14 +142,14 @@ next_record(#state{protocol_buffers =
next_record(State#state{protocol_buffers =
Buffers#protocol_buffers{dtls_cipher_texts = Rest},
connection_states = ConnectionStates});
-next_record(#state{role = server,
- socket = {Listener, {Client, _}}} = State) ->
+next_record(#state{static_env = #static_env{role = server,
+ socket = {Listener, {Client, _}}}} = State) ->
dtls_packet_demux:active_once(Listener, Client, self()),
{no_record, State};
-next_record(#state{role = client,
- socket = {_Server, Socket} = DTLSSocket,
- close_tag = CloseTag,
- transport_cb = Transport} = State) ->
+next_record(#state{static_env = #static_env{role = client,
+ socket = {_Server, Socket} = DTLSSocket,
+ close_tag = CloseTag,
+ transport_cb = Transport}} = State) ->
case dtls_socket:setopts(Transport, Socket, [{active,once}]) of
ok ->
{no_record, State};
@@ -157,9 +163,9 @@ next_record(State) ->
next_event(StateName, Record, State) ->
next_event(StateName, Record, State, []).
-next_event(connection = StateName, no_record,
+next_event(StateName, no_record,
#state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
- case next_record_if_active(State0) of
+ case next_record(State0) of
{no_record, State} ->
ssl_connection:hibernate_after(StateName, State, Actions);
{#ssl_tls{epoch = CurrentEpoch,
@@ -173,21 +179,18 @@ next_event(connection = StateName, no_record,
{#ssl_tls{epoch = Epoch,
type = ?HANDSHAKE,
version = _Version}, State1} = _Record when Epoch == CurrentEpoch-1 ->
- {State2, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
- {NextRecord, State} = next_record(State2),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ {State, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
+ next_event(StateName, no_record, State, Actions ++ MoreActions);
%% From FLIGHT perspective CHANGE_CIPHER_SPEC is treated as a handshake
{#ssl_tls{epoch = Epoch,
type = ?CHANGE_CIPHER_SPEC,
version = _Version}, State1} = _Record when Epoch == CurrentEpoch-1 ->
- {State2, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
- {NextRecord, State} = next_record(State2),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ {State, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
+ next_event(StateName, no_record, State, Actions ++ MoreActions);
{#ssl_tls{epoch = _Epoch,
- version = _Version}, State1} ->
+ version = _Version}, State} ->
%% TODO maybe buffer later epoch
- {Record, State} = next_record(State1),
- next_event(StateName, Record, State, Actions);
+ next_event(StateName, no_record, State, Actions);
{#alert{} = Alert, State} ->
{next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
end;
@@ -205,24 +208,20 @@ next_event(connection = StateName, Record,
#ssl_tls{epoch = Epoch,
type = ?HANDSHAKE,
version = _Version} when Epoch == CurrentEpoch-1 ->
- {State1, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
- {NextRecord, State} = next_record(State1),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ {State, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
+ next_event(StateName, no_record, State, Actions ++ MoreActions);
%% From FLIGHT perspective CHANGE_CIPHER_SPEC is treated as a handshake
#ssl_tls{epoch = Epoch,
type = ?CHANGE_CIPHER_SPEC,
version = _Version} when Epoch == CurrentEpoch-1 ->
- {State1, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
- {NextRecord, State} = next_record(State1),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ {State, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
+ next_event(StateName, no_record, State, Actions ++ MoreActions);
_ ->
next_event(StateName, no_record, State0, Actions)
end;
next_event(StateName, Record,
#state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
case Record of
- no_record ->
- {next_state, StateName, State0, Actions};
#ssl_tls{epoch = CurrentEpoch,
version = Version} = Record ->
State = dtls_version(StateName, Version, State0),
@@ -231,44 +230,49 @@ next_event(StateName, Record,
#ssl_tls{epoch = _Epoch,
version = _Version} = _Record ->
%% TODO maybe buffer later epoch
- {Record, State} = next_record(State0),
- next_event(StateName, Record, State, Actions);
+ next_event(StateName, no_record, State0, Actions);
#alert{} = Alert ->
{next_state, StateName, State0, [{next_event, internal, Alert} | Actions]}
end.
-handle_common_event(internal, #alert{} = Alert, StateName,
- #state{negotiated_version = Version} = State) ->
- handle_own_alert(Alert, Version, StateName, State);
+%%% DTLS record protocol level application data messages
+
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName0, State0) ->
+ case ssl_connection:read_application_data(Data, State0) of
+ {stop, _, _} = Stop->
+ Stop;
+ {Record, State1} ->
+ {next_state, StateName, State, Actions} = next_event(StateName0, Record, State1),
+ ssl_connection:hibernate_after(StateName, State, Actions)
+ end;
%%% DTLS record protocol level handshake messages
-handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE,
+handle_protocol_record(#ssl_tls{type = ?HANDSHAKE,
fragment = Data},
StateName,
#state{protocol_buffers = Buffers0,
- negotiated_version = Version} = State0) ->
+ connection_env = #connection_env{negotiated_version = Version}} = State) ->
try
case dtls_handshake:get_dtls_handshake(Version, Data, Buffers0) of
{[], Buffers} ->
- {Record, State} = next_record(State0#state{protocol_buffers = Buffers}),
- next_event(StateName, Record, State);
+ next_event(StateName, no_record, State#state{protocol_buffers = Buffers});
{Packets, Buffers} ->
- State = State0#state{protocol_buffers = Buffers},
+ HsEnv = State#state.handshake_env,
Events = dtls_handshake_events(Packets),
{next_state, StateName,
- State#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
+ State#state{protocol_buffers = Buffers,
+ handshake_env =
+ HsEnv#handshake_env{unprocessed_handshake_events
+ = unprocessed_events(Events)}}, Events}
end
catch throw:#alert{} = Alert ->
- handle_own_alert(Alert, Version, StateName, State0)
+ handle_own_alert(Alert, Version, StateName, State)
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) ->
+handle_protocol_record(#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) ->
+handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
+ #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
case decode_alerts(EncAlerts) of
Alerts = [_|_] ->
handle_alerts(Alerts, {next_state, StateName, State});
@@ -276,32 +280,31 @@ handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, Sta
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}.
+handle_protocol_record(#ssl_tls{type = _Unknown}, StateName, State) ->
+ {next_state, StateName, State, []}.
%%====================================================================
%% Handshake handling
%%====================================================================
-renegotiate(#state{role = client} = State, Actions) ->
+renegotiate(#state{static_env = #static_env{role = client}} = State, Actions) ->
%% Handle same way as if server requested
%% the renegotiation
{next_state, connection, State,
[{next_event, internal, #hello_request{}} | Actions]};
-renegotiate(#state{role = server} = State0, Actions) ->
+renegotiate(#state{static_env = #static_env{role = server}} = State0, Actions) ->
HelloRequest = ssl_handshake:hello_request(),
State1 = prepare_flight(State0),
- {State2, MoreActions} = send_handshake(HelloRequest, State1),
- {Record, State} = next_record(State2),
- next_event(hello, Record, State, Actions ++ MoreActions).
+ {State, MoreActions} = send_handshake(HelloRequest, State1),
+ next_event(hello, no_record, State, Actions ++ MoreActions).
send_handshake(Handshake, #state{connection_states = ConnectionStates} = State) ->
#{epoch := Epoch} = ssl_record:current_connection_state(ConnectionStates, write),
send_handshake_flight(queue_handshake(Handshake, State), Epoch).
-queue_handshake(Handshake0, #state{tls_handshake_history = Hist0,
- negotiated_version = Version,
+queue_handshake(Handshake0, #state{handshake_env = #handshake_env{tls_handshake_history = Hist0} = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
flight_buffer = #{handshakes := HsBuffer0,
change_cipher_spec := undefined,
next_sequence := Seq} = Flight0} = State) ->
@@ -309,17 +312,17 @@ queue_handshake(Handshake0, #state{tls_handshake_history = Hist0,
Hist = update_handshake_history(Handshake0, Handshake, Hist0),
State#state{flight_buffer = Flight0#{handshakes => [Handshake | HsBuffer0],
next_sequence => Seq +1},
- tls_handshake_history = Hist};
+ handshake_env = HsEnv#handshake_env{tls_handshake_history = Hist}};
-queue_handshake(Handshake0, #state{tls_handshake_history = Hist0,
- negotiated_version = Version,
+queue_handshake(Handshake0, #state{handshake_env = #handshake_env{tls_handshake_history = Hist0} = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
flight_buffer = #{handshakes_after_change_cipher_spec := Buffer0,
next_sequence := Seq} = Flight0} = State) ->
Handshake = dtls_handshake:encode_handshake(Handshake0, Version, Seq),
Hist = update_handshake_history(Handshake0, Handshake, Hist0),
State#state{flight_buffer = Flight0#{handshakes_after_change_cipher_spec => [Handshake | Buffer0],
next_sequence => Seq +1},
- tls_handshake_history = Hist}.
+ handshake_env = HsEnv#handshake_env{tls_handshake_history = Hist}}.
queue_change_cipher(ChangeCipher, #state{flight_buffer = Flight,
connection_states = ConnectionStates0} = State) ->
@@ -327,11 +330,18 @@ queue_change_cipher(ChangeCipher, #state{flight_buffer = Flight,
dtls_record:next_epoch(ConnectionStates0, write),
State#state{flight_buffer = Flight#{change_cipher_spec => ChangeCipher},
connection_states = ConnectionStates}.
-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(),
- flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
+
+reinit(State) ->
+ %% To be API compatible with TLS NOOP here
+ reinit_handshake_data(State).
+reinit_handshake_data(#state{static_env = #static_env{data_tag = DataTag},
+ protocol_buffers = Buffers,
+ protocol_specific = PS,
+ handshake_env = HsEnv} = State) ->
+ State#state{handshake_env = HsEnv#handshake_env{tls_handshake_history = ssl_handshake:init_handshake_history(),
+ public_key_info = undefined,
+ premaster_secret = undefined},
+ protocol_specific = PS#{flight_state => initial_flight_state(DataTag)},
flight_buffer = new_flight(),
protocol_buffers =
Buffers#protocol_buffers{
@@ -355,15 +365,19 @@ empty_connection_state(ConnectionEnd, BeastMitigation) ->
encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
dtls_record:encode_alert_record(Alert, Version, ConnectionStates).
-send_alert(Alert, #state{negotiated_version = Version,
- socket = Socket,
- transport_cb = Transport,
+send_alert(Alert, #state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
+ connection_env = #connection_env{negotiated_version = Version},
connection_states = ConnectionStates0} = State0) ->
{BinMsg, ConnectionStates} =
encode_alert(Alert, Version, ConnectionStates0),
send(Transport, Socket, BinMsg),
State0#state{connection_states = ConnectionStates}.
+send_alert_in_connection(Alert, State) ->
+ _ = send_alert(Alert, State),
+ ok.
+
close(downgrade, _,_,_,_) ->
ok;
%% Other
@@ -377,33 +391,13 @@ protocol_name() ->
%% Data handling
%%====================================================================
-encode_data(Data, Version, ConnectionStates0)->
- dtls_record:encode_data(Data, Version, ConnectionStates0).
-
-passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
- case Buffer of
- <<>> ->
- {Record, State} = next_record(State0),
- next_event(StateName, Record, State);
- _ ->
- {Record, State} = ssl_connection:read_application_data(<<>>, State0),
- next_event(StateName, Record, State)
- end.
-next_record_if_active(State =
- #state{socket_options =
- #socket_options{active = false}}) ->
- {no_record ,State};
-
-next_record_if_active(State) ->
- next_record(State).
-
-send(Transport, {_, {{_,_}, _} = Socket}, Data) ->
- send(Transport, Socket, Data);
-send(Transport, Socket, Data) ->
- dtls_socket:send(Transport, Socket, Data).
+send(Transport, {Listener, Socket}, Data) when is_pid(Listener) -> % Server socket
+ dtls_socket:send(Transport, Socket, Data);
+send(Transport, Socket, Data) -> % Client socket
+ dtls_socket:send(Transport, Socket, Data).
-socket(Pid, Transport, Socket, Connection, _) ->
- dtls_socket:socket(Pid, Transport, Socket, Connection).
+socket(Pid, Transport, Socket, _Tracker) ->
+ dtls_socket:socket(Pid, Transport, Socket, ?MODULE).
setopts(Transport, Socket, Other) ->
dtls_socket:setopts(Transport, Socket, Other).
@@ -422,44 +416,39 @@ getopts(Transport, Socket, Tag) ->
init(enter, _, State) ->
{keep_state, State};
init({call, From}, {start, Timeout},
- #state{host = Host, port = Port, role = client,
+ #state{static_env = #static_env{host = Host,
+ port = Port,
+ role = client,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
+ connection_env = CEnv,
ssl_options = SslOpts,
session = #session{own_certificate = Cert} = Session0,
- connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _},
- session_cache = Cache,
- session_cache_cb = CacheCb
+ connection_states = ConnectionStates0
} = State0) ->
- Timer = ssl_connection:start_or_recv_cancel_timer(Timeout, From),
Hello = dtls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Cache, CacheCb, Renegotiation, Cert),
Version = Hello#client_hello.client_version,
HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions),
- State1 = prepare_flight(State0#state{negotiated_version = Version}),
- {State2, Actions} = send_handshake(Hello, State1#state{negotiated_version = HelloVersion}),
- State3 = State2#state{negotiated_version = Version, %% Requested version
+ State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}),
+ {State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}),
+ State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion
session =
Session0#session{session_id = Hello#client_hello.session_id},
- start_or_recv_from = From,
- timer = Timer,
- flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT}
- },
- {Record, State} = next_record(State3),
- next_event(hello, Record, State, Actions);
-init({call, _} = Type, Event, #state{role = server, data_tag = udp} = State) ->
+ start_or_recv_from = From},
+
+ next_event(hello, no_record, State, [{{timeout, handshake}, Timeout, close} | Actions]);
+init({call, _} = Type, Event, #state{static_env = #static_env{role = server},
+ protocol_specific = PS} = State) ->
Result = gen_handshake(?FUNCTION_NAME, Type, Event,
- State#state{flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
- protocol_specific = #{current_cookie_secret => dtls_v1:cookie_secret(),
- previous_cookie_secret => <<>>,
- ignored_alerts => 0,
- max_ignored_alerts => 10}}),
+ State#state{protocol_specific = PS#{current_cookie_secret => dtls_v1:cookie_secret(),
+ previous_cookie_secret => <<>>,
+ ignored_alerts => 0,
+ max_ignored_alerts => 10}}),
erlang:send_after(dtls_v1:cookie_timeout(), self(), new_cookie_secret),
Result;
-
-init({call, _} = Type, Event, #state{role = server} = State) ->
- %% I.E. DTLS over sctp
- gen_handshake(?FUNCTION_NAME, Type, Event, State#state{flight_state = reliable});
init(Type, Event, State) ->
gen_handshake(?FUNCTION_NAME, Type, Event, State).
@@ -470,9 +459,10 @@ init(Type, Event, State) ->
%%--------------------------------------------------------------------
error(enter, _, State) ->
{keep_state, State};
-error({call, From}, {start, _Timeout}, {Error, State}) ->
- ssl_connection:stop_and_reply(
- normal, {reply, From, {error, Error}}, State);
+error({call, From}, {start, _Timeout},
+ #state{protocol_specific = #{error := Error}} = State) ->
+ {stop_and_reply, {shutdown, normal},
+ [{reply, From, {error, Error}}], State};
error({call, _} = Call, Msg, State) ->
gen_handshake(?FUNCTION_NAME, Call, Msg, State);
error(_, _, _) ->
@@ -484,16 +474,18 @@ error(_, _, _) ->
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-hello(enter, _, #state{role = server} = State) ->
+hello(enter, _, #state{static_env = #static_env{role = server}} = State) ->
{keep_state, State};
-hello(enter, _, #state{role = client} = State0) ->
+hello(enter, _, #state{static_env = #static_env{role = client}} = State0) ->
{State, Actions} = handle_flight_timer(State0),
{keep_state, State, Actions};
hello(internal, #client_hello{cookie = <<>>,
client_version = Version} = Hello,
- #state{role = server,
- transport_cb = Transport,
- socket = Socket,
+ #state{static_env = #static_env{role = server,
+ transport_cb = Transport,
+ socket = Socket},
+ handshake_env = HsEnv,
+ connection_env = CEnv,
protocol_specific = #{current_cookie_secret := Secret}} = State0) ->
{ok, {IP, Port}} = dtls_socket:peername(Transport, Socket),
Cookie = dtls_handshake:cookie(Secret, IP, Port, Hello),
@@ -504,49 +496,61 @@ hello(internal, #client_hello{cookie = <<>>,
%% version 1.0 regardless of the version of TLS that is expected to be
%% negotiated.
VerifyRequest = dtls_handshake:hello_verify_request(Cookie, ?HELLO_VERIFY_REQUEST_VERSION),
- State1 = prepare_flight(State0#state{negotiated_version = Version}),
- {State2, Actions} = send_handshake(VerifyRequest, State1),
- {Record, State} = next_record(State2),
- next_event(?FUNCTION_NAME, Record, State#state{tls_handshake_history = ssl_handshake:init_handshake_history()}, Actions);
-hello(internal, #hello_verify_request{cookie = Cookie}, #state{role = client,
- host = Host, port = Port,
+ State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}),
+ {State, Actions} = send_handshake(VerifyRequest, State1),
+ next_event(?FUNCTION_NAME, no_record,
+ State#state{handshake_env = HsEnv#handshake_env{
+ tls_handshake_history =
+ ssl_handshake:init_handshake_history()}},
+ Actions);
+hello(internal, #hello_verify_request{cookie = Cookie}, #state{static_env = #static_env{role = client,
+ host = Host,
+ port = Port,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ handshake_env = #handshake_env{renegotiation = {Renegotiation, _}} = HsEnv,
+ connection_env = CEnv,
ssl_options = SslOpts,
session = #session{own_certificate = OwnCert}
= Session0,
- connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _},
- session_cache = Cache,
- session_cache_cb = CacheCb
+ connection_states = ConnectionStates0
} = State0) ->
Hello = dtls_handshake:client_hello(Host, Port, Cookie, ConnectionStates0,
SslOpts,
Cache, CacheCb, Renegotiation, OwnCert),
Version = Hello#client_hello.client_version,
- State1 = prepare_flight(State0#state{tls_handshake_history = ssl_handshake:init_handshake_history()}),
+ State1 = prepare_flight(State0#state{handshake_env =
+ HsEnv#handshake_env{tls_handshake_history
+ = ssl_handshake:init_handshake_history()}}),
{State2, Actions} = send_handshake(Hello, State1),
- State3 = State2#state{negotiated_version = Version, %% Requested version
- session =
- Session0#session{session_id =
- Hello#client_hello.session_id}},
- {Record, State} = next_record(State3),
- next_event(?FUNCTION_NAME, Record, State, Actions);
-hello(internal, #client_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
- start_or_recv_from = From} = State) ->
+ State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% Requested version
+ session =
+ Session0#session{session_id =
+ Hello#client_hello.session_id}},
+ next_event(?FUNCTION_NAME, no_record, State, Actions);
+hello(internal, #client_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ handshake_env = HsEnv,
+ start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
- hello = Hello},
+ handshake_env = HsEnv#handshake_env{hello = Hello}},
[{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
-hello(internal, #server_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
- start_or_recv_from = From} = State) ->
+hello(internal, #server_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ handshake_env = HsEnv,
+ start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
- hello = Hello},
+ handshake_env = HsEnv#handshake_env{hello = Hello}},
[{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
-hello(internal, #client_hello{cookie = Cookie} = Hello, #state{role = server,
- transport_cb = Transport,
- socket = Socket,
+
+hello(internal, #client_hello{cookie = Cookie} = Hello, #state{static_env = #static_env{role = server,
+ transport_cb = Transport,
+ socket = Socket},
protocol_specific = #{current_cookie_secret := Secret,
- previous_cookie_secret := PSecret}} = State0) ->
+ previous_cookie_secret := PSecret}
+ } = State0) ->
{ok, {IP, Port}} = dtls_socket:peername(Transport, Socket),
case dtls_handshake:cookie(Secret, IP, Port, Hello) of
Cookie ->
@@ -561,11 +565,12 @@ hello(internal, #client_hello{cookie = Cookie} = Hello, #state{role = server,
end
end;
hello(internal, #server_hello{} = Hello,
- #state{connection_states = ConnectionStates0,
- negotiated_version = ReqVersion,
- role = client,
- renegotiation = {Renegotiation, _},
- ssl_options = SslOptions} = State) ->
+ #state{
+ static_env = #static_env{role = client},
+ handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
+ connection_env = #connection_env{negotiated_version = ReqVersion},
+ connection_states = ConnectionStates0,
+ ssl_options = SslOptions} = State) ->
case dtls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
#alert{} = Alert ->
handle_own_alert(Alert, ReqVersion, ?FUNCTION_NAME, State);
@@ -581,8 +586,7 @@ hello(internal, {handshake, {#hello_verify_request{} = Handshake, _}}, State) ->
{next_state, ?FUNCTION_NAME, State, [{next_event, internal, Handshake}]};
hello(internal, #change_cipher_spec{type = <<1>>}, State0) ->
{State1, Actions0} = send_handshake_flight(State0, retransmit_epoch(?FUNCTION_NAME, State0)),
- {Record, State2} = next_record(State1),
- {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, Record, State2, Actions0),
+ {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, no_record, State1, Actions0),
%% This will reset the retransmission timer by repeating the enter state event
{repeat_state, State, Actions};
hello(info, Event, State) ->
@@ -612,10 +616,11 @@ abbreviated(internal = Type,
ConnectionStates1 = dtls_record:save_current_connection_state(ConnectionStates0, read),
ConnectionStates = dtls_record:next_epoch(ConnectionStates1, read),
gen_handshake(?FUNCTION_NAME, Type, Event, State#state{connection_states = ConnectionStates});
-abbreviated(internal = Type, #finished{} = Event, #state{connection_states = ConnectionStates} = State) ->
+abbreviated(internal = Type, #finished{} = Event, #state{connection_states = ConnectionStates,
+ protocol_specific = PS} = State) ->
gen_handshake(?FUNCTION_NAME, Type, Event,
prepare_flight(State#state{connection_states = ConnectionStates,
- flight_state = connection}));
+ protocol_specific = PS#{flight_state => connection}}));
abbreviated(state_timeout, Event, State) ->
handle_state_timeout(Event, ?FUNCTION_NAME, State);
abbreviated(Type, Event, State) ->
@@ -633,8 +638,7 @@ certify(internal = Type, #server_hello_done{} = Event, State) ->
ssl_connection:certify(Type, Event, prepare_flight(State), ?MODULE);
certify(internal, #change_cipher_spec{type = <<1>>}, State0) ->
{State1, Actions0} = send_handshake_flight(State0, retransmit_epoch(?FUNCTION_NAME, State0)),
- {Record, State2} = next_record(State1),
- {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, Record, State2, Actions0),
+ {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, no_record, State1, Actions0),
%% This will reset the retransmission timer by repeating the enter state event
{repeat_state, State, Actions};
certify(state_timeout, Event, State) ->
@@ -656,10 +660,11 @@ cipher(internal = Type, #change_cipher_spec{type = <<1>>} = Event,
ConnectionStates1 = dtls_record:save_current_connection_state(ConnectionStates0, read),
ConnectionStates = dtls_record:next_epoch(ConnectionStates1, read),
ssl_connection:?FUNCTION_NAME(Type, Event, State#state{connection_states = ConnectionStates}, ?MODULE);
-cipher(internal = Type, #finished{} = Event, #state{connection_states = ConnectionStates} = State) ->
+cipher(internal = Type, #finished{} = Event, #state{connection_states = ConnectionStates,
+ protocol_specific = PS} = State) ->
ssl_connection:?FUNCTION_NAME(Type, Event,
prepare_flight(State#state{connection_states = ConnectionStates,
- flight_state = connection}),
+ protocol_specific = PS#{flight_state => connection}}),
?MODULE);
cipher(state_timeout, Event, State) ->
handle_state_timeout(Event, ?FUNCTION_NAME, State);
@@ -675,39 +680,53 @@ connection(enter, _, State) ->
{keep_state, State};
connection(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
-connection(internal, #hello_request{}, #state{host = Host, port = Port,
+connection(internal, #hello_request{}, #state{static_env = #static_env{host = Host,
+ port = Port,
+ data_tag = DataTag,
+ session_cache = Cache,
+ session_cache_cb = CacheCb
+ },
+ handshake_env = #handshake_env{ renegotiation = {Renegotiation, _}},
+ connection_env = CEnv,
session = #session{own_certificate = Cert} = Session0,
- session_cache = Cache, session_cache_cb = CacheCb,
ssl_options = SslOpts,
connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _}} = State0) ->
+ protocol_specific = PS
+ } = State0) ->
Hello = dtls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Cache, CacheCb, Renegotiation, Cert),
Version = Hello#client_hello.client_version,
HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions),
State1 = prepare_flight(State0),
- {State2, Actions} = send_handshake(Hello, State1#state{negotiated_version = HelloVersion}),
- {Record, State} =
- next_record(
- State2#state{flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
- session = Session0#session{session_id
- = Hello#client_hello.session_id}}),
- next_event(hello, Record, State, Actions);
-connection(internal, #client_hello{} = Hello, #state{role = server, allow_renegotiate = true} = State) ->
+ {State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}),
+ State = State2#state{protocol_specific = PS#{flight_state => initial_flight_state(DataTag)},
+ session = Session0#session{session_id
+ = Hello#client_hello.session_id}},
+ next_event(hello, no_record, State, Actions);
+connection(internal, #client_hello{} = Hello, #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{allow_renegotiate = true} = HsEnv} = State) ->
%% Mitigate Computational DoS attack
%% http://www.educatedguesswork.org/2011/10/ssltls_and_computational_dos.html
%% http://www.thc.org/thc-ssl-dos/ Rather than disabling client
%% initiated renegotiation we will disallow many client initiated
%% renegotiations immediately after each other.
erlang:send_after(?WAIT_TO_ALLOW_RENEGOTIATION, self(), allow_renegotiate),
- {next_state, hello, State#state{allow_renegotiate = false, renegotiation = {true, peer}},
+ {next_state, hello, State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, peer},
+ allow_renegotiate = false}},
[{next_event, internal, Hello}]};
-connection(internal, #client_hello{}, #state{role = server, allow_renegotiate = false} = State0) ->
+connection(internal, #client_hello{}, #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{allow_renegotiate = false}} = State0) ->
Alert = ?ALERT_REC(?WARNING, ?NO_RENEGOTIATION),
State1 = send_alert(Alert, State0),
{Record, State} = ssl_connection:prepare_connection(State1, ?MODULE),
next_event(?FUNCTION_NAME, Record, State);
+connection({call, From}, {application_data, Data}, State) ->
+ try
+ send_application_data(Data, From, ?FUNCTION_NAME, State)
+ catch throw:Error ->
+ ssl_connection:hibernate_after(?FUNCTION_NAME, State, [{reply, From, Error}])
+ end;
connection(Type, Event, State) ->
ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
@@ -752,33 +771,44 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
end,
Monitor = erlang:monitor(process, User),
-
- #state{socket_options = SocketOptions,
+ InitStatEnv = #static_env{
+ role = Role,
+ transport_cb = CbModule,
+ protocol_cb = ?MODULE,
+ data_tag = DataTag,
+ close_tag = CloseTag,
+ error_tag = ErrorTag,
+ host = Host,
+ port = Port,
+ socket = Socket,
+ session_cache_cb = SessionCacheCb
+ },
+
+ #state{static_env = InitStatEnv,
+ handshake_env = #handshake_env{
+ tls_handshake_history = ssl_handshake:init_handshake_history(),
+ renegotiation = {false, first},
+ allow_renegotiate = SSLOptions#ssl_options.client_renegotiation
+ },
+ connection_env = #connection_env{user_application = {Monitor, User}},
+ socket_options = SocketOptions,
%% We do not want to save the password in the state so that
%% could be written in the clear into error logs.
ssl_options = SSLOptions#ssl_options{password = undefined},
session = #session{is_resumable = new},
- transport_cb = CbModule,
- data_tag = DataTag,
- close_tag = CloseTag,
- error_tag = ErrorTag,
- role = Role,
- host = Host,
- port = Port,
- socket = Socket,
connection_states = ConnectionStates,
protocol_buffers = #protocol_buffers{},
- user_application = {Monitor, User},
- user_data_buffer = <<>>,
- session_cache_cb = SessionCacheCb,
- renegotiation = {false, first},
- allow_renegotiate = SSLOptions#ssl_options.client_renegotiation,
+ user_data_buffer = {[],0,[]},
start_or_recv_from = undefined,
- protocol_cb = ?MODULE,
flight_buffer = new_flight(),
- flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT}
+ protocol_specific = #{flight_state => initial_flight_state(DataTag)}
}.
+initial_flight_state(udp)->
+ {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT};
+initial_flight_state(_) ->
+ reliable.
+
next_dtls_record(Data, StateName, #state{protocol_buffers = #protocol_buffers{
dtls_record_buffer = Buf0,
dtls_cipher_texts = CT0} = Buffers} = State0) ->
@@ -796,7 +826,7 @@ next_dtls_record(Data, StateName, #state{protocol_buffers = #protocol_buffers{
acceptable_record_versions(hello, _) ->
[dtls_record:protocol_version(Vsn) || Vsn <- ?ALL_DATAGRAM_SUPPORTED_VERSIONS];
-acceptable_record_versions(_, #state{negotiated_version = Version}) ->
+acceptable_record_versions(_, #state{connection_env = #connection_env{negotiated_version = Version}}) ->
[Version].
dtls_handshake_events(Packets) ->
@@ -815,19 +845,22 @@ decode_cipher_text(#state{protocol_buffers = #protocol_buffers{dtls_cipher_texts
{Alert, State}
end.
-dtls_version(hello, Version, #state{role = server} = State) ->
- State#state{negotiated_version = Version}; %%Inital version
+dtls_version(hello, Version, #state{static_env = #static_env{role = server},
+ connection_env = CEnv} = State) ->
+ State#state{connection_env = CEnv#connection_env{negotiated_version = Version}}; %%Inital version
dtls_version(_,_, State) ->
State.
handle_client_hello(#client_hello{client_version = ClientVersion} = Hello,
#state{connection_states = ConnectionStates0,
- port = Port, session = #session{own_certificate = Cert} = Session0,
- renegotiation = {Renegotiation, _},
- session_cache = Cache,
- session_cache_cb = CacheCb,
- negotiated_protocol = CurrentProtocol,
- key_algorithm = KeyExAlg,
+ static_env = #static_env{port = Port,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ handshake_env = #handshake_env{kex_algorithm = KeyExAlg,
+ renegotiation = {Renegotiation, _},
+ negotiated_protocol = CurrentProtocol} = HsEnv,
+ connection_env = CEnv,
+ session = #session{own_certificate = Cert} = Session0,
ssl_options = SslOpts} = State0) ->
case dtls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
@@ -842,11 +875,12 @@ handle_client_hello(#client_hello{client_version = ClientVersion} = Hello,
end,
State = prepare_flight(State0#state{connection_states = ConnectionStates,
- negotiated_version = Version,
- hashsign_algorithm = HashSign,
- client_hello_version = ClientVersion,
- session = Session,
- negotiated_protocol = Protocol}),
+ connection_env = CEnv#connection_env{negotiated_version = Version},
+ handshake_env = HsEnv#handshake_env{
+ hashsign_algorithm = HashSign,
+ client_hello_version = ClientVersion,
+ negotiated_protocol = Protocol},
+ session = Session}),
ssl_connection:hello(internal, {common_client_hello, Type, ServerHelloExt},
State, ?MODULE)
@@ -855,20 +889,20 @@ handle_client_hello(#client_hello{client_version = ClientVersion} = Hello,
%% raw data from socket, unpack records
handle_info({Protocol, _, _, _, Data}, StateName,
- #state{data_tag = Protocol} = State0) ->
+ #state{static_env = #static_env{data_tag = Protocol}} = State0) ->
case next_dtls_record(Data, StateName, State0) of
{Record, State} ->
next_event(StateName, Record, State);
#alert{} = Alert ->
ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
- ssl_connection:stop({shutdown, own_alert}, State0)
+ {stop, {shutdown, own_alert}, State0}
end;
handle_info({CloseTag, Socket}, StateName,
- #state{socket = Socket,
+ #state{static_env = #static_env{socket = Socket,
+ close_tag = CloseTag},
+ connection_env = #connection_env{negotiated_version = Version},
socket_options = #socket_options{active = Active},
- protocol_buffers = #protocol_buffers{dtls_cipher_texts = CTs},
- close_tag = CloseTag,
- negotiated_version = Version} = State) ->
+ protocol_buffers = #protocol_buffers{dtls_cipher_texts = CTs}} = State) ->
%% Note that as of DTLS 1.2 (TLS 1.1),
%% failure to properly close a connection no longer requires that a
%% session not be resumed. This is a change from DTLS 1.0 to conform
@@ -886,7 +920,7 @@ handle_info({CloseTag, Socket}, StateName,
ok
end,
ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
- ssl_connection:stop({shutdown, transport_closed}, State);
+ {stop, {shutdown, transport_closed}, State};
true ->
%% Fixes non-delivery of final DTLS record in {active, once}.
%% Basically allows the application the opportunity to set {active, once} again
@@ -904,11 +938,11 @@ handle_info(Msg, StateName, State) ->
ssl_connection:StateName(info, Msg, State, ?MODULE).
handle_state_timeout(flight_retransmission_timeout, StateName,
- #state{flight_state = {retransmit, NextTimeout}} = State0) ->
- {State1, Actions0} = send_handshake_flight(State0#state{flight_state = {retransmit, NextTimeout}},
- retransmit_epoch(StateName, State0)),
- {Record, State2} = next_record(State1),
- {next_state, StateName, State, Actions} = next_event(StateName, Record, State2, Actions0),
+ #state{protocol_specific =
+ #{flight_state := {retransmit, _NextTimeout}}} = State0) ->
+ {State1, Actions0} = send_handshake_flight(State0,
+ retransmit_epoch(StateName, State0)),
+ {next_state, StateName, State, Actions} = next_event(StateName, no_record, State1, Actions0),
%% This will reset the retransmission timer by repeating the enter state event
{repeat_state, State, Actions}.
@@ -921,8 +955,8 @@ handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State)).
-handle_own_alert(Alert, Version, StateName, #state{data_tag = udp,
- role = Role,
+handle_own_alert(Alert, Version, StateName, #state{static_env = #static_env{data_tag = udp,
+ role = Role},
ssl_options = Options} = State0) ->
case ignore_alert(Alert, State0) of
{true, State} ->
@@ -947,7 +981,7 @@ decode_alerts(Bin) ->
ssl_alert:decode(Bin).
gen_handshake(StateName, Type, Event,
- #state{negotiated_version = Version} = State) ->
+ #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
try ssl_connection:StateName(Type, Event, State, ?MODULE) of
Result ->
Result
@@ -958,7 +992,7 @@ gen_handshake(StateName, Type, Event,
Version, StateName, State)
end.
-gen_info(Event, connection = StateName, #state{negotiated_version = Version} = State) ->
+gen_info(Event, connection = StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
try handle_info(Event, StateName, State) of
Result ->
Result
@@ -969,7 +1003,7 @@ gen_info(Event, connection = StateName, #state{negotiated_version = Version} =
Version, StateName, State)
end;
-gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
+gen_info(Event, StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
try handle_info(Event, StateName, State) of
Result ->
Result
@@ -1012,18 +1046,18 @@ next_flight(Flight) ->
change_cipher_spec => undefined,
handshakes_after_change_cipher_spec => []}.
-handle_flight_timer(#state{data_tag = udp,
- flight_state = {retransmit, Timeout}} = State) ->
+handle_flight_timer(#state{static_env = #static_env{data_tag = udp},
+ protocol_specific = #{flight_state := {retransmit, Timeout}}} = State) ->
start_retransmision_timer(Timeout, State);
-handle_flight_timer(#state{data_tag = udp,
- flight_state = connection} = State) ->
+handle_flight_timer(#state{static_env = #static_env{data_tag = udp},
+ protocol_specific = #{flight_state := connection}} = State) ->
{State, []};
-handle_flight_timer(State) ->
+handle_flight_timer(#state{protocol_specific = #{flight_state := reliable}} = State) ->
%% No retransmision needed i.e DTLS over SCTP
- {State#state{flight_state = reliable}, []}.
+ {State, []}.
-start_retransmision_timer(Timeout, State) ->
- {State#state{flight_state = {retransmit, new_timeout(Timeout)}},
+start_retransmision_timer(Timeout, #state{protocol_specific = PS} = State) ->
+ {State#state{protocol_specific = PS#{flight_state => {retransmit, new_timeout(Timeout)}}},
[{state_timeout, Timeout, flight_retransmission_timeout}]}.
new_timeout(N) when N =< 30 ->
@@ -1031,11 +1065,11 @@ new_timeout(N) when N =< 30 ->
new_timeout(_) ->
60.
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
- flight_buffer = #{handshakes := Flight,
+send_handshake_flight(#state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
+ connection_env = #connection_env{negotiated_version = Version},
+ flight_buffer = #{handshakes := Flight,
change_cipher_spec := undefined},
- negotiated_version = Version,
connection_states = ConnectionStates0} = State0, Epoch) ->
%% TODO remove hardcoded Max size
{Encoded, ConnectionStates} =
@@ -1043,12 +1077,12 @@ send_handshake_flight(#state{socket = Socket,
send(Transport, Socket, Encoded),
{State0#state{connection_states = ConnectionStates}, []};
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
+send_handshake_flight(#state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
+ connection_env = #connection_env{negotiated_version = Version},
flight_buffer = #{handshakes := [_|_] = Flight0,
change_cipher_spec := ChangeCipher,
handshakes_after_change_cipher_spec := []},
- negotiated_version = Version,
connection_states = ConnectionStates0} = State0, Epoch) ->
{HsBefore, ConnectionStates1} =
encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch, ConnectionStates0),
@@ -1057,12 +1091,12 @@ send_handshake_flight(#state{socket = Socket,
send(Transport, Socket, [HsBefore, EncChangeCipher]),
{State0#state{connection_states = ConnectionStates}, []};
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
+send_handshake_flight(#state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
+ connection_env = #connection_env{negotiated_version = Version},
flight_buffer = #{handshakes := [_|_] = Flight0,
change_cipher_spec := ChangeCipher,
handshakes_after_change_cipher_spec := Flight1},
- negotiated_version = Version,
connection_states = ConnectionStates0} = State0, Epoch) ->
{HsBefore, ConnectionStates1} =
encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch-1, ConnectionStates0),
@@ -1073,12 +1107,12 @@ send_handshake_flight(#state{socket = Socket,
send(Transport, Socket, [HsBefore, EncChangeCipher, HsAfter]),
{State0#state{connection_states = ConnectionStates}, []};
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
+send_handshake_flight(#state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
+ connection_env = #connection_env{negotiated_version = Version},
flight_buffer = #{handshakes := [],
change_cipher_spec := ChangeCipher,
handshakes_after_change_cipher_spec := Flight1},
- negotiated_version = Version,
connection_states = ConnectionStates0} = State0, Epoch) ->
{EncChangeCipher, ConnectionStates1} =
encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates0),
@@ -1129,3 +1163,43 @@ log_ignore_alert(true, StateName, Alert, Role) ->
[Role, StateName, Txt]);
log_ignore_alert(false, _, _,_) ->
ok.
+
+send_application_data(Data, From, _StateName,
+ #state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
+ connection_env = #connection_env{negotiated_version = Version},
+ handshake_env = HsEnv,
+ connection_states = ConnectionStates0,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State0) ->
+
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ renegotiate(State0#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, internal}}},
+ [{next_event, {call, From}, {application_data, Data}}]);
+ false ->
+ {Msgs, ConnectionStates} =
+ dtls_record:encode_data(Data, Version, ConnectionStates0),
+ State = State0#state{connection_states = ConnectionStates},
+ case send(Transport, Socket, Msgs) of
+ ok ->
+ ssl_connection:hibernate_after(connection, State, [{reply, From, ok}]);
+ Result ->
+ ssl_connection:hibernate_after(connection, State, [{reply, From, Result}])
+ end
+ 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.
+
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 35c213a182..6e9bf99e52 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -46,7 +46,7 @@
%% Handshake handling
%%====================================================================
%%--------------------------------------------------------------------
--spec client_hello(host(), inet:port_number(), ssl_record:connection_states(),
+-spec client_hello(ssl:host(), inet:port_number(), ssl_record:connection_states(),
#ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
@@ -59,7 +59,7 @@ client_hello(Host, Port, ConnectionStates, SslOpts,
Cache, CacheCb, Renegotiation, OwnCert).
%%--------------------------------------------------------------------
--spec client_hello(host(), inet:port_number(), term(), ssl_record:connection_states(),
+-spec client_hello(ssl:host(), inet:port_number(), term(), ssl_record:connection_states(),
#ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
@@ -123,7 +123,7 @@ cookie(Key, Address, Port, #client_hello{client_version = {Major, Minor},
Random, SessionId, CipherSuites, CompressionMethods],
crypto:hmac(sha, Key, CookieData).
%%--------------------------------------------------------------------
--spec hello_verify_request(binary(), dtls_record:dtls_version()) -> #hello_verify_request{}.
+-spec hello_verify_request(binary(), ssl_record:ssl_version()) -> #hello_verify_request{}.
%%
%% Description: Creates a hello verify request message sent by server to
%% verify client
@@ -151,7 +151,7 @@ encode_handshake(Handshake, Version, Seq) ->
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
--spec get_dtls_handshake(dtls_record:dtls_version(), binary(), #protocol_buffers{}) ->
+-spec get_dtls_handshake(ssl_record:ssl_version(), binary(), #protocol_buffers{}) ->
{[dtls_handshake()], #protocol_buffers{}}.
%%
%% Description: Given buffered and new data from dtls_record, collects
@@ -194,7 +194,7 @@ handle_client_hello(Version,
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY);
_ ->
- #{key_exchange := KeyExAlg} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg,
SupportedHashSigns, TLSVersion) of
#alert{} = Alert ->
@@ -215,8 +215,6 @@ handle_client_hello_extensions(Version, Type, Random, CipherSuites,
HelloExt, dtls_v1:corresponding_tls_version(Version),
SslOpts, Session0,
ConnectionStates0, Renegotiation) of
- #alert{} = Alert ->
- Alert;
{Session, ConnectionStates, Protocol, ServerHelloExt} ->
{Version, {Type, Session}, ConnectionStates, Protocol, ServerHelloExt, HashSign}
catch throw:Alert ->
@@ -225,17 +223,16 @@ handle_client_hello_extensions(Version, Type, Random, CipherSuites,
handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation) ->
- case ssl_handshake:handle_server_hello_extensions(dtls_record, Random, CipherSuite,
- Compression, HelloExt,
- dtls_v1:corresponding_tls_version(Version),
- SslOpt, ConnectionStates0, Renegotiation) of
- #alert{} = Alert ->
- Alert;
+ try ssl_handshake:handle_server_hello_extensions(dtls_record, Random, CipherSuite,
+ Compression, HelloExt,
+ dtls_v1:corresponding_tls_version(Version),
+ SslOpt, ConnectionStates0, Renegotiation) of
{ConnectionStates, ProtoExt, Protocol} ->
{Version, SessionId, ConnectionStates, ProtoExt, Protocol}
+ catch throw:Alert ->
+ Alert
end.
-
%%--------------------------------------------------------------------
enc_handshake(#hello_verify_request{protocol_version = {Major, Minor},
diff --git a/lib/ssl/src/dtls_handshake.hrl b/lib/ssl/src/dtls_handshake.hrl
index 50e92027d2..41da8e5c8c 100644
--- a/lib/ssl/src/dtls_handshake.hrl
+++ b/lib/ssl/src/dtls_handshake.hrl
@@ -27,6 +27,7 @@
-define(dtls_handshake, true).
-include("ssl_handshake.hrl"). %% Common TLS and DTLS records and Constantes
+-include("ssl_api.hrl").
-define(HELLO_VERIFY_REQUEST, 3).
-define(HELLO_VERIFY_REQUEST_VERSION, {254, 255}).
diff --git a/lib/ssl/src/dtls_packet_demux.erl b/lib/ssl/src/dtls_packet_demux.erl
index 1497c77cf3..092366b7c0 100644
--- a/lib/ssl/src/dtls_packet_demux.erl
+++ b/lib/ssl/src/dtls_packet_demux.erl
@@ -144,11 +144,11 @@ handle_info({Transport, Socket, IP, InPortNo, _} = Msg, #state{listener = Socket
%% UDP socket does not have a connection and should not receive an econnreset
%% This does however happens on some windows versions. Just ignoring it
%% appears to make things work as expected!
-handle_info({Error, Socket, econnreset = Error}, #state{listener = Socket, transport = {_,_,_, udp_error}} = State) ->
+handle_info({udp_error, Socket, econnreset = Error}, #state{listener = Socket, transport = {_,_,_, udp_error}} = State) ->
Report = io_lib:format("Ignore SSL UDP Listener: Socket error: ~p ~n", [Error]),
error_logger:info_report(Report),
{noreply, State};
-handle_info({Error, Socket, Error}, #state{listener = Socket, transport = {_,_,_, Error}} = State) ->
+handle_info({ErrorTag, Socket, Error}, #state{listener = Socket, transport = {_,_,_, ErrorTag}} = State) ->
Report = io_lib:format("SSL Packet muliplxer shutdown: Socket error: ~p ~n", [Error]),
error_logger:info_report(Report),
{noreply, State#state{close=true}};
@@ -297,6 +297,9 @@ do_set_emulated_opts([], Opts) ->
Opts;
do_set_emulated_opts([{mode, Value} | Rest], Opts) ->
do_set_emulated_opts(Rest, Opts#socket_options{mode = Value});
+do_set_emulated_opts([{active, N0} | Rest], Opts=#socket_options{active = Active}) when is_integer(N0) ->
+ N = tls_socket:update_active_n(N0, Active),
+ do_set_emulated_opts(Rest, Opts#socket_options{active = N});
do_set_emulated_opts([{active, Value} | Rest], Opts) ->
do_set_emulated_opts(Rest, Opts#socket_options{active = Value}).
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index 9eb0d8e2d7..2fe875da31 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,9 +49,8 @@
is_acceptable_version/2, hello_version/2]).
--export_type([dtls_version/0, dtls_atom_version/0]).
+-export_type([dtls_atom_version/0]).
--type dtls_version() :: ssl_record:ssl_version().
-type dtls_atom_version() :: dtlsv1 | 'dtlsv1.2'.
-define(REPLAY_WINDOW_SIZE, 64).
@@ -135,7 +134,7 @@ set_connection_state_by_epoch(ReadState, Epoch, #{saved_read := #{epoch := Epoch
States#{saved_read := ReadState}.
%%--------------------------------------------------------------------
--spec init_connection_state_seq(dtls_version(), ssl_record:connection_states()) ->
+-spec init_connection_state_seq(ssl_record:ssl_version(), ssl_record:connection_states()) ->
ssl_record:connection_state().
%%
%% Description: Copy the read sequence number to the write sequence number
@@ -163,7 +162,7 @@ current_connection_state_epoch(#{current_write := #{epoch := Epoch}},
Epoch.
%%--------------------------------------------------------------------
--spec get_dtls_records(binary(), [dtls_version()], binary()) -> {[binary()], binary()} | #alert{}.
+-spec get_dtls_records(binary(), [ssl_record:ssl_version()], binary()) -> {[binary()], binary()} | #alert{}.
%%
%% Description: Given old buffer and new data from UDP/SCTP, packs up a records
%% and returns it as a list of tls_compressed binaries also returns leftover
@@ -188,7 +187,7 @@ get_dtls_records(Data, Versions, Buffer) ->
%%====================================================================
%%--------------------------------------------------------------------
--spec encode_handshake(iolist(), dtls_version(), integer(), ssl_record:connection_states()) ->
+-spec encode_handshake(iolist(), ssl_record:ssl_version(), integer(), ssl_record:connection_states()) ->
{iolist(), ssl_record:connection_states()}.
%
%% Description: Encodes a handshake message to send on the ssl-socket.
@@ -198,7 +197,7 @@ encode_handshake(Frag, Version, Epoch, ConnectionStates) ->
%%--------------------------------------------------------------------
--spec encode_alert_record(#alert{}, dtls_version(), ssl_record:connection_states()) ->
+-spec encode_alert_record(#alert{}, ssl_record:ssl_version(), ssl_record:connection_states()) ->
{iolist(), ssl_record:connection_states()}.
%%
%% Description: Encodes an alert message to send on the ssl-socket.
@@ -210,7 +209,7 @@ encode_alert_record(#alert{level = Level, description = Description},
ConnectionStates).
%%--------------------------------------------------------------------
--spec encode_change_cipher_spec(dtls_version(), integer(), ssl_record:connection_states()) ->
+-spec encode_change_cipher_spec(ssl_record:ssl_version(), integer(), ssl_record:connection_states()) ->
{iolist(), ssl_record:connection_states()}.
%%
%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
@@ -219,7 +218,7 @@ encode_change_cipher_spec(Version, Epoch, ConnectionStates) ->
encode_plain_text(?CHANGE_CIPHER_SPEC, Version, Epoch, ?byte(?CHANGE_CIPHER_SPEC_PROTO), ConnectionStates).
%%--------------------------------------------------------------------
--spec encode_data(binary(), dtls_version(), ssl_record:connection_states()) ->
+-spec encode_data(binary(), ssl_record:ssl_version(), ssl_record:connection_states()) ->
{iolist(),ssl_record:connection_states()}.
%%
%% Description: Encodes data to send on the ssl-socket.
@@ -248,8 +247,8 @@ decode_cipher_text(#ssl_tls{epoch = Epoch} = CipherText, ConnnectionStates0) ->
%%====================================================================
%%--------------------------------------------------------------------
--spec protocol_version(dtls_atom_version() | dtls_version()) ->
- dtls_version() | dtls_atom_version().
+-spec protocol_version(dtls_atom_version() | ssl_record:ssl_version()) ->
+ ssl_record:ssl_version() | dtls_atom_version().
%%
%% Description: Creates a protocol version record from a version atom
%% or vice versa.
@@ -263,7 +262,7 @@ protocol_version({254, 253}) ->
protocol_version({254, 255}) ->
dtlsv1.
%%--------------------------------------------------------------------
--spec lowest_protocol_version(dtls_version(), dtls_version()) -> dtls_version().
+-spec lowest_protocol_version(ssl_record:ssl_version(), ssl_record:ssl_version()) -> ssl_record:ssl_version().
%%
%% Description: Lowes protocol version of two given versions
%%--------------------------------------------------------------------
@@ -277,7 +276,7 @@ lowest_protocol_version(_,Version) ->
Version.
%%--------------------------------------------------------------------
--spec lowest_protocol_version([dtls_version()]) -> dtls_version().
+-spec lowest_protocol_version([ssl_record:ssl_version()]) -> ssl_record:ssl_version().
%%
%% Description: Lowest protocol version present in a list
%%--------------------------------------------------------------------
@@ -288,7 +287,7 @@ lowest_protocol_version(Versions) ->
lowest_list_protocol_version(Ver, Vers).
%%--------------------------------------------------------------------
--spec highest_protocol_version([dtls_version()]) -> dtls_version().
+-spec highest_protocol_version([ssl_record:ssl_version()]) -> ssl_record:ssl_version().
%%
%% Description: Highest protocol version present in a list
%%--------------------------------------------------------------------
@@ -299,7 +298,7 @@ highest_protocol_version(Versions) ->
highest_list_protocol_version(Ver, Vers).
%%--------------------------------------------------------------------
--spec highest_protocol_version(dtls_version(), dtls_version()) -> dtls_version().
+-spec highest_protocol_version(ssl_record:ssl_version(), ssl_record:ssl_version()) -> ssl_record:ssl_version().
%%
%% Description: Highest protocol version of two given versions
%%--------------------------------------------------------------------
@@ -315,7 +314,7 @@ highest_protocol_version(_,Version) ->
Version.
%%--------------------------------------------------------------------
--spec is_higher(V1 :: dtls_version(), V2::dtls_version()) -> boolean().
+-spec is_higher(V1 :: ssl_record:ssl_version(), V2::ssl_record:ssl_version()) -> boolean().
%%
%% Description: Is V1 > V2
%%--------------------------------------------------------------------
@@ -327,7 +326,7 @@ is_higher(_, _) ->
false.
%%--------------------------------------------------------------------
--spec supported_protocol_versions() -> [dtls_version()].
+-spec supported_protocol_versions() -> [ssl_record:ssl_version()].
%%
%% Description: Protocol versions supported
%%--------------------------------------------------------------------
@@ -370,7 +369,7 @@ supported_protocol_versions([_|_] = Vsns) ->
end.
%%--------------------------------------------------------------------
--spec is_acceptable_version(dtls_version(), Supported :: [dtls_version()]) -> boolean().
+-spec is_acceptable_version(ssl_record:ssl_version(), Supported :: [ssl_record:ssl_version()]) -> boolean().
%%
%% Description: ssl version 2 is not acceptable security risks are too big.
%%
@@ -378,7 +377,7 @@ supported_protocol_versions([_|_] = Vsns) ->
is_acceptable_version(Version, Versions) ->
lists:member(Version, Versions).
--spec hello_version(dtls_version(), [dtls_version()]) -> dtls_version().
+-spec hello_version(ssl_record:ssl_version(), [ssl_record:ssl_version()]) -> ssl_record:ssl_version().
hello_version(Version, Versions) ->
case dtls_v1:corresponding_tls_version(Version) of
TLSVersion when TLSVersion >= {3, 3} ->
@@ -499,23 +498,22 @@ encode_dtls_cipher_text(Type, {MajVer, MinVer}, Fragment,
WriteState#{sequence_number => Seq + 1}}.
encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
+ cipher_state := CipherS0,
epoch := Epoch,
sequence_number := Seq,
- cipher_state := CipherS0,
security_parameters :=
#security_parameters{
cipher_type = ?AEAD,
- bulk_cipher_algorithm =
- BulkCipherAlgo,
+ bulk_cipher_algorithm = BCAlg,
compression_algorithm = CompAlg}
} = WriteState0) ->
{Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- AAD = calc_aad(Type, Version, Epoch, Seq),
+ AAD = start_additional_data(Type, Version, Epoch, Seq),
+ CipherS = ssl_record:nonce_seed(BCAlg, <<?UINT16(Epoch), ?UINT48(Seq)>>, CipherS0),
+ WriteState = WriteState0#{compression_state => CompS1,
+ cipher_state => CipherS},
TLSVersion = dtls_v1:corresponding_tls_version(Version),
- {CipherFragment, CipherS1} =
- ssl_cipher:cipher_aead(BulkCipherAlgo, CipherS0, Seq, AAD, Comp, TLSVersion),
- {CipherFragment, WriteState0#{compression_state => CompS1,
- cipher_state => CipherS1}};
+ ssl_record:cipher_aead(TLSVersion, Comp, WriteState, AAD);
encode_plain_text(Type, Version, Fragment, #{compression_state := CompS0,
epoch := Epoch,
sequence_number := Seq,
@@ -547,15 +545,16 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
BulkCipherAlgo,
compression_algorithm = CompAlg}} = ReadState0,
ConnnectionStates0) ->
- AAD = calc_aad(Type, Version, Epoch, Seq),
+ AAD = start_additional_data(Type, Version, Epoch, Seq),
+ CipherS = ssl_record:nonce_seed(BulkCipherAlgo, <<?UINT16(Epoch), ?UINT48(Seq)>>, CipherS0),
TLSVersion = dtls_v1:corresponding_tls_version(Version),
- case ssl_cipher:decipher_aead(BulkCipherAlgo, CipherS0, Seq, AAD, CipherFragment, TLSVersion) of
- {PlainFragment, CipherState} ->
- {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
+ case ssl_record:decipher_aead(BulkCipherAlgo, CipherS, AAD, CipherFragment, TLSVersion) of
+ PlainFragment when is_binary(PlainFragment) ->
+ {Plain, CompressionS} = ssl_record:uncompress(CompAlg,
PlainFragment, CompressionS0),
- ReadState0 = ReadState0#{compression_state => CompressionS1,
- cipher_state => CipherState},
- ReadState = update_replay_window(Seq, ReadState0),
+ ReadState1 = ReadState0#{compression_state := CompressionS,
+ cipher_state := CipherS},
+ ReadState = update_replay_window(Seq, ReadState1),
ConnnectionStates = set_connection_state_by_epoch(ReadState, Epoch, ConnnectionStates0, read),
{CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
#alert{} = Alert ->
@@ -600,7 +599,7 @@ mac_hash({Major, Minor}, MacAlg, MacSecret, Epoch, SeqNo, Type, Length, Fragment
Fragment],
dtls_v1:hmac_hash(MacAlg, MacSecret, Value).
-calc_aad(Type, {MajVer, MinVer}, Epoch, SeqNo) ->
+start_additional_data(Type, {MajVer, MinVer}, Epoch, SeqNo) ->
<<?UINT16(Epoch), ?UINT48(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/dtls_socket.erl b/lib/ssl/src/dtls_socket.erl
index b26d3ae41a..4d07372e31 100644
--- a/lib/ssl/src/dtls_socket.erl
+++ b/lib/ssl/src/dtls_socket.erl
@@ -38,7 +38,9 @@ listen(Port, #config{transport_info = TransportInfo,
case dtls_listener_sup:start_child([Port, TransportInfo, emulated_socket_options(EmOpts, #socket_options{}),
Options ++ internal_inet_values(), SslOpts]) of
{ok, Pid} ->
- {ok, #sslsocket{pid = {dtls, Config#config{dtls_handler = {Pid, Port}}}}};
+ Socket = #sslsocket{pid = {dtls, Config#config{dtls_handler = {Pid, Port}}}},
+ check_active_n(EmOpts, Socket),
+ {ok, Socket};
Err = {error, _} ->
Err
end.
@@ -48,7 +50,7 @@ accept(dtls, #config{transport_info = {Transport,_,_,_},
dtls_handler = {Listner, _}}, _Timeout) ->
case dtls_packet_demux:accept(Listner, self()) of
{ok, Pid, Socket} ->
- {ok, socket(Pid, Transport, {Listner, Socket}, ConnectionCb)};
+ {ok, socket([Pid], Transport, {Listner, Socket}, ConnectionCb)};
{error, Reason} ->
{error, Reason}
end.
@@ -73,16 +75,17 @@ close(gen_udp, {_Client, _Socket}) ->
close(Transport, {_Client, Socket}) ->
Transport:close(Socket).
-socket(Pid, gen_udp = Transport, {{_, _}, Socket}, ConnectionCb) ->
- #sslsocket{pid = Pid,
+socket(Pids, gen_udp = Transport, {{_, _}, Socket}, ConnectionCb) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb}};
-socket(Pid, Transport, Socket, ConnectionCb) ->
- #sslsocket{pid = Pid,
+socket(Pids, Transport, Socket, ConnectionCb) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb}}.
-setopts(_, #sslsocket{pid = {dtls, #config{dtls_handler = {ListenPid, _}}}}, Options) ->
- SplitOpts = tls_socket:split_options(Options),
+setopts(_, Socket = #sslsocket{pid = {dtls, #config{dtls_handler = {ListenPid, _}}}}, Options) ->
+ SplitOpts = {_, EmOpts} = tls_socket:split_options(Options),
+ check_active_n(EmOpts, Socket),
dtls_packet_demux:set_sock_opts(ListenPid, SplitOpts);
%%% Following clauses will not be called for emulated options, they are handled in the connection process
setopts(gen_udp, Socket, Options) ->
@@ -90,6 +93,32 @@ setopts(gen_udp, Socket, Options) ->
setopts(Transport, Socket, Options) ->
Transport:setopts(Socket, Options).
+check_active_n(EmulatedOpts, Socket = #sslsocket{pid = {dtls, #config{dtls_handler = {ListenPid, _}}}}) ->
+ %% We check the resulting options to send an ssl_passive message if necessary.
+ case proplists:lookup(active, EmulatedOpts) of
+ %% The provided value is out of bound.
+ {_, N} when is_integer(N), N < -32768 ->
+ throw(einval);
+ {_, N} when is_integer(N), N > 32767 ->
+ throw(einval);
+ {_, N} when is_integer(N) ->
+ {ok, #socket_options{active = Active}, _} = dtls_packet_demux:get_all_opts(ListenPid),
+ case Active of
+ Atom when is_atom(Atom), N =< 0 ->
+ self() ! {ssl_passive, Socket};
+ %% The result of the addition is out of bound.
+ %% We do not need to check < -32768 because Active can't be below 1.
+ A when is_integer(A), A + N > 32767 ->
+ throw(einval);
+ A when is_integer(A), A + N =< 0 ->
+ self() ! {ssl_passive, Socket};
+ _ ->
+ ok
+ end;
+ _ ->
+ ok
+ end.
+
getopts(_, #sslsocket{pid = {dtls, #config{dtls_handler = {ListenPid, _}}}}, Options) ->
SplitOpts = tls_socket:split_options(Options),
dtls_packet_demux:get_sock_opts(ListenPid, SplitOpts);
@@ -161,9 +190,18 @@ emulated_socket_options(InetValues, #socket_options{
mode = proplists:get_value(mode, InetValues, Mode),
packet = proplists:get_value(packet, InetValues, Packet),
packet_size = proplists:get_value(packet_size, InetValues, PacketSize),
- active = proplists:get_value(active, InetValues, Active)
+ active = emulated_active_option(InetValues, Active)
}.
+emulated_active_option([], Active) ->
+ Active;
+emulated_active_option([{active, Active} | _], _) when Active =< 0 ->
+ false;
+emulated_active_option([{active, Active} | _], _) ->
+ Active;
+emulated_active_option([_|Tail], Active) ->
+ emulated_active_option(Tail, Active).
+
emulated_options([{mode, Value} = Opt |Opts], Inet, Emulated) ->
validate_inet_option(mode, Value),
emulated_options(Opts, Inet, [Opt | proplists:delete(mode, Emulated)]);
@@ -185,6 +223,9 @@ validate_inet_option(mode, Value)
when Value =/= list, Value =/= binary ->
throw({error, {options, {mode,Value}}});
validate_inet_option(active, Value)
+ when Value >= -32768, Value =< 32767 ->
+ ok;
+validate_inet_option(active, Value)
when Value =/= true, Value =/= false, Value =/= once ->
throw({error, {options, {active,Value}}});
validate_inet_option(_, _) ->
diff --git a/lib/ssl/src/dtls_v1.erl b/lib/ssl/src/dtls_v1.erl
index df687f579b..b365961a6a 100644
--- a/lib/ssl/src/dtls_v1.erl
+++ b/lib/ssl/src/dtls_v1.erl
@@ -27,22 +27,22 @@
-define(COOKIE_BASE_TIMEOUT, 30000).
--spec suites(Minor:: 253|255) -> [ssl_cipher:cipher_suite()].
+-spec suites(Minor:: 253|255) -> [ssl_cipher_format:cipher_suite()].
suites(Minor) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
tls_v1:suites(corresponding_minor_tls_version(Minor))).
all_suites(Version) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
ssl_cipher:all_suites(corresponding_tls_version(Version))).
anonymous_suites(Version) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
ssl_cipher:anonymous_suites(corresponding_tls_version(Version))).
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index aa3d7e3f72..5cab35fd4b 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -69,14 +69,14 @@ is_node_name(Node) ->
%% -------------------------------------------------------------------------
-hs_data_common(#sslsocket{pid = DistCtrl} = SslSocket) ->
+hs_data_common(#sslsocket{pid = [_, DistCtrl|_]} = SslSocket) ->
#hs_data{
f_send =
- fun (Ctrl, Packet) when Ctrl == DistCtrl ->
+ fun (_Ctrl, Packet) ->
f_send(SslSocket, Packet)
end,
f_recv =
- fun (Ctrl, Length, Timeout) when Ctrl == DistCtrl ->
+ fun (_, Length, Timeout) ->
f_recv(SslSocket, Length, Timeout)
end,
f_setopts_pre_nodeup =
@@ -175,8 +175,7 @@ mf_getopts(SslSocket, Opts) ->
ssl:getopts(SslSocket, Opts).
f_handshake_complete(DistCtrl, Node, DHandle) ->
- ssl_connection:handshake_complete(DistCtrl, Node, DHandle).
-
+ tls_sender:dist_handshake_complete(DistCtrl, Node, DHandle).
setopts_filter(Opts) ->
[Opt || {K,_} = Opt <- Opts,
@@ -244,7 +243,7 @@ accept_loop(Driver, Listen, Kernel, Socket) ->
trace([{active, false},{packet, 4}|Opts]),
net_kernel:connecttime())
of
- {ok, #sslsocket{pid = DistCtrl} = SslSocket} ->
+ {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
trace(
Kernel !
{accept, self(), DistCtrl,
@@ -404,7 +403,7 @@ gen_accept_connection(
do_accept(
_Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime, Kernel) ->
- SslSocket = ssl_connection:get_sslsocket(DistCtrl),
+ {ok, SslSocket} = tls_sender:dist_tls_socket(DistCtrl),
receive
{AcceptPid, controller} ->
Timer = dist_util:start_timer(SetupTime),
@@ -481,22 +480,25 @@ allowed_nodes(PeerCert, Allowed, PeerIP, Node, Host) ->
allowed_nodes(PeerCert, Allowed, PeerIP)
end.
-
-
setup(Node, Type, MyNode, LongOrShortNames, SetupTime) ->
gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime).
gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
Kernel = self(),
monitor_pid(
- spawn_opt(
- fun() ->
- do_setup(
- Driver, Kernel, Node, Type,
- MyNode, LongOrShortNames, SetupTime)
- end,
- [link, {priority, max}])).
+ spawn_opt(setup_fun(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime),
+ [link, {priority, max}])).
+
+-spec setup_fun(_,_,_,_,_,_,_) -> fun(() -> no_return()).
+setup_fun(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
+ fun() ->
+ do_setup(
+ Driver, Kernel, Node, Type,
+ MyNode, LongOrShortNames, SetupTime)
+ end.
+
+-spec do_setup(_,_,_,_,_,_,_) -> no_return().
do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
{Name, Address} = split_node(Driver, Node, LongOrShortNames),
ErlEpmd = net_kernel:epmd_module(),
@@ -521,6 +523,8 @@ do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
trace({getaddr_failed, Driver, Address, Other}))
end.
+-spec do_setup_connect(_,_,_,_,_,_,_,_,_,_) -> no_return().
+
do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNode, Timer) ->
Opts = trace(connect_options(get_ssl_options(client))),
dist_util:reset_timer(Timer),
@@ -529,7 +533,7 @@ do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNo
[binary, {active, false}, {packet, 4},
Driver:family(), nodelay()] ++ Opts,
net_kernel:connecttime()) of
- {ok, #sslsocket{pid = DistCtrl} = SslSocket} ->
+ {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
_ = monitor_pid(DistCtrl),
ok = ssl:controlling_process(SslSocket, self()),
HSData0 = hs_data_common(SslSocket),
@@ -565,10 +569,10 @@ gen_close(Driver, Socket) ->
%% Determine if EPMD module supports address resolving. Default
%% is to use inet_tcp:getaddr/2.
%% ------------------------------------------------------------
-get_address_resolver(EpmdModule, Driver) ->
+get_address_resolver(EpmdModule, _Driver) ->
case erlang:function_exported(EpmdModule, address_please, 3) of
true -> {EpmdModule, address_please};
- _ -> {Driver, getaddr}
+ _ -> {erl_epmd, address_please}
end.
%% ------------------------------------------------------------
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index da281829cb..936df12e70 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -10,6 +10,7 @@
tls_v1,
ssl_v3,
tls_connection_sup,
+ tls_sender,
%% DTLS
dtls_connection,
dtls_handshake,
@@ -21,8 +22,6 @@
dtls_listener_sup,
%% API
ssl, %% Main API
- tls, %% TLS specific
- dtls, %% DTLS specific
ssl_session_cache_api,
%% Both TLS/SSL and DTLS
ssl_config,
@@ -30,6 +29,7 @@
ssl_handshake,
ssl_record,
ssl_cipher,
+ ssl_cipher_format,
ssl_srp_primes,
ssl_alert,
ssl_listen_tracker_sup, %% may be used by DTLS over SCTP
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index bfdd0c205b..ae4d60b6ed 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,6 +1,7 @@
%% -*- erlang -*-
{"%VSN%",
- [
+[
+ {<<"9\\..*">>, [{restart_application, ssl}]},
{<<"8\\..*">>, [{restart_application, ssl}]},
{<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
@@ -9,6 +10,7 @@
{<<"3\\..*">>, [{restart_application, ssl}]}
],
[
+ {<<"9\\..*">>, [{restart_application, ssl}]},
{<<"8\\..*">>, [{restart_application, ssl}]},
{<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 0f13b737ab..00a7f0a53a 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -61,16 +61,321 @@
-deprecated({ssl_accept, 2, eventually}).
-deprecated({ssl_accept, 3, eventually}).
+-export_type([socket/0,
+ sslsocket/0,
+ socket_option/0,
+ active_msgs/0,
+ host/0,
+ tls_option/0,
+ tls_client_option/0,
+ tls_server_option/0,
+ erl_cipher_suite/0,
+ old_cipher_suite/0,
+ ciphers/0,
+ cipher/0,
+ hash/0,
+ kex_algo/0,
+ prf_random/0,
+ cipher_filters/0,
+ sign_algo/0,
+ protocol_version/0,
+ protocol_extensions/0,
+ session_id/0,
+ error_alert/0,
+ tls_alert/0,
+ srp_param_type/0,
+ named_curve/0]).
+
+%% -------------------------------------------------------------------------------------------------------
+
+-type socket() :: gen_tcp:socket(). % exported
+-type socket_option() :: gen_tcp:connect_option() | gen_tcp:listen_option() | gen_udp:option(). % exported
+-type sslsocket() :: any(). % exported
+-type tls_option() :: tls_client_option() | tls_server_option(). % exported
+-type tls_client_option() :: client_option() | common_option() | socket_option() | transport_option(). % exported
+-type tls_server_option() :: server_option() | common_option() | socket_option() | transport_option(). % exported
+-type active_msgs() :: {ssl, sslsocket(), Data::binary() | list()} | {ssl_closed, sslsocket()} |
+ {ssl_error, sslsocket(), Reason::any()} | {ssl_passive, sslsocket()}. % exported
+-type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(),
+ ClosedTag::atom(), ErrTag::atom()}} |
+ {cb_info, {CallbackModule::atom(), DataTag::atom(),
+ ClosedTag::atom(), ErrTag::atom(), PassiveTag::atom()}}.
+-type host() :: hostname() | ip_address(). % exported
+-type hostname() :: string().
+-type ip_address() :: inet:ip_address().
+-type session_id() :: binary().
+-type protocol_version() :: tls_version() | dtls_version().
+-type tls_version() :: tlsv1 | 'tlsv1.1' | 'tlsv1.2' | 'tlsv1.3' | legacy_version().
+-type dtls_version() :: 'dtlsv1' | 'dtlsv1.2'.
+-type legacy_version() :: sslv3.
+-type verify_type() :: verify_none | verify_peer.
+-type cipher() :: aes_128_cbc |
+ aes_256_cbc |
+ aes_128_gcm |
+ aes_256_gcm |
+ chacha20_poly1305 |
+ legacy_cipher(). % exported
+-type legacy_cipher() :: rc4_128 |
+ des_cbc |
+ '3des_ede_cbc'.
+
+-type hash() :: sha |
+ sha2() |
+ legacy_hash(). % exported
+
+-type sha2() :: sha224 |
+ sha256 |
+ sha384 |
+ sha512.
+
+-type legacy_hash() :: md5.
+
+-type sign_algo() :: rsa | dsa | ecdsa. % exported
+
+-type kex_algo() :: rsa |
+ dhe_rsa | dhe_dss |
+ ecdhe_ecdsa | ecdh_ecdsa | ecdh_rsa |
+ srp_rsa| srp_dss |
+ psk | dhe_psk | rsa_psk |
+ dh_anon | ecdh_anon | srp_anon.
+
+-type erl_cipher_suite() :: #{key_exchange := kex_algo(),
+ cipher := cipher(),
+ mac := hash() | aead,
+ prf := hash() | default_prf %% Old cipher suites, version dependent
+ }.
+
+-type old_cipher_suite() :: {kex_algo(), cipher(), hash()} % Pre TLS 1.2
+ %% TLS 1.2, internally PRE TLS 1.2 will use default_prf
+ | {kex_algo(), cipher(), hash() | aead, hash()}.
+
+-type named_curve() :: sect571r1 |
+ sect571k1 |
+ secp521r1 |
+ brainpoolP512r1 |
+ sect409k1 |
+ sect409r1 |
+ brainpoolP384r1 |
+ secp384r1 |
+ sect283k1 |
+ sect283r1 |
+ brainpoolP256r1 |
+ secp256k1 |
+ secp256r1 |
+ sect239k1 |
+ sect233k1 |
+ sect233r1 |
+ secp224k1 |
+ secp224r1 |
+ sect193r1 |
+ sect193r2 |
+ secp192k1 |
+ secp192r1 |
+ sect163k1 |
+ sect163r1 |
+ sect163r2 |
+ secp160k1 |
+ secp160r1 |
+ secp160r2. % exported
+
+-type srp_param_type() :: srp_1024 |
+ srp_1536 |
+ srp_2048 |
+ srp_3072 |
+ srp_4096 |
+ srp_6144 |
+ srp_8192. % exported
+
+-type error_alert() :: {tls_alert, {tls_alert(), Description::string()}}. % exported
+
+-type tls_alert() :: close_notify |
+ unexpected_message |
+ bad_record_mac |
+ record_overflow |
+ handshake_failure |
+ bad_certificate |
+ unsupported_certificate |
+ certificate_revoked |
+ certificate_expired |
+ certificate_unknown |
+ illegal_parameter |
+ unknown_ca |
+ access_denied |
+ decode_error |
+ decrypt_error |
+ export_restriction|
+ protocol_version |
+ insufficient_security |
+ internal_error |
+ inappropriate_fallback |
+ user_canceled |
+ no_renegotiation |
+ unsupported_extension |
+ certificate_unobtainable |
+ unrecognized_name |
+ bad_certificate_status_response |
+ bad_certificate_hash_value |
+ unknown_psk_identity |
+ no_application_protocol. % exported
+
+%% -------------------------------------------------------------------------------------------------------
+-type common_option() :: {protocol, protocol()} |
+ {handshake, handshake_completion()} |
+ {cert, cert()} |
+ {certfile, cert_pem()} |
+ {key, key()} |
+ {keyfile, key_pem()} |
+ {password, key_password()} |
+ {ciphers, cipher_suites()} |
+ {secure_renegotiate, secure_renegotiation()} |
+ {depth, allowed_cert_chain_length()} |
+ {verify_fun, custom_verify()} |
+ {crl_check, crl_check()} |
+ {crl_cache, crl_cache_opts()} |
+ {max_handshake_size, handshake_size()} |
+ {partial_chain, root_fun()} |
+ {versions, protocol_versions()} |
+ {user_lookup_fun, custom_user_lookup()} |
+ {log_alert, log_alert()} |
+ {hibernate_after, hibernate_after()} |
+ {padding_check, padding_check()} |
+ {beast_mitigation, beast_mitigation()} |
+ {ssl_imp, ssl_imp()}.
+
+-type protocol() :: tls | dtls.
+-type handshake_completion() :: hello | full.
+-type cert() :: public_key:der_encoded().
+-type cert_pem() :: file:filename().
+-type key() :: {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey' |'PrivateKeyInfo',
+ public_key:der_encoded()} |
+ #{algorithm := rsa | dss | ecdsa,
+ engine := crypto:engine_ref(),
+ key_id := crypto:key_id(),
+ password => crypto:password()}. % exported
+-type key_pem() :: file:filename().
+-type key_password() :: string().
+-type cipher_suites() :: ciphers().
+-type ciphers() :: [erl_cipher_suite()] |
+ string(). % (according to old API) exported
+-type cipher_filters() :: list({key_exchange | cipher | mac | prf,
+ algo_filter()}). % exported
+-type algo_filter() :: fun((kex_algo()|cipher()|hash()|aead|default_prf) -> true | false).
+-type secure_renegotiation() :: boolean().
+-type allowed_cert_chain_length() :: integer().
+-type custom_verify() :: {Verifyfun :: fun(), InitialUserState :: term()}.
+-type crl_check() :: boolean() | peer | best_effort.
+-type crl_cache_opts() :: [term()].
+-type handshake_size() :: integer().
+-type hibernate_after() :: timeout().
+-type root_fun() :: fun().
+-type protocol_versions() :: [protocol_version()].
+-type signature_algs() :: [{hash(), sign_algo()}].
+-type custom_user_lookup() :: {Lookupfun :: fun(), UserState :: term()}.
+-type padding_check() :: boolean().
+-type beast_mitigation() :: one_n_minus_one | zero_n | disabled.
+-type srp_identity() :: {Username :: string(), Password :: string()}.
+-type psk_identity() :: string().
+-type log_alert() :: boolean().
+
+%% -------------------------------------------------------------------------------------------------------
+
+-type client_option() :: {verify, client_verify_type()} |
+ {reuse_session, client_reuse_session()} |
+ {reuse_sessions, client_reuse_sessions()} |
+ {cacerts, client_cacerts()} |
+ {cacertfile, client_cafile()} |
+ {alpn_advertised_protocols, client_alpn()} |
+ {client_preferred_next_protocols, client_preferred_next_protocols()} |
+ {psk_identity, client_psk_identity()} |
+ {srp_identity, client_srp_identity()} |
+ {server_name_indication, sni()} |
+ {customize_hostname_check, customize_hostname_check()} |
+ {signature_algs, client_signature_algs()} |
+ {fallback, fallback()}.
+
+-type client_verify_type() :: verify_type().
+-type client_reuse_session() :: session_id().
+-type client_reuse_sessions() :: boolean() | save.
+-type client_cacerts() :: [public_key:der_encoded()].
+-type client_cafile() :: file:filename().
+-type app_level_protocol() :: binary().
+-type client_alpn() :: [app_level_protocol()].
+-type client_preferred_next_protocols() :: {Precedence :: server | client,
+ ClientPrefs :: [app_level_protocol()]} |
+ {Precedence :: server | client,
+ ClientPrefs :: [app_level_protocol()],
+ Default::app_level_protocol()}.
+-type client_psk_identity() :: psk_identity().
+-type client_srp_identity() :: srp_identity().
+-type customize_hostname_check() :: list().
+-type sni() :: HostName :: hostname() | disable.
+-type client_signature_algs() :: signature_algs().
+-type fallback() :: boolean().
+-type ssl_imp() :: new | old.
+
+%% -------------------------------------------------------------------------------------------------------
+-type server_option() :: {cacerts, server_cacerts()} |
+ {cacertfile, server_cafile()} |
+ {dh, dh_der()} |
+ {dhfile, dh_file()} |
+ {verify, server_verify_type()} |
+ {fail_if_no_peer_cert, fail_if_no_peer_cert()} |
+ {reuse_sessions, server_reuse_sessions()} |
+ {reuse_session, server_reuse_session()} |
+ {alpn_preferred_protocols, server_alpn()} |
+ {next_protocols_advertised, server_next_protocol()} |
+ {psk_identity, server_psk_identity()} |
+ {honor_cipher_order, boolean()} |
+ {sni_hosts, sni_hosts()} |
+ {sni_fun, sni_fun()} |
+ {honor_cipher_order, honor_cipher_order()} |
+ {honor_ecc_order, honor_ecc_order()} |
+ {client_renegotiation, client_renegotiation()}|
+ {signature_algs, server_signature_algs()}.
+
+-type server_cacerts() :: [public_key:der_encoded()].
+-type server_cafile() :: file:filename().
+-type server_alpn() :: [app_level_protocol()].
+-type server_next_protocol() :: [app_level_protocol()].
+-type server_psk_identity() :: psk_identity().
+-type dh_der() :: binary().
+-type dh_file() :: file:filename().
+-type server_verify_type() :: verify_type().
+-type fail_if_no_peer_cert() :: boolean().
+-type server_signature_algs() :: signature_algs().
+-type server_reuse_session() :: fun().
+-type server_reuse_sessions() :: boolean().
+-type sni_hosts() :: [{hostname(), [server_option() | common_option()]}].
+-type sni_fun() :: fun().
+-type honor_cipher_order() :: boolean().
+-type honor_ecc_order() :: boolean().
+-type client_renegotiation() :: boolean().
+%% -------------------------------------------------------------------------------------------------------
+-type prf_random() :: client_random | server_random. % exported
+-type protocol_extensions() :: #{renegotiation_info => binary(),
+ signature_algs => signature_algs(),
+ alpn => app_level_protocol(),
+ srp => binary(),
+ next_protocol => app_level_protocol(),
+ ec_point_formats => [0..2],
+ elliptic_curves => [public_key:oid()],
+ sni => hostname()}. % exported
+%% -------------------------------------------------------------------------------------------------------
+
+%%%--------------------------------------------------------------------
+%%% API
+%%%--------------------------------------------------------------------
+
%%--------------------------------------------------------------------
--spec start() -> ok | {error, reason()}.
--spec start(permanent | transient | temporary) -> ok | {error, reason()}.
%%
%% Description: Utility function that starts the ssl and applications
%% that it depends on.
%% see application(3)
%%--------------------------------------------------------------------
+-spec start() -> ok | {error, reason()}.
start() ->
start(temporary).
+-spec start(permanent | transient | temporary) -> ok | {error, reason()}.
start(Type) ->
case application:ensure_all_started(ssl, Type) of
{ok, _} ->
@@ -87,24 +392,36 @@ stop() ->
application:stop(ssl).
%%--------------------------------------------------------------------
--spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
- {error, reason()}.
--spec connect(host() | port(), [connect_option()] | inet:port_number(),
- timeout() | list()) ->
- {ok, #sslsocket{}} | {error, reason()}.
--spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
%%
%% Description: Connect to an ssl server.
%%--------------------------------------------------------------------
+-spec connect(TCPSocket, TLSOptions) ->
+ {ok, sslsocket()} |
+ {error, reason()} |
+ {option_not_a_key_value_tuple, any()} when
+ TCPSocket :: socket(),
+ TLSOptions :: [tls_client_option()].
+
connect(Socket, SslOptions) when is_port(Socket) ->
connect(Socket, SslOptions, infinity).
+-spec connect(TCPSocket, TLSOptions, Timeout) ->
+ {ok, sslsocket()} | {error, reason()} when
+ TCPSocket :: socket(),
+ TLSOptions :: [tls_client_option()],
+ Timeout :: timeout();
+ (Host, Port, TLSOptions) ->
+ {ok, sslsocket()} |
+ {ok, sslsocket(),Ext :: protocol_extensions()} |
+ {error, reason()} |
+ {option_not_a_key_value_tuple, any()} when
+ Host :: host(),
+ Port :: inet:port_number(),
+ TLSOptions :: [tls_client_option()].
connect(Socket, SslOptions0, Timeout) when is_port(Socket),
- (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
- {Transport,_,_,_} = proplists:get_value(cb_info, SslOptions0,
- {gen_tcp, tcp, tcp_closed, tcp_error}),
+ (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+ CbInfo = handle_option(cb_info, SslOptions0, default_cb_info(tls)),
+ Transport = element(1, CbInfo),
EmulatedOptions = tls_socket:emulated_options(),
{ok, SocketValues} = tls_socket:getopts(Transport, Socket, EmulatedOptions),
try handle_options(SslOptions0 ++ SocketValues, client) of
@@ -117,6 +434,16 @@ connect(Socket, SslOptions0, Timeout) when is_port(Socket),
connect(Host, Port, Options) ->
connect(Host, Port, Options, infinity).
+-spec connect(Host, Port, TLSOptions, Timeout) ->
+ {ok, sslsocket()} |
+ {ok, sslsocket(),Ext :: protocol_extensions()} |
+ {error, reason()} |
+ {option_not_a_key_value_tuple, any()} when
+ Host :: host(),
+ Port :: inet:port_number(),
+ TLSOptions :: [tls_client_option()],
+ Timeout :: timeout().
+
connect(Host, Port, Options, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
try
{ok, Config} = handle_options(Options, client, Host),
@@ -132,7 +459,10 @@ connect(Host, Port, Options, Timeout) when (is_integer(Timeout) andalso Timeout
end.
%%--------------------------------------------------------------------
--spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
+-spec listen(Port, Options) -> {ok, ListenSocket} | {error, reason()} when
+ Port::inet:port_number(),
+ Options::[tls_server_option()],
+ ListenSocket :: sslsocket().
%%
%% Description: Creates an ssl listen socket.
@@ -148,16 +478,23 @@ listen(Port, Options0) ->
Error
end.
%%--------------------------------------------------------------------
--spec transport_accept(#sslsocket{}) -> {ok, #sslsocket{}} |
- {error, reason()}.
--spec transport_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {error, reason()}.
%%
%% Description: Performs transport accept on an ssl listen socket
%%--------------------------------------------------------------------
+-spec transport_accept(ListenSocket) -> {ok, SslSocket} |
+ {error, reason()} when
+ ListenSocket :: sslsocket(),
+ SslSocket :: sslsocket().
+
transport_accept(ListenSocket) ->
transport_accept(ListenSocket, infinity).
+-spec transport_accept(ListenSocket, Timeout) -> {ok, SslSocket} |
+ {error, reason()} when
+ ListenSocket :: sslsocket(),
+ Timeout :: timeout(),
+ SslSocket :: sslsocket().
+
transport_accept(#sslsocket{pid = {ListenSocket,
#config{connection_cb = ConnectionCb} = Config}}, Timeout)
when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
@@ -169,25 +506,40 @@ transport_accept(#sslsocket{pid = {ListenSocket,
end.
%%--------------------------------------------------------------------
--spec ssl_accept(#sslsocket{}) -> ok | {error, reason()}.
--spec ssl_accept(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
-
--spec ssl_accept(#sslsocket{} | port(), [ssl_option()] | [ssl_option()| transport_option()], timeout()) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
+-spec ssl_accept(SslSocket) ->
+ ok |
+ {error, Reason} when
+ SslSocket :: sslsocket(),
+ Reason :: closed | timeout | error_alert().
+
ssl_accept(ListenSocket) ->
ssl_accept(ListenSocket, [], infinity).
+
+-spec ssl_accept(Socket, TimeoutOrOptions) ->
+ ok |
+ {ok, sslsocket()} | {error, Reason} when
+ Socket :: sslsocket() | socket(),
+ TimeoutOrOptions :: timeout() | [tls_server_option()],
+ Reason :: timeout | closed | {options, any()} | error_alert().
+
ssl_accept(Socket, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_accept(Socket, [], Timeout);
ssl_accept(ListenSocket, SslOptions) when is_port(ListenSocket) ->
ssl_accept(ListenSocket, SslOptions, infinity);
ssl_accept(Socket, Timeout) ->
ssl_accept(Socket, [], Timeout).
+
+-spec ssl_accept(Socket, Options, Timeout) ->
+ ok | {ok, sslsocket()} | {error, Reason} when
+ Socket :: sslsocket() | socket(),
+ Options :: [tls_server_option()],
+ Timeout :: timeout(),
+ Reason :: timeout | closed | {options, any()} | error_alert().
+
ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
handshake(Socket, SslOptions, Timeout);
ssl_accept(Socket, SslOptions, Timeout) ->
@@ -198,20 +550,35 @@ ssl_accept(Socket, SslOptions, Timeout) ->
Error
end.
%%--------------------------------------------------------------------
--spec handshake(#sslsocket{}) -> {ok, #sslsocket{}} | {error, reason()}.
--spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
--spec handshake(#sslsocket{} | port(), [ssl_option()] | [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
+
+%% Performs the SSL/TLS/DTLS server-side handshake.
+
+-spec handshake(HsSocket) -> {ok, SslSocket} | {ok, SslSocket, Ext} | {error, Reason} when
+ HsSocket :: sslsocket(),
+ SslSocket :: sslsocket(),
+ Ext :: protocol_extensions(),
+ Reason :: closed | timeout | error_alert().
+
handshake(ListenSocket) ->
handshake(ListenSocket, infinity).
+-spec handshake(HsSocket, Timeout) -> {ok, SslSocket} | {ok, SslSocket, Ext} | {error, Reason} when
+ HsSocket :: sslsocket(),
+ Timeout :: timeout(),
+ SslSocket :: sslsocket(),
+ Ext :: protocol_extensions(),
+ Reason :: closed | timeout | error_alert();
+ (Socket, Options) -> {ok, SslSocket} | {ok, SslSocket, Ext} | {error, Reason} when
+ Socket :: socket() | sslsocket(),
+ SslSocket :: sslsocket(),
+ Options :: [server_option()],
+ Ext :: protocol_extensions(),
+ Reason :: closed | timeout | error_alert().
+
handshake(#sslsocket{} = Socket, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or
(Timeout == infinity) ->
ssl_connection:handshake(Socket, Timeout);
@@ -219,6 +586,17 @@ handshake(#sslsocket{} = Socket, Timeout) when (is_integer(Timeout) andalso Tim
handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
handshake(ListenSocket, SslOptions, infinity).
+-spec handshake(Socket, Options, Timeout) ->
+ {ok, SslSocket} |
+ {ok, SslSocket, Ext} |
+ {error, Reason} when
+ Socket :: socket() | sslsocket(),
+ SslSocket :: sslsocket(),
+ Options :: [server_option()],
+ Timeout :: timeout(),
+ Ext :: protocol_extensions(),
+ Reason :: closed | timeout | {options, any()} | error_alert().
+
handshake(#sslsocket{} = Socket, [], Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or
(Timeout == infinity)->
handshake(Socket, Timeout);
@@ -231,7 +609,7 @@ handshake(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts, Timeout) when
catch
Error = {error, _Reason} -> Error
end;
-handshake(#sslsocket{pid = Pid, fd = {_, _, _}} = Socket, SslOpts, Timeout) when
+handshake(#sslsocket{pid = [Pid|_], fd = {_, _, _}} = Socket, SslOpts, Timeout) when
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
try
{ok, EmOpts, _} = dtls_packet_demux:get_all_opts(Pid),
@@ -242,8 +620,8 @@ handshake(#sslsocket{pid = Pid, fd = {_, _, _}} = Socket, SslOpts, Timeout) when
end;
handshake(Socket, SslOptions, Timeout) when is_port(Socket),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
- {Transport,_,_,_} =
- proplists:get_value(cb_info, SslOptions, {gen_tcp, tcp, tcp_closed, tcp_error}),
+ CbInfo = handle_option(cb_info, SslOptions, default_cb_info(tls)),
+ Transport = element(1, CbInfo),
EmulatedOptions = tls_socket:emulated_options(),
{ok, SocketValues} = tls_socket:getopts(Transport, Socket, EmulatedOptions),
ConnetionCb = connection_cb(SslOptions),
@@ -261,8 +639,12 @@ handshake(Socket, SslOptions, Timeout) when is_port(Socket),
%%--------------------------------------------------------------------
--spec handshake_continue(#sslsocket{}, [ssl_option()]) ->
- {ok, #sslsocket{}} | {error, reason()}.
+-spec handshake_continue(HsSocket, Options) ->
+ {ok, SslSocket} | {error, Reason} when
+ HsSocket :: sslsocket(),
+ Options :: [tls_client_option() | tls_server_option()],
+ SslSocket :: sslsocket(),
+ Reason :: closed | timeout | error_alert().
%%
%%
%% Description: Continues the handshke possible with newly supplied options.
@@ -270,8 +652,13 @@ handshake(Socket, SslOptions, Timeout) when is_port(Socket),
handshake_continue(Socket, SSLOptions) ->
handshake_continue(Socket, SSLOptions, infinity).
%%--------------------------------------------------------------------
--spec handshake_continue(#sslsocket{}, [ssl_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
+-spec handshake_continue(HsSocket, Options, Timeout) ->
+ {ok, SslSocket} | {error, Reason} when
+ HsSocket :: sslsocket(),
+ Options :: [tls_client_option() | tls_server_option()],
+ Timeout :: timeout(),
+ SslSocket :: sslsocket(),
+ Reason :: closed | timeout | error_alert().
%%
%%
%% Description: Continues the handshke possible with newly supplied options.
@@ -279,7 +666,7 @@ handshake_continue(Socket, SSLOptions) ->
handshake_continue(Socket, SSLOptions, Timeout) ->
ssl_connection:handshake_continue(Socket, SSLOptions, Timeout).
%%--------------------------------------------------------------------
--spec handshake_cancel(#sslsocket{}) -> term().
+-spec handshake_cancel(#sslsocket{}) -> any().
%%
%% Description: Cancels the handshakes sending a close alert.
%%--------------------------------------------------------------------
@@ -287,77 +674,103 @@ handshake_cancel(Socket) ->
ssl_connection:handshake_cancel(Socket).
%%--------------------------------------------------------------------
--spec close(#sslsocket{}) -> term().
+-spec close(SslSocket) -> ok | {error, Reason} when
+ SslSocket :: sslsocket(),
+ Reason :: any().
%%
%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+close(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
ssl_connection:close(Pid, {close, ?DEFAULT_TIMEOUT});
close(#sslsocket{pid = {dtls, #config{dtls_handler = {Pid, _}}}}) ->
dtls_packet_demux:close(Pid);
-close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}) ->
+close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_,_,_,_}}}}) ->
Transport:close(ListenSocket).
%%--------------------------------------------------------------------
--spec close(#sslsocket{}, timeout() | {pid(), integer()}) -> term().
+-spec close(SslSocket, How) -> ok | {ok, port()} | {error,Reason} when
+ SslSocket :: sslsocket(),
+ How :: timeout() | {NewController::pid(), timeout()},
+ Reason :: any().
%%
%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = TLSPid},
+close(#sslsocket{pid = [TLSPid|_]},
{Pid, Timeout} = DownGrade) when is_pid(TLSPid),
is_pid(Pid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_connection:close(TLSPid, {close, DownGrade});
-close(#sslsocket{pid = TLSPid}, Timeout) when is_pid(TLSPid),
+close(#sslsocket{pid = [TLSPid|_]}, Timeout) when is_pid(TLSPid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_connection:close(TLSPid, {close, Timeout});
-close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}, _) ->
+close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_,_,_,_}}}}, _) ->
Transport:close(ListenSocket).
%%--------------------------------------------------------------------
--spec send(#sslsocket{}, iodata()) -> ok | {error, reason()}.
+-spec send(SslSocket, Data) -> ok | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Data :: iodata().
%%
%% Description: Sends data over the ssl connection
%%--------------------------------------------------------------------
-send(#sslsocket{pid = Pid}, Data) when is_pid(Pid) ->
+send(#sslsocket{pid = [Pid]}, Data) when is_pid(Pid) ->
ssl_connection:send(Pid, Data);
+send(#sslsocket{pid = [_, Pid]}, Data) when is_pid(Pid) ->
+ tls_sender:send_data(Pid, erlang:iolist_to_iovec(Data));
send(#sslsocket{pid = {_, #config{transport_info={_, udp, _, _}}}}, _) ->
{error,enotconn}; %% Emulate connection behaviour
send(#sslsocket{pid = {dtls,_}}, _) ->
{error,enotconn}; %% Emulate connection behaviour
-send(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport, _, _, _}}}}, Data) ->
+send(#sslsocket{pid = {ListenSocket, #config{transport_info = Info}}}, Data) ->
+ Transport = element(1, Info),
Transport:send(ListenSocket, Data). %% {error,enotconn}
%%--------------------------------------------------------------------
--spec recv(#sslsocket{}, integer()) -> {ok, binary()| list()} | {error, reason()}.
--spec recv(#sslsocket{}, integer(), timeout()) -> {ok, binary()| list()} | {error, reason()}.
%%
%% Description: Receives data when active = false
%%--------------------------------------------------------------------
+-spec recv(SslSocket, Length) -> {ok, Data} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Length :: integer(),
+ Data :: binary() | list() | HttpPacket,
+ HttpPacket :: any().
+
recv(Socket, Length) ->
recv(Socket, Length, infinity).
-recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid),
+
+-spec recv(SslSocket, Length, Timeout) -> {ok, Data} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Length :: integer(),
+ Data :: binary() | list() | HttpPacket,
+ Timeout :: timeout(),
+ HttpPacket :: any().
+
+recv(#sslsocket{pid = [Pid|_]}, Length, Timeout) when is_pid(Pid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
ssl_connection:recv(Pid, Length, Timeout);
recv(#sslsocket{pid = {dtls,_}}, _, _) ->
{error,enotconn};
recv(#sslsocket{pid = {Listen,
- #config{transport_info = {Transport, _, _, _}}}}, _,_) when is_port(Listen)->
+ #config{transport_info = Info}}},_,_) when is_port(Listen)->
+ Transport = element(1, Info),
Transport:recv(Listen, 0). %% {error,enotconn}
%%--------------------------------------------------------------------
--spec controlling_process(#sslsocket{}, pid()) -> ok | {error, reason()}.
+-spec controlling_process(SslSocket, NewOwner) -> ok | {error, Reason} when
+ SslSocket :: sslsocket(),
+ NewOwner :: pid(),
+ Reason :: any().
%%
%% Description: Changes process that receives the messages when active = true
%% or once.
%%--------------------------------------------------------------------
-controlling_process(#sslsocket{pid = Pid}, NewOwner) when is_pid(Pid), is_pid(NewOwner) ->
+controlling_process(#sslsocket{pid = [Pid|_]}, NewOwner) when is_pid(Pid), is_pid(NewOwner) ->
ssl_connection:new_user(Pid, NewOwner);
controlling_process(#sslsocket{pid = {dtls, _}},
NewOwner) when is_pid(NewOwner) ->
ok; %% Meaningless but let it be allowed to conform with TLS
controlling_process(#sslsocket{pid = {Listen,
- #config{transport_info = {Transport, _, _, _}}}},
+ #config{transport_info = {Transport,_,_,_,_}}}},
NewOwner) when is_port(Listen),
is_pid(NewOwner) ->
%% Meaningless but let it be allowed to conform with normal sockets
@@ -365,11 +778,15 @@ controlling_process(#sslsocket{pid = {Listen,
%%--------------------------------------------------------------------
--spec connection_information(#sslsocket{}) -> {ok, list()} | {error, reason()}.
+-spec connection_information(SslSocket) -> {ok, Result} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Result :: [{OptionName, OptionValue}],
+ OptionName :: atom(),
+ OptionValue :: any().
%%
%% Description: Return SSL information for the connection
%%--------------------------------------------------------------------
-connection_information(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+connection_information(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
case ssl_connection:connection_information(Pid, false) of
{ok, Info} ->
{ok, [Item || Item = {_Key, Value} <- Info, Value =/= undefined]};
@@ -382,11 +799,16 @@ connection_information(#sslsocket{pid = {dtls,_}}) ->
{error,enotconn}.
%%--------------------------------------------------------------------
--spec connection_information(#sslsocket{}, [atom()]) -> {ok, list()} | {error, reason()}.
+-spec connection_information(SslSocket, Items) -> {ok, Result} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Items :: [OptionName],
+ Result :: [{OptionName, OptionValue}],
+ OptionName :: atom(),
+ OptionValue :: any().
%%
%% Description: Return SSL information for the connection
%%--------------------------------------------------------------------
-connection_information(#sslsocket{pid = Pid}, Items) when is_pid(Pid) ->
+connection_information(#sslsocket{pid = [Pid|_]}, Items) when is_pid(Pid) ->
case ssl_connection:connection_information(Pid, include_security_info(Items)) of
{ok, Info} ->
{ok, [Item || Item = {Key, Value} <- Info, lists:member(Key, Items),
@@ -396,27 +818,33 @@ connection_information(#sslsocket{pid = Pid}, Items) when is_pid(Pid) ->
end.
%%--------------------------------------------------------------------
--spec peername(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
+-spec peername(SslSocket) -> {ok, {Address, Port}} |
+ {error, reason()} when
+ SslSocket :: sslsocket(),
+ Address :: inet:ip_address(),
+ Port :: inet:port_number().
%%
%% Description: same as inet:peername/1.
%%--------------------------------------------------------------------
-peername(#sslsocket{pid = Pid, fd = {Transport, Socket, _}}) when is_pid(Pid)->
+peername(#sslsocket{pid = [Pid|_], fd = {Transport, Socket,_}}) when is_pid(Pid)->
dtls_socket:peername(Transport, Socket);
-peername(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}) when is_pid(Pid)->
+peername(#sslsocket{pid = [Pid|_], fd = {Transport, Socket,_,_}}) when is_pid(Pid)->
tls_socket:peername(Transport, Socket);
-peername(#sslsocket{pid = {dtls, #config{dtls_handler = {_Pid, _}}}}) ->
+peername(#sslsocket{pid = {dtls, #config{dtls_handler = {_Pid,_}}}}) ->
dtls_socket:peername(dtls, undefined);
-peername(#sslsocket{pid = {ListenSocket, #config{transport_info = {Transport,_,_,_}}}}) ->
+peername(#sslsocket{pid = {ListenSocket, #config{transport_info = {Transport,_,_,_,_}}}}) ->
tls_socket:peername(Transport, ListenSocket); %% Will return {error, enotconn}
peername(#sslsocket{pid = {dtls,_}}) ->
{error,enotconn}.
%%--------------------------------------------------------------------
--spec peercert(#sslsocket{}) ->{ok, DerCert::binary()} | {error, reason()}.
+-spec peercert(SslSocket) -> {ok, Cert} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Cert :: binary().
%%
%% Description: Returns the peercert.
%%--------------------------------------------------------------------
-peercert(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+peercert(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
case ssl_connection:peer_certificate(Pid) of
{ok, undefined} ->
{error, no_peercert};
@@ -429,38 +857,43 @@ peercert(#sslsocket{pid = {Listen, _}}) when is_port(Listen) ->
{error, enotconn}.
%%--------------------------------------------------------------------
--spec negotiated_protocol(#sslsocket{}) -> {ok, binary()} | {error, reason()}.
+-spec negotiated_protocol(SslSocket) -> {ok, Protocol} | {error, Reason} when
+ SslSocket :: sslsocket(),
+ Protocol :: binary(),
+ Reason :: protocol_not_negotiated.
%%
%% Description: Returns the protocol that has been negotiated. If no
%% protocol has been negotiated will return {error, protocol_not_negotiated}
%%--------------------------------------------------------------------
-negotiated_protocol(#sslsocket{pid = Pid}) ->
+negotiated_protocol(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
ssl_connection:negotiated_protocol(Pid).
%%--------------------------------------------------------------------
--spec cipher_suites() -> [ssl_cipher:old_erl_cipher_suite()] | [string()].
+-spec cipher_suites() -> [old_cipher_suite()] | [string()].
%%--------------------------------------------------------------------
cipher_suites() ->
cipher_suites(erlang).
%%--------------------------------------------------------------------
--spec cipher_suites(erlang | openssl | all) ->
- [ssl_cipher:old_erl_cipher_suite() | string()].
+-spec cipher_suites(Type) -> [old_cipher_suite() | string()] when
+ Type :: erlang | openssl | all.
+
%% Description: Returns all supported cipher suites.
%%--------------------------------------------------------------------
cipher_suites(erlang) ->
- [ssl_cipher:erl_suite_definition(Suite) || Suite <- available_suites(default)];
+ [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(default)];
cipher_suites(openssl) ->
- [ssl_cipher:openssl_suite_name(Suite) ||
+ [ssl_cipher_format:openssl_suite_name(Suite) ||
Suite <- available_suites(default)];
cipher_suites(all) ->
- [ssl_cipher:erl_suite_definition(Suite) || Suite <- available_suites(all)].
+ [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(all)].
%%--------------------------------------------------------------------
--spec cipher_suites(default | all | anonymous, tls_record:tls_version() | dtls_record:dtls_version() |
- tls_record:tls_atom_version() | dtls_record:dtls_atom_version()) ->
- [ssl_cipher:erl_cipher_suite()].
+-spec cipher_suites(Supported, Version) -> ciphers() when
+ Supported :: default | all | anonymous,
+ Version :: protocol_version().
+
%% Description: Returns all default and all supported cipher suites for a
%% TLS/DTLS version
%%--------------------------------------------------------------------
@@ -473,12 +906,14 @@ cipher_suites(Base, Version) when Version == 'dtlsv1.2';
Version == 'dtlsv1'->
cipher_suites(Base, dtls_record:protocol_version(Version));
cipher_suites(Base, Version) ->
- [ssl_cipher:suite_definition(Suite) || Suite <- supported_suites(Base, Version)].
+ [ssl_cipher_format:suite_definition(Suite) || Suite <- supported_suites(Base, Version)].
%%--------------------------------------------------------------------
--spec filter_cipher_suites([ssl_cipher:erl_cipher_suite()],
- [{key_exchange | cipher | mac | prf, fun()}] | []) ->
- [ssl_cipher:erl_cipher_suite()].
+-spec filter_cipher_suites(Suites, Filters) -> Ciphers when
+ Suites :: ciphers(),
+ Filters :: cipher_filters(),
+ Ciphers :: ciphers().
+
%% Description: Removes cipher suites if any of the filter functions returns false
%% for any part of the cipher suite. This function also calls default filter functions
%% to make sure the cipher suite are supported by crypto.
@@ -495,10 +930,10 @@ filter_cipher_suites(Suites, Filters0) ->
prf_filters => add_filter(proplists:get_value(prf, Filters0), PrfF)},
ssl_cipher:filter_suites(Suites, Filters).
%%--------------------------------------------------------------------
--spec prepend_cipher_suites([ssl_cipher:erl_cipher_suite()] |
- [{key_exchange | cipher | mac | prf, fun()}],
- [ssl_cipher:erl_cipher_suite()]) ->
- [ssl_cipher:erl_cipher_suite()].
+-spec prepend_cipher_suites(Preferred, Suites) -> ciphers() when
+ Preferred :: ciphers() | cipher_filters(),
+ Suites :: ciphers().
+
%% Description: Make <Preferred> suites become the most prefered
%% suites that is put them at the head of the cipher suite list
%% and remove them from <Suites> if present. <Preferred> may be a
@@ -513,10 +948,10 @@ prepend_cipher_suites(Filters, Suites) ->
Preferred = filter_cipher_suites(Suites, Filters),
Preferred ++ (Suites -- Preferred).
%%--------------------------------------------------------------------
--spec append_cipher_suites(Deferred :: [ssl_cipher:erl_cipher_suite()] |
- [{key_exchange | cipher | mac | prf, fun()}],
- [ssl_cipher:erl_cipher_suite()]) ->
- [ssl_cipher:erl_cipher_suite()].
+-spec append_cipher_suites(Deferred, Suites) -> ciphers() when
+ Deferred :: ciphers() | cipher_filters(),
+ Suites :: ciphers().
+
%% Description: Make <Deferred> suites suites become the
%% least prefered suites that is put them at the end of the cipher suite list
%% and removed them from <Suites> if present.
@@ -530,7 +965,9 @@ append_cipher_suites(Filters, Suites) ->
(Suites -- Deferred) ++ Deferred.
%%--------------------------------------------------------------------
--spec eccs() -> tls_v1:curves().
+-spec eccs() -> NamedCurves when
+ NamedCurves :: [named_curve()].
+
%% Description: returns all supported curves across all versions
%%--------------------------------------------------------------------
eccs() ->
@@ -538,27 +975,24 @@ eccs() ->
eccs_filter_supported(Curves).
%%--------------------------------------------------------------------
--spec eccs(tls_record:tls_version() | tls_record:tls_atom_version() |
- dtls_record:dtls_version() | dtls_record:dtls_atom_version()) ->
- tls_v1:curves().
+-spec eccs(Version) -> NamedCurves when
+ Version :: protocol_version(),
+ NamedCurves :: [named_curve()].
+
%% Description: returns the curves supported for a given version of
%% ssl/tls.
%%--------------------------------------------------------------------
-eccs({3,0}) ->
+eccs(sslv3) ->
[];
-eccs({3,_}) ->
- Curves = tls_v1:ecc_curves(all),
- eccs_filter_supported(Curves);
-eccs({254,_} = Version) ->
- eccs(dtls_v1:corresponding_tls_version(Version));
+eccs('dtlsv1') ->
+ eccs('tlsv1.1');
+eccs('dtlsv1.2') ->
+ eccs('tlsv1.2');
eccs(Version) when Version == 'tlsv1.2';
Version == 'tlsv1.1';
- Version == tlsv1;
- Version == sslv3 ->
- eccs(tls_record:protocol_version(Version));
-eccs(Version) when Version == 'dtlsv1.2';
- Version == 'dtlsv1'->
- eccs(dtls_v1:corresponding_tls_version(dtls_record:protocol_version(Version))).
+ Version == tlsv1 ->
+ Curves = tls_v1:ecc_curves(all),
+ eccs_filter_supported(Curves).
eccs_filter_supported(Curves) ->
CryptoCurves = crypto:ec_curves(),
@@ -566,12 +1000,14 @@ eccs_filter_supported(Curves) ->
Curves).
%%--------------------------------------------------------------------
--spec getopts(#sslsocket{}, [gen_tcp:option_name()]) ->
- {ok, [gen_tcp:option()]} | {error, reason()}.
+-spec getopts(SslSocket, OptionNames) ->
+ {ok, [gen_tcp:option()]} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ OptionNames :: [gen_tcp:option_name()].
%%
%% Description: Gets options
%%--------------------------------------------------------------------
-getopts(#sslsocket{pid = Pid}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
+getopts(#sslsocket{pid = [Pid|_]}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
ssl_connection:get_opts(Pid, OptionTags);
getopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, OptionTags) when is_list(OptionTags) ->
try dtls_socket:getopts(Transport, ListenSocket, OptionTags) of
@@ -583,7 +1019,7 @@ getopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} =
_:Error ->
{error, {options, {socket_options, OptionTags, Error}}}
end;
-getopts(#sslsocket{pid = {_, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket,
+getopts(#sslsocket{pid = {_, #config{transport_info = {Transport,_,_,_,_}}}} = ListenSocket,
OptionTags) when is_list(OptionTags) ->
try tls_socket:getopts(Transport, ListenSocket, OptionTags) of
{ok, _} = Result ->
@@ -598,11 +1034,32 @@ getopts(#sslsocket{}, OptionTags) ->
{error, {options, {socket_options, OptionTags}}}.
%%--------------------------------------------------------------------
--spec setopts(#sslsocket{}, [gen_tcp:option()]) -> ok | {error, reason()}.
+-spec setopts(SslSocket, Options) -> ok | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Options :: [gen_tcp:option()].
%%
%% Description: Sets options
%%--------------------------------------------------------------------
-setopts(#sslsocket{pid = Pid}, Options0) when is_pid(Pid), is_list(Options0) ->
+setopts(#sslsocket{pid = [Pid, Sender]}, Options0) when is_pid(Pid), is_list(Options0) ->
+ try proplists:expand([{binary, [{mode, binary}]},
+ {list, [{mode, list}]}], Options0) of
+ Options ->
+ case proplists:get_value(packet, Options, undefined) of
+ undefined ->
+ ssl_connection:set_opts(Pid, Options);
+ PacketOpt ->
+ case tls_sender:setopts(Sender, [{packet, PacketOpt}]) of
+ ok ->
+ ssl_connection:set_opts(Pid, Options);
+ Error ->
+ Error
+ end
+ end
+ catch
+ _:_ ->
+ {error, {options, {not_a_proplist, Options0}}}
+ end;
+setopts(#sslsocket{pid = [Pid|_]}, Options0) when is_pid(Pid), is_list(Options0) ->
try proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Options0) of
Options ->
@@ -621,7 +1078,7 @@ setopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} =
_:Error ->
{error, {options, {socket_options, Options, Error}}}
end;
-setopts(#sslsocket{pid = {_, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, Options) when is_list(Options) ->
+setopts(#sslsocket{pid = {_, #config{transport_info = {Transport,_,_,_,_}}}} = ListenSocket, Options) when is_list(Options) ->
try tls_socket:setopts(Transport, ListenSocket, Options) of
ok ->
ok;
@@ -635,9 +1092,9 @@ setopts(#sslsocket{}, Options) ->
{error, {options,{not_a_proplist, Options}}}.
%%---------------------------------------------------------------
--spec getstat(Socket) ->
- {ok, OptionValues} | {error, inet:posix()} when
- Socket :: #sslsocket{},
+-spec getstat(SslSocket) ->
+ {ok, OptionValues} | {error, inet:posix()} when
+ SslSocket :: sslsocket(),
OptionValues :: [{inet:stat_option(), integer()}].
%%
%% Description: Get all statistic options for a socket.
@@ -646,9 +1103,9 @@ getstat(Socket) ->
getstat(Socket, inet:stats()).
%%---------------------------------------------------------------
--spec getstat(Socket, Options) ->
- {ok, OptionValues} | {error, inet:posix()} when
- Socket :: #sslsocket{},
+-spec getstat(SslSocket, Options) ->
+ {ok, OptionValues} | {error, inet:posix()} when
+ SslSocket :: sslsocket(),
Options :: [inet:stat_option()],
OptionValues :: [{inet:stat_option(), integer()}].
%%
@@ -657,41 +1114,48 @@ getstat(Socket) ->
getstat(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}, Options) when is_port(Listen), is_list(Options) ->
tls_socket:getstat(Transport, Listen, Options);
-getstat(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
+getstat(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
tls_socket:getstat(Transport, Socket, Options).
%%---------------------------------------------------------------
--spec shutdown(#sslsocket{}, read | write | read_write) -> ok | {error, reason()}.
+-spec shutdown(SslSocket, How) -> ok | {error, reason()} when
+ SslSocket :: sslsocket(),
+ How :: read | write | read_write.
%%
%% Description: Same as gen_tcp:shutdown/2
%%--------------------------------------------------------------------
-shutdown(#sslsocket{pid = {Listen, #config{transport_info = {Transport,_, _, _}}}},
+shutdown(#sslsocket{pid = {Listen, #config{transport_info = Info}}},
How) when is_port(Listen) ->
+ Transport = element(1, Info),
Transport:shutdown(Listen, How);
shutdown(#sslsocket{pid = {dtls,_}},_) ->
{error, enotconn};
-shutdown(#sslsocket{pid = Pid}, How) ->
+shutdown(#sslsocket{pid = [Pid|_]}, How) when is_pid(Pid) ->
ssl_connection:shutdown(Pid, How).
%%--------------------------------------------------------------------
--spec sockname(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
+-spec sockname(SslSocket) ->
+ {ok, {Address, Port}} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Address :: inet:ip_address(),
+ Port :: inet:port_number().
%%
%% Description: Same as inet:sockname/1
%%--------------------------------------------------------------------
-sockname(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}) when is_port(Listen) ->
+sockname(#sslsocket{pid = {Listen, #config{transport_info = {Transport,_,_,_,_}}}}) when is_port(Listen) ->
tls_socket:sockname(Transport, Listen);
sockname(#sslsocket{pid = {dtls, #config{dtls_handler = {Pid, _}}}}) ->
dtls_packet_demux:sockname(Pid);
-sockname(#sslsocket{pid = Pid, fd = {Transport, Socket, _}}) when is_pid(Pid) ->
+sockname(#sslsocket{pid = [Pid|_], fd = {Transport, Socket,_}}) when is_pid(Pid) ->
dtls_socket:sockname(Transport, Socket);
-sockname(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}) when is_pid(Pid) ->
+sockname(#sslsocket{pid = [Pid| _], fd = {Transport, Socket,_,_}}) when is_pid(Pid) ->
tls_socket:sockname(Transport, Socket).
%%---------------------------------------------------------------
--spec versions() -> [{ssl_app, string()} | {supported, [tls_record:tls_atom_version()]} |
- {supported_dtls, [dtls_record:dtls_atom_version()]} |
- {available, [tls_record:tls_atom_version()]} |
- {available_dtls, [dtls_record:dtls_atom_version()]}].
+-spec versions() -> [VersionInfo] when
+ VersionInfo :: {ssl_app, string()} |
+ {supported | available, [tls_version()]} |
+ {supported_dtls | available_dtls, [dtls_version()]}.
%%
%% Description: Returns a list of relevant versions.
%%--------------------------------------------------------------------
@@ -702,18 +1166,27 @@ versions() ->
SupportedDTLSVsns = [dtls_record:protocol_version(Vsn) || Vsn <- DTLSVsns],
AvailableTLSVsns = ?ALL_AVAILABLE_VERSIONS,
AvailableDTLSVsns = ?ALL_AVAILABLE_DATAGRAM_VERSIONS,
- [{ssl_app, ?VSN}, {supported, SupportedTLSVsns},
+ [{ssl_app, "9.2"}, {supported, SupportedTLSVsns},
{supported_dtls, SupportedDTLSVsns},
{available, AvailableTLSVsns},
{available_dtls, AvailableDTLSVsns}].
%%---------------------------------------------------------------
--spec renegotiate(#sslsocket{}) -> ok | {error, reason()}.
+-spec renegotiate(SslSocket) -> ok | {error, reason()} when
+ SslSocket :: sslsocket().
%%
%% Description: Initiates a renegotiation.
%%--------------------------------------------------------------------
-renegotiate(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+renegotiate(#sslsocket{pid = [Pid, Sender |_]}) when is_pid(Pid),
+ is_pid(Sender) ->
+ case tls_sender:renegotiate(Sender) of
+ {ok, Write} ->
+ tls_connection:renegotiation(Pid, Write);
+ Error ->
+ Error
+ end;
+renegotiate(#sslsocket{pid = [Pid |_]}) when is_pid(Pid) ->
ssl_connection:renegotiation(Pid);
renegotiate(#sslsocket{pid = {dtls,_}}) ->
{error, enotconn};
@@ -721,13 +1194,17 @@ renegotiate(#sslsocket{pid = {Listen,_}}) when is_port(Listen) ->
{error, enotconn}.
%%--------------------------------------------------------------------
--spec prf(#sslsocket{}, binary() | 'master_secret', binary(),
- [binary() | prf_random()], non_neg_integer()) ->
- {ok, binary()} | {error, reason()}.
+-spec prf(SslSocket, Secret, Label, Seed, WantedLength) ->
+ {ok, binary()} | {error, reason()} when
+ SslSocket :: sslsocket(),
+ Secret :: binary() | 'master_secret',
+ Label::binary(),
+ Seed :: [binary() | prf_random()],
+ WantedLength :: non_neg_integer().
%%
%% Description: use a ssl sessions TLS PRF to generate key material
%%--------------------------------------------------------------------
-prf(#sslsocket{pid = Pid},
+prf(#sslsocket{pid = [Pid|_]},
Secret, Label, Seed, WantedLength) when is_pid(Pid) ->
ssl_connection:prf(Pid, Secret, Label, Seed, WantedLength);
prf(#sslsocket{pid = {dtls,_}}, _,_,_,_) ->
@@ -744,7 +1221,8 @@ clear_pem_cache() ->
ssl_pem_cache:clear().
%%---------------------------------------------------------------
--spec format_error({error, term()}) -> list().
+-spec format_error({error, Reason}) -> string() when
+ Reason :: any().
%%
%% Description: Creates error string.
%%--------------------------------------------------------------------
@@ -754,8 +1232,8 @@ format_error(Reason) when is_list(Reason) ->
Reason;
format_error(closed) ->
"TLS connection is closed";
-format_error({tls_alert, Description}) ->
- "TLS Alert: " ++ Description;
+format_error({tls_alert, {_, Description}}) ->
+ Description;
format_error({options,{FileType, File, Reason}}) when FileType == cacertfile;
FileType == certfile;
FileType == keyfile;
@@ -784,12 +1262,19 @@ tls_version({254, _} = Version) ->
%%--------------------------------------------------------------------
--spec suite_to_str(ssl_cipher:erl_cipher_suite()) -> string().
+-spec suite_to_str(CipherSuite) -> string() when
+ CipherSuite :: erl_cipher_suite();
+ (CipherSuite) -> string() when
+ %% For internal use!
+ CipherSuite :: #{key_exchange := null,
+ cipher := null,
+ mac := null,
+ prf := null}.
%%
%% Description: Return the string representation of a cipher suite.
%%--------------------------------------------------------------------
suite_to_str(Cipher) ->
- ssl_cipher:suite_to_str(Cipher).
+ ssl_cipher_format:suite_to_str(Cipher).
%%%--------------------------------------------------------------
@@ -810,7 +1295,7 @@ supported_suites(all, Version) ->
supported_suites(anonymous, Version) ->
ssl_cipher:anonymous_suites(Version).
-do_listen(Port, #config{transport_info = {Transport, _, _, _}} = Config, tls_connection) ->
+do_listen(Port, #config{transport_info = {Transport, _, _, _,_}} = Config, tls_connection) ->
tls_socket:listen(Transport, Port, Config);
do_listen(Port, Config, dtls_connection) ->
@@ -862,15 +1347,12 @@ handle_options(Opts0, Role, Host) ->
{list, [{mode, list}]}], Opts0),
assert_proplist(Opts),
RecordCb = record_cb(Opts),
-
- ReuseSessionFun = fun(_, _, _, _) -> true end,
CaCerts = handle_option(cacerts, Opts, undefined),
{Verify, FailIfNoPeerCert, CaCertDefault, VerifyFun, PartialChainHanlder, VerifyClientOnce} =
handle_verify_options(Opts, CaCerts),
CertFile = handle_option(certfile, Opts, <<>>),
- RecordCb = record_cb(Opts),
Versions = case handle_option(versions, Opts, []) of
[] ->
@@ -916,9 +1398,8 @@ handle_options(Opts0, Role, Host) ->
default_option_role(server,
tls_v1:default_signature_algs(Versions), Role)),
tls_version(RecordCb:highest_protocol_version(Versions))),
- %% Server side option
- reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun),
- reuse_sessions = handle_option(reuse_sessions, Opts, true),
+ reuse_sessions = handle_reuse_sessions_option(reuse_sessions, Opts, Role),
+ reuse_session = handle_reuse_session_option(reuse_session, Opts, Role),
secure_renegotiate = handle_option(secure_renegotiate, Opts, true),
client_renegotiation = handle_option(client_renegotiation, Opts,
default_option_role(server, true, Role),
@@ -962,7 +1443,7 @@ handle_options(Opts0, Role, Host) ->
customize_hostname_check = handle_option(customize_hostname_check, Opts, [])
},
- CbInfo = proplists:get_value(cb_info, Opts, default_cb_info(Protocol)),
+ CbInfo = handle_option(cb_info, Opts, default_cb_info(Protocol)),
SslOptions = [protocol, versions, verify, verify_fun, partial_chain,
fail_if_no_peer_cert, verify_client_once,
depth, cert, certfile, key, keyfile,
@@ -974,8 +1455,8 @@ handle_options(Opts0, Role, Host) ->
alpn_preferred_protocols, next_protocols_advertised,
client_preferred_next_protocols, log_alert,
server_name_indication, honor_cipher_order, padding_check, crl_check, crl_cache,
- fallback, signature_algs, eccs, honor_ecc_order, beast_mitigation,
- max_handshake_size, handshake, customize_hostname_check],
+ fallback, signature_algs, eccs, honor_ecc_order,
+ beast_mitigation, max_handshake_size, handshake, customize_hostname_check],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
end, Opts, SslOptions),
@@ -1004,6 +1485,10 @@ handle_option(sni_fun, Opts, Default) ->
_ ->
throw({error, {conflict_options, [sni_fun, sni_hosts]}})
end;
+handle_option(cb_info, Opts, Default) ->
+ CbInfo = proplists:get_value(cb_info, Opts, Default),
+ true = validate_option(cb_info, CbInfo),
+ handle_cb_info(CbInfo, Default);
handle_option(OptionName, Opts, Default) ->
validate_option(OptionName,
proplists:get_value(OptionName, Opts, Default)).
@@ -1109,11 +1594,16 @@ validate_option(srp_identity, {Username, Password})
{unicode:characters_to_binary(Username),
unicode:characters_to_binary(Password)};
+validate_option(reuse_session, undefined) ->
+ undefined;
validate_option(reuse_session, Value) when is_function(Value) ->
Value;
+validate_option(reuse_session, Value) when is_binary(Value) ->
+ Value;
validate_option(reuse_sessions, Value) when is_boolean(Value) ->
Value;
-
+validate_option(reuse_sessions, save = Value) ->
+ Value;
validate_option(secure_renegotiate, Value) when is_boolean(Value) ->
Value;
validate_option(client_renegotiation, Value) when is_boolean(Value) ->
@@ -1220,9 +1710,29 @@ validate_option(handshake, full = Value) ->
Value;
validate_option(customize_hostname_check, Value) when is_list(Value) ->
Value;
+validate_option(cb_info, {V1, V2, V3, V4}) when is_atom(V1),
+ is_atom(V2),
+ is_atom(V3),
+ is_atom(V4)
+ ->
+ true;
+validate_option(cb_info, {V1, V2, V3, V4, V5}) when is_atom(V1),
+ is_atom(V2),
+ is_atom(V3),
+ is_atom(V4),
+ is_atom(V5)
+ ->
+ true;
+validate_option(cb_info, _) ->
+ false;
validate_option(Opt, Value) ->
throw({error, {options, {Opt, Value}}}).
+handle_cb_info({V1, V2, V3, V4}, {_,_,_,_,_}) ->
+ {V1,V2,V3,V4, list_to_atom(atom_to_list(V2) ++ "passive")};
+handle_cb_info(CbInfo, _) ->
+ CbInfo.
+
handle_hashsigns_option(Value, Version) when is_list(Value)
andalso Version >= {3, 3} ->
case tls_v1:signature_algs(Version, Value) of
@@ -1236,6 +1746,26 @@ handle_hashsigns_option(_, Version) when Version >= {3, 3} ->
handle_hashsigns_option(_, _Version) ->
undefined.
+handle_reuse_sessions_option(Key, Opts, client) ->
+ Value = proplists:get_value(Key, Opts, true),
+ validate_option(Key, Value),
+ Value;
+handle_reuse_sessions_option(Key, Opts0, server) ->
+ Opts = proplists:delete({Key, save}, Opts0),
+ Value = proplists:get_value(Key, Opts, true),
+ validate_option(Key, Value),
+ Value.
+
+handle_reuse_session_option(Key, Opts, client) ->
+ Value = proplists:get_value(Key, Opts, undefined),
+ validate_option(Key, Value),
+ Value;
+handle_reuse_session_option(Key, Opts, server) ->
+ ReuseSessionFun = fun(_, _, _, _) -> true end,
+ Value = proplists:get_value(Key, Opts, ReuseSessionFun),
+ validate_option(Key, Value),
+ Value.
+
validate_options([]) ->
[];
validate_options([{Opt, Value} | Tail]) ->
@@ -1323,10 +1853,10 @@ binary_cipher_suites(Version, []) ->
%% not require explicit configuration
default_binary_suites(Version);
binary_cipher_suites(Version, [Map|_] = Ciphers0) when is_map(Map) ->
- Ciphers = [ssl_cipher:suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite(C) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, [Tuple|_] = Ciphers0) when is_tuple(Tuple) ->
- Ciphers = [ssl_cipher:suite(tuple_to_map(C)) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite(tuple_to_map(C)) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) ->
All = ssl_cipher:all_suites(Version) ++
@@ -1341,11 +1871,11 @@ binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0)
end;
binary_cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) ->
%% Format: ["RC4-SHA","RC4-MD5"]
- Ciphers = [ssl_cipher:openssl_suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, Ciphers0) ->
%% Format: "RC4-SHA:RC4-MD5"
- Ciphers = [ssl_cipher:openssl_suite(C) || C <- string:lexemes(Ciphers0, ":")],
+ Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- string:lexemes(Ciphers0, ":")],
binary_cipher_suites(Version, Ciphers).
default_binary_suites(Version) ->
@@ -1613,7 +2143,7 @@ default_option_role(_,_,_) ->
undefined.
default_cb_info(tls) ->
- {gen_tcp, tcp, tcp_closed, tcp_error};
+ {gen_tcp, tcp, tcp_closed, tcp_error, tcp_passive};
default_cb_info(dtls) ->
{gen_udp, udp, udp_closed, udp_error}.
diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index 34e9797f1f..81167b5ba3 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -32,7 +32,11 @@
-include("ssl_record.hrl").
-include("ssl_internal.hrl").
--export([decode/1, own_alert_txt/1, alert_txt/1, reason_code/2]).
+-export([decode/1,
+ own_alert_txt/1,
+ alert_txt/1,
+ alert_txt/4,
+ reason_code/4]).
%%====================================================================
%% Internal application API
@@ -48,18 +52,29 @@ decode(Bin) ->
decode(Bin, [], 0).
%%--------------------------------------------------------------------
--spec reason_code(#alert{}, client | server) ->
- closed | {tls_alert, unicode:chardata()}.
-%-spec reason_code(#alert{}, client | server) -> closed | {essl, string()}.
+-spec reason_code(#alert{}, client | server, ProtocolName::string(), StateName::atom()) ->
+ {tls_alert, {atom(), unicode:chardata()}} | closed.
%%
%% Description: Returns the error reason that will be returned to the
%% user.
%%--------------------------------------------------------------------
-reason_code(#alert{description = ?CLOSE_NOTIFY}, _) ->
+reason_code(#alert{description = ?CLOSE_NOTIFY}, _, _, _) ->
closed;
-reason_code(#alert{description = Description}, _) ->
- {tls_alert, string:casefold(description_txt(Description))}.
+reason_code(#alert{description = Description, role = Role} = Alert, Role, ProtocolName, StateName) ->
+ Txt = lists:flatten(alert_txt(ProtocolName, Role, StateName, own_alert_txt(Alert))),
+ {tls_alert, {description_atom(Description), Txt}};
+reason_code(#alert{description = Description} = Alert, Role, ProtocolName, StateName) ->
+ Txt = lists:flatten(alert_txt(ProtocolName, Role, StateName, alert_txt(Alert))),
+ {tls_alert, {description_atom(Description), Txt}}.
+
+%%--------------------------------------------------------------------
+-spec alert_txt(string(), server | client, StateNam::atom(), string()) -> string().
+%%
+%% Description: Generates alert text for log or string part of error return.
+%%--------------------------------------------------------------------
+alert_txt(ProtocolName, Role, StateName, Txt) ->
+ io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]).
%%--------------------------------------------------------------------
-spec own_alert_txt(#alert{}) -> string().
@@ -181,3 +196,70 @@ description_txt(?NO_APPLICATION_PROTOCOL) ->
"No application protocol";
description_txt(Enum) ->
lists:flatten(io_lib:format("unsupported/unknown alert: ~p", [Enum])).
+
+description_atom(?CLOSE_NOTIFY) ->
+ close_notify;
+description_atom(?UNEXPECTED_MESSAGE) ->
+ unexpected_message;
+description_atom(?BAD_RECORD_MAC) ->
+ bad_record_mac;
+description_atom(?DECRYPTION_FAILED_RESERVED) ->
+ decryption_failed_reserved;
+description_atom(?RECORD_OVERFLOW) ->
+ record_overflow;
+description_atom(?DECOMPRESSION_FAILURE) ->
+ decompression_failure;
+description_atom(?HANDSHAKE_FAILURE) ->
+ handshake_failure;
+description_atom(?NO_CERTIFICATE_RESERVED) ->
+ no_certificate_reserved;
+description_atom(?BAD_CERTIFICATE) ->
+ bad_certificate;
+description_atom(?UNSUPPORTED_CERTIFICATE) ->
+ unsupported_certificate;
+description_atom(?CERTIFICATE_REVOKED) ->
+ certificate_revoked;
+description_atom(?CERTIFICATE_EXPIRED) ->
+ certificate_expired;
+description_atom(?CERTIFICATE_UNKNOWN) ->
+ certificate_unknown;
+description_atom(?ILLEGAL_PARAMETER) ->
+ illegal_parameter;
+description_atom(?UNKNOWN_CA) ->
+ unknown_ca;
+description_atom(?ACCESS_DENIED) ->
+ access_denied;
+description_atom(?DECODE_ERROR) ->
+ decode_error;
+description_atom(?DECRYPT_ERROR) ->
+ decrypt_error;
+description_atom(?EXPORT_RESTRICTION) ->
+ export_restriction;
+description_atom(?PROTOCOL_VERSION) ->
+ protocol_version;
+description_atom(?INSUFFICIENT_SECURITY) ->
+ insufficient_security;
+description_atom(?INTERNAL_ERROR) ->
+ internal_error;
+description_atom(?USER_CANCELED) ->
+ user_canceled;
+description_atom(?NO_RENEGOTIATION) ->
+ no_renegotiation;
+description_atom(?UNSUPPORTED_EXTENSION) ->
+ unsupported_extension;
+description_atom(?CERTIFICATE_UNOBTAINABLE) ->
+ certificate_unobtainable;
+description_atom(?UNRECOGNISED_NAME) ->
+ unrecognised_name;
+description_atom(?BAD_CERTIFICATE_STATUS_RESPONSE) ->
+ bad_certificate_status_response;
+description_atom(?BAD_CERTIFICATE_HASH_VALUE) ->
+ bad_certificate_hash_value;
+description_atom(?UNKNOWN_PSK_IDENTITY) ->
+ unknown_psk_identity;
+description_atom(?INAPPROPRIATE_FALLBACK) ->
+ inappropriate_fallback;
+description_atom(?NO_APPLICATION_PROTOCOL) ->
+ no_application_protocol;
+description_atom(_) ->
+ 'unsupported/unkonwn_alert'.
diff --git a/lib/ssl/src/ssl_api.hrl b/lib/ssl/src/ssl_api.hrl
index 2bd51cf91e..f4594912bd 100644
--- a/lib/ssl/src/ssl_api.hrl
+++ b/lib/ssl/src/ssl_api.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,48 +21,7 @@
-ifndef(ssl_api).
-define(ssl_api, true).
--include("ssl_cipher.hrl").
-
-%% Visible in API
--export_type([connect_option/0, listen_option/0, ssl_option/0, transport_option/0,
- prf_random/0, sslsocket/0]).
-
-
%% Looks like it does for backwards compatibility reasons
-record(sslsocket, {fd = nil, pid = nil}).
-
--type sslsocket() :: #sslsocket{}.
--type connect_option() :: socket_connect_option() | ssl_option() | transport_option().
--type socket_connect_option() :: gen_tcp:connect_option().
--type listen_option() :: socket_listen_option() | ssl_option() | transport_option().
--type socket_listen_option() :: gen_tcp:listen_option().
-
--type ssl_option() :: {versions, ssl_record:ssl_atom_version()} |
- {verify, verify_type()} |
- {verify_fun, {fun(), InitialUserState::term()}} |
- {fail_if_no_peer_cert, boolean()} | {depth, integer()} |
- {cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} |
- {keyfile, path()} | {password, string()} | {cacerts, [Der::binary()]} |
- {cacertfile, path()} | {dh, Der::binary()} | {dhfile, path()} |
- {user_lookup_fun, {fun(), InitialUserState::term()}} |
- {psk_identity, string()} |
- {srp_identity, {string(), string()}} |
- {ciphers, ciphers()} | {ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} |
- {reuse_session, fun()} | {hibernate_after, integer()|undefined} |
- {alpn_advertised_protocols, [binary()]} |
- {alpn_preferred_protocols, [binary()]} |
- {next_protocols_advertised, list(binary())} |
- {client_preferred_next_protocols, binary(), client | server, list(binary())}.
-
--type verify_type() :: verify_none | verify_peer.
--type path() :: string().
--type ciphers() :: [ssl_cipher:erl_cipher_suite()] |
- string(). % (according to old API)
--type ssl_imp() :: new | old.
-
--type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(),
- ClosedTag::atom(), ErrTag::atom()}}.
--type prf_random() :: client_random | server_random.
-
-endif. % -ifdef(ssl_api).
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index c15e8a2138..549e557beb 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -33,6 +33,7 @@
-export([trusted_cert_and_path/4,
certificate_chain/3,
+ certificate_chain/4,
file_to_certificats/2,
file_to_crls/2,
validate/3,
@@ -40,7 +41,8 @@
is_valid_key_usage/2,
select_extension/2,
extensions_list/1,
- public_key_type/1
+ public_key_type/1,
+ foldl_db/3
]).
%%====================================================================
@@ -79,7 +81,8 @@ trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef, PartialChainHandler) -
%% Trusted must be selfsigned or it is an incomplete chain
handle_path(Trusted, Path, PartialChainHandler);
_ ->
- %% Root CA could not be verified
+ %% Root CA could not be verified, but partial
+ %% chain handler may trusted a cert that we got
handle_incomplete_chain(Path, PartialChainHandler)
end
end.
@@ -94,10 +97,23 @@ certificate_chain(undefined, _, _) ->
{error, no_cert};
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) when is_binary(OwnCert) ->
ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
- certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert]);
+ certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert], []);
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) ->
DerCert = public_key:pkix_encode('OTPCertificate', OwnCert, otp),
- certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert]).
+ certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert], []).
+
+%%--------------------------------------------------------------------
+-spec certificate_chain(undefined | binary() | #'OTPCertificate'{} , db_handle(), certdb_ref(), [der_cert()]) ->
+ {error, no_cert} | {ok, #'OTPCertificate'{} | undefined, [der_cert()]}.
+%%
+%% Description: Create certificate chain with certs from
+%%--------------------------------------------------------------------
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) when is_binary(Cert) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ certificate_chain(ErlCert, Cert, CertDbHandle, CertsDbRef, [Cert], Candidates);
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) ->
+ DerCert = public_key:pkix_encode('OTPCertificate', Cert, otp),
+ certificate_chain(Cert, DerCert, CertDbHandle, CertsDbRef, [DerCert], Candidates).
%%--------------------------------------------------------------------
-spec file_to_certificats(binary(), term()) -> [der_cert()].
%%
@@ -187,9 +203,20 @@ public_key_type(?'id-ecPublicKey') ->
ec.
%%--------------------------------------------------------------------
+-spec foldl_db(fun(), db_handle() | {extracted, list()}, list()) ->
+ {ok, term()} | issuer_not_found.
+%%
+%% Description:
+%%--------------------------------------------------------------------
+foldl_db(IsIssuerFun, CertDbHandle, []) ->
+ ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle);
+foldl_db(IsIssuerFun, _, [_|_] = ListDb) ->
+ lists:foldl(IsIssuerFun, issuer_not_found, ListDb).
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
+certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain, ListDb) ->
IssuerAndSelfSigned =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -200,12 +227,12 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
case IssuerAndSelfSigned of
{_, true = SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned, ListDb);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) of
{ok, {SerialNr, Issuer}} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain,
- SerialNr, Issuer, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain,
+ SerialNr, Issuer, SelfSigned, ListDb);
_ ->
%% Guess the the issuer must be the root
%% certificate. The verification of the
@@ -214,19 +241,19 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
{ok, undefined, lists:reverse(Chain)}
end;
{{ok, {SerialNr, Issuer}}, SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned, ListDb)
end.
-certificate_chain(_, _, [RootCert | _] = Chain, _, _, true) ->
+do_certificate_chain(_, _, [RootCert | _] = Chain, _, _, true, _) ->
{ok, RootCert, lists:reverse(Chain)};
-certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
+do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _, ListDb) ->
case ssl_manager:lookup_trusted_cert(CertDbHandle, CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
- CertDbHandle, CertsDbRef, [IssuerCert | Chain]);
+ CertDbHandle, CertsDbRef, [IssuerCert | Chain], ListDb);
_ ->
%% The trusted cert may be obmitted from the chain as the
%% counter part needs to have it anyway to be able to
@@ -234,7 +261,8 @@ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned
{ok, undefined, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
+
+find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) ->
IsIssuerFun =
fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) ->
case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
@@ -252,26 +280,29 @@ find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
Acc
end,
- if is_reference(CertsDbRef) -> % actual DB exists
- try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end;
- is_tuple(CertsDbRef), element(1,CertsDbRef) =:= extracted -> % cache bypass byproduct
- {extracted, CertsData} = CertsDbRef,
- DB = [Entry || {decoded, Entry} <- CertsData],
- try lists:foldl(IsIssuerFun, issuer_not_found, DB) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end
+ Result = case is_reference(CertsDbRef) of
+ true ->
+ do_find_issuer(IsIssuerFun, CertDbHandle, ListDb);
+ false ->
+ {extracted, CertsData} = CertsDbRef,
+ DB = [Entry || {decoded, Entry} <- CertsData],
+ do_find_issuer(IsIssuerFun, CertDbHandle, DB)
+ end,
+ case Result of
+ issuer_not_found ->
+ {error, issuer_not_found};
+ Result ->
+ Result
end.
+do_find_issuer(IssuerFun, CertDbHandle, CertDb) ->
+ try
+ foldl_db(IssuerFun, CertDbHandle, CertDb)
+ catch
+ throw:{ok, _} = Return ->
+ Return
+ end.
+
is_valid_extkey_usage(KeyUse, client) ->
%% Client wants to verify server
is_valid_key_usage(KeyUse,?'id-kp-serverAuth');
@@ -300,7 +331,7 @@ other_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) ->
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef, []) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 754fc46404..fce48d1678 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,43 +33,25 @@
-include("ssl_alert.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([security_parameters/2, security_parameters/3, suite_definition/1,
- erl_suite_definition/1,
- cipher_init/3, decipher/6, cipher/5, decipher_aead/6, cipher_aead/6,
- suite/1, suites/1, all_suites/1, crypto_support_filters/0,
+-export([security_parameters/2, security_parameters/3,
+ cipher_init/3, nonce_seed/2, decipher/6, cipher/5, aead_encrypt/5, aead_decrypt/6,
+ suites/1, all_suites/1, crypto_support_filters/0,
chacha_suites/1, anonymous_suites/1, psk_suites/1, psk_suites_anon/1,
srp_suites/0, srp_suites_anon/0,
- rc4_suites/1, des_suites/1, rsa_suites/1, openssl_suite/1, openssl_suite_name/1,
+ rc4_suites/1, des_suites/1, rsa_suites/1,
filter/3, filter_suites/1, filter_suites/2,
hash_algorithm/1, sign_algorithm/1, is_acceptable_hash/2, is_fallback/1,
- random_bytes/1, calc_mac_hash/4,
- is_stream_ciphersuite/1, suite_to_str/1]).
-
--export_type([cipher_suite/0,
- erl_cipher_suite/0, old_erl_cipher_suite/0, openssl_cipher_suite/0,
- hash/0, key_algo/0, sign_algo/0]).
-
--type cipher() :: null |rc4_128 | des_cbc | '3des_ede_cbc' | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305.
--type hash() :: null | md5 | sha | sha224 | sha256 | sha384 | sha512.
--type sign_algo() :: rsa | dsa | ecdsa.
--type key_algo() :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss | psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon.
--type erl_cipher_suite() :: #{key_exchange := key_algo(),
- cipher := cipher(),
- mac := hash() | aead,
- prf := hash() | default_prf %% Old cipher suites, version dependent
- }.
--type old_erl_cipher_suite() :: {key_algo(), cipher(), hash()} % Pre TLS 1.2
- %% TLS 1.2, internally PRE TLS 1.2 will use default_prf
- | {key_algo(), cipher(), hash(), hash() | default_prf}.
--type cipher_suite() :: binary().
--type cipher_enum() :: integer().
--type openssl_cipher_suite() :: string().
-
+ random_bytes/1, calc_mac_hash/4, calc_mac_hash/6,
+ is_stream_ciphersuite/1]).
-compile(inline).
+-type cipher_enum() :: integer().
+
+-export_type([cipher_enum/0]).
+
%%--------------------------------------------------------------------
--spec security_parameters(cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(ssl_cipher_format:cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%% Only security_parameters/2 should call security_parameters/3 with undefined as
%% first argument.
@@ -79,7 +61,8 @@ security_parameters(?TLS_NULL_WITH_NULL_NULL = CipherSuite, SecParams) ->
security_parameters(undefined, CipherSuite, SecParams).
%%--------------------------------------------------------------------
--spec security_parameters(ssl_record:ssl_version() | undefined, cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(ssl_record:ssl_version() | undefined,
+ ssl_cipher_format:cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%%
%% Description: Returns a security parameters record where the
@@ -87,7 +70,7 @@ security_parameters(?TLS_NULL_WITH_NULL_NULL = CipherSuite, SecParams) ->
%%-------------------------------------------------------------------
security_parameters(Version, CipherSuite, SecParams) ->
#{cipher := Cipher, mac := Hash,
- prf := PrfHashAlg} = suite_definition(CipherSuite),
+ prf := PrfHashAlg} = ssl_cipher_format:suite_definition(CipherSuite),
SecParams#security_parameters{
cipher_suite = CipherSuite,
bulk_cipher_algorithm = bulk_cipher_algorithm(Cipher),
@@ -110,9 +93,15 @@ cipher_init(?RC4, IV, Key) ->
#cipher_state{iv = IV, key = Key, state = State};
cipher_init(?AES_GCM, IV, Key) ->
<<Nonce:64>> = random_bytes(8),
- #cipher_state{iv = IV, key = Key, nonce = Nonce};
+ #cipher_state{iv = IV, key = Key, nonce = Nonce, tag_len = 16};
+cipher_init(?CHACHA20_POLY1305, IV, Key) ->
+ #cipher_state{iv = IV, key = Key, tag_len = 16};
cipher_init(_BCA, IV, Key) ->
- #cipher_state{iv = IV, key = Key}.
+ %% Initialize random IV cache, not used for aead ciphers
+ #cipher_state{iv = IV, key = Key, state = <<>>}.
+
+nonce_seed(Seed, CipherState) ->
+ CipherState#cipher_state{nonce = Seed}.
%%--------------------------------------------------------------------
-spec cipher(cipher_enum(), #cipher_state{}, binary(), iodata(), ssl_record:ssl_version()) ->
@@ -124,12 +113,11 @@ cipher_init(_BCA, IV, Key) ->
%% data is calculated and the data plus the HMAC is ecncrypted.
%%-------------------------------------------------------------------
cipher(?NULL, CipherState, <<>>, Fragment, _Version) ->
- GenStreamCipherList = [Fragment, <<>>],
- {GenStreamCipherList, CipherState};
+ {iolist_to_binary(Fragment), CipherState};
cipher(?RC4, CipherState = #cipher_state{state = State0}, Mac, Fragment, _Version) ->
GenStreamCipherList = [Fragment, Mac],
{State1, T} = crypto:stream_encrypt(State0, GenStreamCipherList),
- {T, CipherState#cipher_state{state = State1}};
+ {iolist_to_binary(T), CipherState#cipher_state{state = State1}};
cipher(?DES, CipherState, Mac, Fragment, Version) ->
block_cipher(fun(Key, IV, T) ->
crypto:block_encrypt(des_cbc, Key, IV, T)
@@ -145,37 +133,20 @@ cipher(?AES_CBC, CipherState, Mac, Fragment, Version) ->
crypto:block_encrypt(aes_cbc256, Key, IV, T)
end, block_size(aes_128_cbc), CipherState, Mac, Fragment, Version).
-%%--------------------------------------------------------------------
--spec cipher_aead(cipher_enum(), #cipher_state{}, integer(), binary(), iodata(), ssl_record:ssl_version()) ->
- {binary(), #cipher_state{}}.
-%%
-%% Description: Encrypts the data and protects associated data (AAD) using chipher
-%% described by cipher_enum() and updating the cipher state
-%% Use for suites that use authenticated encryption with associated data (AEAD)
-%%-------------------------------------------------------------------
-cipher_aead(?AES_GCM, CipherState, SeqNo, AAD, Fragment, Version) ->
- aead_cipher(aes_gcm, CipherState, SeqNo, AAD, Fragment, Version);
-cipher_aead(?CHACHA20_POLY1305, CipherState, SeqNo, AAD, Fragment, Version) ->
- aead_cipher(chacha20_poly1305, CipherState, SeqNo, AAD, Fragment, Version).
-
-aead_cipher(chacha20_poly1305, #cipher_state{key=Key} = CipherState, SeqNo, AAD0, Fragment, _Version) ->
- CipherLen = erlang:iolist_size(Fragment),
- AAD = <<AAD0/binary, ?UINT16(CipherLen)>>,
- Nonce = ?uint64(SeqNo),
- {Content, CipherTag} = crypto:block_encrypt(chacha20_poly1305, Key, Nonce, {AAD, Fragment}),
- {<<Content/binary, CipherTag/binary>>, CipherState};
-aead_cipher(Type, #cipher_state{key=Key, iv = IV0, nonce = Nonce} = CipherState, _SeqNo, AAD0, Fragment, _Version) ->
- CipherLen = erlang:iolist_size(Fragment),
- AAD = <<AAD0/binary, ?UINT16(CipherLen)>>,
- <<Salt:4/bytes, _/binary>> = IV0,
- IV = <<Salt/binary, Nonce:64/integer>>,
- {Content, CipherTag} = crypto:block_encrypt(Type, Key, IV, {AAD, Fragment}),
- {<<Nonce:64/integer, Content/binary, CipherTag/binary>>, CipherState#cipher_state{nonce = Nonce + 1}}.
+aead_encrypt(Type, Key, Nonce, Fragment, AdditionalData) ->
+ crypto:block_encrypt(aead_type(Type), Key, Nonce, {AdditionalData, Fragment}).
+
+aead_decrypt(Type, Key, Nonce, CipherText, CipherTag, AdditionalData) ->
+ crypto:block_decrypt(aead_type(Type), Key, Nonce, {AdditionalData, CipherText, CipherTag}).
+
+aead_type(?AES_GCM) ->
+ aes_gcm;
+aead_type(?CHACHA20_POLY1305) ->
+ chacha20_poly1305.
build_cipher_block(BlockSz, Mac, Fragment) ->
TotSz = byte_size(Mac) + erlang:iolist_size(Fragment) + 1,
- {PaddingLength, Padding} = get_padding(TotSz, BlockSz),
- [Fragment, Mac, PaddingLength, Padding].
+ [Fragment, Mac, padding_with_len(TotSz, BlockSz)].
block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
Mac, Fragment, {3, N})
@@ -185,14 +156,21 @@ block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
NextIV = next_iv(T, IV),
{T, CS0#cipher_state{iv=NextIV}};
-block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
+block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV, state = IV_Cache0} = CS0,
Mac, Fragment, {3, N})
when N == 2; N == 3 ->
- NextIV = random_iv(IV),
+ IV_Size = byte_size(IV),
+ <<NextIV:IV_Size/binary, IV_Cache/binary>> =
+ case IV_Cache0 of
+ <<>> ->
+ random_bytes(IV_Size bsl 5); % 32 IVs
+ _ ->
+ IV_Cache0
+ end,
L0 = build_cipher_block(BlockSz, Mac, Fragment),
L = [NextIV|L0],
T = Fun(Key, IV, L),
- {T, CS0#cipher_state{iv=NextIV}}.
+ {T, CS0#cipher_state{iv=NextIV, state = IV_Cache}}.
%%--------------------------------------------------------------------
-spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(),
@@ -237,19 +215,6 @@ decipher(?AES_CBC, HashSz, CipherState, Fragment, Version, PaddingCheck) ->
crypto:block_decrypt(aes_cbc256, Key, IV, T)
end, CipherState, HashSz, Fragment, Version, PaddingCheck).
-%%--------------------------------------------------------------------
--spec decipher_aead(cipher_enum(), #cipher_state{}, integer(), binary(), binary(), ssl_record:ssl_version()) ->
- {binary(), #cipher_state{}} | #alert{}.
-%%
-%% Description: Decrypts the data and checks the associated data (AAD) MAC using
-%% cipher described by cipher_enum() and updating the cipher state.
-%% Use for suites that use authenticated encryption with associated data (AEAD)
-%%-------------------------------------------------------------------
-decipher_aead(?AES_GCM, CipherState, SeqNo, AAD, Fragment, Version) ->
- aead_decipher(aes_gcm, CipherState, SeqNo, AAD, Fragment, Version);
-decipher_aead(?CHACHA20_POLY1305, CipherState, SeqNo, AAD, Fragment, Version) ->
- aead_decipher(chacha20_poly1305, CipherState, SeqNo, AAD, Fragment, Version).
-
block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
HashSz, Fragment, Version, PaddingCheck) ->
try
@@ -280,36 +245,8 @@ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
end.
-aead_ciphertext_to_state(chacha20_poly1305, SeqNo, _IV, AAD0, Fragment, _Version) ->
- CipherLen = size(Fragment) - 16,
- <<CipherText:CipherLen/bytes, CipherTag:16/bytes>> = Fragment,
- AAD = <<AAD0/binary, ?UINT16(CipherLen)>>,
- Nonce = ?uint64(SeqNo),
- {Nonce, AAD, CipherText, CipherTag};
-aead_ciphertext_to_state(_, _SeqNo, <<Salt:4/bytes, _/binary>>, AAD0, Fragment, _Version) ->
- CipherLen = size(Fragment) - 24,
- <<ExplicitNonce:8/bytes, CipherText:CipherLen/bytes, CipherTag:16/bytes>> = Fragment,
- AAD = <<AAD0/binary, ?UINT16(CipherLen)>>,
- Nonce = <<Salt/binary, ExplicitNonce/binary>>,
- {Nonce, AAD, CipherText, CipherTag}.
-
-aead_decipher(Type, #cipher_state{key = Key, iv = IV} = CipherState,
- SeqNo, AAD0, Fragment, Version) ->
- try
- {Nonce, AAD, CipherText, CipherTag} = aead_ciphertext_to_state(Type, SeqNo, IV, AAD0, Fragment, Version),
- case crypto:block_decrypt(Type, Key, Nonce, {AAD, CipherText, CipherTag}) of
- Content when is_binary(Content) ->
- {Content, CipherState};
- _ ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
- end
- catch
- _:_ ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
- end.
-
%%--------------------------------------------------------------------
--spec suites(ssl_record:ssl_version()) -> [cipher_suite()].
+-spec suites(ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of supported cipher suites.
%%--------------------------------------------------------------------
@@ -332,7 +269,8 @@ all_suites({3, _} = Version) ->
all_suites(Version) ->
dtls_v1:all_suites(Version).
%%--------------------------------------------------------------------
--spec chacha_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec chacha_suites(ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns list of the chacha cipher suites, only supported
%% if explicitly set by user for now due to interop problems, proably need
@@ -346,7 +284,8 @@ chacha_suites(_) ->
[].
%%--------------------------------------------------------------------
--spec anonymous_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec anonymous_suites(ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the anonymous cipher suites, only supported
%% if explicitly set by user. Intended only for testing.
@@ -382,7 +321,7 @@ anonymous_suites(N) when N == 0;
].
%%--------------------------------------------------------------------
--spec psk_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec psk_suites(ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the PSK cipher suites, only supported
%% if explicitly set by user.
@@ -404,7 +343,7 @@ psk_suites(_) ->
?TLS_RSA_PSK_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
--spec psk_suites_anon(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec psk_suites_anon(ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the anonymous PSK cipher suites, only supported
%% if explicitly set by user.
@@ -439,7 +378,7 @@ psk_suites_anon(_) ->
?TLS_DHE_PSK_WITH_RC4_128_SHA,
?TLS_PSK_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
--spec srp_suites() -> [cipher_suite()].
+-spec srp_suites() -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the SRP cipher suites, only supported
%% if explicitly set by user.
@@ -453,7 +392,7 @@ srp_suites() ->
?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA].
%%--------------------------------------------------------------------
--spec srp_suites_anon() -> [cipher_suite()].
+-spec srp_suites_anon() -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the SRP anonymous cipher suites, only supported
%% if explicitly set by user.
@@ -464,7 +403,8 @@ srp_suites_anon() ->
?TLS_SRP_SHA_WITH_AES_256_CBC_SHA].
%%--------------------------------------------------------------------
--spec rc4_suites(Version::ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec rc4_suites(Version::ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the RSA|(ECDH/RSA)| (ECDH/ECDSA)
%% with RC4 cipher suites, only supported if explicitly set by user.
@@ -484,7 +424,7 @@ rc4_suites(N) when N =< 3 ->
?TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDH_RSA_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
--spec des_suites(Version::ssl_record:ssl_version()) -> [cipher_suite()].
+-spec des_suites(Version::ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the cipher suites
%% with DES cipher, only supported if explicitly set by user.
@@ -502,7 +442,7 @@ des_suites(_)->
].
%%--------------------------------------------------------------------
--spec rsa_suites(Version::ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec rsa_suites(Version::ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the RSA key exchange
%% cipher suites, only supported if explicitly set by user.
@@ -524,1721 +464,10 @@ rsa_suites(N) when N =< 3 ->
?TLS_RSA_WITH_AES_128_GCM_SHA256,
?TLS_RSA_WITH_AES_128_CBC_SHA256
].
-%%--------------------------------------------------------------------
--spec suite_definition(cipher_suite()) -> erl_cipher_suite().
-%%
-%% Description: Return erlang cipher suite definition.
-%% Note: Currently not supported suites are commented away.
-%% They should be supported or removed in the future.
-%%-------------------------------------------------------------------
-%% TLS v1.1 suites
-suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
- #{key_exchange => null,
- cipher => null,
- mac => null,
- prf => null};
-%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension
-%% to avoid handshake failure from old servers that do not ignore
-%% hello extension data as they should.
-suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
- #{key_exchange => null,
- cipher => null,
- mac => null,
- prf => null};
-suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
- #{key_exchange => rsa,
- cipher => rc4_128,
- mac => md5,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
- #{key_exchange => rsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-%%% TSL V1.1 AES suites
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%% TLS v1.2 suites
-%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
-%% {rsa, null, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => rsa,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dhe_dss,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => dhe_dss,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-%% not defined YET:
-%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH_DSS AES_128_CBC SHA256
-%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH_RSA AES_128_CBC SHA256
-%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH_DSS AES_256_CBC SHA256
-%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
-%%% DH-ANON deprecated by TLS spec and not available
-%%% by default, but good for testing purposes.
-suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
- #{key_exchange => dh_anon,
- cipher => rc4_128,
- mac => md5,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dh_anon,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => dh_anon,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-%%% PSK Cipher Suites RFC 4279
-suite_definition(?TLS_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%%% PSK NULL Cipher Suites RFC 4785
-suite_definition(?TLS_PSK_WITH_NULL_SHA) ->
- #{key_exchange => psk,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => null,
- mac => sha,
- prf => default_prf};
-%%% TLS 1.2 PSK Cipher Suites RFC 5487
-suite_definition(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => psk,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => psk,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dhe_psk,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dhe_psk,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => rsa_psk,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => rsa_psk,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dhe_psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => dhe_psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => rsa_psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => rsa_psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => psk,
- cipher => null,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => dhe_psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => dhe_psk,
- cipher => null,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => rsa_psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => rsa_psk,
- cipher => null,
- mac => sha384,
- prf => default_prf};
-%%% ECDHE PSK Cipher Suites RFC 5489
-suite_definition(?TLS_ECDHE_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => ecdhe_psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => ecdhe_psk,
- cipher => null, mac => sha384,
- prf => default_prf};
-%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_128_gcm,
- mac => null,
- prf => sha256};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_256_gcm,
- mac => null,
- prf => sha384};
-%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256) ->
-%% #{key_exchange => ecdhe_psk,
-%% cipher => aes_128_ccm,
-%% mac => null,
-%% prf =>sha256};
-%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256) ->
-%% #{key_exchange => ecdhe_psk,
-%% cipher => aes_256_ccm,
-%% mac => null,
-%% prf => sha256};
-%%% SRP Cipher Suites RFC 5054
-suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => srp_anon,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => srp_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => srp_dss,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => srp_anon,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => srp_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => srp_dss,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => srp_anon,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => srp_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => srp_dss,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%% RFC 4492 EC TLS suites
-suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%% RFC 5289 EC TLS suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-%% RFC 5288 AES-GCM Cipher Suites
-suite_definition(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dh_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dh_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dhe_dss,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dhe_dss,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dh_dss,
- cipher => aes_128_gcm,
- mac => null,
- prf => sha256};
-suite_definition(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dh_dss,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dh_anon,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dh_anon,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-%% RFC 5289 ECC AES-GCM Cipher Suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
- #{key_exchange => ecdhe_rsa,
- cipher => chacha20_poly1305,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => chacha20_poly1305,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => chacha20_poly1305,
- mac => aead,
- prf => sha256}.
-
-%%--------------------------------------------------------------------
--spec erl_suite_definition(cipher_suite() | erl_cipher_suite()) -> old_erl_cipher_suite().
-%%
-%% Description: Return erlang cipher suite definition. Filters last value
-%% for now (compatibility reasons).
-%%--------------------------------------------------------------------
-erl_suite_definition(Bin) when is_binary(Bin) ->
- erl_suite_definition(suite_definition(Bin));
-erl_suite_definition(#{key_exchange := KeyExchange, cipher := Cipher,
- mac := Hash, prf := Prf}) ->
- case Prf of
- default_prf ->
- {KeyExchange, Cipher, Hash};
- _ ->
- {KeyExchange, Cipher, Hash, Prf}
- end.
%%--------------------------------------------------------------------
--spec suite(erl_cipher_suite()) -> cipher_suite().
-%%
-%% Description: Return TLS cipher suite definition.
-%%--------------------------------------------------------------------
-%% TLS v1.1 suites
-suite(#{key_exchange := rsa,
- cipher := rc4_128,
- mac := md5}) ->
- ?TLS_RSA_WITH_RC4_128_MD5;
-suite(#{key_exchange := rsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := rsa,
- cipher := des_cbc,
- mac := sha}) ->
- ?TLS_RSA_WITH_DES_CBC_SHA;
-suite(#{key_exchange := rsa,
- cipher :='3des_ede_cbc',
- mac := sha}) ->
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher:= des_cbc,
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher:= '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher:= des_cbc,
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher:= '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher:= rc4_128,
- mac := md5}) ->
- ?TLS_DH_anon_WITH_RC4_128_MD5;
-suite(#{key_exchange := dh_anon,
- cipher:= des_cbc,
- mac := sha}) ->
- ?TLS_DH_anon_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher:= '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
-%%% TSL V1.1 AES suites
-suite(#{key_exchange := rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA;
-%% TLS v1.2 suites
-suite(#{key_exchange := rsa,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := rsa,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dh_anon,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dh_anon,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA256;
-%%% PSK Cipher Suites RFC 4279
-suite(#{key_exchange := psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := psk,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
-%%% PSK NULL Cipher Suites RFC 4785
-suite(#{key_exchange := psk,
- cipher := null,
- mac := sha}) ->
- ?TLS_PSK_WITH_NULL_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := null,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := null,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA;
-%%% TLS 1.2 PSK Cipher Suites RFC 5487
-suite(#{key_exchange := psk,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := psk,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_PSK_WITH_NULL_SHA384;
-suite(#{key_exchange := dhe_psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := dhe_psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA384;
-suite(#{key_exchange := rsa_psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := rsa_psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA384;
-%%% ECDHE PSK Cipher Suites RFC 5489
-suite(#{key_exchange := ecdhe_psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher :='3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdhe_psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_ECDHE_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := ecdhe_psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_ECDHE_PSK_WITH_NULL_SHA384;
-%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_128_gcm,
- mac := null,
- prf := sha256}) ->
- ?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_256_gcm,
- mac := null,
- prf := sha384}) ->
- ?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384;
- %% suite(#{key_exchange := ecdhe_psk,
- %% cipher := aes_128_ccm,
- %% mac := null,
- %% prf := sha256}) ->
- %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256;
- %% suite(#{key_exchange := ecdhe_psk,
- %% cipher := aes_256_ccm,
- %% mac := null,
- %% prf := sha256}) ->
- %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256;
-%%% SRP Cipher Suites RFC 5054
-suite(#{key_exchange := srp_anon,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_dss,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_anon,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_dss,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_anon,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := srp_dss,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
-%%% RFC 4492 EC TLS suites
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := '3des_ede_cbc', mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA;
-%%% RFC 5289 EC TLS suites
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_128_cbc,
- mac:= sha256,
- prf := sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_128_cbc,
- mac := sha256,
- prf := sha256}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_128_cbc,
- mac := sha256,
- prf := sha256}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_128_cbc,
- mac := sha256,
- prf := sha256}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
-%% RFC 5288 AES-GCM Cipher Suites
-suite(#{key_exchange := rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_dss,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_dss,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_anon,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DH_anon_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_anon,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DH_anon_WITH_AES_256_GCM_SHA384;
-%% RFC 5289 ECC AES-GCM Cipher Suites
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
-%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite(#{key_exchange := ecdhe_rsa,
- cipher := chacha20_poly1305,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := chacha20_poly1305,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := chacha20_poly1305,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
-
-
-%%--------------------------------------------------------------------
--spec suite_to_str(erl_cipher_suite()) -> string().
-%%
-%% Description: Return the string representation of a cipher suite.
-%%--------------------------------------------------------------------
-suite_to_str(#{key_exchange := null,
- cipher := null,
- mac := null,
- prf := null}) ->
- "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
-suite_to_str(#{key_exchange := Kex,
- cipher := Cipher,
- mac := aead,
- prf := PRF}) ->
- "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
- "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
- "_" ++ string:to_upper(atom_to_list(PRF));
-suite_to_str(#{key_exchange := Kex,
- cipher := Cipher,
- mac := Mac}) ->
- "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
- "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
- "_" ++ string:to_upper(atom_to_list(Mac)).
-
-
-%%--------------------------------------------------------------------
--spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
-%%
-%% Description: Return TLS cipher suite definition.
-%%--------------------------------------------------------------------
-%% translate constants <-> openssl-strings
-openssl_suite("DHE-RSA-AES256-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-DSS-AES256-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-openssl_suite("AES256-SHA256") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-RSA-AES128-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-DSS-AES128-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-openssl_suite("AES128-SHA256") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-RSA-AES256-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("DHE-DSS-AES256-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("AES256-SHA") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("EDH-RSA-DES-CBC3-SHA") ->
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("EDH-DSS-DES-CBC3-SHA") ->
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DES-CBC3-SHA") ->
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DHE-RSA-AES128-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("DHE-DSS-AES128-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("AES128-SHA") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("RC4-SHA") ->
- ?TLS_RSA_WITH_RC4_128_SHA;
-openssl_suite("RC4-MD5") ->
- ?TLS_RSA_WITH_RC4_128_MD5;
-openssl_suite("EDH-RSA-DES-CBC-SHA") ->
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-openssl_suite("DES-CBC-SHA") ->
- ?TLS_RSA_WITH_DES_CBC_SHA;
-
-%%% SRP Cipher Suites RFC 5054
-
-openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-
-%% RFC 4492 EC TLS suites
-openssl_suite("ECDH-ECDSA-RC4-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES128-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES256-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDHE-ECDSA-RC4-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES128-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES256-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDHE-RSA-RC4-SHA") ->
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES128-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES256-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDH-RSA-RC4-SHA") ->
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-RSA-AES128-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-RSA-AES256-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-
-%% RFC 5289 EC TLS suites
-openssl_suite("ECDHE-ECDSA-AES128-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDHE-RSA-AES128-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-RSA-AES256-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-RSA-AES128-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-RSA-AES256-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
-
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite("AES128-GCM-SHA256") ->
- ?TLS_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("AES256-GCM-SHA384") ->
- ?TLS_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-RSA-AES128-GCM-SHA256") ->
- ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-RSA-AES256-GCM-SHA384") ->
- ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-DSS-AES128-GCM-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-DSS-AES256-GCM-SHA384") ->
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-DSS-AES128-GCM-SHA256") ->
- ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-DSS-AES256-GCM-SHA384") ->
- ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite("ECDHE-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384.
-
-%%--------------------------------------------------------------------
--spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite() | erl_cipher_suite().
-%%
-%% Description: Return openssl cipher suite name if possible
-%%-------------------------------------------------------------------
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- "DHE-RSA-AES256-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- "DHE-DSS-AES256-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- "AES256-SHA";
-openssl_suite_name(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-DSS-DES-CBC3-SHA";
-openssl_suite_name(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "DES-CBC3-SHA";
-openssl_suite_name( ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- "DHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- "DHE-DSS-AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- "AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
- "RC4-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
- "RC4-MD5";
-openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- "EDH-RSA-DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
- "DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
- "NULL-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
- "AES128-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
- "AES256-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
- "DH-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
- "DH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
- "DHE-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "DHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
- "DH-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
- "DH-RSA-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
- "DHE-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
- "DHE-RSA-AES256-SHA256";
-
-%%% PSK Cipher Suites RFC 4279
-
-openssl_suite_name(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
- "PSK-AES256-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
- "PSK-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
- "PSK-AES128-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
- "PSK-RC4-SHA";
-
-%%% SRP Cipher Suites RFC 5054
-
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-RSA-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-DSS-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
- "SRP-RSA-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
- "SRP-DSS-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
- "SRP-RSA-AES-256-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
- "SRP-DSS-AES-256-CBC-SHA";
-
-%% RFC 4492 EC TLS suites
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
- "ECDH-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-ECDSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
- "ECDHE-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-ECDSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
- "ECDH-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-RSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
- "ECDHE-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-RSA-AES256-SHA";
-
-%% RFC 5289 EC TLS suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-RSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-RSA-AES256-SHA384";
-
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite_name(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
- "AES128-GCM-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
- "AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "DHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "DHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
- "DH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
- "DH-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
- "DHE-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
- "DHE-DSS-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
- "DH-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
- "DH-DSS-AES256-GCM-SHA384";
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-RSA-AES256-GCM-SHA384";
-
-%% No oppenssl name
-openssl_suite_name(Cipher) ->
- suite_definition(Cipher).
-
-%%--------------------------------------------------------------------
--spec filter(undefined | binary(), [cipher_suite()], ssl_record:ssl_version()) -> [cipher_suite()].
+-spec filter(undefined | binary(), [ssl_cipher_format:cipher_suite()],
+ ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Select the cipher suites that can be used together with the
%% supplied certificate. (Server side functionality)
@@ -2258,8 +487,8 @@ filter(DerCert, Ciphers0, Version) ->
filter_suites_signature(Sign, Ciphers, Version).
%%--------------------------------------------------------------------
--spec filter_suites([erl_cipher_suite()] | [cipher_suite()], map()) ->
- [erl_cipher_suite()] | [cipher_suite()].
+-spec filter_suites([ssl:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()], map()) ->
+ [ssl:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()].
%%
%% Description: Filter suites using supplied filter funs
%%-------------------------------------------------------------------
@@ -2282,11 +511,11 @@ filter_suite(#{key_exchange := KeyExchange,
all_filters(Hash, HashFilters) andalso
all_filters(Prf, PrfFilters);
filter_suite(Suite, Filters) ->
- filter_suite(suite_definition(Suite), Filters).
+ filter_suite(ssl_cipher_format:suite_definition(Suite), Filters).
%%--------------------------------------------------------------------
--spec filter_suites([erl_cipher_suite()] | [cipher_suite()]) ->
- [erl_cipher_suite()] | [cipher_suite()].
+-spec filter_suites([ssl:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()]) ->
+ [ssl:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()].
%%
%% Description: Filter suites for algorithms supported by crypto.
%%-------------------------------------------------------------------
@@ -2370,7 +599,7 @@ is_acceptable_cipher(rc4_128, Algos) ->
is_acceptable_cipher(des_cbc, Algos) ->
proplists:get_bool(des_cbc, Algos);
is_acceptable_cipher('3des_ede_cbc', Algos) ->
- proplists:get_bool(des3_cbc, Algos);
+ proplists:get_bool(des_ede3, Algos);
is_acceptable_cipher(aes_128_cbc, Algos) ->
proplists:get_bool(aes_cbc128, Algos);
is_acceptable_cipher(aes_256_cbc, Algos) ->
@@ -2410,12 +639,13 @@ random_bytes(N) ->
calc_mac_hash(Type, Version,
PlainFragment, #{sequence_number := SeqNo,
mac_secret := MacSecret,
- security_parameters:=
- SecPars}) ->
+ security_parameters :=
+ #security_parameters{mac_algorithm = MacAlgorithm}}) ->
+ calc_mac_hash(Type, Version, PlainFragment, MacAlgorithm, MacSecret, SeqNo).
+%%
+calc_mac_hash(Type, Version, PlainFragment, MacAlgorithm, MacSecret, SeqNo) ->
Length = erlang:iolist_size(PlainFragment),
- mac_hash(Version, SecPars#security_parameters.mac_algorithm,
- MacSecret, SeqNo, Type,
- Length, PlainFragment).
+ mac_hash(Version, MacAlgorithm, MacSecret, SeqNo, Type, Length, PlainFragment).
is_stream_ciphersuite(#{cipher := rc4_128}) ->
true;
@@ -2499,7 +729,6 @@ expanded_key_material(Cipher) when Cipher == aes_128_cbc;
Cipher == chacha20_poly1305 ->
unknown.
-
effective_key_bits(null) ->
0;
effective_key_bits(des_cbc) ->
@@ -2519,18 +748,15 @@ iv_size(Cipher) when Cipher == null;
Cipher == rc4_128;
Cipher == chacha20_poly1305->
0;
-
iv_size(Cipher) when Cipher == aes_128_gcm;
Cipher == aes_256_gcm ->
4;
-
iv_size(Cipher) ->
block_size(Cipher).
block_size(Cipher) when Cipher == des_cbc;
Cipher == '3des_ede_cbc' ->
8;
-
block_size(Cipher) when Cipher == aes_128_cbc;
Cipher == aes_256_cbc;
Cipher == aes_128_gcm;
@@ -2665,21 +891,51 @@ is_correct_padding(GenBlockCipher, {3, 1}, false) ->
%% Padding must be checked in TLS 1.1 and after
is_correct_padding(#generic_block_cipher{padding_length = Len,
padding = Padding}, _, _) ->
- Len == byte_size(Padding) andalso
- list_to_binary(lists:duplicate(Len, Len)) == Padding.
-
-get_padding(Length, BlockSize) ->
- get_padding_aux(BlockSize, Length rem BlockSize).
-
-get_padding_aux(_, 0) ->
- {0, <<>>};
-get_padding_aux(BlockSize, PadLength) ->
- N = BlockSize - PadLength,
- {N, list_to_binary(lists:duplicate(N, N))}.
+ (Len == byte_size(Padding)) andalso (padding(Len) == Padding).
+
+padding(PadLen) ->
+ case PadLen of
+ 0 -> <<>>;
+ 1 -> <<1>>;
+ 2 -> <<2,2>>;
+ 3 -> <<3,3,3>>;
+ 4 -> <<4,4,4,4>>;
+ 5 -> <<5,5,5,5,5>>;
+ 6 -> <<6,6,6,6,6,6>>;
+ 7 -> <<7,7,7,7,7,7,7>>;
+ 8 -> <<8,8,8,8,8,8,8,8>>;
+ 9 -> <<9,9,9,9,9,9,9,9,9>>;
+ 10 -> <<10,10,10,10,10,10,10,10,10,10>>;
+ 11 -> <<11,11,11,11,11,11,11,11,11,11,11>>;
+ 12 -> <<12,12,12,12,12,12,12,12,12,12,12,12>>;
+ 13 -> <<13,13,13,13,13,13,13,13,13,13,13,13,13>>;
+ 14 -> <<14,14,14,14,14,14,14,14,14,14,14,14,14,14>>;
+ 15 -> <<15,15,15,15,15,15,15,15,15,15,15,15,15,15,15>>;
+ _ ->
+ binary:copy(<<PadLen>>, PadLen)
+ end.
-random_iv(IV) ->
- IVSz = byte_size(IV),
- random_bytes(IVSz).
+padding_with_len(TextLen, BlockSize) ->
+ case BlockSize - (TextLen rem BlockSize) of
+ 0 -> <<0>>;
+ 1 -> <<1,1>>;
+ 2 -> <<2,2,2>>;
+ 3 -> <<3,3,3,3>>;
+ 4 -> <<4,4,4,4,4>>;
+ 5 -> <<5,5,5,5,5,5>>;
+ 6 -> <<6,6,6,6,6,6,6>>;
+ 7 -> <<7,7,7,7,7,7,7,7>>;
+ 8 -> <<8,8,8,8,8,8,8,8,8>>;
+ 9 -> <<9,9,9,9,9,9,9,9,9,9>>;
+ 10 -> <<10,10,10,10,10,10,10,10,10,10,10>>;
+ 11 -> <<11,11,11,11,11,11,11,11,11,11,11,11>>;
+ 12 -> <<12,12,12,12,12,12,12,12,12,12,12,12,12>>;
+ 13 -> <<13,13,13,13,13,13,13,13,13,13,13,13,13,13>>;
+ 14 -> <<14,14,14,14,14,14,14,14,14,14,14,14,14,14,14>>;
+ 15 -> <<15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15>>;
+ PadLen ->
+ binary:copy(<<PadLen>>, PadLen + 1)
+ end.
next_iv(Bin, IV) ->
BinSz = byte_size(Bin),
@@ -2709,6 +965,8 @@ filter_suites_pubkey(ec, Ciphers, _, OtpCert) ->
ec_ecdhe_suites(Ciphers)),
filter_keyuse_suites(keyAgreement, Uses, CiphersSuites, ec_ecdh_suites(Ciphers)).
+filter_suites_signature(_, Ciphers, {3, N}) when N >= 3 ->
+ Ciphers;
filter_suites_signature(rsa, Ciphers, Version) ->
(Ciphers -- ecdsa_signed_suites(Ciphers, Version)) -- dsa_signed_suites(Ciphers, Version);
filter_suites_signature(dsa, Ciphers, Version) ->
@@ -2775,6 +1033,8 @@ ecdsa_signed_suites(Ciphers, Version) ->
rsa_keyed(dhe_rsa) ->
true;
+rsa_keyed(ecdhe_rsa) ->
+ true;
rsa_keyed(rsa) ->
true;
rsa_keyed(rsa_psk) ->
@@ -2838,6 +1098,8 @@ ec_keyed(ecdh_ecdsa) ->
true;
ec_keyed(ecdh_rsa) ->
true;
+ec_keyed(ecdhe_ecdsa) ->
+ true;
ec_keyed(_) ->
false.
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index ba6a98b92a..2371e8bd32 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -48,7 +48,8 @@
iv,
key,
state,
- nonce
+ nonce,
+ tag_len
}).
%%% TLS_NULL_WITH_NULL_NULL is specified and is the initial state of a
diff --git a/lib/ssl/src/ssl_cipher_format.erl b/lib/ssl/src/ssl_cipher_format.erl
new file mode 100644
index 0000000000..1d28e1e3b4
--- /dev/null
+++ b/lib/ssl/src/ssl_cipher_format.erl
@@ -0,0 +1,1763 @@
+%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Convert between diffrent cipher suite representations
+%%
+%%----------------------------------------------------------------------
+-module(ssl_cipher_format).
+
+-include("ssl_api.hrl").
+-include("ssl_cipher.hrl").
+-include("ssl_internal.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-export_type([old_erl_cipher_suite/0, openssl_cipher_suite/0, cipher_suite/0]).
+
+-type internal_cipher() :: null | ssl:cipher().
+-type internal_hash() :: null | ssl:hash().
+-type internal_kex_algo() :: null | ssl:kex_algo().
+-type internal_erl_cipher_suite() :: #{key_exchange := internal_kex_algo(),
+ cipher := internal_cipher(),
+ mac := internal_hash() | aead,
+ prf := internal_hash() | default_prf %% Old cipher suites, version dependent
+ }.
+-type old_erl_cipher_suite() :: {ssl:kex_algo(), internal_cipher(), internal_hash()} % Pre TLS 1.2
+ %% TLS 1.2, internally PRE TLS 1.2 will use default_prf
+ | {ssl:kex_algo(), internal_cipher(), internal_hash(),
+ internal_hash() | default_prf}.
+-type cipher_suite() :: binary().
+-type openssl_cipher_suite() :: string().
+
+
+-export([suite_to_str/1, suite_definition/1, suite/1, erl_suite_definition/1,
+ openssl_suite/1, openssl_suite_name/1]).
+
+%%--------------------------------------------------------------------
+-spec suite_to_str(internal_erl_cipher_suite()) -> string().
+%%
+%% Description: Return the string representation of a cipher suite.
+%%--------------------------------------------------------------------
+suite_to_str(#{key_exchange := null,
+ cipher := null,
+ mac := null,
+ prf := null}) ->
+ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
+suite_to_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := aead,
+ prf := PRF}) ->
+ "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
+ "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
+ "_" ++ string:to_upper(atom_to_list(PRF));
+suite_to_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := Mac}) ->
+ "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
+ "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
+ "_" ++ string:to_upper(atom_to_list(Mac)).
+
+%%--------------------------------------------------------------------
+-spec suite_definition(cipher_suite()) -> internal_erl_cipher_suite().
+%%
+%% Description: Return erlang cipher suite definition.
+%% Note: Currently not supported suites are commented away.
+%% They should be supported or removed in the future.
+%%-------------------------------------------------------------------
+%% TLS v1.1 suites
+suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
+ #{key_exchange => null,
+ cipher => null,
+ mac => null,
+ prf => null};
+%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension
+%% to avoid handshake failure from old servers that do not ignore
+%% hello extension data as they should.
+suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
+ #{key_exchange => null,
+ cipher => null,
+ mac => null,
+ prf => null};
+suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
+ #{key_exchange => rsa,
+ cipher => rc4_128,
+ mac => md5,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+%%% TSL V1.1 AES suites
+suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% TLS v1.2 suites
+%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
+%% {rsa, null, sha, default_prf};
+suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+%% not defined YET:
+%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH_DSS AES_128_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH_RSA AES_128_CBC SHA256
+%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH_DSS AES_256_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
+%%% DH-ANON deprecated by TLS spec and not available
+%%% by default, but good for testing purposes.
+suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
+ #{key_exchange => dh_anon,
+ cipher => rc4_128,
+ mac => md5,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+%%% PSK Cipher Suites RFC 4279
+suite_definition(?TLS_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%%% PSK NULL Cipher Suites RFC 4785
+suite_definition(?TLS_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+%%% TLS 1.2 PSK Cipher Suites RFC 5487
+suite_definition(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+%%% ECDHE PSK Cipher Suites RFC 5489
+suite_definition(?TLS_ECDHE_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => null, mac => sha384,
+ prf => default_prf};
+%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_gcm,
+ mac => null,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_gcm,
+ mac => null,
+ prf => sha384};
+%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256) ->
+%% #{key_exchange => ecdhe_psk,
+%% cipher => aes_128_ccm,
+%% mac => null,
+%% prf =>sha256};
+%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256) ->
+%% #{key_exchange => ecdhe_psk,
+%% cipher => aes_256_ccm,
+%% mac => null,
+%% prf => sha256};
+%%% SRP Cipher Suites RFC 5054
+suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% RFC 4492 EC TLS suites
+suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% RFC 5289 EC TLS suites
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+%% RFC 5288 AES-GCM Cipher Suites
+suite_definition(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_dss,
+ cipher => aes_128_gcm,
+ mac => null,
+ prf => sha256};
+suite_definition(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_dss,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+%% RFC 5289 ECC AES-GCM Cipher Suites
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256}.
+
+%%--------------------------------------------------------------------
+-spec erl_suite_definition(cipher_suite() | internal_erl_cipher_suite()) -> old_erl_cipher_suite().
+%%
+%% Description: Return erlang cipher suite definition. Filters last value
+%% for now (compatibility reasons).
+%%--------------------------------------------------------------------
+erl_suite_definition(Bin) when is_binary(Bin) ->
+ erl_suite_definition(suite_definition(Bin));
+erl_suite_definition(#{key_exchange := KeyExchange, cipher := Cipher,
+ mac := Hash, prf := Prf}) ->
+ case Prf of
+ default_prf ->
+ {KeyExchange, Cipher, Hash};
+ _ ->
+ {KeyExchange, Cipher, Hash, Prf}
+ end.
+
+%%--------------------------------------------------------------------
+-spec suite(internal_erl_cipher_suite()) -> cipher_suite().
+%%
+%% Description: Return TLS cipher suite definition.
+%%--------------------------------------------------------------------
+%% TLS v1.1 suites
+suite(#{key_exchange := rsa,
+ cipher := rc4_128,
+ mac := md5}) ->
+ ?TLS_RSA_WITH_RC4_128_MD5;
+suite(#{key_exchange := rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := rsa,
+ cipher := des_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_DES_CBC_SHA;
+suite(#{key_exchange := rsa,
+ cipher :='3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher:= rc4_128,
+ mac := md5}) ->
+ ?TLS_DH_anon_WITH_RC4_128_MD5;
+suite(#{key_exchange := dh_anon,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
+%%% TSL V1.1 AES suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA;
+%% TLS v1.2 suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA256;
+%%% PSK Cipher Suites RFC 4279
+suite(#{key_exchange := psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
+%%% PSK NULL Cipher Suites RFC 4785
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_NULL_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA;
+%%% TLS 1.2 PSK Cipher Suites RFC 5487
+suite(#{key_exchange := psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_PSK_WITH_NULL_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA384;
+%%% ECDHE PSK Cipher Suites RFC 5489
+suite(#{key_exchange := ecdhe_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher :='3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_NULL_SHA384;
+%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_gcm,
+ mac := null,
+ prf := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_gcm,
+ mac := null,
+ prf := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384;
+ %% suite(#{key_exchange := ecdhe_psk,
+ %% cipher := aes_128_ccm,
+ %% mac := null,
+ %% prf := sha256}) ->
+ %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256;
+ %% suite(#{key_exchange := ecdhe_psk,
+ %% cipher := aes_256_ccm,
+ %% mac := null,
+ %% prf := sha256}) ->
+ %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256;
+%%% SRP Cipher Suites RFC 5054
+suite(#{key_exchange := srp_anon,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+%%% RFC 4492 EC TLS suites
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := '3des_ede_cbc', mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA;
+%%% RFC 5289 EC TLS suites
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_cbc,
+ mac:= sha256,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+%% RFC 5288 AES-GCM Cipher Suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_dss,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_dss,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_anon_WITH_AES_256_GCM_SHA384;
+%% RFC 5289 ECC AES-GCM Cipher Suites
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
+
+%%--------------------------------------------------------------------
+-spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
+%%
+%% Description: Return TLS cipher suite definition.
+%%--------------------------------------------------------------------
+%% translate constants <-> openssl-strings
+openssl_suite("DHE-RSA-AES256-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-DSS-AES256-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+openssl_suite("AES256-SHA256") ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-RSA-AES128-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("DHE-DSS-AES128-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+openssl_suite("AES128-SHA256") ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("DHE-RSA-AES256-SHA") ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("DHE-DSS-AES256-SHA") ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+openssl_suite("AES256-SHA") ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("EDH-RSA-DES-CBC3-SHA") ->
+ ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("EDH-DSS-DES-CBC3-SHA") ->
+ ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("DES-CBC3-SHA") ->
+ ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("DHE-RSA-AES128-SHA") ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("DHE-DSS-AES128-SHA") ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+openssl_suite("AES128-SHA") ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("RC4-SHA") ->
+ ?TLS_RSA_WITH_RC4_128_SHA;
+openssl_suite("RC4-MD5") ->
+ ?TLS_RSA_WITH_RC4_128_MD5;
+openssl_suite("EDH-RSA-DES-CBC-SHA") ->
+ ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
+openssl_suite("DES-CBC-SHA") ->
+ ?TLS_RSA_WITH_DES_CBC_SHA;
+
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+
+%% RFC 4492 EC TLS suites
+openssl_suite("ECDH-ECDSA-RC4-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDH-ECDSA-AES128-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDH-ECDSA-AES256-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDHE-ECDSA-RC4-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDHE-ECDSA-AES128-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDHE-ECDSA-AES256-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDHE-RSA-RC4-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+openssl_suite("ECDHE-RSA-DES-CBC3-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDHE-RSA-AES128-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDHE-RSA-AES256-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDH-RSA-RC4-SHA") ->
+ ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
+openssl_suite("ECDH-RSA-DES-CBC3-SHA") ->
+ ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDH-RSA-AES128-SHA") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDH-RSA-AES256-SHA") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+
+%% RFC 5289 EC TLS suites
+openssl_suite("ECDHE-ECDSA-AES128-SHA256") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDHE-ECDSA-AES256-SHA384") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDH-ECDSA-AES128-SHA256") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDH-ECDSA-AES256-SHA384") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDHE-RSA-AES128-SHA256") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDHE-RSA-AES256-SHA384") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDH-RSA-AES128-SHA256") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDH-RSA-AES256-SHA384") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+
+%% RFC 5288 AES-GCM Cipher Suites
+openssl_suite("AES128-GCM-SHA256") ->
+ ?TLS_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("AES256-GCM-SHA384") ->
+ ?TLS_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DHE-RSA-AES128-GCM-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("DHE-RSA-AES256-GCM-SHA384") ->
+ ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DH-RSA-AES128-GCM-SHA256") ->
+ ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("DH-RSA-AES256-GCM-SHA384") ->
+ ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DHE-DSS-AES128-GCM-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
+openssl_suite("DHE-DSS-AES256-GCM-SHA384") ->
+ ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
+openssl_suite("DH-DSS-AES128-GCM-SHA256") ->
+ ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
+openssl_suite("DH-DSS-AES256-GCM-SHA384") ->
+ ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+
+%% RFC 5289 ECC AES-GCM Cipher Suites
+openssl_suite("ECDHE-ECDSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDHE-ECDSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDH-ECDSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDH-ECDSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDHE-RSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDHE-RSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDH-RSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDH-RSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384.
+
+%%--------------------------------------------------------------------
+-spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite() | internal_erl_cipher_suite().
+%%
+%% Description: Return openssl cipher suite name if possible
+%%-------------------------------------------------------------------
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
+ "DHE-RSA-AES256-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
+ "DHE-DSS-AES256-SHA";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
+ "AES256-SHA";
+openssl_suite_name(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "EDH-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ "EDH-DSS-DES-CBC3-SHA";
+openssl_suite_name(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "DES-CBC3-SHA";
+openssl_suite_name( ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
+ "DHE-RSA-AES128-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
+ "DHE-DSS-AES128-SHA";
+openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
+ "AES128-SHA";
+openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
+ "RC4-SHA";
+openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
+ "RC4-MD5";
+openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
+ "EDH-RSA-DES-CBC-SHA";
+openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
+ "DES-CBC-SHA";
+openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
+ "NULL-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ "AES128-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ "AES256-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DH-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DH-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DHE-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DHE-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DH-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DH-RSA-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DHE-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DHE-RSA-AES256-SHA256";
+
+%%% PSK Cipher Suites RFC 4279
+
+openssl_suite_name(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
+ "PSK-AES256-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ "PSK-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
+ "PSK-AES128-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
+ "PSK-RC4-SHA";
+
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-RSA-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-DSS-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ "SRP-RSA-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ "SRP-DSS-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ "SRP-RSA-AES-256-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ "SRP-DSS-AES-256-CBC-SHA";
+
+%% RFC 4492 EC TLS suites
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
+ "ECDH-ECDSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDH-ECDSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
+ "ECDH-ECDSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
+ "ECDH-ECDSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
+ "ECDHE-ECDSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDHE-ECDSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
+ "ECDHE-ECDSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
+ "ECDHE-ECDSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
+ "ECDH-RSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDH-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
+ "ECDH-RSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
+ "ECDH-RSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
+ "ECDHE-RSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDHE-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
+ "ECDHE-RSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
+ "ECDHE-RSA-AES256-SHA";
+
+%% RFC 5289 EC TLS suites
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDHE-ECDSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDHE-ECDSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDH-ECDSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDH-ECDSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDHE-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDHE-RSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDH-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDH-RSA-AES256-SHA384";
+
+%% RFC 5288 AES-GCM Cipher Suites
+openssl_suite_name(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
+ "AES128-GCM-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
+ "AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ "DHE-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ "DHE-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
+ "DH-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
+ "DH-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
+ "DHE-DSS-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
+ "DHE-DSS-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
+ "DH-DSS-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
+ "DH-DSS-AES256-GCM-SHA384";
+
+%% RFC 5289 ECC AES-GCM Cipher Suites
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDHE-ECDSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDHE-ECDSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDH-ECDSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDH-ECDSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDHE-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDHE-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDH-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDH-RSA-AES256-GCM-SHA384";
+
+%% No oppenssl name
+openssl_suite_name(Cipher) ->
+ suite_definition(Cipher).
diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl
index 63c0a416ef..1e6dab9276 100644
--- a/lib/ssl/src/ssl_config.erl
+++ b/lib/ssl/src/ssl_config.erl
@@ -91,9 +91,9 @@ init_certificates(undefined, #{pem_cache := PemCache} = Config, CertFile, server
end;
init_certificates(Cert, Config, _, _) ->
{ok, Config#{own_certificate => Cert}}.
-init_private_key(_, #{algorithm := Alg} = Key, <<>>, _Password, _Client) when Alg == ecdsa;
- Alg == rsa;
- Alg == dss ->
+init_private_key(_, #{algorithm := Alg} = Key, _, _Password, _Client) when Alg == ecdsa;
+ Alg == rsa;
+ Alg == dss ->
case maps:is_key(engine, Key) andalso maps:is_key(key_id, Key) of
true ->
Key;
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 556c204ab1..a5f29c058a 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@
-export([connect/8, handshake/7, handshake/2, handshake/3,
handshake_continue/3, handshake_cancel/1,
- socket_control/4, socket_control/5, start_or_recv_cancel_timer/2]).
+ socket_control/4, socket_control/5]).
%% User Events
-export([send/2, recv/3, close/2, shutdown/2,
@@ -51,11 +51,11 @@
%% Alert and close handling
-export([handle_own_alert/4, handle_alert/3,
- handle_normal_shutdown/3, stop/2, stop_and_reply/3
- ]).
+ handle_normal_shutdown/3,
+ handle_trusted_certs_db/1]).
%% Data handling
--export([write_application_data/3, read_application_data/2]).
+-export([read_application_data/2, internal_renegotiation/2]).
%% Help functions for tls|dtls_connection.erl
-export([handle_session/7, ssl_config/3,
@@ -64,20 +64,20 @@
%% General gen_statem state functions with extra callback argument
%% to determine if it is an SSL/TLS or DTLS gen_statem machine
-export([init/4, error/4, hello/4, user_hello/4, abbreviated/4, certify/4, cipher/4,
- connection/4, death_row/4, downgrade/4]).
+ connection/4, downgrade/4]).
%% gen_statem callbacks
-export([terminate/3, format_status/2]).
%% Erlang Distribution export
--export([get_sslsocket/1, handshake_complete/3]).
+-export([dist_handshake_complete/2]).
%%====================================================================
%% Setup
%%====================================================================
%%--------------------------------------------------------------------
-spec connect(tls_connection | dtls_connection,
- host(), inet:port_number(),
+ ssl:host(), inet:port_number(),
port() | {tuple(), port()}, %% TLS | DTLS
{#ssl_options{}, #socket_options{},
%% Tracker only needed on server side
@@ -114,11 +114,11 @@ handshake(Connection, Port, Socket, Opts, User, CbInfo, Timeout) ->
%%--------------------------------------------------------------------
-spec handshake(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {ok, #sslsocket{}, map()}| {error, reason()}.
+ {ok, #sslsocket{}, map()}| {error, reason()}.
%%
%% Description: Starts ssl handshake.
%%--------------------------------------------------------------------
-handshake(#sslsocket{pid = Pid} = Socket, Timeout) ->
+handshake(#sslsocket{pid = [Pid|_]} = Socket, Timeout) ->
case call(Pid, {start, Timeout}) of
connected ->
{ok, Socket};
@@ -129,12 +129,12 @@ handshake(#sslsocket{pid = Pid} = Socket, Timeout) ->
end.
%%--------------------------------------------------------------------
--spec handshake(#sslsocket{}, {#ssl_options{},#socket_options{}},
- timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec handshake(#sslsocket{}, {#ssl_options{},#socket_options{}}, timeout()) ->
+ {ok, #sslsocket{}} | {ok, #sslsocket{}, map()} | {error, reason()}.
%%
%% Description: Starts ssl handshake with some new options
%%--------------------------------------------------------------------
-handshake(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
+handshake(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) ->
case call(Pid, {start, SslOptions, Timeout}) of
connected ->
{ok, Socket};
@@ -143,12 +143,12 @@ handshake(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
end.
%%--------------------------------------------------------------------
--spec handshake_continue(#sslsocket{}, [ssl_option()],
+-spec handshake_continue(#sslsocket{}, [ssl:tls_server_option()],
timeout()) -> {ok, #sslsocket{}}| {error, reason()}.
%%
%% Description: Continues handshake with new options
%%--------------------------------------------------------------------
-handshake_continue(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
+handshake_continue(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) ->
case call(Pid, {handshake_continue, SslOptions, Timeout}) of
connected ->
{ok, Socket};
@@ -160,7 +160,7 @@ handshake_continue(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
%%
%% Description: Cancels connection
%%--------------------------------------------------------------------
-handshake_cancel(#sslsocket{pid = Pid}) ->
+handshake_cancel(#sslsocket{pid = [Pid|_]}) ->
case call(Pid, cancel) of
closed ->
ok;
@@ -168,7 +168,7 @@ handshake_cancel(#sslsocket{pid = Pid}) ->
Error
end.
%--------------------------------------------------------------------
--spec socket_control(tls_connection | dtls_connection, port(), pid(), atom()) ->
+-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Set the ssl process to own the accept socket
@@ -177,32 +177,28 @@ socket_control(Connection, Socket, Pid, Transport) ->
socket_control(Connection, Socket, Pid, Transport, undefined).
%--------------------------------------------------------------------
--spec socket_control(tls_connection | dtls_connection, port(), pid(), atom(), pid()| undefined) ->
+-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom(), pid()| atom()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%--------------------------------------------------------------------
-socket_control(Connection, Socket, Pid, Transport, udp_listener) ->
+socket_control(Connection, Socket, Pids, Transport, udp_listener) ->
%% dtls listener process must have the socket control
- {ok, Connection:socket(Pid, Transport, Socket, Connection, undefined)};
+ {ok, Connection:socket(Pids, Transport, Socket, undefined)};
-socket_control(tls_connection = Connection, Socket, Pid, Transport, ListenTracker) ->
+socket_control(tls_connection = Connection, Socket, [Pid|_] = Pids, Transport, ListenTracker) ->
case Transport:controlling_process(Socket, Pid) of
ok ->
- {ok, Connection:socket(Pid, Transport, Socket, Connection, ListenTracker)};
+ {ok, Connection:socket(Pids, Transport, Socket, ListenTracker)};
{error, Reason} ->
{error, Reason}
end;
-socket_control(dtls_connection = Connection, {_, Socket}, Pid, Transport, ListenTracker) ->
+socket_control(dtls_connection = Connection, {_, Socket}, [Pid|_] = Pids, Transport, ListenTracker) ->
case Transport:controlling_process(Socket, Pid) of
ok ->
- {ok, Connection:socket(Pid, Transport, Socket, Connection, ListenTracker)};
+ {ok, Connection:socket(Pids, Transport, Socket, ListenTracker)};
{error, Reason} ->
{error, Reason}
end.
-start_or_recv_cancel_timer(infinity, _RecvFrom) ->
- undefined;
-start_or_recv_cancel_timer(Timeout, RecvFrom) ->
- erlang:send_after(Timeout, self(), {cancel_start_or_recv, RecvFrom}).
%%====================================================================
%% User events
@@ -215,9 +211,9 @@ start_or_recv_cancel_timer(Timeout, RecvFrom) ->
%%--------------------------------------------------------------------
send(Pid, Data) ->
call(Pid, {application_data,
- %% iolist_to_binary should really
- %% be called iodata_to_binary()
- erlang:iolist_to_binary(Data)}).
+ %% iolist_to_iovec should really
+ %% be called iodata_to_iovec()
+ erlang:iolist_to_iovec(Data)}).
%%--------------------------------------------------------------------
-spec recv(pid(), integer(), timeout()) ->
@@ -306,12 +302,17 @@ peer_certificate(ConnectionPid) ->
renegotiation(ConnectionPid) ->
call(ConnectionPid, renegotiate).
+%%--------------------------------------------------------------------
+-spec internal_renegotiation(pid(), ssl_record:connection_states()) ->
+ ok.
+%%
+%% Description: Starts a renegotiation of the ssl session.
+%%--------------------------------------------------------------------
+internal_renegotiation(ConnectionPid, #{current_write := WriteState}) ->
+ gen_statem:cast(ConnectionPid, {internal_renegotiate, WriteState}).
-get_sslsocket(ConnectionPid) ->
- call(ConnectionPid, get_sslsocket).
-
-handshake_complete(ConnectionPid, Node, DHandle) ->
- call(ConnectionPid, {handshake_complete, Node, DHandle}).
+dist_handshake_complete(ConnectionPid, DHandle) ->
+ gen_statem:cast(ConnectionPid, {dist_handshake_complete, DHandle}).
%%--------------------------------------------------------------------
-spec prf(pid(), binary() | 'master_secret', binary(),
@@ -326,191 +327,365 @@ prf(ConnectionPid, Secret, Label, Seed, WantedLength) ->
%%====================================================================
%% Alert and close handling
%%====================================================================
-handle_own_alert(Alert, Version, StateName,
- #state{role = Role,
- transport_cb = Transport,
- socket = Socket,
- protocol_cb = Connection,
- connection_states = ConnectionStates,
+handle_own_alert(Alert0, _, StateName,
+ #state{static_env = #static_env{role = Role,
+ protocol_cb = Connection},
ssl_options = SslOpts} = State) ->
try %% Try to tell the other side
- {BinMsg, _} =
- Connection:encode_alert(Alert, Version, ConnectionStates),
- Connection:send(Transport, Socket, BinMsg)
+ send_alert(Alert0, StateName, State)
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, Role, Connection:protocol_name(), StateName, Alert#alert{role = Role}),
+ Alert = Alert0#alert{role = Role},
+ log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), StateName, Alert),
handle_normal_shutdown(Alert,StateName, State)
catch _:_ ->
ok
end,
- stop({shutdown, own_alert}, State).
-
-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).
-
-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} = State) ->
+ {stop, {shutdown, own_alert}, State}.
+
+handle_normal_shutdown(Alert, StateName, #state{static_env = #static_env{role = Role,
+ socket = Socket,
+ transport_cb = Transport,
+ protocol_cb = Connection,
+ tracker = Tracker},
+ handshake_env = #handshake_env{renegotiation = {false, first}},
+ start_or_recv_from = StartFrom} = State) ->
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker,Socket, StartFrom, Alert, Role, StateName, Connection);
+
+handle_normal_shutdown(Alert, StateName, #state{static_env = #static_env{role = Role,
+ socket = Socket,
+ transport_cb = Transport,
+ protocol_cb = Connection,
+ tracker = Tracker},
+ connection_env = #connection_env{user_application = {_Mon, Pid}},
+ socket_options = Opts,
+ start_or_recv_from = RecvFrom} = State) ->
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, StateName, Connection).
+
+handle_alert(#alert{level = ?FATAL} = Alert0, StateName,
+ #state{static_env = #static_env{role = Role,
+ socket = Socket,
+ host = Host,
+ port = Port,
+ tracker = Tracker,
+ transport_cb = Transport,
+ protocol_cb = Connection},
+ connection_env = #connection_env{user_application = {_Mon, Pid}},
+ ssl_options = SslOpts,
+ start_or_recv_from = From,
+ session = Session,
+ socket_options = Opts} = State) ->
invalidate_session(Role, Host, Port, Session),
+ Alert = Alert0#alert{role = opposite_role(Role)},
log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(),
- StateName, Alert#alert{role = opposite_role(Role)}),
- alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
- stop(normal, State);
+ StateName, Alert),
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, StateName, Connection),
+ {stop, {shutdown, normal}, State};
handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
- StateName, State) ->
+ downgrade= StateName, State) ->
+ {next_state, StateName, State, [{next_event, internal, Alert}]};
+handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
+ StateName, State) ->
handle_normal_shutdown(Alert, StateName, State),
- stop({shutdown, peer_close}, State);
-
-handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{role = Role, ssl_options = SslOpts, protocol_cb = Connection, renegotiation = {true, internal}} = State) ->
+ {stop,{shutdown, peer_close}, State};
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert0, StateName,
+ #state{static_env = #static_env{role = Role,
+ protocol_cb = Connection},
+ handshake_env = #handshake_env{renegotiation = {true, internal}},
+ ssl_options = SslOpts} = State) ->
+ Alert = Alert0#alert{role = opposite_role(Role)},
log_alert(SslOpts#ssl_options.log_alert, Role,
- Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ Connection:protocol_name(), StateName, Alert),
handle_normal_shutdown(Alert, StateName, State),
- stop({shutdown, peer_close}, State);
+ {stop,{shutdown, peer_close}, State};
+
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, connection = StateName,
+ #state{static_env = #static_env{role = Role,
+ protocol_cb = Connection},
+ handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv,
+ ssl_options = SslOpts
+ } = State0) ->
+ log_alert(SslOpts#ssl_options.log_alert, Role,
+ Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ gen_statem:reply(From, {error, renegotiation_rejected}),
+ State = Connection:reinit_handshake_data(State0),
+ Connection:next_event(connection, no_record, State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}});
handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{role = Role,
- ssl_options = SslOpts, renegotiation = {true, From},
- protocol_cb = Connection} = State0) ->
+ #state{static_env = #static_env{role = Role,
+ protocol_cb = Connection},
+ handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv,
+ ssl_options = SslOpts
+ } = State0) ->
log_alert(SslOpts#ssl_options.log_alert, Role,
Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
gen_statem:reply(From, {error, renegotiation_rejected}),
- {Record, State1} = Connection:next_record(State0),
%% Go back to connection!
- State = Connection:reinit_handshake_data(State1#state{renegotiation = undefined}),
- Connection:next_event(connection, Record, State);
+ State = Connection:reinit(State0#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}}),
+ Connection:next_event(connection, no_record, State);
%% Gracefully log and ignore all other warning alerts
handle_alert(#alert{level = ?WARNING} = Alert, StateName,
- #state{ssl_options = SslOpts, protocol_cb = Connection, role = Role} = State0) ->
+ #state{static_env = #static_env{role = Role,
+ protocol_cb = Connection},
+ ssl_options = SslOpts} = State) ->
log_alert(SslOpts#ssl_options.log_alert, Role,
Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
- {Record, State} = Connection:next_record(State0),
- Connection:next_event(StateName, Record, State).
+ Connection:next_event(StateName, no_record, State).
%%====================================================================
%% Data handling
%%====================================================================
-write_application_data(Data0, {FromPid, _} = 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} =
- Connection:encode_data(Data, Version, ConnectionStates0),
- NewState = State#state{connection_states = ConnectionStates},
- case Connection:send(Transport, Socket, Msgs) of
- ok when FromPid =:= self() ->
- hibernate_after(connection, NewState, []);
- Error when FromPid =:= self() ->
- stop({shutdown, Error}, NewState);
- ok ->
- hibernate_after(connection, NewState, [{reply, From, ok}]);
- Result ->
- hibernate_after(connection, NewState, [{reply, From, Result}])
+passive_receive(State0 = #state{user_data_buffer = {_,BufferSize,_}}, StateName, Connection, StartTimerAction) ->
+ case BufferSize of
+ 0 ->
+ Connection:next_event(StateName, no_record, State0, StartTimerAction);
+ _ ->
+ case read_application_data(<<>>, State0) of
+ {stop, _, _} = ShutdownError ->
+ ShutdownError;
+ {Record, State} ->
+ case State#state.start_or_recv_from of
+ undefined ->
+ %% Cancel recv timeout as data has been delivered
+ Connection:next_event(StateName, Record, State,
+ [{{timeout, recv}, infinity, timeout}]);
+ _ ->
+ Connection:next_event(StateName, Record, State, StartTimerAction)
+ end
end
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
- case State0 of
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := DHandle}} ->
- State =
- State0#state{
- user_data_buffer = Buffer,
- bytes_to_read = undefined},
- try erlang:dist_ctrl_put_data(DHandle, ClientData) of
- _
- when SOpts#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);
- _ -> %% We have more data
- read_application_data(<<>>, State)
- catch error:_ ->
- death_row(State, disconnect)
- end;
- _ ->
- 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
+read_application_data(
+ Data,
+ #state{
+ user_data_buffer = {Front0,BufferSize0,Rear0},
+ connection_env = #connection_env{erl_dist_handle = DHandle}} = State) ->
+ %%
+ Front = Front0,
+ BufferSize = BufferSize0 + byte_size(Data),
+ Rear = [Data|Rear0],
+ case DHandle of
+ undefined ->
+ read_application_data(State, Front, BufferSize, Rear);
+ _ ->
+ try read_application_dist_data(DHandle, Front, BufferSize, Rear) of
+ Buffer ->
+ {no_record, State#state{user_data_buffer = Buffer}}
+ catch error:_ ->
+ {stop,disconnect,
+ State#state{user_data_buffer = {Front,BufferSize,Rear}}}
+ end
+ end.
+
+
+read_application_data(#state{
+ socket_options = SocketOpts,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom} = State, Front, BufferSize, Rear) ->
+ read_application_data(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead).
+
+%% Pick binary from queue front, if empty wait for more data
+read_application_data(State, [Bin|Front], BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead) ->
+ read_application_data_bin(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead, Bin);
+read_application_data(State, [] = Front, BufferSize, [] = Rear, SocketOpts, RecvFrom, BytesToRead) ->
+ 0 = BufferSize, % Assert
+ {no_record, State#state{socket_options = SocketOpts,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ user_data_buffer = {Front,BufferSize,Rear}}};
+read_application_data(State, [], BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead) ->
+ [Bin|Front] = lists:reverse(Rear),
+ read_application_data_bin(State, Front, BufferSize, [], SocketOpts, RecvFrom, BytesToRead, Bin).
+
+read_application_data_bin(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead, <<>>) ->
+ %% Done with this binary - get next
+ read_application_data(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead);
+read_application_data_bin(State, Front0, BufferSize0, Rear0, SocketOpts0, RecvFrom, BytesToRead, Bin0) ->
+ %% Decode one packet from a binary
+ case get_data(SocketOpts0, BytesToRead, Bin0) of
+ {ok, Data, Bin} -> % Send data
+ BufferSize = BufferSize0 - (byte_size(Bin0) - byte_size(Bin)),
+ read_application_data_deliver(
+ State, [Bin|Front0], BufferSize, Rear0, SocketOpts0, RecvFrom, Data);
+ {more, undefined} ->
+ %% We need more data, do not know how much
+ if
+ byte_size(Bin0) < BufferSize0 ->
+ %% We have more data in the buffer besides the first binary - concatenate all and retry
+ Bin = iolist_to_binary([Bin0,Front0|lists:reverse(Rear0)]),
+ read_application_data_bin(
+ State, [], BufferSize0, [], SocketOpts0, RecvFrom, BytesToRead, Bin);
+ true ->
+ %% All data is in the first binary, no use to retry - wait for more
+ {no_record, State#state{socket_options = SocketOpts0,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ user_data_buffer = {[Bin0|Front0],BufferSize0,Rear0}}}
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)
+ {more, Size} when Size =< BufferSize0 ->
+ %% We have a packet in the buffer - collect it in a binary and decode
+ {Data,Front,Rear} = iovec_from_front(Size - byte_size(Bin0), Front0, Rear0, [Bin0]),
+ Bin = iolist_to_binary(Data),
+ read_application_data_bin(
+ State, Front, BufferSize0, Rear, SocketOpts0, RecvFrom, BytesToRead, Bin);
+ {more, _Size} ->
+ %% We do not have a packet in the buffer - wait for more
+ {no_record, State#state{socket_options = SocketOpts0,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ user_data_buffer = {[Bin0|Front0],BufferSize0,Rear0}}};
+ passive ->
+ {no_record, State#state{socket_options = SocketOpts0,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ user_data_buffer = {[Bin0|Front0],BufferSize0,Rear0}}};
+ {error,_Reason} ->
+ %% Invalid packet in packet mode
+ #state{
+ static_env =
+ #static_env{
+ socket = Socket,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ tracker = Tracker},
+ connection_env =
+ #connection_env{user_application = {_Mon, Pid}}} = State,
+ Buffer = iolist_to_binary([Bin0,Front0|lists:reverse(Rear0)]),
+ deliver_packet_error(
+ Connection:pids(State), Transport, Socket, SocketOpts0,
+ Buffer, Pid, RecvFrom, Tracker, Connection),
+ {stop, {shutdown, normal}, State#state{socket_options = SocketOpts0,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ user_data_buffer = {[Buffer],BufferSize0,[]}}}
+ end.
+
+read_application_data_deliver(State, Front, BufferSize, Rear, SocketOpts0, RecvFrom, Data) ->
+ #state{
+ static_env =
+ #static_env{
+ socket = Socket,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ tracker = Tracker},
+ connection_env =
+ #connection_env{user_application = {_Mon, Pid}}} = State,
+ SocketOpts =
+ deliver_app_data(
+ Connection:pids(State), Transport, Socket, SocketOpts0, Data, Pid, RecvFrom, Tracker, Connection),
+ if
+ SocketOpts#socket_options.active =:= false ->
+ %% Passive mode, wait for active once or recv
+ {no_record,
+ State#state{
+ user_data_buffer = {Front,BufferSize,Rear},
+ start_or_recv_from = undefined,
+ bytes_to_read = undefined,
+ socket_options = SocketOpts
+ }};
+ true -> %% Try to deliver more data
+ read_application_data(State, Front, BufferSize, Rear, SocketOpts, undefined, undefined)
+ end.
+
+
+read_application_dist_data(DHandle, [Bin|Front], BufferSize, Rear) ->
+ read_application_dist_data(DHandle, Front, BufferSize, Rear, Bin);
+read_application_dist_data(_DHandle, [] = Front, BufferSize, [] = Rear) ->
+ BufferSize = 0,
+ {Front,BufferSize,Rear};
+read_application_dist_data(DHandle, [], BufferSize, Rear) ->
+ [Bin|Front] = lists:reverse(Rear),
+ read_application_dist_data(DHandle, Front, BufferSize, [], Bin).
+%%
+read_application_dist_data(DHandle, Front0, BufferSize, Rear0, Bin0) ->
+ case Bin0 of
+ %%
+ %% START Optimization
+ %% It is cheaper to match out several packets in one match operation than to loop for each
+ <<SizeA:32, DataA:SizeA/binary,
+ SizeB:32, DataB:SizeB/binary,
+ SizeC:32, DataC:SizeC/binary,
+ SizeD:32, DataD:SizeD/binary, Rest/binary>> ->
+ %% We have 4 complete packets in the first binary
+ erlang:dist_ctrl_put_data(DHandle, DataA),
+ erlang:dist_ctrl_put_data(DHandle, DataB),
+ erlang:dist_ctrl_put_data(DHandle, DataC),
+ erlang:dist_ctrl_put_data(DHandle, DataD),
+ read_application_dist_data(
+ DHandle, Front0, BufferSize - (4*4+SizeA+SizeB+SizeC+SizeD), Rear0, Rest);
+ <<SizeA:32, DataA:SizeA/binary,
+ SizeB:32, DataB:SizeB/binary,
+ SizeC:32, DataC:SizeC/binary, Rest/binary>> ->
+ %% We have 3 complete packets in the first binary
+ erlang:dist_ctrl_put_data(DHandle, DataA),
+ erlang:dist_ctrl_put_data(DHandle, DataB),
+ erlang:dist_ctrl_put_data(DHandle, DataC),
+ read_application_dist_data(
+ DHandle, Front0, BufferSize - (3*4+SizeA+SizeB+SizeC), Rear0, Rest);
+ <<SizeA:32, DataA:SizeA/binary,
+ SizeB:32, DataB:SizeB/binary, Rest/binary>> ->
+ %% We have 2 complete packets in the first binary
+ erlang:dist_ctrl_put_data(DHandle, DataA),
+ erlang:dist_ctrl_put_data(DHandle, DataB),
+ read_application_dist_data(
+ DHandle, Front0, BufferSize - (2*4+SizeA+SizeB), Rear0, Rest);
+ %% END Optimization
+ %%
+ %% Basic one packet code path
+ <<Size:32, Data:Size/binary, Rest/binary>> ->
+ %% We have a complete packet in the first binary
+ erlang:dist_ctrl_put_data(DHandle, Data),
+ read_application_dist_data(DHandle, Front0, BufferSize - (4+Size), Rear0, Rest);
+ <<Size:32, FirstData/binary>> when 4+Size =< BufferSize ->
+ %% We have a complete packet in the buffer
+ %% - fetch the missing content from the buffer front
+ {Data,Front,Rear} = iovec_from_front(Size - byte_size(FirstData), Front0, Rear0, [FirstData]),
+ erlang:dist_ctrl_put_data(DHandle, Data),
+ read_application_dist_data(DHandle, Front, BufferSize - (4+Size), Rear);
+ <<Bin/binary>> ->
+ %% In OTP-21 the match context reuse optimization fails if we use Bin0 in recursion, so here we
+ %% match out the whole binary which will trick the optimization into keeping the match context
+ %% for the first binary contains complete packet code above
+ case Bin of
+ <<_Size:32, _InsufficientData/binary>> ->
+ %% We have a length field in the first binary but there is not enough data
+ %% in the buffer to form a complete packet - await more data
+ {[Bin|Front0],BufferSize,Rear0};
+ <<IncompleteLengthField/binary>> when 4 < BufferSize ->
+ %% We do not have a length field in the first binary but the buffer
+ %% contains enough data to maybe form a packet
+ %% - fetch a tiny binary from the buffer front to complete the length field
+ {LengthField,Front,Rear} =
+ iovec_from_front(4 - byte_size(IncompleteLengthField), Front0, Rear0, [IncompleteLengthField]),
+ LengthBin = iolist_to_binary(LengthField),
+ read_application_dist_data(DHandle, Front, BufferSize, Rear, LengthBin);
+ <<IncompleteLengthField/binary>> ->
+ %% We do not have enough data in the buffer to even form a length field - await more data
+ {[IncompleteLengthField|Front0],BufferSize,Rear0}
+ end
end.
+
+iovec_from_front(Size, [], Rear, Acc) ->
+ iovec_from_front(Size, lists:reverse(Rear), [], Acc);
+iovec_from_front(Size, [Bin|Front], Rear, Acc) ->
+ case Bin of
+ <<Last:Size/binary>> -> % Just enough
+ {lists:reverse(Acc, [Last]),Front,Rear};
+ <<Last:Size/binary, Rest/binary>> -> % More than enough, split here
+ {lists:reverse(Acc, [Last]),[Rest|Front],Rear};
+ <<_/binary>> -> % Not enough
+ BinSize = byte_size(Bin),
+ iovec_from_front(Size - BinSize, Front, Rear, [Bin|Acc])
+ end.
+
+
%%====================================================================
%% Help functions for tls|dtls_connection.erl
%%====================================================================
@@ -523,10 +698,10 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression},
Version, NewId, ConnectionStates, ProtoExt, Protocol0,
#state{session = #session{session_id = OldId},
- negotiated_version = ReqVersion,
- negotiated_protocol = CurrentProtocol} = State0) ->
+ handshake_env = #handshake_env{negotiated_protocol = CurrentProtocol} = HsEnv,
+ connection_env = #connection_env{negotiated_version = ReqVersion} = CEnv} = State0) ->
#{key_exchange := KeyAlgorithm} =
- ssl_cipher:suite_definition(CipherSuite),
+ ssl_cipher_format:suite_definition(CipherSuite),
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
@@ -537,12 +712,12 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
{ProtoExt =:= npn, Protocol0}
end,
- State = State0#state{key_algorithm = KeyAlgorithm,
- negotiated_version = Version,
- connection_states = ConnectionStates,
- premaster_secret = PremasterSecret,
- expecting_next_protocol_negotiation = ExpectNPN,
- negotiated_protocol = Protocol},
+ State = State0#state{connection_states = ConnectionStates,
+ handshake_env = HsEnv#handshake_env{kex_algorithm = KeyAlgorithm,
+ premaster_secret = PremasterSecret,
+ expecting_next_protocol_negotiation = ExpectNPN,
+ negotiated_protocol = Protocol},
+ connection_env = CEnv#connection_env{negotiated_version = Version}},
case ssl_session:is_new(OldId, NewId) of
true ->
@@ -556,10 +731,9 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
%%--------------------------------------------------------------------
-spec ssl_config(#ssl_options{}, client | server, #state{}) -> #state{}.
%%--------------------------------------------------------------------
-ssl_config(Opts, Role, State) ->
- ssl_config(Opts, Role, State, new).
-
-ssl_config(Opts, Role, State0, Type) ->
+ssl_config(Opts, Role, #state{static_env = InitStatEnv0,
+ handshake_env = HsEnv,
+ connection_env = CEnv} = State0) ->
{ok, #{cert_db_ref := Ref,
cert_db_handle := CertDbHandle,
fileref_db_handle := FileRefHandle,
@@ -571,24 +745,19 @@ ssl_config(Opts, Role, State0, Type) ->
ssl_config:init(Opts, Role),
TimeStamp = erlang:monotonic_time(),
Session = State0#state.session,
- State = State0#state{session = Session#session{own_certificate = OwnCert,
- time_stamp = TimeStamp},
- 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 = Opts},
- case Type of
- new ->
- Handshake = ssl_handshake:init_handshake_history(),
- State#state{tls_handshake_history = Handshake};
- continue ->
- State
- end.
-
+
+ State0#state{session = Session#session{own_certificate = OwnCert,
+ time_stamp = TimeStamp},
+ static_env = InitStatEnv0#static_env{
+ file_ref_db = FileRefHandle,
+ cert_db_ref = Ref,
+ cert_db = CertDbHandle,
+ crl_db = CRLDbHandle,
+ session_cache = CacheHandle
+ },
+ handshake_env = HsEnv#handshake_env{diffie_hellman_params = DHParams},
+ connection_env = CEnv#connection_env{private_key = Key},
+ ssl_options = Opts}.
%%====================================================================
%% gen_statem general state functions with connection cb argument
@@ -601,30 +770,25 @@ ssl_config(Opts, Role, State0, Type) ->
%%--------------------------------------------------------------------
init({call, From}, {start, Timeout}, State0, Connection) ->
- Timer = start_or_recv_cancel_timer(Timeout, From),
- {Record, State} = Connection:next_record(State0#state{start_or_recv_from = From,
- timer = Timer}),
- Connection:next_event(hello, Record, State);
+ Connection:next_event(hello, no_record, State0#state{start_or_recv_from = From},
+ [{{timeout, handshake}, Timeout, close}]);
init({call, From}, {start, {Opts, EmOpts}, Timeout},
- #state{role = Role, ssl_options = OrigSSLOptions,
+ #state{static_env = #static_env{role = Role},
+ ssl_options = OrigSSLOptions,
socket_options = SockOpts} = State0, Connection) ->
try
SslOpts = ssl:handle_options(Opts, OrigSSLOptions),
- case SslOpts of
- #ssl_options{erl_dist = true} ->
- process_flag(priority, max);
- _ ->
- ok
- end,
State = ssl_config(SslOpts, Role, State0),
init({call, From}, {start, Timeout},
State#state{ssl_options = SslOpts,
socket_options = new_emulated(EmOpts, SockOpts)}, Connection)
catch throw:Error ->
- stop_and_reply(normal, {reply, From, {error, Error}}, State0)
+ {stop_and_reply, {shutdown, normal}, {reply, From, {error, Error}}, State0}
end;
-init({call, From}, Msg, State, Connection) ->
+init({call, From}, {new_user, _} = Msg, State, Connection) ->
handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
+init({call, From}, _Msg, _State, _Connection) ->
+ {keep_state_and_data, [{reply, From, {error, notsup_on_transport_accept_socket}}]};
init(_Type, _Event, _State, _Connection) ->
{keep_state_and_data, [postpone]}.
@@ -634,8 +798,10 @@ init(_Type, _Event, _State, _Connection) ->
tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-error({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, ?FUNCTION_NAME, State, Connection).
+error({call, From}, {close, _}, State, _Connection) ->
+ {stop_and_reply, {shutdown, normal}, {reply, From, ok}, State};
+error({call, From}, _Msg, State, _Connection) ->
+ {next_state, ?FUNCTION_NAME, State, [{reply, From, {error, closed}}]}.
%%--------------------------------------------------------------------
-spec hello(gen_statem:event_type(),
@@ -652,20 +818,18 @@ hello(info, Msg, State, _) ->
hello(Type, Msg, State, Connection) ->
handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
-user_hello({call, From}, cancel, #state{negotiated_version = Version} = State, _) ->
+user_hello({call, From}, cancel, #state{connection_env = #connection_env{negotiated_version = Version}} = State, _) ->
gen_statem:reply(From, ok),
handle_own_alert(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled),
Version, ?FUNCTION_NAME, State);
-user_hello({call, From}, {handshake_continue, NewOptions, Timeout}, #state{hello = Hello,
- role = Role,
- start_or_recv_from = RecvFrom,
- ssl_options = Options0} = State0, _Connection) ->
- Timer = start_or_recv_cancel_timer(Timeout, RecvFrom),
+user_hello({call, From}, {handshake_continue, NewOptions, Timeout},
+ #state{static_env = #static_env{role = Role},
+ handshake_env = #handshake_env{hello = Hello},
+ ssl_options = Options0} = State0, _Connection) ->
Options = ssl:handle_options(NewOptions, Options0#ssl_options{handshake = full}),
- State = ssl_config(Options, Role, State0, continue),
- {next_state, hello, State#state{start_or_recv_from = From,
- timer = Timer},
- [{next_event, internal, Hello}]};
+ State = ssl_config(Options, Role, State0),
+ {next_state, hello, State#state{start_or_recv_from = From},
+ [{next_event, internal, Hello}, {{timeout, handshake}, Timeout, close}]};
user_hello(_, _, _, _) ->
{keep_state_and_data, [postpone]}.
@@ -678,61 +842,63 @@ user_hello(_, _, _, _) ->
abbreviated({call, From}, Msg, State, Connection) ->
handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
abbreviated(internal, #finished{verify_data = Data} = Finished,
- #state{role = server,
- negotiated_version = Version,
- expecting_finished = true,
- tls_handshake_history = Handshake,
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{tls_handshake_history = Hist,
+ expecting_finished = true} = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
session = #session{master_secret = MasterSecret},
connection_states = ConnectionStates0} =
State0, Connection) ->
case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished, client,
get_current_prf(ConnectionStates0, write),
- MasterSecret, Handshake) of
+ MasterSecret, Hist) of
verified ->
ConnectionStates =
ssl_record:set_client_verify_data(current_both, Data, ConnectionStates0),
{Record, State} = prepare_connection(State0#state{connection_states = ConnectionStates,
- expecting_finished = false}, Connection),
- Connection:next_event(connection, Record, State);
+ handshake_env = HsEnv#handshake_env{expecting_finished = false}}, Connection),
+ Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close}]);
#alert{} = Alert ->
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
abbreviated(internal, #finished{verify_data = Data} = Finished,
- #state{role = client, tls_handshake_history = Handshake0,
+ #state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{tls_handshake_history = Hist0},
+ connection_env = #connection_env{negotiated_version = Version},
session = #session{master_secret = MasterSecret},
- negotiated_version = Version,
connection_states = ConnectionStates0} = State0, Connection) ->
case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished, server,
get_pending_prf(ConnectionStates0, write),
- MasterSecret, Handshake0) of
+ MasterSecret, Hist0) of
verified ->
ConnectionStates1 =
ssl_record:set_server_verify_data(current_read, Data, ConnectionStates0),
- {State1, Actions} =
+ {#state{handshake_env = HsEnv} = State1, Actions} =
finalize_handshake(State0#state{connection_states = ConnectionStates1},
?FUNCTION_NAME, Connection),
- {Record, State} = prepare_connection(State1#state{expecting_finished = false}, Connection),
- Connection:next_event(connection, Record, State, Actions);
+ {Record, State} = prepare_connection(State1#state{handshake_env = HsEnv#handshake_env{expecting_finished = false}}, Connection),
+ Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close} | Actions]);
#alert{} = Alert ->
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
%% only allowed to send next_protocol message after change cipher spec
%% & before finished message and it is not allowed during renegotiation
abbreviated(internal, #next_protocol{selected_protocol = SelectedProtocol},
- #state{role = server, expecting_next_protocol_negotiation = true} = State0,
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{expecting_next_protocol_negotiation = true} = HsEnv} = State,
Connection) ->
- {Record, State} =
- Connection:next_record(State0#state{negotiated_protocol = SelectedProtocol}),
- Connection:next_event(?FUNCTION_NAME, Record,
- State#state{expecting_next_protocol_negotiation = false});
+ Connection:next_event(?FUNCTION_NAME, no_record,
+ State#state{handshake_env = HsEnv#handshake_env{negotiated_protocol = SelectedProtocol,
+ expecting_next_protocol_negotiation = false}});
abbreviated(internal,
- #change_cipher_spec{type = <<1>>}, #state{connection_states = ConnectionStates0} =
- State0, Connection) ->
+ #change_cipher_spec{type = <<1>>},
+ #state{connection_states = ConnectionStates0,
+ handshake_env = HsEnv} = State, Connection) ->
ConnectionStates1 =
ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection),
- {Record, State} = Connection:next_record(State0#state{connection_states =
- ConnectionStates1}),
- Connection:next_event(?FUNCTION_NAME, Record, State#state{expecting_finished = true});
+ Connection:next_event(?FUNCTION_NAME, no_record, State#state{connection_states =
+ ConnectionStates1,
+ handshake_env = HsEnv#handshake_env{expecting_finished = true}});
abbreviated(info, Msg, State, _) ->
handle_info(Msg, ?FUNCTION_NAME, State);
abbreviated(Type, Msg, State, Connection) ->
@@ -750,34 +916,34 @@ certify({call, From}, Msg, State, Connection) ->
certify(info, Msg, State, _) ->
handle_info(Msg, ?FUNCTION_NAME, State);
certify(internal, #certificate{asn1_certificates = []},
- #state{role = server, negotiated_version = Version,
+ #state{static_env = #static_env{role = server},
+ connection_env = #connection_env{negotiated_version = Version},
ssl_options = #ssl_options{verify = verify_peer,
fail_if_no_peer_cert = true}} =
State, _) ->
Alert = ?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE),
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
certify(internal, #certificate{asn1_certificates = []},
- #state{role = server,
+ #state{static_env = #static_env{role = server},
ssl_options = #ssl_options{verify = verify_peer,
fail_if_no_peer_cert = false}} =
State0, Connection) ->
- {Record, State} =
- Connection:next_record(State0#state{client_certificate_requested = false}),
- Connection:next_event(?FUNCTION_NAME, Record, State);
+ Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_requested = false});
certify(internal, #certificate{},
- #state{role = server,
- negotiated_version = Version,
+ #state{static_env = #static_env{role = server},
+ connection_env = #connection_env{negotiated_version = Version},
ssl_options = #ssl_options{verify = verify_none}} =
State, _) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, unrequested_certificate),
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
certify(internal, #certificate{} = Cert,
- #state{negotiated_version = Version,
- role = Role,
- host = Host,
- cert_db = CertDbHandle,
- cert_db_ref = CertDbRef,
- crl_db = CRLDbInfo,
+ #state{static_env = #static_env{
+ role = Role,
+ host = Host,
+ cert_db = CertDbHandle,
+ cert_db_ref = CertDbRef,
+ crl_db = CRLDbInfo},
+ connection_env = #connection_env{negotiated_version = Version},
ssl_options = Opts} = State, Connection) ->
case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef,
Opts, CRLDbInfo, Role, Host) of
@@ -788,111 +954,131 @@ certify(internal, #certificate{} = Cert,
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
end;
certify(internal, #server_key_exchange{exchange_keys = Keys},
- #state{role = client, negotiated_version = Version,
- key_algorithm = Alg,
- public_key_info = PubKeyInfo,
+ #state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ public_key_info = PubKeyInfo} = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
+ session = Session,
connection_states = ConnectionStates} = State, Connection)
- when Alg == dhe_dss; Alg == dhe_rsa;
- Alg == ecdhe_rsa; Alg == ecdhe_ecdsa;
- Alg == dh_anon; Alg == ecdh_anon;
- Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk;
- Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
-
- Params = ssl_handshake:decode_server_key(Keys, Alg, ssl:tls_version(Version)),
+ when KexAlg == dhe_dss;
+ KexAlg == dhe_rsa;
+ KexAlg == ecdhe_rsa;
+ KexAlg == ecdhe_ecdsa;
+ KexAlg == dh_anon;
+ KexAlg == ecdh_anon;
+ KexAlg == psk;
+ KexAlg == dhe_psk;
+ KexAlg == ecdhe_psk;
+ KexAlg == rsa_psk;
+ KexAlg == srp_dss;
+ KexAlg == srp_rsa;
+ KexAlg == srp_anon ->
+
+ Params = ssl_handshake:decode_server_key(Keys, KexAlg, ssl:tls_version(Version)),
%% Use negotiated value if TLS-1.2 otherwhise return default
- HashSign = negotiated_hashsign(Params#server_key_params.hashsign, Alg, PubKeyInfo, ssl:tls_version(Version)),
+ HashSign = negotiated_hashsign(Params#server_key_params.hashsign, KexAlg, PubKeyInfo, ssl:tls_version(Version)),
- case is_anonymous(Alg) of
+ case is_anonymous(KexAlg) of
true ->
calculate_secret(Params#server_key_params.params,
- State#state{hashsign_algorithm = HashSign}, Connection);
+ State#state{handshake_env = HsEnv#handshake_env{hashsign_algorithm = HashSign}}, Connection);
false ->
case ssl_handshake:verify_server_key(Params, HashSign,
ConnectionStates, ssl:tls_version(Version), PubKeyInfo) of
true ->
calculate_secret(Params#server_key_params.params,
- State#state{hashsign_algorithm = HashSign},
- Connection);
+ State#state{handshake_env = HsEnv#handshake_env{hashsign_algorithm = HashSign},
+ session = session_handle_params(Params#server_key_params.params, Session)},
+ Connection);
false ->
handle_own_alert(?ALERT_REC(?FATAL, ?DECRYPT_ERROR),
Version, ?FUNCTION_NAME, State)
end
end;
certify(internal, #certificate_request{},
- #state{role = client, negotiated_version = Version,
- key_algorithm = Alg} = State, _)
- when Alg == dh_anon; Alg == ecdh_anon;
- Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk;
- Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
+ #state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg},
+ connection_env = #connection_env{negotiated_version = Version}} = State, _)
+ when KexAlg == dh_anon;
+ KexAlg == ecdh_anon;
+ KexAlg == psk;
+ KexAlg == dhe_psk;
+ KexAlg == ecdhe_psk;
+ KexAlg == rsa_psk;
+ KexAlg == srp_dss;
+ KexAlg == srp_rsa;
+ KexAlg == srp_anon ->
handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE),
Version, ?FUNCTION_NAME, State);
certify(internal, #certificate_request{},
- #state{session = #session{own_certificate = undefined},
- role = client} = State0, Connection) ->
+ #state{static_env = #static_env{role = client},
+ session = #session{own_certificate = undefined}} = State, Connection) ->
%% The client does not have a certificate and will send an empty reply, the server may fail
%% or accept the connection by its own preference. No signature algorihms needed as there is
%% no certificate to verify.
- {Record, State} = Connection:next_record(State0),
- Connection:next_event(?FUNCTION_NAME, Record, State#state{client_certificate_requested = true});
+ Connection:next_event(?FUNCTION_NAME, no_record, State#state{client_certificate_requested = true});
certify(internal, #certificate_request{} = CertRequest,
- #state{session = #session{own_certificate = Cert},
- role = client,
- ssl_options = #ssl_options{signature_algs = SupportedHashSigns},
- negotiated_version = Version} = State0, Connection) ->
+ #state{static_env = #static_env{role = client},
+ handshake_env = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
+ session = #session{own_certificate = Cert},
+ ssl_options = #ssl_options{signature_algs = SupportedHashSigns}} = State, Connection) ->
case ssl_handshake:select_hashsign(CertRequest, Cert, SupportedHashSigns, ssl:tls_version(Version)) of
#alert {} = Alert ->
- handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
- NegotiatedHashSign ->
- {Record, State} = Connection:next_record(State0#state{client_certificate_requested = true}),
- Connection:next_event(?FUNCTION_NAME, Record,
- State#state{cert_hashsign_algorithm = NegotiatedHashSign})
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
+ NegotiatedHashSign ->
+ Connection:next_event(?FUNCTION_NAME, no_record,
+ State#state{client_certificate_requested = true,
+ handshake_env = HsEnv#handshake_env{cert_hashsign_algorithm = NegotiatedHashSign}})
end;
%% PSK and RSA_PSK might bypass the Server-Key-Exchange
certify(internal, #server_hello_done{},
- #state{session = #session{master_secret = undefined},
- negotiated_version = Version,
- psk_identity = PSKIdentity,
- ssl_options = #ssl_options{user_lookup_fun = PSKLookup},
- premaster_secret = undefined,
- role = client,
- key_algorithm = Alg} = State0, Connection)
- when Alg == psk ->
- case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup) of
+ #state{static_env = #static_env{role = client},
+ session = #session{master_secret = undefined},
+ connection_env = #connection_env{negotiated_version = Version},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ premaster_secret = undefined,
+ server_psk_identity = PSKIdentity} = HsEnv,
+ ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = State0, Connection)
+ when KexAlg == psk ->
+ case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup) of
#alert{} = Alert ->
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
PremasterSecret ->
State = master_secret(PremasterSecret,
- State0#state{premaster_secret = PremasterSecret}),
- client_certify_and_key_exchange(State, Connection)
+ State0#state{handshake_env =
+ HsEnv#handshake_env{premaster_secret = PremasterSecret}}),
+ client_certify_and_key_exchange(State, Connection)
end;
certify(internal, #server_hello_done{},
- #state{session = #session{master_secret = undefined},
- ssl_options = #ssl_options{user_lookup_fun = PSKLookup},
- negotiated_version = {Major, Minor} = Version,
- psk_identity = PSKIdentity,
- premaster_secret = undefined,
- role = client,
- key_algorithm = Alg} = State0, Connection)
- when Alg == rsa_psk ->
+ #state{static_env = #static_env{role = client},
+ connection_env = #connection_env{negotiated_version = {Major, Minor}} = Version,
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ premaster_secret = undefined,
+ server_psk_identity = PSKIdentity} = HsEnv,
+ session = #session{master_secret = undefined},
+ ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = State0, Connection)
+ when KexAlg == rsa_psk ->
Rand = ssl_cipher:random_bytes(?NUM_OF_PREMASTERSECRET_BYTES-2),
RSAPremasterSecret = <<?BYTE(Major), ?BYTE(Minor), Rand/binary>>,
- case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup,
+ case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup,
RSAPremasterSecret) of
#alert{} = Alert ->
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
PremasterSecret ->
State = master_secret(PremasterSecret,
- State0#state{premaster_secret = RSAPremasterSecret}),
+ State0#state{handshake_env =
+ HsEnv#handshake_env{premaster_secret = RSAPremasterSecret}}),
client_certify_and_key_exchange(State, Connection)
end;
%% Master secret was determined with help of server-key exchange msg
certify(internal, #server_hello_done{},
- #state{session = #session{master_secret = MasterSecret} = Session,
- connection_states = ConnectionStates0,
- negotiated_version = Version,
- premaster_secret = undefined,
- role = client} = State0, Connection) ->
+ #state{static_env = #static_env{role = client},
+ connection_env = #connection_env{negotiated_version = Version},
+ handshake_env = #handshake_env{premaster_secret = undefined},
+ session = #session{master_secret = MasterSecret} = Session,
+ connection_states = ConnectionStates0} = State0, Connection) ->
case ssl_handshake:master_secret(ssl:tls_version(Version), Session,
ConnectionStates0, client) of
{MasterSecret, ConnectionStates} ->
@@ -903,11 +1089,11 @@ certify(internal, #server_hello_done{},
end;
%% Master secret is calculated from premaster_secret
certify(internal, #server_hello_done{},
- #state{session = Session0,
- connection_states = ConnectionStates0,
- negotiated_version = Version,
- premaster_secret = PremasterSecret,
- role = client} = State0, Connection) ->
+ #state{static_env = #static_env{role = client},
+ connection_env = #connection_env{negotiated_version = Version},
+ handshake_env = #handshake_env{premaster_secret = PremasterSecret},
+ session = Session0,
+ connection_states = ConnectionStates0} = State0, Connection) ->
case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret,
ConnectionStates0, client) of
{MasterSecret, ConnectionStates} ->
@@ -919,14 +1105,15 @@ certify(internal, #server_hello_done{},
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
certify(internal = Type, #client_key_exchange{} = Msg,
- #state{role = server,
+ #state{static_env = #static_env{role = server},
client_certificate_requested = true,
ssl_options = #ssl_options{fail_if_no_peer_cert = true}} = State,
Connection) ->
%% We expect a certificate here
handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection);
certify(internal, #client_key_exchange{exchange_keys = Keys},
- State = #state{key_algorithm = KeyAlg, negotiated_version = Version}, Connection) ->
+ State = #state{handshake_env = #handshake_env{kex_algorithm = KeyAlg},
+ connection_env = #connection_env{negotiated_version = Version}}, Connection) ->
try
certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, ssl:tls_version(Version)),
State, Connection)
@@ -949,70 +1136,70 @@ cipher(info, Msg, State, _) ->
handle_info(Msg, ?FUNCTION_NAME, State);
cipher(internal, #certificate_verify{signature = Signature,
hashsign_algorithm = CertHashSign},
- #state{role = server,
- key_algorithm = KexAlg,
- public_key_info = PublicKeyInfo,
- negotiated_version = Version,
- session = #session{master_secret = MasterSecret},
- tls_handshake_history = Handshake
- } = State0, Connection) ->
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{tls_handshake_history = Hist,
+ kex_algorithm = KexAlg,
+ public_key_info = PubKeyInfo} = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
+ session = #session{master_secret = MasterSecret}
+ } = State, Connection) ->
TLSVersion = ssl:tls_version(Version),
%% Use negotiated value if TLS-1.2 otherwhise return default
- HashSign = negotiated_hashsign(CertHashSign, KexAlg, PublicKeyInfo, TLSVersion),
- case ssl_handshake:certificate_verify(Signature, PublicKeyInfo,
- TLSVersion, HashSign, MasterSecret, Handshake) of
+ HashSign = negotiated_hashsign(CertHashSign, KexAlg, PubKeyInfo, TLSVersion),
+ case ssl_handshake:certificate_verify(Signature, PubKeyInfo,
+ TLSVersion, HashSign, MasterSecret, Hist) of
valid ->
- {Record, State} = Connection:next_record(State0),
- Connection:next_event(?FUNCTION_NAME, Record,
- State#state{cert_hashsign_algorithm = HashSign});
+ Connection:next_event(?FUNCTION_NAME, no_record,
+ State#state{handshake_env = HsEnv#handshake_env{cert_hashsign_algorithm = HashSign}});
#alert{} = Alert ->
- handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
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,
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{expecting_next_protocol_negotiation = true,
+ negotiated_protocol = undefined},
+ connection_env = #connection_env{negotiated_version = Version}} = State0,
_Connection) ->
handle_own_alert(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE), Version, ?FUNCTION_NAME, State0);
cipher(internal, #finished{verify_data = Data} = Finished,
- #state{negotiated_version = Version,
- host = Host,
- port = Port,
- role = Role,
- expecting_finished = true,
+ #state{static_env = #static_env{role = Role,
+ host = Host,
+ port = Port},
+ handshake_env = #handshake_env{tls_handshake_history = Hist,
+ expecting_finished = true} = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
session = #session{master_secret = MasterSecret}
= Session0,
ssl_options = SslOpts,
- connection_states = ConnectionStates0,
- tls_handshake_history = Handshake0} = State, Connection) ->
+ connection_states = ConnectionStates0} = State, Connection) ->
case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished,
opposite_role(Role),
get_current_prf(ConnectionStates0, read),
- MasterSecret, Handshake0) of
+ MasterSecret, Hist) of
verified ->
- Session = register_session(Role, host_id(Role, Host, SslOpts), Port, Session0),
+ Session = handle_session(Role, SslOpts, Host, Port, Session0),
cipher_role(Role, Data, Session,
- State#state{expecting_finished = false}, Connection);
+ State#state{handshake_env = HsEnv#handshake_env{expecting_finished = false}}, Connection);
#alert{} = Alert ->
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
end;
%% only allowed to send next_protocol message after change cipher spec
%% & before finished message and it is not allowed during renegotiation
cipher(internal, #next_protocol{selected_protocol = SelectedProtocol},
- #state{role = server, expecting_next_protocol_negotiation = true,
- expecting_finished = true} = State0, Connection) ->
- {Record, State} =
- Connection:next_record(State0#state{negotiated_protocol = SelectedProtocol}),
- Connection:next_event(?FUNCTION_NAME, Record,
- State#state{expecting_next_protocol_negotiation = false});
-cipher(internal, #change_cipher_spec{type = <<1>>}, #state{connection_states = ConnectionStates0} =
- State0, Connection) ->
- ConnectionStates1 =
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{expecting_finished = true,
+ expecting_next_protocol_negotiation = true} = HsEnv} = State, Connection) ->
+ Connection:next_event(?FUNCTION_NAME, no_record,
+ State#state{handshake_env = HsEnv#handshake_env{negotiated_protocol = SelectedProtocol,
+ expecting_next_protocol_negotiation = false}});
+cipher(internal, #change_cipher_spec{type = <<1>>}, #state{handshake_env = HsEnv, connection_states = ConnectionStates0} =
+ State, Connection) ->
+ ConnectionStates =
ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection),
- {Record, State} = Connection:next_record(State0#state{connection_states =
- ConnectionStates1}),
- Connection:next_event(?FUNCTION_NAME, Record, State#state{expecting_finished = true});
+ Connection:next_event(?FUNCTION_NAME, no_record, State#state{handshake_env = HsEnv#handshake_env{expecting_finished = true},
+ connection_states = ConnectionStates});
cipher(Type, Msg, State, Connection) ->
handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
@@ -1021,32 +1208,18 @@ cipher(Type, Msg, State, Connection) ->
#state{}, tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-connection({call, {FromPid, _} = From}, {application_data, Data},
- #state{protocol_cb = Connection} = State, Connection) ->
- %% We should look into having a worker process to do this to
- %% parallize send and receive decoding and not block the receiver
- %% if sending is overloading the socket.
- try
- write_application_data(Data, From, State)
- catch throw:Error ->
- case self() of
- FromPid ->
- stop({shutdown, Error}, State);
- _ ->
- hibernate_after(
- ?FUNCTION_NAME, State, [{reply, From, Error}])
- end
- end;
connection({call, RecvFrom}, {recv, N, Timeout},
- #state{protocol_cb = Connection, socket_options =
- #socket_options{active = false}} = State0, Connection) ->
- Timer = start_or_recv_cancel_timer(Timeout, RecvFrom),
- Connection:passive_receive(State0#state{bytes_to_read = N,
- start_or_recv_from = RecvFrom,
- timer = Timer}, ?FUNCTION_NAME);
-connection({call, From}, renegotiate, #state{protocol_cb = Connection} = State,
+ #state{static_env = #static_env{protocol_cb = Connection},
+ socket_options =
+ #socket_options{active = false}} = State0, Connection) ->
+ passive_receive(State0#state{bytes_to_read = N,
+ start_or_recv_from = RecvFrom}, ?FUNCTION_NAME, Connection,
+ [{{timeout, recv}, Timeout, timeout}]);
+
+connection({call, From}, renegotiate, #state{static_env = #static_env{protocol_cb = Connection},
+ handshake_env = HsEnv} = State,
Connection) ->
- Connection:renegotiate(State#state{renegotiation = {true, From}}, []);
+ Connection:renegotiate(State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, From}}}, []);
connection({call, From}, peer_certificate,
#state{session = #session{peer_certificate = Cert}} = State, _) ->
hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Cert}}]);
@@ -1057,118 +1230,44 @@ connection({call, From}, {connection_information, false}, State, _) ->
Info = connection_info(State),
hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Info}}]);
connection({call, From}, negotiated_protocol,
- #state{negotiated_protocol = undefined} = State, _) ->
+ #state{handshake_env = #handshake_env{negotiated_protocol = undefined}} = State, _) ->
hibernate_after(?FUNCTION_NAME, State, [{reply, From, {error, protocol_not_negotiated}}]);
connection({call, From}, negotiated_protocol,
- #state{negotiated_protocol = SelectedProtocol} = State, _) ->
+ #state{handshake_env = #handshake_env{negotiated_protocol = SelectedProtocol}} = State, _) ->
hibernate_after(?FUNCTION_NAME, State,
[{reply, From, {ok, SelectedProtocol}}]);
-connection(
- {call, From}, {handshake_complete, _Node, DHandle},
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- socket_options = SockOpts,
- protocol_specific = ProtocolSpecific} = State,
- Connection) ->
- %% From now on we execute on normal priority
- process_flag(priority, normal),
- try erlang:dist_ctrl_get_data_notification(DHandle) of
- _ ->
- NewState =
- State#state{
- socket_options =
- SockOpts#socket_options{active = true},
- protocol_specific =
- ProtocolSpecific#{d_handle => DHandle}},
- {Record, NewerState} = Connection:next_record_if_active(NewState),
- Connection:next_event(connection, Record, NewerState, [{reply, From, ok}])
- catch error:_ ->
- death_row(State, disconnect)
- end;
connection({call, From}, Msg, State, Connection) ->
handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
-connection(
- info, dist_data = Msg,
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := DHandle}} = State,
- _) ->
- eat_msgs(Msg),
- try send_dist_data(?FUNCTION_NAME, State, DHandle, [])
- catch error:_ ->
- death_row(State, disconnect)
- end;
-connection(
- info, {send, From, Ref, Data},
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := _}},
- _) ->
- %% This is for testing only!
- %%
- %% Needed by some OTP distribution
- %% test suites...
- From ! {Ref, ok},
- {keep_state_and_data,
- [{next_event, {call, {self(), undefined}},
- {application_data, iolist_to_binary(Data)}}]};
-connection(
- info, tick = Msg,
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := _}},
- _) ->
- eat_msgs(Msg),
- {keep_state_and_data,
- [{next_event, {call, {self(), undefined}}, {application_data, <<>>}}]};
+connection(cast, {internal_renegotiate, WriteState}, #state{static_env = #static_env{protocol_cb = Connection},
+ handshake_env = HsEnv,
+ connection_states = ConnectionStates}
+ = State, Connection) ->
+ Connection:renegotiate(State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, internal}},
+ connection_states = ConnectionStates#{current_write => WriteState}}, []);
+connection(cast, {dist_handshake_complete, DHandle},
+ #state{ssl_options = #ssl_options{erl_dist = true},
+ connection_env = CEnv,
+ socket_options = SockOpts} = State0, Connection) ->
+ process_flag(priority, normal),
+ State1 =
+ State0#state{
+ socket_options = SockOpts#socket_options{active = true},
+ connection_env = CEnv#connection_env{erl_dist_handle = DHandle},
+ bytes_to_read = undefined},
+ {Record, State} = read_application_data(<<>>, State1),
+ Connection:next_event(connection, Record, State);
connection(info, Msg, State, _) ->
handle_info(Msg, ?FUNCTION_NAME, State);
-connection(internal, {recv, _}, State, Connection) ->
- Connection:passive_receive(State, ?FUNCTION_NAME);
+connection(internal, {recv, Timeout}, State, Connection) ->
+ passive_receive(State, ?FUNCTION_NAME, Connection, [{{timeout, recv}, Timeout, timeout}]);
connection(Type, Msg, State, Connection) ->
handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
--spec death_row(gen_statem:event_type(), term(),
- #state{}, tls_connection | dtls_connection) ->
- gen_statem:state_function_result().
-%%--------------------------------------------------------------------
-%% We just wait for the owner to die which triggers the monitor,
-%% or the socket may die too
-death_row(
- info, {'DOWN', MonitorRef, _, _, Reason},
- #state{user_application={MonitorRef,_Pid}},
- _) ->
- {stop, {shutdown, Reason}};
-death_row(
- info, {'EXIT', Socket, Reason}, #state{socket = Socket}, _) ->
- {stop, {shutdown, Reason}};
-death_row(state_timeout, Reason, _State, _Connection) ->
- {stop, {shutdown,Reason}};
-death_row(_Type, _Msg, _State, _Connection) ->
- %% Waste all other events
- keep_state_and_data.
-
-%% State entry function
-death_row(State, Reason) ->
- {next_state, death_row, State,
- [{state_timeout, 5000, Reason}]}.
-
-%%--------------------------------------------------------------------
-spec downgrade(gen_statem:event_type(), term(),
#state{}, tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-downgrade(internal, #alert{description = ?CLOSE_NOTIFY},
- #state{transport_cb = Transport, socket = Socket,
- downgrade = {Pid, From}} = State, _) ->
- tls_socket:setopts(Transport, Socket, [{active, false}, {packet, 0}, {mode, binary}]),
- Transport:controlling_process(Socket, Pid),
- gen_statem:reply(From, {ok, Socket}),
- stop(normal, State);
-downgrade(timeout, downgrade, #state{downgrade = {_, From}} = State, _) ->
- gen_statem:reply(From, {error, timeout}),
- stop(normal, State);
downgrade(Type, Event, State, Connection) ->
handle_common_event(Type, Event, ?FUNCTION_NAME, State, Connection).
@@ -1177,40 +1276,45 @@ downgrade(Type, Event, State, Connection) ->
%% common or unexpected events for the state.
%%--------------------------------------------------------------------
handle_common_event(internal, {handshake, {#hello_request{} = Handshake, _}}, connection = StateName,
- #state{role = client} = State, _) ->
+ #state{static_env = #static_env{role = client},
+ handshake_env = HsEnv} = State, _) ->
%% Should not be included in handshake history
- {next_state, StateName, State#state{renegotiation = {true, peer}}, [{next_event, internal, Handshake}]};
-handle_common_event(internal, {handshake, {#hello_request{}, _}}, StateName, #state{role = client}, _)
+ {next_state, StateName, State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, peer}}},
+ [{next_event, internal, Handshake}]};
+handle_common_event(internal, {handshake, {#hello_request{}, _}}, StateName,
+ #state{static_env = #static_env{role = client}}, _)
when StateName =/= connection ->
- {keep_state_and_data};
+ keep_state_and_data;
handle_common_event(internal, {handshake, {Handshake, Raw}}, StateName,
- #state{tls_handshake_history = Hs0} = State0,
+ #state{handshake_env = #handshake_env{tls_handshake_history = Hist0}} = 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 = handle_sni_extension(PossibleSNI, State0),
- HsHist = ssl_handshake:update_handshake_history(Hs0, iolist_to_binary(Raw)),
- {next_state, StateName, State#state{tls_handshake_history = HsHist},
+ State = #state{handshake_env = HsEnv} = handle_sni_extension(PossibleSNI, State0),
+
+ Hist = ssl_handshake:update_handshake_history(Hist0, Raw),
+ {next_state, StateName, State#state{handshake_env = HsEnv#handshake_env{tls_handshake_history = Hist}},
[{next_event, internal, Handshake}]};
handle_common_event(internal, {protocol_record, TLSorDTLSRecord}, StateName, State, Connection) ->
- Connection:handle_common_event(internal, TLSorDTLSRecord, StateName, State);
+ Connection:handle_protocol_record(TLSorDTLSRecord, StateName, State);
handle_common_event(timeout, hibernate, _, _, _) ->
{keep_state_and_data, [hibernate]};
-handle_common_event(internal, {application_data, Data}, StateName, State0, Connection) ->
- case read_application_data(Data, State0) of
- {stop, _, _} = Stop->
- Stop;
- {Record, State} ->
- Connection:next_event(StateName, Record, State)
- end;
handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
- #state{negotiated_version = Version} = State, _) ->
+ #state{connection_env = #connection_env{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,
+handle_common_event({timeout, handshake}, close, _StateName, #state{start_or_recv_from = StartFrom} = State, _) ->
+ {stop_and_reply,
+ {shutdown, user_timeout},
+ {reply, StartFrom, {error, timeout}}, State#state{start_or_recv_from = undefined}};
+handle_common_event({timeout, recv}, timeout, StateName, #state{start_or_recv_from = RecvFrom} = State, _) ->
+ {next_state, StateName, State#state{start_or_recv_from = undefined,
+ bytes_to_read = undefined}, [{reply, RecvFrom, {error, timeout}}]};
+handle_common_event(_Type, Msg, StateName, #state{connection_env =
+ #connection_env{negotiated_version = Version}} = State,
_) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, Msg}),
handle_own_alert(Alert, Version, StateName, State).
@@ -1218,43 +1322,41 @@ handle_common_event(_Type, Msg, StateName, #state{negotiated_version = Version}
handle_call({application_data, _Data}, _, _, _, _) ->
%% In renegotiation priorities handshake, send data when handshake is finished
{keep_state_and_data, [postpone]};
-handle_call({close, {Pid, Timeout}}, From, StateName, State0, Connection) when is_pid(Pid) ->
- %% terminate will send close alert to peer
- State = State0#state{downgrade = {Pid, From}},
- Connection:terminate(downgrade, StateName, State),
- %% User downgrades connection
- %% When downgrading an TLS connection to a transport connection
- %% we must recive the close alert from the peer before releasing the
- %% transport socket.
- {next_state, downgrade, State#state{terminated = true}, [{timeout, Timeout, downgrade}]};
-handle_call({close, _} = Close, From, StateName, State, Connection) ->
+handle_call({close, _} = Close, From, StateName, #state{connection_env = CEnv} = State, _Connection) ->
%% Run terminate before returning so that the reuseaddr
%% inet-option works properly
- Result = Connection:terminate(Close, StateName, State#state{terminated = true}),
- stop_and_reply(
- {shutdown, normal},
- {reply, From, Result}, State);
-handle_call({shutdown, How0}, From, _,
- #state{transport_cb = Transport,
- negotiated_version = Version,
- connection_states = ConnectionStates,
- socket = Socket} = State, Connection) ->
- case How0 of
- How when How == write; How == both ->
- Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- {BinMsg, _} =
- Connection:encode_alert(Alert, Version, ConnectionStates),
- Connection:send(Transport, Socket, BinMsg);
- _ ->
- ok
- end,
-
+ Result = terminate(Close, StateName, State),
+ {stop_and_reply,
+ {shutdown, normal},
+ {reply, From, Result}, State#state{connection_env = CEnv#connection_env{terminated = true}}};
+handle_call({shutdown, read_write = How}, From, StateName,
+ #state{static_env = #static_env{transport_cb = Transport,
+ socket = Socket},
+ connection_env = CEnv} = State, _) ->
+ try send_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
+ StateName, State) of
+ _ ->
+ case Transport:shutdown(Socket, How) of
+ ok ->
+ {next_state, StateName, State#state{connection_env =
+ CEnv#connection_env{terminated = true}},
+ [{reply, From, ok}]};
+ Error ->
+ {stop_and_reply, {shutdown, normal}, {reply, From, Error},
+ State#state{connection_env = CEnv#connection_env{terminated = true}}}
+ end
+ catch
+ throw:Return ->
+ Return
+ end;
+handle_call({shutdown, How0}, From, StateName,
+ #state{static_env = #static_env{transport_cb = Transport,
+ socket = Socket}} = State, _) ->
case Transport:shutdown(Socket, How0) of
ok ->
- {keep_state_and_data, [{reply, From, ok}]};
+ {next_state, StateName, State, [{reply, From, ok}]};
Error ->
- gen_statem:reply(From, {error, Error}),
- stop(normal, State)
+ {stop_and_reply, {shutdown, normal}, {reply, From, Error}, State}
end;
handle_call({recv, _N, _Timeout}, From, _,
#state{socket_options =
@@ -1263,44 +1365,47 @@ handle_call({recv, _N, _Timeout}, From, _,
handle_call({recv, N, Timeout}, RecvFrom, StateName, State, _) ->
%% Doing renegotiate wait with handling request until renegotiate is
%% finished.
- Timer = start_or_recv_cancel_timer(Timeout, RecvFrom),
- {next_state, StateName, State#state{bytes_to_read = N, start_or_recv_from = RecvFrom,
- timer = Timer},
- [{next_event, internal, {recv, RecvFrom}}]};
+ {next_state, StateName, State#state{bytes_to_read = N, start_or_recv_from = RecvFrom},
+ [{next_event, internal, {recv, RecvFrom}} , {{timeout, recv}, Timeout, timeout}]};
handle_call({new_user, User}, From, StateName,
- State =#state{user_application = {OldMon, _}}, _) ->
+ State = #state{connection_env = #connection_env{user_application = {OldMon, _}} = CEnv}, _) ->
NewMon = erlang:monitor(process, User),
erlang:demonitor(OldMon, [flush]),
- {next_state, StateName, State#state{user_application = {NewMon,User}},
+ {next_state, StateName, State#state{connection_env = CEnv#connection_env{user_application = {NewMon, User}}},
[{reply, From, ok}]};
handle_call({get_opts, OptTags}, From, _,
- #state{socket = Socket,
- transport_cb = Transport,
+ #state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
socket_options = SockOpts}, Connection) ->
OptsReply = get_socket_opts(Connection, Transport, Socket, OptTags, SockOpts, []),
{keep_state_and_data, [{reply, From, OptsReply}]};
handle_call({set_opts, Opts0}, From, StateName,
- #state{socket_options = Opts1,
- socket = Socket,
- transport_cb = Transport} = State0, Connection) ->
+ #state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport,
+ tracker = Tracker},
+ connection_env =
+ #connection_env{user_application = {_Mon, Pid}},
+ socket_options = Opts1
+ } = State0, Connection) ->
{Reply, Opts} = set_socket_opts(Connection, Transport, Socket, Opts0, Opts1, []),
+ case {proplists:lookup(active, Opts0), Opts} of
+ {{_, N}, #socket_options{active=false}} when is_integer(N) ->
+ send_user(
+ Pid,
+ format_passive(
+ Connection:pids(State0), Transport, Socket, Tracker, Connection));
+ _ ->
+ ok
+ end,
State = State0#state{socket_options = Opts},
handle_active_option(Opts#socket_options.active, StateName, From, Reply, State);
handle_call(renegotiate, From, StateName, _, _) when StateName =/= connection ->
{keep_state_and_data, [{reply, From, {error, already_renegotiating}}]};
-handle_call(
- get_sslsocket, From, _StateName,
- #state{transport_cb = Transport, socket = Socket, tracker = Tracker},
- Connection) ->
- SslSocket =
- Connection:socket(self(), Transport, Socket, Connection, Tracker),
- {keep_state_and_data, [{reply, From, SslSocket}]};
-
handle_call({prf, Secret, Label, Seed, WantedLength}, From, _,
#state{connection_states = ConnectionStates,
- negotiated_version = Version}, _) ->
+ connection_env = #connection_env{negotiated_version = Version}}, _) ->
#{security_parameters := SecParams} =
ssl_record:current_connection_state(ConnectionStates, read),
#security_parameters{master_secret = MasterSecret,
@@ -1327,66 +1432,51 @@ handle_call(_,_,_,_,_) ->
{keep_state_and_data, [postpone]}.
handle_info({ErrorTag, Socket, econnaborted}, StateName,
- #state{socket = Socket, transport_cb = Transport,
- protocol_cb = Connection,
- start_or_recv_from = StartFrom, role = Role,
- error_tag = ErrorTag,
- tracker = Tracker} = State) when StateName =/= connection ->
- 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,
- error_tag = ErrorTag} = State) ->
+ #state{static_env = #static_env{role = Role,
+ socket = Socket,
+ transport_cb = Transport,
+ error_tag = ErrorTag,
+ tracker = Tracker,
+ protocol_cb = Connection},
+ start_or_recv_from = StartFrom
+ } = State) when StateName =/= connection ->
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker,Socket,
+ StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, StateName, Connection),
+ {stop, {shutdown, normal}, State};
+
+handle_info({ErrorTag, Socket, Reason}, StateName, #state{static_env = #static_env{socket = Socket,
+ error_tag = ErrorTag}} = State) ->
Report = io_lib:format("SSL: Socket error: ~p ~n", [Reason]),
error_logger:error_report(Report),
handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
- stop(normal, State);
+ {stop, {shutdown,normal}, State};
-handle_info(
- {'DOWN', MonitorRef, _, _, Reason}, _,
- #state{
- user_application = {MonitorRef, _Pid},
- ssl_options = #ssl_options{erl_dist = true}}) ->
+handle_info({'DOWN', MonitorRef, _, _, Reason}, _,
+ #state{connection_env = #connection_env{user_application = {MonitorRef, _Pid}},
+ ssl_options = #ssl_options{erl_dist = true}}) ->
{stop, {shutdown, Reason}};
-handle_info(
- {'DOWN', MonitorRef, _, _, _}, _,
- #state{user_application = {MonitorRef, _Pid}}) ->
- {stop, normal};
-handle_info(
- {'EXIT', Pid, _Reason}, StateName,
- #state{user_application = {_MonitorRef, Pid}} = State) ->
+handle_info({'DOWN', MonitorRef, _, _, _}, _,
+ #state{connection_env = #connection_env{user_application = {MonitorRef, _Pid}}}) ->
+ {stop, {shutdown, normal}};
+handle_info({'EXIT', Pid, _Reason}, StateName,
+ #state{connection_env = #connection_env{user_application = {_MonitorRef, Pid}}} = State) ->
%% It seems the user application has linked to us
%% - ignore that and let the monitor handle this
{next_state, StateName, State};
-
%%% So that terminate will be run when supervisor issues shutdown
handle_info({'EXIT', _Sup, shutdown}, _StateName, State) ->
- stop(shutdown, State);
-handle_info({'EXIT', Socket, normal}, _StateName, #state{socket = Socket} = State) ->
+ {stop, shutdown, State};
+handle_info({'EXIT', Socket, normal}, _StateName, #state{static_env = #static_env{socket = Socket}} = State) ->
%% Handle as transport close"
- stop({shutdown, transport_closed}, State);
-handle_info({'EXIT', Socket, Reason}, _StateName, #state{socket = Socket} = State) ->
- stop({shutdown, Reason}, State);
-
-handle_info(allow_renegotiate, StateName, State) ->
- {next_state, StateName, State#state{allow_renegotiate = true}};
-
-handle_info({cancel_start_or_recv, StartFrom}, StateName,
- #state{renegotiation = {false, first}} = State) when StateName =/= connection ->
- stop_and_reply(
- {shutdown, user_timeout},
- {reply, StartFrom, {error, timeout}},
- State#state{timer = undefined});
-handle_info({cancel_start_or_recv, RecvFrom}, StateName,
- #state{start_or_recv_from = RecvFrom} = State) when RecvFrom =/= undefined ->
- {next_state, StateName, State#state{start_or_recv_from = undefined,
- bytes_to_read = undefined,
- timer = undefined}, [{reply, RecvFrom, {error, timeout}}]};
-handle_info({cancel_start_or_recv, _RecvFrom}, StateName, State) ->
- {next_state, StateName, State#state{timer = undefined}};
+ {stop,{shutdown, transport_closed}, State};
+handle_info({'EXIT', Socket, Reason}, _StateName, #state{static_env = #static_env{socket = Socket}} = State) ->
+ {stop,{shutdown, Reason}, State};
+
+handle_info(allow_renegotiate, StateName, #state{handshake_env = HsEnv} = State) ->
+ {next_state, StateName, State#state{handshake_env = HsEnv#handshake_env{allow_renegotiate = true}}};
-handle_info(Msg, StateName, #state{socket = Socket, error_tag = Tag} = State) ->
+handle_info(Msg, StateName, #state{static_env = #static_env{socket = Socket, error_tag = Tag}} = State) ->
Report = io_lib:format("SSL: Got unexpected info: ~p ~n", [{Msg, Tag, Socket}]),
error_logger:info_report(Report),
{next_state, StateName, State}.
@@ -1394,7 +1484,7 @@ handle_info(Msg, StateName, #state{socket = Socket, error_tag = Tag} = State) ->
%%====================================================================
%% general gen_statem callbacks
%%====================================================================
-terminate(_, _, #state{terminated = true}) ->
+terminate(_, _, #state{connection_env = #connection_env{terminated = true}}) ->
%% Happens when user closes the connection using ssl:close/1
%% we want to guarantee that Transport:close has been called
%% when ssl:close/1 returns unless it is a downgrade where
@@ -1403,14 +1493,15 @@ terminate(_, _, #state{terminated = true}) ->
%% before run by gen_statem which will end up here
ok;
terminate({shutdown, transport_closed} = Reason,
- _StateName, #state{protocol_cb = Connection,
- socket = Socket, transport_cb = Transport} = State) ->
+ _StateName, #state{static_env = #static_env{protocol_cb = Connection,
+ socket = Socket,
+ transport_cb = Transport}} = State) ->
handle_trusted_certs_db(State),
Connection:close(Reason, Socket, Transport, undefined, undefined);
-terminate({shutdown, own_alert}, _StateName, #state{%%send_queue = SendQueue,
- protocol_cb = Connection,
- socket = Socket,
- transport_cb = Transport} = State) ->
+terminate({shutdown, own_alert}, _StateName, #state{
+ static_env = #static_env{protocol_cb = Connection,
+ socket = Socket,
+ transport_cb = Transport}} = State) ->
handle_trusted_certs_db(State),
case application:get_env(ssl, alert_timeout) of
{ok, Timeout} when is_integer(Timeout) ->
@@ -1418,18 +1509,27 @@ terminate({shutdown, own_alert}, _StateName, #state{%%send_queue = SendQueue,
_ ->
Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, undefined, undefined)
end;
-terminate(Reason, connection, #state{negotiated_version = Version,
- protocol_cb = Connection,
- connection_states = ConnectionStates0,
- ssl_options = #ssl_options{padding_check = Check},
- transport_cb = Transport, socket = Socket
- } = State) ->
+terminate({shutdown, downgrade = Reason}, downgrade, #state{static_env = #static_env{protocol_cb = Connection,
+ transport_cb = Transport,
+ socket = Socket}
+ } = State) ->
+ handle_trusted_certs_db(State),
+ Connection:close(Reason, Socket, Transport, undefined, undefined);
+terminate(Reason, connection, #state{static_env = #static_env{
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ socket = Socket},
+ connection_states = ConnectionStates,
+ ssl_options = #ssl_options{padding_check = Check}
+ } = State) ->
handle_trusted_certs_db(State),
- {BinAlert, ConnectionStates} = terminate_alert(Reason, Version, ConnectionStates0, Connection),
- Connection:send(Transport, Socket, BinAlert),
- Connection:close(Reason, Socket, Transport, ConnectionStates, Check);
-terminate(Reason, _StateName, #state{transport_cb = Transport, protocol_cb = Connection,
- socket = Socket
+ Alert = terminate_alert(Reason),
+ %% Send the termination ALERT if possible
+ catch (ok = Connection:send_alert_in_connection(Alert, State)),
+ Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, ConnectionStates, Check);
+terminate(Reason, _StateName, #state{static_env = #static_env{transport_cb = Transport,
+ protocol_cb = Connection,
+ socket = Socket}
} = State) ->
handle_trusted_certs_db(State),
Connection:close(Reason, Socket, Transport, undefined, undefined).
@@ -1448,14 +1548,9 @@ format_status(terminate, [_, StateName, State]) ->
[{data, [{"State", {StateName, State#state{connection_states = ?SECRET_PRINTOUT,
protocol_buffers = ?SECRET_PRINTOUT,
user_data_buffer = ?SECRET_PRINTOUT,
- tls_handshake_history = ?SECRET_PRINTOUT,
+ handshake_env = ?SECRET_PRINTOUT,
+ connection_env = ?SECRET_PRINTOUT,
session = ?SECRET_PRINTOUT,
- private_key = ?SECRET_PRINTOUT,
- diffie_hellman_params = ?SECRET_PRINTOUT,
- diffie_hellman_keys = ?SECRET_PRINTOUT,
- srp_params = ?SECRET_PRINTOUT,
- srp_keys = ?SECRET_PRINTOUT,
- premaster_secret = ?SECRET_PRINTOUT,
ssl_options = NewOptions,
flight_buffer = ?SECRET_PRINTOUT}
}}]}].
@@ -1463,16 +1558,21 @@ format_status(terminate, [_, StateName, State]) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-connection_info(#state{sni_hostname = SNIHostname,
- session = #session{session_id = SessionId,
+send_alert(Alert, connection, #state{static_env = #static_env{protocol_cb = Connection}} = State) ->
+ Connection:send_alert_in_connection(Alert, State);
+send_alert(Alert, _, #state{static_env = #static_env{protocol_cb = Connection}} = State) ->
+ Connection:send_alert(Alert, State).
+
+connection_info(#state{static_env = #static_env{protocol_cb = Connection},
+ handshake_env = #handshake_env{sni_hostname = SNIHostname},
+ session = #session{session_id = SessionId,
cipher_suite = CipherSuite, ecc = ECCCurve},
- protocol_cb = Connection,
- negotiated_version = {_,_} = Version,
+ connection_env = #connection_env{negotiated_version = {_,_} = Version},
ssl_options = Opts}) ->
RecordCB = record_cb(Connection),
- CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher:suite_definition(CipherSuite),
+ CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher_format:suite_definition(CipherSuite),
IsNamedCurveSuite = lists:member(KexAlg,
- [ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdh_anon]),
+ [ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdhe_rsa, ecdh_anon]),
CurveInfo = case ECCCurve of
{namedCurve, Curve} when IsNamedCurveSuite ->
[{ecc, {named_curve, pubkey_cert_records:namedCurves(Curve)}}];
@@ -1481,7 +1581,8 @@ connection_info(#state{sni_hostname = SNIHostname,
end,
[{protocol, RecordCB:protocol_version(Version)},
{session_id, SessionId},
- {cipher_suite, ssl_cipher:erl_suite_definition(CipherSuiteDef)},
+ {cipher_suite, ssl_cipher_format:erl_suite_definition(CipherSuiteDef)},
+ {selected_cipher_suite, CipherSuiteDef},
{sni_hostname, SNIHostname} | CurveInfo] ++ ssl_options_list(Opts).
security_info(#state{connection_states = ConnectionStates}) ->
@@ -1494,16 +1595,17 @@ security_info(#state{connection_states = ConnectionStates}) ->
do_server_hello(Type, #hello_extensions{next_protocol_negotiation = NextProtocols} =
ServerHelloExt,
- #state{negotiated_version = Version,
+ #state{connection_env = #connection_env{negotiated_version = Version},
+ handshake_env = HsEnv,
session = #session{session_id = SessId},
connection_states = ConnectionStates0}
= State0, Connection) when is_atom(Type) ->
-
+
ServerHello =
ssl_handshake:server_hello(SessId, ssl:tls_version(Version), ConnectionStates0, ServerHelloExt),
State = server_hello(ServerHello,
- State0#state{expecting_next_protocol_negotiation =
- NextProtocols =/= undefined}, Connection),
+ State0#state{handshake_env = HsEnv#handshake_env{expecting_next_protocol_negotiation =
+ NextProtocols =/= undefined}}, Connection),
case Type of
new ->
new_server_hello(ServerHello, State, Connection);
@@ -1514,17 +1616,16 @@ do_server_hello(Type, #hello_extensions{next_protocol_negotiation = NextProtocol
new_server_hello(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression,
session_id = SessionId},
- #state{session = Session0,
- negotiated_version = Version} = State0, Connection) ->
+ #state{session = Session0,
+ connection_env = #connection_env{negotiated_version = Version}} = State0, Connection) ->
try server_certify_and_key_exchange(State0, Connection) of
#state{} = State1 ->
- {State2, Actions} = server_hello_done(State1, Connection),
+ {State, Actions} = server_hello_done(State1, Connection),
Session =
Session0#session{session_id = SessionId,
cipher_suite = CipherSuite,
compression_method = Compression},
- {Record, State} = Connection:next_record(State2#state{session = Session}),
- Connection:next_event(certify, Record, State, Actions)
+ Connection:next_event(certify, no_record, State#state{session = Session}, Actions)
catch
#alert{} = Alert ->
handle_own_alert(Alert, Version, hello, State0)
@@ -1532,69 +1633,58 @@ new_server_hello(#server_hello{cipher_suite = CipherSuite,
resumed_server_hello(#state{session = Session,
connection_states = ConnectionStates0,
- negotiated_version = Version} = State0, Connection) ->
+ connection_env = #connection_env{negotiated_version = Version}} = State0, Connection) ->
case ssl_handshake:master_secret(ssl:tls_version(Version), Session,
ConnectionStates0, server) of
{_, ConnectionStates1} ->
State1 = State0#state{connection_states = ConnectionStates1,
session = Session},
- {State2, Actions} =
+ {State, Actions} =
finalize_handshake(State1, abbreviated, Connection),
- {Record, State} = Connection:next_record(State2),
- Connection:next_event(abbreviated, Record, State, Actions);
+ Connection:next_event(abbreviated, no_record, State, Actions);
#alert{} = Alert ->
handle_own_alert(Alert, Version, hello, State0)
end.
server_hello(ServerHello, State0, Connection) ->
CipherSuite = ServerHello#server_hello.cipher_suite,
- #{key_exchange := KeyAlgorithm} = ssl_cipher:suite_definition(CipherSuite),
- State = Connection:queue_handshake(ServerHello, State0),
- State#state{key_algorithm = KeyAlgorithm}.
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
+ #state{handshake_env = HsEnv} = State = Connection:queue_handshake(ServerHello, State0),
+ State#state{handshake_env = HsEnv#handshake_env{kex_algorithm = KeyAlgorithm}}.
server_hello_done(State, Connection) ->
HelloDone = ssl_handshake:server_hello_done(),
Connection:send_handshake(HelloDone, State).
handle_peer_cert(Role, PeerCert, PublicKeyInfo,
- #state{session = #session{cipher_suite = CipherSuite} = Session} = State0,
+ #state{handshake_env = HsEnv,
+ session = #session{cipher_suite = CipherSuite} = Session} = State0,
Connection) ->
- State1 = State0#state{session =
- Session#session{peer_certificate = PeerCert},
- public_key_info = PublicKeyInfo},
- #{key_exchange := KeyAlgorithm} = ssl_cipher:suite_definition(CipherSuite),
- State2 = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlgorithm, State1),
-
- {Record, State} = Connection:next_record(State2),
- Connection:next_event(certify, Record, State).
+ State1 = State0#state{handshake_env = HsEnv#handshake_env{public_key_info = PublicKeyInfo},
+ session =
+ Session#session{peer_certificate = PeerCert}},
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
+ State = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlgorithm, State1),
+ Connection:next_event(certify, no_record, State).
handle_peer_cert_key(client, _,
{?'id-ecPublicKey', #'ECPoint'{point = _ECPoint} = PublicKey,
PublicKeyParams},
- KeyAlg, #state{session = Session} = State) when KeyAlg == ecdh_rsa;
+ KeyAlg, #state{handshake_env = HsEnv,
+ session = Session} = State) when KeyAlg == ecdh_rsa;
KeyAlg == ecdh_ecdsa ->
ECDHKey = public_key:generate_key(PublicKeyParams),
- {namedCurve, Oid} = PublicKeyParams,
- Curve = pubkey_cert_records:namedCurves(Oid), %% Need API function
PremasterSecret = ssl_handshake:premaster_secret(PublicKey, ECDHKey),
- master_secret(PremasterSecret, State#state{diffie_hellman_keys = ECDHKey,
- session = Session#session{ecc = {named_curve, Curve}}});
-%% We do currently not support cipher suites that use fixed DH.
-%% If we want to implement that the following clause can be used
-%% to extract DH parameters form cert.
-%% handle_peer_cert_key(client, _PeerCert, {?dhpublicnumber, PublicKey, PublicKeyParams},
-%% {_,SignAlg},
-%% #state{diffie_hellman_keys = {_, MyPrivatKey}} = State) when
-%% SignAlg == dh_rsa;
-%% SignAlg == dh_dss ->
-%% dh_master_secret(PublicKeyParams, PublicKey, MyPrivatKey, State);
+ master_secret(PremasterSecret, State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKey},
+ session = Session#session{ecc = PublicKeyParams}});
handle_peer_cert_key(_, _, _, _, State) ->
State.
-certify_client(#state{client_certificate_requested = true, role = client,
- cert_db = CertDbHandle,
- cert_db_ref = CertDbRef,
+certify_client(#state{static_env = #static_env{role = client,
+ cert_db = CertDbHandle,
+ cert_db_ref = CertDbRef},
+ client_certificate_requested = true,
session = #session{own_certificate = OwnCert}}
= State, Connection) ->
Certificate = ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, client),
@@ -1602,16 +1692,17 @@ certify_client(#state{client_certificate_requested = true, role = client,
certify_client(#state{client_certificate_requested = false} = State, _) ->
State.
-verify_client_cert(#state{client_certificate_requested = true, role = client,
- negotiated_version = Version,
- private_key = PrivateKey,
+verify_client_cert(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{tls_handshake_history = Hist,
+ cert_hashsign_algorithm = HashSign},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
+ client_certificate_requested = true,
session = #session{master_secret = MasterSecret,
- own_certificate = OwnCert},
- cert_hashsign_algorithm = HashSign,
- tls_handshake_history = Handshake0} = State, Connection) ->
+ own_certificate = OwnCert}} = State, Connection) ->
case ssl_handshake:client_certificate_verify(OwnCert, MasterSecret,
- ssl:tls_version(Version), HashSign, PrivateKey, Handshake0) of
+ ssl:tls_version(Version), HashSign, PrivateKey, Hist) of
#certificate_verify{} = Verified ->
Connection:queue_handshake(Verified, State);
ignore ->
@@ -1622,16 +1713,15 @@ verify_client_cert(#state{client_certificate_requested = true, role = client,
verify_client_cert(#state{client_certificate_requested = false} = State, _) ->
State.
-client_certify_and_key_exchange(#state{negotiated_version = Version} =
+client_certify_and_key_exchange(#state{connection_env = #connection_env{negotiated_version = Version}} =
State0, Connection) ->
try do_client_certify_and_key_exchange(State0, Connection) of
State1 = #state{} ->
{State2, Actions} = finalize_handshake(State1, certify, Connection),
- State3 = State2#state{
- %% Reinitialize
- client_certificate_requested = false},
- {Record, State} = Connection:next_record(State3),
- Connection:next_event(cipher, Record, State, Actions)
+ State = State2#state{
+ %% Reinitialize
+ client_certificate_requested = false},
+ Connection:next_event(cipher, no_record, State, Actions)
catch
throw:#alert{} = Alert ->
handle_own_alert(Alert, Version, certify, State0)
@@ -1648,7 +1738,9 @@ server_certify_and_key_exchange(State0, Connection) ->
request_client_cert(State2, Connection).
certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS},
- #state{private_key = Key, client_hello_version = {Major, Minor} = Version} = State, Connection) ->
+ #state{connection_env = #connection_env{private_key = Key},
+ handshake_env = #handshake_env{client_hello_version = {Major, Minor} = Version}}
+ = State, Connection) ->
FakeSecret = make_premaster_secret(Version, rsa),
%% Countermeasure for Bleichenbacher attack always provide some kind of premaster secret
%% and fail handshake later.RFC 5246 section 7.4.7.1.
@@ -1669,14 +1761,15 @@ certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS
end,
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
- #state{diffie_hellman_params = #'DHParameter'{} = Params,
- diffie_hellman_keys = {_, ServerDhPrivateKey}} = State,
+ #state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
+ kex_keys = {_, ServerDhPrivateKey}}
+ } = State,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientPublicDhKey, ServerDhPrivateKey, Params),
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
certify_client_key_exchange(#client_ec_diffie_hellman_public{dh_public = ClientPublicEcDhPoint},
- #state{diffie_hellman_keys = ECDHKey} = State, Connection) ->
+ #state{handshake_env = #handshake_env{kex_keys = ECDHKey}} = State, Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(#'ECPoint'{point = ClientPublicEcDhPoint}, ECDHKey),
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
certify_client_key_exchange(#client_psk_identity{} = ClientKey,
@@ -1686,8 +1779,8 @@ certify_client_key_exchange(#client_psk_identity{} = ClientKey,
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
- #state{diffie_hellman_params = #'DHParameter'{} = Params,
- diffie_hellman_keys = {_, ServerDhPrivateKey},
+ #state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
+ kex_keys = {_, ServerDhPrivateKey}},
ssl_options =
#ssl_options{user_lookup_fun = PSKLookup}} = State0,
Connection) ->
@@ -1695,7 +1788,7 @@ certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
ssl_handshake:premaster_secret(ClientKey, ServerDhPrivateKey, Params, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey,
- #state{diffie_hellman_keys = ServerEcDhPrivateKey,
+ #state{handshake_env = #handshake_env{kex_keys = ServerEcDhPrivateKey},
ssl_options =
#ssl_options{user_lookup_fun = PSKLookup}} = State,
Connection) ->
@@ -1703,28 +1796,29 @@ certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey,
ssl_handshake:premaster_secret(ClientKey, ServerEcDhPrivateKey, PSKLookup),
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
certify_client_key_exchange(#client_rsa_psk_identity{} = ClientKey,
- #state{private_key = Key,
+ #state{connection_env = #connection_env{private_key = Key},
ssl_options =
#ssl_options{user_lookup_fun = PSKLookup}} = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
certify_client_key_exchange(#client_srp_public{} = ClientKey,
- #state{srp_params = Params,
- srp_keys = Key
+ #state{handshake_env = #handshake_env{srp_params = Params,
+ kex_keys = Key}
} = State0, Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, Params),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher).
-certify_server(#state{key_algorithm = Algo} = State, _) when Algo == dh_anon;
- Algo == ecdh_anon;
- Algo == psk;
- Algo == dhe_psk;
- Algo == ecdhe_psk;
- Algo == srp_anon ->
+certify_server(#state{handshake_env = #handshake_env{kex_algorithm = KexAlg}} =
+ State, _) when KexAlg == dh_anon;
+ KexAlg == ecdh_anon;
+ KexAlg == psk;
+ KexAlg == dhe_psk;
+ KexAlg == ecdhe_psk;
+ KexAlg == srp_anon ->
State;
-certify_server(#state{cert_db = CertDbHandle,
- cert_db_ref = CertDbRef,
+certify_server(#state{static_env = #static_env{cert_db = CertDbHandle,
+ cert_db_ref = CertDbRef},
session = #session{own_certificate = OwnCert}} = State, Connection) ->
case ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, server) of
Cert = #certificate{} ->
@@ -1733,18 +1827,19 @@ certify_server(#state{cert_db = CertDbHandle,
throw(Alert)
end.
-key_exchange(#state{role = server, key_algorithm = rsa} = State,_) ->
+key_exchange(#state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{kex_algorithm = rsa}} = State,_) ->
State;
-key_exchange(#state{role = server, key_algorithm = Algo,
- hashsign_algorithm = HashSignAlgo,
- diffie_hellman_params = #'DHParameter'{} = Params,
- private_key = PrivateKey,
- connection_states = ConnectionStates0,
- negotiated_version = Version
- } = State0, Connection)
- when Algo == dhe_dss;
- Algo == dhe_rsa;
- Algo == dh_anon ->
+key_exchange(#state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ diffie_hellman_params = #'DHParameter'{} = Params,
+ hashsign_algorithm = HashSignAlgo},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
+ connection_states = ConnectionStates0} = State0, Connection)
+ when KexAlg == dhe_dss;
+ KexAlg == dhe_rsa;
+ KexAlg == dh_anon ->
DHKeys = public_key:generate_key(Params),
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
@@ -1754,20 +1849,26 @@ key_exchange(#state{role = server, key_algorithm = Algo,
HashSignAlgo, ClientRandom,
ServerRandom,
PrivateKey}),
- State = Connection:queue_handshake(Msg, State0),
- State#state{diffie_hellman_keys = DHKeys};
-key_exchange(#state{role = server, private_key = Key, key_algorithm = Algo} = State, _)
- when Algo == ecdh_ecdsa; Algo == ecdh_rsa ->
- State#state{diffie_hellman_keys = Key};
-key_exchange(#state{role = server, key_algorithm = Algo,
- hashsign_algorithm = HashSignAlgo,
- private_key = PrivateKey,
+ #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0),
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = DHKeys}};
+key_exchange(#state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg} = HsEnv,
+ connection_env = #connection_env{private_key = #'ECPrivateKey'{parameters = ECCurve} = Key},
+ session = Session} = State, _)
+ when KexAlg == ecdh_ecdsa;
+ KexAlg == ecdh_rsa ->
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = Key},
+ session = Session#session{ecc = ECCurve}};
+key_exchange(#state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ hashsign_algorithm = HashSignAlgo},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
session = #session{ecc = ECCCurve},
- connection_states = ConnectionStates0,
- negotiated_version = Version
- } = State0, Connection)
- when Algo == ecdhe_ecdsa; Algo == ecdhe_rsa;
- Algo == ecdh_anon ->
+ connection_states = ConnectionStates0} = State0, Connection)
+ when KexAlg == ecdhe_ecdsa;
+ KexAlg == ecdhe_rsa;
+ KexAlg == ecdh_anon ->
ECDHKeys = public_key:generate_key(ECCCurve),
#{security_parameters := SecParams} =
@@ -1779,18 +1880,19 @@ key_exchange(#state{role = server, key_algorithm = Algo,
HashSignAlgo, ClientRandom,
ServerRandom,
PrivateKey}),
- State = Connection:queue_handshake(Msg, State0),
- State#state{diffie_hellman_keys = ECDHKeys};
-key_exchange(#state{role = server, key_algorithm = psk,
+ #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0),
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}};
+key_exchange(#state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{kex_algorithm = psk},
ssl_options = #ssl_options{psk_identity = undefined}} = State, _) ->
State;
-key_exchange(#state{role = server, key_algorithm = psk,
+key_exchange(#state{static_env = #static_env{role = server},
ssl_options = #ssl_options{psk_identity = PskIdentityHint},
- hashsign_algorithm = HashSignAlgo,
- private_key = PrivateKey,
- connection_states = ConnectionStates0,
- negotiated_version = Version
- } = State0, Connection) ->
+ handshake_env = #handshake_env{kex_algorithm = psk,
+ hashsign_algorithm = HashSignAlgo},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
+ connection_states = ConnectionStates0} = State0, Connection) ->
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
#security_parameters{client_random = ClientRandom,
@@ -1799,15 +1901,16 @@ key_exchange(#state{role = server, key_algorithm = psk,
{psk, PskIdentityHint,
HashSignAlgo, ClientRandom,
ServerRandom,
- PrivateKey}),
+ PrivateKey}),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = server, key_algorithm = dhe_psk,
+key_exchange(#state{static_env = #static_env{role = server},
ssl_options = #ssl_options{psk_identity = PskIdentityHint},
- hashsign_algorithm = HashSignAlgo,
- diffie_hellman_params = #'DHParameter'{} = Params,
- private_key = PrivateKey,
- connection_states = ConnectionStates0,
- negotiated_version = Version
+ handshake_env = #handshake_env{kex_algorithm = dhe_psk,
+ diffie_hellman_params = #'DHParameter'{} = Params,
+ hashsign_algorithm = HashSignAlgo},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
+ connection_states = ConnectionStates0
} = State0, Connection) ->
DHKeys = public_key:generate_key(Params),
#{security_parameters := SecParams} =
@@ -1820,15 +1923,16 @@ key_exchange(#state{role = server, key_algorithm = dhe_psk,
HashSignAlgo, ClientRandom,
ServerRandom,
PrivateKey}),
- State = Connection:queue_handshake(Msg, State0),
- State#state{diffie_hellman_keys = DHKeys};
-key_exchange(#state{role = server, key_algorithm = ecdhe_psk,
+ #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0),
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = DHKeys}};
+key_exchange(#state{static_env = #static_env{role = server},
ssl_options = #ssl_options{psk_identity = PskIdentityHint},
- hashsign_algorithm = HashSignAlgo,
- private_key = PrivateKey,
+ handshake_env = #handshake_env{kex_algorithm = ecdhe_psk,
+ hashsign_algorithm = HashSignAlgo},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
session = #session{ecc = ECCCurve},
- connection_states = ConnectionStates0,
- negotiated_version = Version
+ connection_states = ConnectionStates0
} = State0, Connection) ->
ECDHKeys = public_key:generate_key(ECCCurve),
#{security_parameters := SecParams} =
@@ -1841,17 +1945,19 @@ key_exchange(#state{role = server, key_algorithm = ecdhe_psk,
HashSignAlgo, ClientRandom,
ServerRandom,
PrivateKey}),
- State = Connection:queue_handshake(Msg, State0),
- State#state{diffie_hellman_keys = ECDHKeys};
-key_exchange(#state{role = server, key_algorithm = rsa_psk,
+ #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0),
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}};
+key_exchange(#state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{kex_algorithm = rsa_psk},
ssl_options = #ssl_options{psk_identity = undefined}} = State, _) ->
State;
-key_exchange(#state{role = server, key_algorithm = rsa_psk,
+key_exchange(#state{static_env = #static_env{role = server},
ssl_options = #ssl_options{psk_identity = PskIdentityHint},
- hashsign_algorithm = HashSignAlgo,
- private_key = PrivateKey,
- connection_states = ConnectionStates0,
- negotiated_version = Version
+ handshake_env = #handshake_env{kex_algorithm = rsa_psk,
+ hashsign_algorithm = HashSignAlgo},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
+ connection_states = ConnectionStates0
} = State0, Connection) ->
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates0, read),
@@ -1863,17 +1969,18 @@ key_exchange(#state{role = server, key_algorithm = rsa_psk,
ServerRandom,
PrivateKey}),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = server, key_algorithm = Algo,
+key_exchange(#state{static_env = #static_env{role = server},
ssl_options = #ssl_options{user_lookup_fun = LookupFun},
- hashsign_algorithm = HashSignAlgo,
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ hashsign_algorithm = HashSignAlgo},
+ connection_env = #connection_env{negotiated_version = Version,
+ private_key = PrivateKey},
session = #session{srp_username = Username},
- private_key = PrivateKey,
- connection_states = ConnectionStates0,
- negotiated_version = Version
+ connection_states = ConnectionStates0
} = State0, Connection)
- when Algo == srp_dss;
- Algo == srp_rsa;
- Algo == srp_anon ->
+ when KexAlg == srp_dss;
+ KexAlg == srp_rsa;
+ KexAlg == srp_anon ->
SrpParams = handle_srp_identity(Username, LookupFun),
Keys = case generate_srp_server_keys(SrpParams, 0) of
Alert = #alert{} ->
@@ -1890,81 +1997,86 @@ key_exchange(#state{role = server, key_algorithm = Algo,
HashSignAlgo, ClientRandom,
ServerRandom,
PrivateKey}),
- State = Connection:queue_handshake(Msg, State0),
- State#state{srp_params = SrpParams,
- srp_keys = Keys};
-key_exchange(#state{role = client,
- key_algorithm = rsa,
- public_key_info = PublicKeyInfo,
- negotiated_version = Version,
- premaster_secret = PremasterSecret} = State0, Connection) ->
+ #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0),
+ State#state{handshake_env = HsEnv#handshake_env{srp_params = SrpParams,
+ kex_keys = Keys}};
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = rsa,
+ public_key_info = PublicKeyInfo,
+ premaster_secret = PremasterSecret},
+ connection_env = #connection_env{negotiated_version = Version}
+ } = State0, Connection) ->
Msg = rsa_key_exchange(ssl:tls_version(Version), PremasterSecret, PublicKeyInfo),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = client,
- key_algorithm = Algorithm,
- negotiated_version = Version,
- diffie_hellman_keys = {DhPubKey, _}
- } = State0, Connection)
- when Algorithm == dhe_dss;
- Algorithm == dhe_rsa;
- Algorithm == dh_anon ->
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ kex_keys = {DhPubKey, _}},
+ connection_env = #connection_env{negotiated_version = Version}
+ } = State0, Connection)
+ when KexAlg == dhe_dss;
+ KexAlg == dhe_rsa;
+ KexAlg == dh_anon ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {dh, DhPubKey}),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = client,
- key_algorithm = Algorithm,
- negotiated_version = Version,
- diffie_hellman_keys = Keys} = State0, Connection)
- when Algorithm == ecdhe_ecdsa; Algorithm == ecdhe_rsa;
- Algorithm == ecdh_ecdsa; Algorithm == ecdh_rsa;
- Algorithm == ecdh_anon ->
- 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) ->
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ kex_keys = #'ECPrivateKey'{parameters = ECCurve} = Key},
+ connection_env = #connection_env{negotiated_version = Version},
+ session = Session
+ } = State0, Connection)
+ when KexAlg == ecdhe_ecdsa;
+ KexAlg == ecdhe_rsa;
+ KexAlg == ecdh_ecdsa;
+ KexAlg == ecdh_rsa;
+ KexAlg == ecdh_anon ->
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Key}),
+ Connection:queue_handshake(Msg, State0#state{session = Session#session{ecc = ECCurve}});
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = psk},
+ connection_env = #connection_env{negotiated_version = Version},
+ ssl_options = SslOpts} = State0, Connection) ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{psk, SslOpts#ssl_options.psk_identity}),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = client,
- ssl_options = SslOpts,
- key_algorithm = dhe_psk,
- negotiated_version = Version,
- diffie_hellman_keys = {DhPubKey, _}} = State0, Connection) ->
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = dhe_psk,
+ kex_keys = {DhPubKey, _}},
+ connection_env = #connection_env{negotiated_version = Version},
+ ssl_options = SslOpts} = State0, Connection) ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{dhe_psk,
SslOpts#ssl_options.psk_identity, DhPubKey}),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = client,
- ssl_options = SslOpts,
- key_algorithm = ecdhe_psk,
- negotiated_version = Version,
- diffie_hellman_keys = ECDHKeys} = State0, Connection) ->
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = ecdhe_psk,
+ kex_keys = ECDHKeys},
+ connection_env = #connection_env{negotiated_version = Version},
+ ssl_options = SslOpts} = State0, Connection) ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{ecdhe_psk,
SslOpts#ssl_options.psk_identity, ECDHKeys}),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = client,
- ssl_options = SslOpts,
- key_algorithm = rsa_psk,
- public_key_info = PublicKeyInfo,
- negotiated_version = Version,
- premaster_secret = PremasterSecret}
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = rsa_psk,
+ public_key_info = PublicKeyInfo,
+ premaster_secret = PremasterSecret},
+ connection_env = #connection_env{negotiated_version = Version},
+ ssl_options = SslOpts}
= State0, Connection) ->
Msg = rsa_psk_key_exchange(ssl:tls_version(Version), SslOpts#ssl_options.psk_identity,
PremasterSecret, PublicKeyInfo),
Connection:queue_handshake(Msg, State0);
-key_exchange(#state{role = client,
- key_algorithm = Algorithm,
- negotiated_version = Version,
- srp_keys = {ClientPubKey, _}}
+key_exchange(#state{static_env = #static_env{role = client},
+ handshake_env = #handshake_env{kex_algorithm = KexAlg,
+ kex_keys = {ClientPubKey, _}},
+ connection_env = #connection_env{negotiated_version = Version}}
= State0, Connection)
- when Algorithm == srp_dss;
- Algorithm == srp_rsa;
- Algorithm == srp_anon ->
+ when KexAlg == srp_dss;
+ KexAlg == srp_rsa;
+ KexAlg == srp_anon ->
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {srp, ClientPubKey}),
Connection:queue_handshake(Msg, State0).
@@ -2001,18 +2113,24 @@ rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret,
rsa_psk_key_exchange(_, _, _, _) ->
throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)).
-request_client_cert(#state{key_algorithm = Alg} = State, _)
- when Alg == dh_anon; Alg == ecdh_anon;
- Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk;
- Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
+request_client_cert(#state{handshake_env = #handshake_env{kex_algorithm = Alg}} = State, _)
+ when Alg == dh_anon;
+ Alg == ecdh_anon;
+ Alg == psk;
+ Alg == dhe_psk;
+ Alg == ecdhe_psk;
+ Alg == rsa_psk;
+ Alg == srp_dss;
+ Alg == srp_rsa;
+ Alg == srp_anon ->
State;
-request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer,
- signature_algs = SupportedHashSigns},
- connection_states = ConnectionStates0,
- cert_db = CertDbHandle,
- cert_db_ref = CertDbRef,
- negotiated_version = Version} = State0, Connection) ->
+request_client_cert(#state{static_env = #static_env{cert_db = CertDbHandle,
+ cert_db_ref = CertDbRef},
+ connection_env = #connection_env{negotiated_version = Version},
+ ssl_options = #ssl_options{verify = verify_peer,
+ signature_algs = SupportedHashSigns},
+ connection_states = ConnectionStates0} = State0, Connection) ->
#{security_parameters :=
#security_parameters{cipher_suite = CipherSuite}} =
ssl_record:pending_connection_state(ConnectionStates0, read),
@@ -2029,7 +2147,7 @@ request_client_cert(#state{ssl_options = #ssl_options{verify = verify_none}} =
State.
calculate_master_secret(PremasterSecret,
- #state{negotiated_version = Version,
+ #state{connection_env = #connection_env{negotiated_version = Version},
connection_states = ConnectionStates0,
session = Session0} = State0, Connection,
_Current, Next) ->
@@ -2037,10 +2155,9 @@ calculate_master_secret(PremasterSecret,
ConnectionStates0, server) of
{MasterSecret, ConnectionStates} ->
Session = Session0#session{master_secret = MasterSecret},
- State1 = State0#state{connection_states = ConnectionStates,
+ State = State0#state{connection_states = ConnectionStates,
session = Session},
- {Record, State} = Connection:next_record(State1),
- Connection:next_event(Next, Record, State);
+ Connection:next_event(Next, no_record, State);
#alert{} = Alert ->
handle_own_alert(Alert, Version, certify, State0)
end.
@@ -2057,27 +2174,29 @@ finalize_handshake(State0, StateName, Connection) ->
State = next_protocol(State2, Connection),
finished(State, StateName, Connection).
-next_protocol(#state{role = server} = State, _) ->
+next_protocol(#state{static_env = #static_env{role = server}} = State, _) ->
State;
-next_protocol(#state{negotiated_protocol = undefined} = State, _) ->
+next_protocol(#state{handshake_env = #handshake_env{negotiated_protocol = undefined}} = State, _) ->
State;
-next_protocol(#state{expecting_next_protocol_negotiation = false} = State, _) ->
+next_protocol(#state{handshake_env = #handshake_env{expecting_next_protocol_negotiation = false}} = State, _) ->
State;
-next_protocol(#state{negotiated_protocol = NextProtocol} = State0, Connection) ->
+next_protocol(#state{handshake_env = #handshake_env{negotiated_protocol = NextProtocol}} = State0, Connection) ->
NextProtocolMessage = ssl_handshake:next_protocol(NextProtocol),
Connection:queue_handshake(NextProtocolMessage, State0).
cipher_protocol(State, Connection) ->
Connection:queue_change_cipher(#change_cipher_spec{}, State).
-finished(#state{role = Role, negotiated_version = Version,
+finished(#state{static_env = #static_env{role = Role},
+ handshake_env = #handshake_env{tls_handshake_history = Hist},
+ connection_env = #connection_env{negotiated_version = Version},
session = Session,
- connection_states = ConnectionStates0,
- tls_handshake_history = Handshake0} = State0, StateName, Connection) ->
+ connection_states = ConnectionStates0} = State0,
+ StateName, Connection) ->
MasterSecret = Session#session.master_secret,
Finished = ssl_handshake:finished(ssl:tls_version(Version), Role,
get_current_prf(ConnectionStates0, write),
- MasterSecret, Handshake0),
+ MasterSecret, Hist),
ConnectionStates = save_verify_data(Role, Finished, ConnectionStates0, StateName),
Connection:send_handshake(Finished, State0#state{connection_states =
ConnectionStates}).
@@ -2093,65 +2212,71 @@ save_verify_data(server, #finished{verify_data = Data}, ConnectionStates, abbrev
calculate_secret(#server_dh_params{dh_p = Prime, dh_g = Base,
dh_y = ServerPublicDhKey} = Params,
- State, Connection) ->
+ #state{handshake_env = HsEnv} = State, Connection) ->
Keys = {_, PrivateDhKey} = crypto:generate_key(dh, [Prime, Base]),
PremasterSecret =
ssl_handshake:premaster_secret(ServerPublicDhKey, PrivateDhKey, Params),
calculate_master_secret(PremasterSecret,
- State#state{diffie_hellman_keys = Keys},
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = Keys}},
Connection, certify, certify);
calculate_secret(#server_ecdh_params{curve = ECCurve, public = ECServerPubKey},
- State=#state{session=Session}, Connection) ->
+ #state{handshake_env = HsEnv,
+ session = Session} = State, Connection) ->
ECDHKeys = public_key:generate_key(ECCurve),
PremasterSecret =
ssl_handshake:premaster_secret(#'ECPoint'{point = ECServerPubKey}, ECDHKeys),
calculate_master_secret(PremasterSecret,
- State#state{diffie_hellman_keys = ECDHKeys,
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys},
session = Session#session{ecc = ECCurve}},
Connection, certify, certify);
calculate_secret(#server_psk_params{
hint = IdentityHint},
- State0, Connection) ->
+ #state{handshake_env = HsEnv} = State, Connection) ->
%% store for later use
- {Record, State} = Connection:next_record(State0#state{psk_identity = IdentityHint}),
- Connection:next_event(certify, Record, State);
+ Connection:next_event(certify, no_record,
+ State#state{handshake_env =
+ HsEnv#handshake_env{server_psk_identity = IdentityHint}});
calculate_secret(#server_dhe_psk_params{
dh_params = #server_dh_params{dh_p = Prime, dh_g = Base}} = ServerKey,
- #state{ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} =
+ #state{handshake_env = HsEnv,
+ ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} =
State, Connection) ->
Keys = {_, PrivateDhKey} =
crypto:generate_key(dh, [Prime, Base]),
PremasterSecret = ssl_handshake:premaster_secret(ServerKey, PrivateDhKey, PSKLookup),
- calculate_master_secret(PremasterSecret, State#state{diffie_hellman_keys = Keys},
+ calculate_master_secret(PremasterSecret, State#state{handshake_env = HsEnv#handshake_env{kex_keys = Keys}},
Connection, certify, certify);
calculate_secret(#server_ecdhe_psk_params{
dh_params = #server_ecdh_params{curve = ECCurve}} = ServerKey,
#state{ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} =
- State=#state{session=Session}, Connection) ->
+ #state{handshake_env = HsEnv,
+ session = Session} = State, Connection) ->
ECDHKeys = public_key:generate_key(ECCurve),
PremasterSecret = ssl_handshake:premaster_secret(ServerKey, ECDHKeys, PSKLookup),
calculate_master_secret(PremasterSecret,
- State#state{diffie_hellman_keys = ECDHKeys,
+ State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys},
session = Session#session{ecc = ECCurve}},
Connection, certify, certify);
calculate_secret(#server_srp_params{srp_n = Prime, srp_g = Generator} = ServerKey,
- #state{ssl_options = #ssl_options{srp_identity = SRPId}} = State,
+ #state{handshake_env = HsEnv,
+ ssl_options = #ssl_options{srp_identity = SRPId}} = State,
Connection) ->
Keys = generate_srp_client_keys(Generator, Prime, 0),
PremasterSecret = ssl_handshake:premaster_secret(ServerKey, Keys, SRPId),
- calculate_master_secret(PremasterSecret, State#state{srp_keys = Keys}, Connection,
+ calculate_master_secret(PremasterSecret, State#state{handshake_env = HsEnv#handshake_env{kex_keys = Keys}}, Connection,
certify, certify).
master_secret(#alert{} = Alert, _) ->
Alert;
-master_secret(PremasterSecret, #state{session = Session,
- negotiated_version = Version, role = Role,
+master_secret(PremasterSecret, #state{static_env = #static_env{role = Role},
+ connection_env = #connection_env{negotiated_version = Version},
+ session = Session,
connection_states = ConnectionStates0} = State) ->
case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret,
ConnectionStates0, Role) of
@@ -2169,22 +2294,24 @@ generate_srp_server_keys(_SrpParams, 10) ->
generate_srp_server_keys(SrpParams =
#srp_user{generator = Generator, prime = Prime,
verifier = Verifier}, N) ->
- case crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of
- error ->
- generate_srp_server_keys(SrpParams, N+1);
+ try crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of
Keys ->
Keys
+ catch
+ error:_ ->
+ generate_srp_server_keys(SrpParams, N+1)
end.
generate_srp_client_keys(_Generator, _Prime, 10) ->
?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
generate_srp_client_keys(Generator, Prime, N) ->
- case crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
- error ->
- generate_srp_client_keys(Generator, Prime, N+1);
+ try crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
Keys ->
Keys
+ catch
+ error:_ ->
+ generate_srp_client_keys(Generator, Prime, N+1)
end.
handle_srp_identity(Username, {Fun, UserState}) ->
@@ -2209,7 +2336,7 @@ cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0}
{Record, State} = prepare_connection(State0#state{session = Session,
connection_states = ConnectionStates},
Connection),
- Connection:next_event(connection, Record, State);
+ Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close}]);
cipher_role(server, Data, Session, #state{connection_states = ConnectionStates0} = State0,
Connection) ->
ConnectionStates1 = ssl_record:set_client_verify_data(current_read, Data,
@@ -2218,15 +2345,15 @@ cipher_role(server, Data, Session, #state{connection_states = ConnectionStates0
finalize_handshake(State0#state{connection_states = ConnectionStates1,
session = Session}, cipher, Connection),
{Record, State} = prepare_connection(State1, Connection),
- Connection:next_event(connection, Record, State, Actions).
-
-is_anonymous(Algo) when Algo == dh_anon;
- Algo == ecdh_anon;
- Algo == psk;
- Algo == dhe_psk;
- Algo == ecdhe_psk;
- Algo == rsa_psk;
- Algo == srp_anon ->
+ Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close} | Actions]).
+
+is_anonymous(KexAlg) when KexAlg == dh_anon;
+ KexAlg == ecdh_anon;
+ KexAlg == psk;
+ KexAlg == dhe_psk;
+ KexAlg == ecdhe_psk;
+ KexAlg == rsa_psk;
+ KexAlg == srp_anon ->
true;
is_anonymous(_) ->
false.
@@ -2340,6 +2467,30 @@ set_socket_opts(ConnectionCb, Transport, Socket, [{active, Active}| Opts], SockO
Active == false ->
set_socket_opts(ConnectionCb, Transport, Socket, Opts,
SockOpts#socket_options{active = Active}, Other);
+set_socket_opts(ConnectionCb, Transport, Socket, [{active, Active1} = Opt| Opts],
+ SockOpts=#socket_options{active = Active0}, Other)
+ when Active1 >= -32768, Active1 =< 32767 ->
+ Active = if
+ is_integer(Active0), Active0 + Active1 < -32768 ->
+ error;
+ is_integer(Active0), Active0 + Active1 =< 0 ->
+ false;
+ is_integer(Active0), Active0 + Active1 > 32767 ->
+ error;
+ Active1 =< 0 ->
+ false;
+ is_integer(Active0) ->
+ Active0 + Active1;
+ true ->
+ Active1
+ end,
+ case Active of
+ error ->
+ {{error, {options, {socket_options, Opt}} }, SockOpts};
+ _ ->
+ set_socket_opts(ConnectionCb, Transport, Socket, Opts,
+ SockOpts#socket_options{active = Active}, Other)
+ end;
set_socket_opts(_,_, _, [{active, _} = Opt| _], SockOpts, _) ->
{{error, {options, {socket_options, Opt}} }, SockOpts};
set_socket_opts(ConnectionCb, Transport, Socket, [Opt | Opts], SockOpts, Other) ->
@@ -2371,35 +2522,30 @@ map_extensions(#hello_extensions{renegotiation_info = RenegotiationInfo,
elliptic_curves => ssl_handshake:extension_value(ECCCurves),
sni => ssl_handshake:extension_value(SNI)}.
-terminate_alert(normal, Version, ConnectionStates, Connection) ->
- Connection:encode_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- Version, ConnectionStates);
-terminate_alert({Reason, _}, Version, ConnectionStates, Connection) when Reason == close;
- Reason == shutdown ->
- Connection:encode_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- Version, ConnectionStates);
-
-terminate_alert(_, Version, ConnectionStates, Connection) ->
- {BinAlert, _} = Connection:encode_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR),
- Version, ConnectionStates),
- BinAlert.
+terminate_alert(normal) ->
+ ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY);
+terminate_alert({Reason, _}) when Reason == close;
+ Reason == shutdown ->
+ ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY);
+terminate_alert(_) ->
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR).
handle_trusted_certs_db(#state{ssl_options =
#ssl_options{cacertfile = <<>>, cacerts = []}}) ->
%% No trusted certs specified
ok;
-handle_trusted_certs_db(#state{cert_db_ref = Ref,
- cert_db = CertDb,
- ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined ->
+handle_trusted_certs_db(#state{static_env = #static_env{cert_db_ref = Ref,
+ cert_db = CertDb},
+ ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined ->
%% Certs provided as DER directly can not be shared
%% with other connections and it is safe to delete them when the connection ends.
ssl_pkix_db:remove_trusted_certs(Ref, CertDb);
-handle_trusted_certs_db(#state{file_ref_db = undefined}) ->
+handle_trusted_certs_db(#state{static_env = #static_env{file_ref_db = undefined}}) ->
%% Something went wrong early (typically cacertfile does not
%% exist) so there is nothing to handle
ok;
-handle_trusted_certs_db(#state{cert_db_ref = Ref,
- file_ref_db = RefDb,
+handle_trusted_certs_db(#state{static_env = #static_env{cert_db_ref = Ref,
+ file_ref_db = RefDb},
ssl_options = #ssl_options{cacertfile = File}}) ->
case ssl_pkix_db:ref_count(Ref, RefDb, -1) of
0 ->
@@ -2408,49 +2554,64 @@ handle_trusted_certs_db(#state{cert_db_ref = Ref,
ok
end.
-prepare_connection(#state{renegotiation = Renegotiate,
+prepare_connection(#state{handshake_env = #handshake_env{renegotiation = Renegotiate},
start_or_recv_from = RecvFrom} = State0, Connection)
when Renegotiate =/= {false, first},
RecvFrom =/= undefined ->
- State1 = Connection:reinit_handshake_data(State0),
- {Record, State} = Connection:next_record(State1),
- {Record, ack_connection(State)};
+ State = Connection:reinit(State0),
+ {no_record, ack_connection(State)};
prepare_connection(State0, Connection) ->
- State = Connection:reinit_handshake_data(State0),
+ State = Connection:reinit(State0),
{no_record, ack_connection(State)}.
-ack_connection(#state{renegotiation = {true, Initiater}} = State)
- when Initiater == internal;
- Initiater == peer ->
- State#state{renegotiation = undefined};
-ack_connection(#state{renegotiation = {true, From}} = State) ->
+ack_connection(#state{handshake_env = #handshake_env{renegotiation = {true, Initiater}} = HsEnv} = State) when Initiater == peer;
+ Initiater == internal ->
+ State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}};
+ack_connection(#state{handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv} = State) ->
gen_statem:reply(From, ok),
- State#state{renegotiation = undefined};
-ack_connection(#state{renegotiation = {false, first},
- start_or_recv_from = StartFrom,
- timer = Timer} = State) when StartFrom =/= undefined ->
+ State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}};
+ack_connection(#state{handshake_env = #handshake_env{renegotiation = {false, first}} = HsEnv,
+ start_or_recv_from = StartFrom} = State) when StartFrom =/= undefined ->
gen_statem:reply(StartFrom, connected),
- cancel_timer(Timer),
- State#state{renegotiation = undefined,
- start_or_recv_from = undefined, timer = undefined};
+ State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined},
+ start_or_recv_from = undefined};
ack_connection(State) ->
State.
-cancel_timer(undefined) ->
- ok;
-cancel_timer(Timer) ->
- erlang:cancel_timer(Timer),
- ok.
+session_handle_params(#server_ecdh_params{curve = ECCurve}, Session) ->
+ Session#session{ecc = ECCurve};
+session_handle_params(_, Session) ->
+ Session.
+
+handle_session(Role = server, #ssl_options{reuse_sessions = true} = SslOpts,
+ Host, Port, Session0) ->
+ register_session(Role, host_id(Role, Host, SslOpts), Port, Session0, true);
+handle_session(Role = client, #ssl_options{verify = verify_peer,
+ reuse_sessions = Reuse} = SslOpts,
+ Host, Port, Session0) when Reuse =/= false ->
+ register_session(Role, host_id(Role, Host, SslOpts), Port, Session0, reg_type(Reuse));
+handle_session(server, _, Host, Port, Session) ->
+ %% Remove "session of type new" entry from session DB
+ ssl_manager:invalidate_session(Host, Port, Session),
+ Session;
+handle_session(client, _,_,_, Session) ->
+ %% In client case there is no entry yet, so nothing to remove
+ Session.
-register_session(client, Host, Port, #session{is_resumable = new} = Session0) ->
+reg_type(save) ->
+ true;
+reg_type(true) ->
+ unique.
+
+register_session(client, Host, Port, #session{is_resumable = new} = Session0, Save) ->
Session = Session0#session{is_resumable = true},
- ssl_manager:register_session(Host, Port, Session),
+ ssl_manager:register_session(Host, Port, Session, Save),
Session;
-register_session(server, _, Port, #session{is_resumable = new} = Session0) ->
+register_session(server, _, Port, #session{is_resumable = new} = Session0, _) ->
Session = Session0#session{is_resumable = true},
ssl_manager:register_session(Port, Session),
Session;
-register_session(_, _, _, Session) ->
+register_session(_, _, _, Session, _) ->
Session. %% Already registered
host_id(client, _Host, #ssl_options{server_name_indication = Hostname}) when is_list(Hostname) ->
@@ -2459,31 +2620,30 @@ host_id(_, Host, _) ->
Host.
handle_new_session(NewId, CipherSuite, Compression,
- #state{session = Session0,
- protocol_cb = Connection} = State0) ->
+ #state{static_env = #static_env{protocol_cb = Connection},
+ session = Session0
+ } = State0) ->
Session = Session0#session{session_id = NewId,
cipher_suite = CipherSuite,
compression_method = Compression},
- {Record, State} = Connection:next_record(State0#state{session = Session}),
- Connection:next_event(certify, Record, State).
-
-handle_resumed_session(SessId, #state{connection_states = ConnectionStates0,
- negotiated_version = Version,
- host = Host, port = Port,
- protocol_cb = Connection,
- session_cache = Cache,
- session_cache_cb = CacheCb} = State0) ->
+ Connection:next_event(certify, no_record, State0#state{session = Session}).
+
+handle_resumed_session(SessId, #state{static_env = #static_env{host = Host,
+ port = Port,
+ protocol_cb = Connection,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ connection_env = #connection_env{negotiated_version = Version},
+ connection_states = ConnectionStates0} = State) ->
Session = CacheCb:lookup(Cache, {{Host, Port}, SessId}),
case ssl_handshake:master_secret(ssl:tls_version(Version), Session,
ConnectionStates0, client) of
{_, ConnectionStates} ->
- {Record, State} =
- Connection:next_record(State0#state{
- connection_states = ConnectionStates,
- session = Session}),
- Connection:next_event(abbreviated, Record, State);
+ Connection:next_event(abbreviated, no_record, State#state{
+ connection_states = ConnectionStates,
+ session = Session});
#alert{} = Alert ->
- handle_own_alert(Alert, Version, hello, State0)
+ handle_own_alert(Alert, Version, hello, State)
end.
make_premaster_secret({MajVer, MinVer}, rsa) ->
@@ -2522,7 +2682,7 @@ ssl_options_list([ciphers = Key | Keys], [Value | Values], Acc) ->
ssl_options_list(Keys, Values,
[{Key, lists:map(
fun(Suite) ->
- ssl_cipher:erl_suite_definition(Suite)
+ ssl_cipher_format:suite_definition(Suite)
end, Value)}
| Acc]);
ssl_options_list([Key | Keys], [Value | Values], Acc) ->
@@ -2531,12 +2691,14 @@ ssl_options_list([Key | Keys], [Value | Values], Acc) ->
handle_active_option(false, connection = StateName, To, Reply, State) ->
hibernate_after(StateName, State, [{reply, To, Reply}]);
-handle_active_option(_, connection = StateName0, To, Reply, #state{protocol_cb = Connection,
- user_data_buffer = <<>>} = State0) ->
- %% Need data, set active once
- {Record, State1} = Connection:next_record_if_active(State0),
- %% Note: Renogotiation may cause StateName0 =/= StateName
- case Connection:next_event(StateName0, Record, State1) of
+handle_active_option(_, connection = StateName, To, _Reply, #state{connection_env = #connection_env{terminated = true},
+ user_data_buffer = {_,0,_}} = State) ->
+ handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY, all_data_deliverd), StateName,
+ State#state{start_or_recv_from = To}),
+ {stop,{shutdown, peer_close}, State};
+handle_active_option(_, connection = StateName0, To, Reply, #state{static_env = #static_env{protocol_cb = Connection},
+ user_data_buffer = {_,0,_}} = State0) ->
+ case Connection:next_event(StateName0, no_record, State0) of
{next_state, StateName, State} ->
hibernate_after(StateName, State, [{reply, To, Reply}]);
{next_state, StateName, State, Actions} ->
@@ -2544,12 +2706,13 @@ handle_active_option(_, connection = StateName0, To, Reply, #state{protocol_cb =
{stop, _, _} = Stop ->
Stop
end;
-handle_active_option(_, StateName, To, Reply, #state{user_data_buffer = <<>>} = State) ->
+handle_active_option(_, StateName, To, Reply, #state{user_data_buffer = {_,0,_}} = State) ->
%% Active once already set
{next_state, StateName, State, [{reply, To, Reply}]};
-%% user_data_buffer =/= <<>>
-handle_active_option(_, StateName0, To, Reply, #state{protocol_cb = Connection} = State0) ->
+%% user_data_buffer nonempty
+handle_active_option(_, StateName0, To, Reply,
+ #state{static_env = #static_env{protocol_cb = Connection}} = State0) ->
case read_application_data(<<>>, State0) of
{stop, _, _} = Stop ->
Stop;
@@ -2565,64 +2728,27 @@ handle_active_option(_, StateName0, To, Reply, #state{protocol_cb = Connection}
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)
+get_data(#socket_options{active=false}, undefined, _Bin) ->
+ %% Recv timed out save buffer data until next recv
+ passive;
+get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Bin)
when Raw =:= raw; Raw =:= 0 -> %% Raw Mode
- if
- Active =/= false orelse BytesToRead =:= 0 ->
+ case Bin of
+ <<_/binary>> when Active =/= false orelse BytesToRead =:= 0 ->
%% Active true or once, or passive mode recv(0)
- {ok, Buffer, <<>>};
- byte_size(Buffer) >= BytesToRead ->
+ {ok, Bin, <<>>};
+ <<Data:BytesToRead/binary, Rest/binary>> ->
%% Passive Mode, recv(Bytes)
- <<Data:BytesToRead/binary, Rest/binary>> = Buffer,
- {ok, Data, Rest};
- true ->
+ {ok, Data, Rest};
+ <<_/binary>> ->
%% Passive Mode not enough data
- {more, Buffer}
+ {more, BytesToRead}
end;
-get_data(#socket_options{packet=Type, packet_size=Size}, _, Buffer) ->
+get_data(#socket_options{packet=Type, packet_size=Size}, _, Bin) ->
PacketOpts = [{packet_size, Size}],
- case decode_packet(Type, Buffer, PacketOpts) of
- {more, _} ->
- {more, Buffer};
- Decoded ->
- Decoded
- end.
+ decode_packet(Type, Bin, PacketOpts).
decode_packet({http, headers}, Buffer, PacketOpts) ->
decode_packet(httph, Buffer, PacketOpts);
@@ -2640,42 +2766,61 @@ decode_packet(Type, Buffer, PacketOpts) ->
%% 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,
+deliver_app_data(
+ CPids, Transport, Socket,
+ #socket_options{active=Active, packet=Type} = SOpts,
+ Data, Pid, From, Tracker, Connection) ->
+ %%
+ send_or_reply(
+ Active, Pid, From,
+ format_reply(
+ CPids, 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};
+ 1 ->
+ send_user(
+ Pid,
+ format_passive(
+ CPids, Transport, Socket, Tracker, Connection)),
+ SO#socket_options{active=false};
+ N when is_integer(N) ->
+ SO#socket_options{active=N - 1};
_ ->
SO
end.
-format_reply(_, _,#socket_options{active = false, mode = Mode, packet = Packet,
+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,
+format_reply(CPids, Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet,
header = Header}, Data, Tracker, Connection) ->
- {ssl, Connection:socket(self(), Transport, Socket, Connection, Tracker),
+ {ssl, Connection:socket(CPids, Transport, Socket, 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)).
+deliver_packet_error(CPids, Transport, Socket,
+ SO= #socket_options{active = Active}, Data, Pid, From, Tracker, Connection) ->
+ send_or_reply(Active, Pid, From, format_packet_error(CPids,
+ Transport, Socket, SO, Data, Tracker, Connection)).
-format_packet_error(_, _,#socket_options{active = false, mode = Mode}, Data, _, _) ->
+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, Connection:socket(self(), Transport, Socket, Connection, Tracker),
+format_packet_error(CPids, Transport, Socket, #socket_options{active = _, mode = Mode},
+ Data, Tracker, Connection) ->
+ {ssl_error, Connection:socket(CPids, Transport, Socket, Tracker),
{invalid_packet, do_format_reply(Mode, raw, 0, Data)}}.
do_format_reply(binary, _, N, Data) when N > 0 -> % Header mode
@@ -2690,6 +2835,9 @@ do_format_reply(list, Packet, _, Data)
do_format_reply(list, _,_, Data) ->
binary_to_list(Data).
+format_passive(CPids, Transport, Socket, Tracker, Connection) ->
+ {ssl_passive, Connection:socket(CPids, Transport, Socket, Tracker)}.
+
header(0, <<>>) ->
<<>>;
header(_, <<>>) ->
@@ -2713,38 +2861,36 @@ send_user(Pid, Msg) ->
Pid ! Msg,
ok.
-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(Pids, Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, StateName, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, StateName, Connection);
+alert_user(Pids, Transport, Tracker, Socket,_, _, _, From, Alert, Role, StateName, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, StateName, Connection).
-alert_user(Transport, Tracker, Socket, From, Alert, Role, Connection) ->
- alert_user(Transport, Tracker, Socket, false, no_pid, From, Alert, Role, Connection).
+alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, StateName, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, false, no_pid, From, Alert, Role, StateName, Connection).
-alert_user(_, _, _, false = Active, Pid, From, Alert, Role, _) when From =/= undefined ->
+alert_user(_, _, _, _, false = Active, Pid, From, Alert, Role, StateName, Connection) 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),
+ ReasonCode = ssl_alert:reason_code(Alert, Role, Connection:protocol_name(), StateName),
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
+alert_user(Pids, Transport, Tracker, Socket, Active, Pid, From, Alert, Role, StateName, Connection) ->
+ case ssl_alert:reason_code(Alert, Role, Connection:protocol_name(), StateName) of
closed ->
send_or_reply(Active, Pid, From,
- {ssl_closed, Connection:socket(self(),
- Transport, Socket, Connection, Tracker)});
+ {ssl_closed, Connection:socket(Pids, Transport, Socket, Tracker)});
ReasonCode ->
send_or_reply(Active, Pid, From,
- {ssl_error, Connection:socket(self(),
- Transport, Socket, Connection, Tracker), ReasonCode})
+ {ssl_error, Connection:socket(Pids, Transport, Socket, Tracker), ReasonCode})
end.
log_alert(true, Role, ProtocolName, StateName, #alert{role = Role} = Alert) ->
Txt = ssl_alert:own_alert_txt(Alert),
- error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
+ error_logger:info_report(ssl_alert:alert_txt(ProtocolName, Role, StateName, Txt));
log_alert(true, Role, ProtocolName, StateName, Alert) ->
Txt = ssl_alert:alert_txt(Alert),
- error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
+ error_logger:info_report(ssl_alert:alert_txt(ProtocolName, Role, StateName, Txt));
log_alert(false, _, _, _, _) ->
ok.
@@ -2755,7 +2901,9 @@ invalidate_session(server, _, Port, Session) ->
handle_sni_extension(undefined, State) ->
State;
-handle_sni_extension(#sni{hostname = Hostname}, State0) ->
+handle_sni_extension(#sni{hostname = Hostname}, #state{static_env = #static_env{role = Role} = InitStatEnv0,
+ handshake_env = HsEnv,
+ connection_env = CEnv} = State0) ->
NewOptions = update_ssl_options_from_sni(State0#state.ssl_options, Hostname),
case NewOptions of
undefined ->
@@ -2769,19 +2917,21 @@ handle_sni_extension(#sni{hostname = Hostname}, State0) ->
private_key := Key,
dh_params := DHParams,
own_certificate := OwnCert}} =
- ssl_config:init(NewOptions, State0#state.role),
+ ssl_config:init(NewOptions, 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
- }
+ static_env = InitStatEnv0#static_env{
+ file_ref_db = FileRefHandle,
+ cert_db_ref = Ref,
+ cert_db = CertDbHandle,
+ crl_db = CRLDbHandle,
+ session_cache = CacheHandle
+ },
+ connection_env = CEnv#connection_env{private_key = Key},
+ ssl_options = NewOptions,
+ handshake_env = HsEnv#handshake_env{sni_hostname = Hostname,
+ diffie_hellman_params = DHParams}
+ }
end.
update_ssl_options_from_sni(OrigSSLOptions, SNIHostname) ->
@@ -2804,42 +2954,3 @@ new_emulated([], EmOpts) ->
EmOpts;
new_emulated(NewEmOpts, _) ->
NewEmOpts.
-%%---------------Erlang distribution --------------------------------------
-
-send_dist_data(StateName, State, DHandle, Acc) ->
- case erlang:dist_ctrl_get_data(DHandle) of
- none ->
- erlang:dist_ctrl_get_data_notification(DHandle),
- hibernate_after(StateName, State, lists:reverse(Acc));
- Data ->
- send_dist_data(
- StateName, State, DHandle,
- [{next_event, {call, {self(), undefined}}, {application_data, Data}}
- |Acc])
- end.
-
-%% Overload mitigation
-eat_msgs(Msg) ->
- receive Msg -> eat_msgs(Msg)
- after 0 -> ok
- end.
-
-%% When acting as distribution controller map the exit reason
-%% to follow the documented nodedown_reason for net_kernel
-stop(Reason, State) ->
- {stop, erl_dist_stop_reason(Reason, State), State}.
-
-stop_and_reply(Reason, Replies, State) ->
- {stop_and_reply, erl_dist_stop_reason(Reason, State), Replies, State}.
-
-erl_dist_stop_reason(
- Reason, #state{ssl_options = #ssl_options{erl_dist = true}}) ->
- case Reason of
- normal ->
- %% We can not exit with normal since that will not bring
- %% down the rest of the distribution processes
- {shutdown, normal};
- _ -> Reason
- end;
-erl_dist_stop_reason(Reason, _State) ->
- Reason.
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 811aa779d5..c90fe926b7 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,69 +33,91 @@
-include("ssl_cipher.hrl").
-include_lib("public_key/include/public_key.hrl").
+-record(static_env, {
+ role :: client | server,
+ transport_cb :: atom(), % callback module
+ protocol_cb :: tls_connection | dtls_connection,
+ data_tag :: atom(), % ex tcp.
+ close_tag :: atom(), % ex tcp_closed
+ error_tag :: atom(), % ex tcp_error
+ passive_tag :: atom(), % ex tcp_passive
+ host :: string() | inet:ip_address(),
+ port :: integer(),
+ socket :: port() | tuple(), %% TODO: dtls socket
+ cert_db :: reference() | 'undefined',
+ session_cache :: db_handle(),
+ session_cache_cb :: atom(),
+ crl_db :: term(),
+ file_ref_db :: db_handle(),
+ cert_db_ref :: certdb_ref() | 'undefined',
+ tracker :: pid() | 'undefined' %% Tracker process for listen socket
+ }).
+
+-record(handshake_env, {
+ client_hello_version :: ssl_record:ssl_version() | 'undefined',
+ unprocessed_handshake_events = 0 :: integer(),
+ tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
+ | 'undefined',
+ expecting_finished = false ::boolean(),
+ renegotiation :: undefined | {boolean(), From::term() | internal | peer},
+ allow_renegotiate = true ::boolean(),
+ %% Ext handling
+ hello, %%:: #client_hello{} | #server_hello{}
+ sni_hostname = undefined,
+ expecting_next_protocol_negotiation = false ::boolean(),
+ next_protocol = undefined :: undefined | binary(),
+ negotiated_protocol,
+ hashsign_algorithm = {undefined, undefined},
+ cert_hashsign_algorithm = {undefined, undefined},
+ %% key exchange
+ kex_algorithm :: ssl:kex_algo(),
+ kex_keys :: {PublicKey :: binary(), PrivateKey :: binary()} | #'ECPrivateKey'{} | undefined | secret_printout(),
+ diffie_hellman_params:: #'DHParameter'{} | undefined | secret_printout(),
+ srp_params :: #srp_user{} | secret_printout() | 'undefined',
+ public_key_info :: ssl_handshake:public_key_info() | 'undefined',
+ premaster_secret :: binary() | secret_printout() | 'undefined',
+ server_psk_identity :: binary() | 'undefined' % server psk identity hint
+ }).
+
+-record(connection_env, {
+ user_application :: {Monitor::reference(), User::pid()},
+ downgrade,
+ terminated = false ::boolean() | closed,
+ negotiated_version :: ssl_record:ssl_version() | 'undefined',
+ erl_dist_handle = undefined :: erlang:dist_handle() | 'undefined',
+ private_key :: public_key:private_key() | secret_printout() | 'undefined'
+ }).
+
-record(state, {
- role :: client | server,
- user_application :: {Monitor::reference(), User::pid()},
- transport_cb :: atom(), % callback module
- protocol_cb :: tls_connection | dtls_connection,
- data_tag :: atom(), % ex tcp.
- close_tag :: atom(), % ex tcp_closed
- error_tag :: atom(), % ex tcp_error
- host :: string() | inet:ip_address(),
- port :: integer(),
- socket :: port() | tuple(), %% TODO: dtls socket
- ssl_options :: #ssl_options{},
- socket_options :: #socket_options{},
- connection_states :: ssl_record:connection_states() | secret_printout(),
- protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl
- unprocessed_handshake_events = 0 :: integer(),
- tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
- | 'undefined',
- cert_db :: reference() | 'undefined',
- session :: #session{} | secret_printout(),
- session_cache :: db_handle(),
- session_cache_cb :: atom(),
- crl_db :: term(),
- negotiated_version :: ssl_record:ssl_version() | 'undefined',
- client_hello_version :: ssl_record:ssl_version() | 'undefined',
- client_certificate_requested = false :: boolean(),
- key_algorithm :: ssl_cipher:key_algo(),
- hashsign_algorithm = {undefined, undefined},
- cert_hashsign_algorithm = {undefined, undefined},
- public_key_info :: ssl_handshake:public_key_info() | 'undefined',
- private_key :: public_key:private_key() | secret_printout() | 'undefined',
- diffie_hellman_params:: #'DHParameter'{} | undefined | secret_printout(),
- diffie_hellman_keys :: {PublicKey :: binary(), PrivateKey :: binary()} | #'ECPrivateKey'{} | undefined | secret_printout(),
- psk_identity :: binary() | 'undefined', % server psk identity hint
- srp_params :: #srp_user{} | secret_printout() | 'undefined',
- srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout() | 'undefined',
- premaster_secret :: binary() | secret_printout() | 'undefined',
- file_ref_db :: db_handle(),
- cert_db_ref :: certdb_ref() | 'undefined',
- bytes_to_read :: undefined | integer(), %% bytes to read in passive mode
- user_data_buffer :: undefined | binary() | secret_printout(),
- renegotiation :: undefined | {boolean(), From::term() | internal | peer},
- start_or_recv_from :: term(),
- timer :: undefined | reference(), % start_or_recive_timer
- %%send_queue :: queue:queue(),
- hello, %%:: #client_hello{} | #server_hello{},
- terminated = false ::boolean(),
- allow_renegotiate = true ::boolean(),
- expecting_next_protocol_negotiation = false ::boolean(),
- expecting_finished = false ::boolean(),
- next_protocol = undefined :: undefined | binary(),
- negotiated_protocol,
- tracker :: pid() | 'undefined', %% Tracker process for listen socket
- sni_hostname = undefined,
- downgrade,
- flight_buffer = [] :: list() | map(), %% Buffer of TLS/DTLS records, used during the TLS handshake
- %% to when possible pack more than one TLS record into the
- %% underlaying packet format. Introduced by DTLS - RFC 4347.
- %% The mecahnism is also usefull in TLS although we do not
- %% need to worry about packet loss in TLS. In DTLS we need to track DTLS handshake seqnr
- flight_state = reliable, %% reliable | {retransmit, integer()}| {waiting, ref(), integer()} - last two is used in DTLS over udp.
- protocol_specific = #{} :: map()
- }).
+ static_env :: #static_env{},
+ connection_env :: #connection_env{} | secret_printout(),
+ ssl_options :: #ssl_options{},
+ socket_options :: #socket_options{},
+
+ %% Hanshake %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ handshake_env :: #handshake_env{} | secret_printout(),
+ %% Buffer of TLS/DTLS records, used during the TLS
+ %% handshake to when possible pack more than one TLS
+ %% record into the underlaying packet
+ %% format. Introduced by DTLS - RFC 4347. The
+ %% mecahnism is also usefull in TLS although we do not
+ %% need to worry about packet loss in TLS. In DTLS we
+ %% need to track DTLS handshake seqnr
+ flight_buffer = [] :: list() | map(),
+ client_certificate_requested = false :: boolean(),
+ protocol_specific = #{} :: map(),
+ session :: #session{} | secret_printout(),
+ %% Data shuffling %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ connection_states :: ssl_record:connection_states() | secret_printout(),
+ protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hr
+ user_data_buffer :: undefined | {[binary()],non_neg_integer(),[binary()]} | secret_printout(),
+ bytes_to_read :: undefined | integer(), %% bytes to read in passive mode
+
+ %% recv and start handling
+ start_or_recv_from :: term()
+ }).
+
+
-define(DEFAULT_DIFFIE_HELLMAN_PARAMS,
#'DHParameter'{prime = ?DEFAULT_DIFFIE_HELLMAN_PRIME,
base = ?DEFAULT_DIFFIE_HELLMAN_GENERATOR}).
diff --git a/lib/ssl/src/ssl_crl_cache.erl b/lib/ssl/src/ssl_crl_cache.erl
index 9c1af86eeb..841620ce57 100644
--- a/lib/ssl/src/ssl_crl_cache.erl
+++ b/lib/ssl/src/ssl_crl_cache.erl
@@ -28,6 +28,10 @@
-behaviour(ssl_crl_cache_api).
+-export_type([crl_src/0, uri/0]).
+-type crl_src() :: {file, file:filename()} | {der, public_key:der_encoded()}.
+-type uri() :: uri_string:uri_string().
+
-export([lookup/3, select/2, fresh_crl/2]).
-export([insert/1, insert/2, delete/1]).
diff --git a/lib/ssl/src/ssl_crl_cache_api.erl b/lib/ssl/src/ssl_crl_cache_api.erl
index d5380583e7..8a750b3929 100644
--- a/lib/ssl/src/ssl_crl_cache_api.erl
+++ b/lib/ssl/src/ssl_crl_cache_api.erl
@@ -21,12 +21,15 @@
%%
-module(ssl_crl_cache_api).
-
-include_lib("public_key/include/public_key.hrl").
--type db_handle() :: term().
--type issuer_name() :: {rdnSequence, [#'AttributeTypeAndValue'{}]}.
+-export_type([dist_point/0, crl_cache_ref/0]).
+
+-type crl_cache_ref() :: any().
+-type issuer_name() :: {rdnSequence,[#'AttributeTypeAndValue'{}]}.
+-type dist_point() :: #'DistributionPoint'{}.
--callback lookup(#'DistributionPoint'{}, issuer_name(), db_handle()) -> not_available | [public_key:der_encoded()].
--callback select(issuer_name(), db_handle()) -> [public_key:der_encoded()].
--callback fresh_crl(#'DistributionPoint'{}, public_key:der_encoded()) -> public_key:der_encoded().
+
+-callback lookup(dist_point(), issuer_name(), crl_cache_ref()) -> not_available | [public_key:der_encoded()].
+-callback select(issuer_name(), crl_cache_ref()) -> [public_key:der_encoded()].
+-callback fresh_crl(dist_point(), public_key:der_encoded()) -> public_key:der_encoded().
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 3028ae9617..9e7f6851c9 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -92,8 +92,8 @@ hello_request() ->
#hello_request{}.
%%--------------------------------------------------------------------
--spec server_hello(#session{}, ssl_record:ssl_version(), ssl_record:connection_states(),
- #hello_extensions{}) -> #server_hello{}.
+%%-spec server_hello(binary(), ssl_record:ssl_version(), ssl_record:connection_states(),
+%% Extension::map()) -> #server_hello{}.
%%
%% Description: Creates a server hello message.
%%--------------------------------------------------------------------
@@ -169,14 +169,14 @@ client_certificate_verify(OwnCert, MasterSecret, Version,
end.
%%--------------------------------------------------------------------
--spec certificate_request(ssl_cipher:cipher_suite(), db_handle(),
+-spec certificate_request(ssl_cipher_format:cipher_suite(), db_handle(),
certdb_ref(), #hash_sign_algos{}, ssl_record:ssl_version()) ->
#certificate_request{}.
%%
%% Description: Creates a certificate_request message, called by the server.
%%--------------------------------------------------------------------
certificate_request(CipherSuite, CertDbHandle, CertDbRef, HashSigns, Version) ->
- Types = certificate_types(ssl_cipher:suite_definition(CipherSuite), Version),
+ Types = certificate_types(ssl_cipher_format:suite_definition(CipherSuite), Version),
Authorities = certificate_authorities(CertDbHandle, CertDbRef),
#certificate_request{
certificate_types = Types,
@@ -338,7 +338,7 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
Opts, CRLDbHandle, Role, Host) ->
ServerName = server_name(Opts#ssl_options.server_name_indication, Host, Role),
- [PeerCert | _] = ASN1Certs,
+ [PeerCert | ChainCerts ] = ASN1Certs,
try
{TrustedCert, CertPath} =
ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef,
@@ -347,14 +347,14 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
CertDbHandle, CertDbRef, ServerName,
Opts#ssl_options.customize_hostname_check,
Opts#ssl_options.crl_check, CRLDbHandle, CertPath),
- case public_key:pkix_path_validation(TrustedCert,
- CertPath,
- [{max_path_length, Opts#ssl_options.depth},
- {verify_fun, ValidationFunAndState}]) of
+ Options = [{max_path_length, Opts#ssl_options.depth},
+ {verify_fun, ValidationFunAndState}],
+ case public_key:pkix_path_validation(TrustedCert, CertPath, Options) of
{ok, {PublicKeyInfo,_}} ->
{PeerCert, PublicKeyInfo};
{error, Reason} ->
- path_validation_alert(Reason)
+ handle_path_validation_error(Reason, PeerCert, ChainCerts, Opts, Options,
+ CertDbHandle, CertDbRef)
end
catch
error:{badmatch,{asn1, Asn1Reason}} ->
@@ -363,7 +363,6 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
error:OtherReason ->
?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {unexpected_error, OtherReason})
end.
-
%%--------------------------------------------------------------------
-spec certificate_verify(binary(), public_key_info(), ssl_record:ssl_version(), term(),
binary(), ssl_handshake_history()) -> valid | #alert{}.
@@ -611,7 +610,7 @@ encode_hello_extensions([#ec_point_formats{ec_point_format_list = ECPointFormats
?UINT16(Len), ?BYTE(ListLen), ECPointFormatList/binary, Acc/binary>>);
encode_hello_extensions([#srp{username = UserName} | Rest], Acc) ->
SRPLen = byte_size(UserName),
- Len = SRPLen + 2,
+ Len = SRPLen + 1,
encode_hello_extensions(Rest, <<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen),
UserName/binary, Acc/binary>>);
encode_hello_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Rest], Acc) ->
@@ -730,7 +729,7 @@ decode_hello_extensions(Extensions) ->
dec_hello_extensions(Extensions, #hello_extensions{}).
%%--------------------------------------------------------------------
--spec decode_server_key(binary(), ssl_cipher:key_algo(), ssl_record:ssl_version()) ->
+-spec decode_server_key(binary(), ssl:kex_algo(), ssl_record:ssl_version()) ->
#server_key_params{}.
%%
%% Description: Decode server_key data and return appropriate type
@@ -739,7 +738,7 @@ decode_server_key(ServerKey, Type, Version) ->
dec_server_key(ServerKey, key_exchange_alg(Type), Version).
%%--------------------------------------------------------------------
--spec decode_client_key(binary(), ssl_cipher:key_algo(), ssl_record:ssl_version()) ->
+-spec decode_client_key(binary(), ssl:kex_algo(), ssl_record:ssl_version()) ->
#encrypted_premaster_secret{}
| #client_diffie_hellman_public{}
| #client_ec_diffie_hellman_public{}
@@ -777,7 +776,7 @@ available_suites(ServerCert, UserSuites, Version, undefined, Curve) ->
filter_unavailable_ecc_suites(Curve, Suites);
available_suites(ServerCert, UserSuites, Version, HashSigns, Curve) ->
Suites = available_suites(ServerCert, UserSuites, Version, undefined, Curve),
- filter_hashsigns(Suites, [ssl_cipher:suite_definition(Suite) || Suite <- Suites], HashSigns,
+ filter_hashsigns(Suites, [ssl_cipher_format:suite_definition(Suite) || Suite <- Suites], HashSigns,
Version, []).
available_signature_algs(undefined, _) ->
@@ -859,22 +858,24 @@ premaster_secret(PublicDhKey, PrivateDhKey, #server_dh_params{dh_p = Prime, dh_g
end;
premaster_secret(#client_srp_public{srp_a = ClientPublicKey}, ServerKey, #srp_user{prime = Prime,
verifier = Verifier}) ->
- case crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']}) of
- error ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
+ try crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']}) of
PremasterSecret ->
PremasterSecret
+ catch
+ error:_ ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
premaster_secret(#server_srp_params{srp_n = Prime, srp_g = Generator, srp_s = Salt, srp_b = Public},
ClientKeys, {Username, Password}) ->
case ssl_srp_primes:check_srp_params(Generator, Prime) of
ok ->
DerivedKey = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, Password])]),
- case crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']}) of
- error ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
+ try crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']}) of
PremasterSecret ->
PremasterSecret
+ catch
+ error ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
_ ->
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
@@ -924,6 +925,13 @@ premaster_secret(EncSecret, #'RSAPrivateKey'{} = RSAPrivateKey) ->
catch
_:_ ->
throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
+ end;
+premaster_secret(EncSecret, #{algorithm := rsa} = Engine) ->
+ try crypto:private_decrypt(rsa, EncSecret, maps:remove(algorithm, Engine),
+ [{rsa_pad, rsa_pkcs1_padding}])
+ catch
+ _:_ ->
+ throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
end.
%%====================================================================
%% Extensions handling
@@ -932,7 +940,7 @@ client_hello_extensions(Version, CipherSuites,
#ssl_options{signature_algs = SupportedHashSigns,
eccs = SupportedECCs} = SslOpts, ConnectionStates, Renegotiation) ->
{EcPointFormats, EllipticCurves} =
- case advertises_ec_ciphers(lists:map(fun ssl_cipher:suite_definition/1, CipherSuites)) of
+ case advertises_ec_ciphers(lists:map(fun ssl_cipher_format:suite_definition/1, CipherSuites)) of
true ->
client_ecc_extensions(SupportedECCs);
false ->
@@ -964,34 +972,30 @@ handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites,
#session{cipher_suite = NegotiatedCipherSuite,
compression_method = Compression} = Session0,
ConnectionStates0, Renegotiation) ->
- Session = handle_srp_extension(SRP, Session0),
- ConnectionStates = handle_renegotiation_extension(server, RecordCB, Version, Info,
- Random, NegotiatedCipherSuite,
+ Session = handle_srp_extension(SRP, Session0),
+ ConnectionStates = handle_renegotiation_extension(server, RecordCB, Version, Info,
+ Random, NegotiatedCipherSuite,
ClientCipherSuites, Compression,
- ConnectionStates0, Renegotiation, SecureRenegotation),
-
- ServerHelloExtensions = #hello_extensions{
- renegotiation_info = renegotiation_info(RecordCB, server,
- ConnectionStates, Renegotiation),
- ec_point_formats = server_ecc_extension(Version, ECCFormat)
- },
-
+ ConnectionStates0, Renegotiation, SecureRenegotation),
+
+ ServerHelloExtensions = #hello_extensions{
+ renegotiation_info = renegotiation_info(RecordCB, server,
+ ConnectionStates, Renegotiation),
+ ec_point_formats = server_ecc_extension(Version, ECCFormat)
+ },
+
%% If we receive an ALPN extension and have ALPN configured for this connection,
%% we handle it. Otherwise we check for the NPN extension.
if
ALPN =/= undefined, ALPNPreferredProtocols =/= undefined ->
- case handle_alpn_extension(ALPNPreferredProtocols, decode_alpn(ALPN)) of
- #alert{} = Alert ->
- Alert;
- Protocol ->
- {Session, ConnectionStates, Protocol,
- ServerHelloExtensions#hello_extensions{alpn=encode_alpn([Protocol], Renegotiation)}}
- end;
+ Protocol = handle_alpn_extension(ALPNPreferredProtocols, decode_alpn(ALPN)),
+ {Session, ConnectionStates, Protocol,
+ ServerHelloExtensions#hello_extensions{alpn=encode_alpn([Protocol], Renegotiation)}};
true ->
- ProtocolsToAdvertise = handle_next_protocol_extension(NextProtocolNegotiation, Renegotiation, Opts),
+ ProtocolsToAdvertise = handle_next_protocol_extension(NextProtocolNegotiation, Renegotiation, Opts),
{Session, ConnectionStates, undefined,
- ServerHelloExtensions#hello_extensions{next_protocol_negotiation=
- encode_protocols_advertised_on_server(ProtocolsToAdvertise)}}
+ ServerHelloExtensions#hello_extensions{next_protocol_negotiation=
+ encode_protocols_advertised_on_server(ProtocolsToAdvertise)}}
end.
handle_server_hello_extensions(RecordCB, Random, CipherSuite, Compression,
@@ -1014,12 +1018,8 @@ handle_server_hello_extensions(RecordCB, Random, CipherSuite, Compression,
[Protocol] when not Renegotiation ->
{ConnectionStates, alpn, Protocol};
undefined ->
- case handle_next_protocol(NextProtocolNegotiation, NextProtoSelector, Renegotiation) of
- #alert{} = Alert ->
- Alert;
- Protocol ->
- {ConnectionStates, npn, Protocol}
- end;
+ Protocol = handle_next_protocol(NextProtocolNegotiation, NextProtoSelector, Renegotiation),
+ {ConnectionStates, npn, Protocol};
{error, Reason} ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, Reason);
[] ->
@@ -1055,7 +1055,10 @@ select_curve(undefined, _, _) ->
%%--------------------------------------------------------------------
select_hashsign(_, _, KeyExAlgo, _, _Version) when KeyExAlgo == dh_anon;
KeyExAlgo == ecdh_anon;
- KeyExAlgo == srp_anon ->
+ KeyExAlgo == srp_anon;
+ KeyExAlgo == psk;
+ KeyExAlgo == dhe_psk;
+ KeyExAlgo == ecdhe_psk ->
{null, anon};
%% The signature_algorithms extension was introduced with TLS 1.2. Ignore it if we have
%% negotiated a lower version.
@@ -1064,17 +1067,14 @@ select_hashsign(HashSigns, Cert, KeyExAlgo,
select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version);
select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns,
{Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
- #'OTPCertificate'{tbsCertificate = TBSCert,
- signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp),
+ #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
#'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
- Sign = sign_algo(SignAlgo),
SubSign = sign_algo(SubjAlgo),
case lists:filter(fun({_, S} = Algos) when S == SubSign ->
- is_acceptable_hash_sign(Algos, Sign,
- SubSign, KeyExAlgo, SupportedHashSigns);
+ is_acceptable_hash_sign(Algos, KeyExAlgo, SupportedHashSigns);
(_) ->
false
end, HashSigns) of
@@ -1310,6 +1310,45 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState, _CertPath)
{unknown, {SslState, UserState}}
end.
+handle_path_validation_error({bad_cert, unknown_ca} = Reason, PeerCert, Chain,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ handle_incomplete_chain(PeerCert, Chain, Opts, Options, CertDbHandle, CertsDbRef, Reason);
+handle_path_validation_error({bad_cert, invalid_issuer} = Reason, PeerCert, Chain0,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef, Chain0) of
+ {ok, _, [PeerCert | Chain] = OrdedChain} when Chain =/= Chain0 -> %% Chain appaears to be unorded
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(OrdedChain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ handle_path_validation_error(PathError, PeerCert, Path,
+ Opts, Options, CertDbHandle, CertsDbRef)
+ end;
+ _ ->
+ path_validation_alert(Reason)
+ end;
+handle_path_validation_error(Reason, _, _, _, _,_, _) ->
+ path_validation_alert(Reason).
+
+handle_incomplete_chain(PeerCert, Chain0, Opts, Options, CertDbHandle, CertsDbRef, PathError0) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef) of
+ {ok, _, [PeerCert | _] = Chain} when Chain =/= Chain0 -> %% Chain candidate found
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(Chain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ path_validation_alert(PathError)
+ end;
+ _ ->
+ path_validation_alert(PathError0)
+ end.
+
path_validation_alert({bad_cert, cert_expired}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_EXPIRED);
path_validation_alert({bad_cert, invalid_issuer}) ->
@@ -1322,8 +1361,6 @@ path_validation_alert({bad_cert, unknown_critical_extension}) ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
path_validation_alert({bad_cert, {revoked, _}}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED);
-%%path_validation_alert({bad_cert, revocation_status_undetermined}) ->
-%% ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
path_validation_alert({bad_cert, {revocation_status_undetermined, Details}}) ->
Alert = ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE),
Alert#alert{reason = Details};
@@ -1896,7 +1933,7 @@ dec_hello_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), Info:Len/binar
RenegotiateInfo}});
dec_hello_extensions(<<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen), SRP:SRPLen/binary, Rest/binary>>, Acc)
- when Len == SRPLen + 2 ->
+ when Len == SRPLen + 1 ->
dec_hello_extensions(Rest, Acc#hello_extensions{srp = #srp{username = SRP}});
dec_hello_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
@@ -1933,7 +1970,7 @@ dec_hello_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len),
ECPointFormats}});
dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len), Rest/binary>>, Acc) when Len == 0 ->
- dec_hello_extensions(Rest, Acc#hello_extensions{sni = ""}); %% Server may send an empy SNI
+ dec_hello_extensions(Rest, Acc#hello_extensions{sni = #sni{hostname = ""}}); %% Server may send an empy SNI
dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Acc) ->
@@ -2144,30 +2181,26 @@ filter_unavailable_ecc_suites(_, Suites) ->
handle_renegotiation_extension(Role, RecordCB, Version, Info, Random, NegotiatedCipherSuite,
ClientCipherSuites, Compression,
ConnectionStates0, Renegotiation, SecureRenegotation) ->
- case handle_renegotiation_info(RecordCB, Role, Info, ConnectionStates0,
- Renegotiation, SecureRenegotation,
- ClientCipherSuites) of
- {ok, ConnectionStates} ->
- hello_pending_connection_states(RecordCB, Role,
- Version,
- NegotiatedCipherSuite,
- Random,
- Compression,
- ConnectionStates);
- #alert{} = Alert ->
- throw(Alert)
- end.
+ {ok, ConnectionStates} = handle_renegotiation_info(RecordCB, Role, Info, ConnectionStates0,
+ Renegotiation, SecureRenegotation,
+ ClientCipherSuites),
+ hello_pending_connection_states(RecordCB, Role,
+ Version,
+ NegotiatedCipherSuite,
+ Random,
+ Compression,
+ ConnectionStates).
%% Receive protocols, choose one from the list, return it.
handle_alpn_extension(_, {error, Reason}) ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, Reason);
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, Reason));
handle_alpn_extension([], _) ->
- ?ALERT_REC(?FATAL, ?NO_APPLICATION_PROTOCOL);
+ throw(?ALERT_REC(?FATAL, ?NO_APPLICATION_PROTOCOL));
handle_alpn_extension([ServerProtocol|Tail], ClientProtocols) ->
- case lists:member(ServerProtocol, ClientProtocols) of
- true -> ServerProtocol;
- false -> handle_alpn_extension(Tail, ClientProtocols)
- end.
+ case lists:member(ServerProtocol, ClientProtocols) of
+ true -> ServerProtocol;
+ false -> handle_alpn_extension(Tail, ClientProtocols)
+ end.
handle_next_protocol(undefined,
_NextProtocolSelector, _Renegotiating) ->
@@ -2180,14 +2213,14 @@ handle_next_protocol(#next_protocol_negotiation{} = NextProtocols,
true ->
select_next_protocol(decode_next_protocols(NextProtocols), NextProtocolSelector);
false ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, unexpected_next_protocol_extension)
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, unexpected_next_protocol_extension))
end.
handle_next_protocol_extension(NextProtocolNegotiation, Renegotiation, SslOpts)->
case handle_next_protocol_on_server(NextProtocolNegotiation, Renegotiation, SslOpts) of
#alert{} = Alert ->
- Alert;
+ throw(Alert);
ProtocolsToAdvertise ->
ProtocolsToAdvertise
end.
@@ -2231,37 +2264,7 @@ sign_algo(Alg) ->
{_, Sign} =public_key:pkix_sign_types(Alg),
Sign.
-is_acceptable_hash_sign(Algos, _, _, KeyExAlgo, SupportedHashSigns) when
- KeyExAlgo == dh_dss;
- KeyExAlgo == dh_rsa;
- KeyExAlgo == ecdh_rsa;
- KeyExAlgo == ecdh_ecdsa
- ->
- %% *dh_* could be called only *dh in TLS-1.2
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign(Algos, rsa, ecdsa, ecdhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, dhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, ecdhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, srp_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, rsa_psk, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, dhe_dss, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, srp_dss, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, _, dhe_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdh_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdhe_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when
+is_acceptable_hash_sign( _, KeyExAlgo, _) when
KeyExAlgo == psk;
KeyExAlgo == dhe_psk;
KeyExAlgo == ecdhe_psk;
@@ -2270,8 +2273,9 @@ is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when
KeyExAlgo == ecdhe_anon
->
true;
-is_acceptable_hash_sign(_,_,_,_,_) ->
- false.
+is_acceptable_hash_sign(Algos,_, SupportedHashSigns) ->
+ is_acceptable_hash_sign(Algos, SupportedHashSigns).
+
is_acceptable_hash_sign(Algos, SupportedHashSigns) ->
lists:member(Algos, SupportedHashSigns).
@@ -2412,14 +2416,14 @@ handle_renegotiation_info(_RecordCB, client, #renegotiation_info{renegotiated_co
true ->
{ok, ConnectionStates};
false ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, client_renegotiation)
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, client_renegotiation))
end;
handle_renegotiation_info(_RecordCB, server, #renegotiation_info{renegotiated_connection = ClientVerify},
ConnectionStates, true, _, CipherSuites) ->
case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
true ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv});
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv}));
false ->
ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
Data = maps:get(client_verify_data, ConnectionState),
@@ -2427,7 +2431,7 @@ handle_renegotiation_info(_RecordCB, server, #renegotiation_info{renegotiated_co
true ->
{ok, ConnectionStates};
false ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, server_renegotiation)
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, server_renegotiation))
end
end;
@@ -2437,7 +2441,7 @@ handle_renegotiation_info(RecordCB, client, undefined, ConnectionStates, true, S
handle_renegotiation_info(RecordCB, server, undefined, ConnectionStates, true, SecureRenegotation, CipherSuites) ->
case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
true ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv});
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv}));
false ->
handle_renegotiation_info(RecordCB, ConnectionStates, SecureRenegotation)
end.
@@ -2446,9 +2450,9 @@ handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) ->
ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
case {SecureRenegotation, maps:get(secure_renegotiation, ConnectionState)} of
{_, true} ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, already_secure);
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, already_secure));
{true, false} ->
- ?ALERT_REC(?FATAL, ?NO_RENEGOTIATION);
+ throw(?ALERT_REC(?FATAL, ?NO_RENEGOTIATION));
{false, false} ->
{ok, ConnectionStates}
end.
@@ -2456,7 +2460,7 @@ handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) ->
cert_curve(_, _, no_suite) ->
{no_curve, no_suite};
cert_curve(Cert, ECCCurve0, CipherSuite) ->
- case ssl_cipher:suite_definition(CipherSuite) of
+ case ssl_cipher_format:suite_definition(CipherSuite) of
#{key_exchange := Kex} when Kex == ecdh_ecdsa;
Kex == ecdh_rsa ->
OtpCert = public_key:pkix_decode_cert(Cert, otp),
@@ -2464,13 +2468,7 @@ cert_curve(Cert, ECCCurve0, CipherSuite) ->
#'OTPSubjectPublicKeyInfo'{algorithm = AlgInfo}
= TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
{namedCurve, Oid} = AlgInfo#'PublicKeyAlgorithm'.parameters,
- try pubkey_cert_records:namedCurves(Oid) of
- Curve ->
- {{named_curve, Curve}, CipherSuite}
- catch
- _:_ ->
- {no_curve, no_suite}
- end;
+ {{namedCurve, Oid}, CipherSuite};
_ ->
{ECCCurve0, CipherSuite}
end.
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index ae1c3ea47c..ddd7a8eb7b 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -27,14 +27,12 @@
-define(SECRET_PRINTOUT, "***").
--type reason() :: term().
--type reply() :: term().
--type msg() :: term().
--type from() :: term().
--type host() :: inet:ip_address() | inet:hostname().
--type session_id() :: 0 | binary().
+-type reason() :: any().
+-type reply() :: any().
+-type msg() :: any().
+-type from() :: any().
-type certdb_ref() :: reference().
--type db_handle() :: term().
+-type db_handle() :: any().
-type der_cert() :: binary().
-type issuer() :: tuple().
-type serialnumber() :: integer().
@@ -60,6 +58,7 @@
-define(CDR_MAGIC, "GIOP").
-define(CDR_HDR_SIZE, 12).
+-define(INTERNAL_ACTIVE_N, 100).
-define(DEFAULT_TIMEOUT, 5000).
-define(NO_DIST_POINT, "http://dummy/no_distribution_point").
@@ -83,25 +82,26 @@
-define('24H_in_sec', 86400).
-record(ssl_options, {
- protocol :: tls | dtls,
- versions :: [ssl_record:ssl_version()], %% ssl_record:atom_version() in API
- verify :: verify_none | verify_peer,
+ protocol :: tls | dtls | 'undefined',
+ versions :: [ssl_record:ssl_version()] | 'undefined', %% ssl_record:atom_version() in API
+ verify :: verify_none | verify_peer | 'undefined',
verify_fun, %%:: fun(CertVerifyErrors::term()) -> boolean(),
- partial_chain :: fun(),
- fail_if_no_peer_cert :: boolean(),
- verify_client_once :: boolean(),
+ partial_chain :: fun() | 'undefined',
+ fail_if_no_peer_cert :: boolean() | 'undefined',
+ verify_client_once :: boolean() | 'undefined',
%% fun(Extensions, State, Verify, AccError) -> {Extensions, State, AccError}
validate_extensions_fun,
- depth :: integer(),
- certfile :: binary(),
+ depth :: integer() | 'undefined',
+ certfile :: binary() | 'undefined',
cert :: public_key:der_encoded() | secret_printout() | 'undefined',
- keyfile :: binary(),
- key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo',
- public_key:der_encoded()} | key_map() | secret_printout() | 'undefined',
+ keyfile :: binary() | 'undefined',
+ key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo' | 'undefined',
+ public_key:der_encoded()} | map() %%map() -> ssl:key() how to handle dialyzer?
+ | secret_printout() | 'undefined',
password :: string() | secret_printout() | 'undefined',
cacerts :: [public_key:der_encoded()] | secret_printout() | 'undefined',
- cacertfile :: binary(),
- dh :: public_key:der_encoded() | secret_printout(),
+ cacertfile :: binary() | 'undefined',
+ dh :: public_key:der_encoded() | secret_printout() | 'undefined',
dhfile :: binary() | secret_printout() | 'undefined',
user_lookup_fun, % server option, fun to lookup the user
psk_identity :: binary() | secret_printout() | 'undefined',
@@ -110,26 +110,26 @@
%% Local policy for the server if it want's to reuse the session
%% or not. Defaluts to allways returning true.
%% fun(SessionId, PeerCert, Compression, CipherSuite) -> boolean()
- reuse_session,
+ reuse_session :: fun() | binary() | undefined, %% Server side is a fun()
%% If false sessions will never be reused, if true they
%% will be reused if possible.
- reuse_sessions :: boolean(),
+ reuse_sessions :: boolean() | save | 'undefined', %% Only client side can use value save
renegotiate_at,
secure_renegotiate,
client_renegotiation,
%% undefined if not hibernating, or number of ms of
%% inactivity after which ssl_connection will go into
%% hibernation
- hibernate_after :: timeout(),
+ hibernate_after :: timeout() | 'undefined',
%% This option should only be set to true by inet_tls_dist
erl_dist = false :: boolean(),
- alpn_advertised_protocols = undefined :: [binary()] | undefined ,
+ alpn_advertised_protocols = undefined :: [binary()] | undefined,
alpn_preferred_protocols = undefined :: [binary()] | undefined,
next_protocols_advertised = undefined :: [binary()] | undefined,
next_protocol_selector = undefined, %% fun([binary()]) -> binary())
log_alert :: boolean(),
server_name_indication = undefined,
- sni_hosts :: [{inet:hostname(), [tuple()]}],
+ sni_hosts :: [{inet:hostname(), [tuple()]}] | 'undefined',
sni_fun :: function() | undefined,
%% Should the server prefer its own cipher order over the one provided by
%% the client?
@@ -139,7 +139,7 @@
%%mitigation entirely?
beast_mitigation = one_n_minus_one :: one_n_minus_one | zero_n | disabled,
fallback = false :: boolean(),
- crl_check :: boolean() | peer | best_effort,
+ crl_check :: boolean() | peer | best_effort | 'undefined',
crl_cache,
signature_algs,
eccs,
@@ -147,6 +147,8 @@
max_handshake_size :: integer(),
handshake,
customize_hostname_check
+ %% ,
+ %% save_session :: boolean()
}).
-record(socket_options,
@@ -177,9 +179,12 @@
password => crypto:password()
}.
-type state_name() :: hello | abbreviated | certify | cipher | connection.
--type gen_fsm_state_return() :: {next_state, state_name(), term()} |
- {next_state, state_name(), term(), timeout()} |
- {stop, term(), term()}.
+
+-type gen_fsm_state_return() :: {next_state, state_name(), any()} |
+ {next_state, state_name(), any(), timeout()} |
+ {stop, any(), any()}.
+-type ssl_options() :: #ssl_options{}.
+
-endif. % -ifdef(ssl_internal).
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index f44fe6a2bf..c56675b691 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
connection_init/3, cache_pem_file/2,
lookup_trusted_cert/4,
new_session_id/1, clean_cert_db/2,
- register_session/2, register_session/3, invalidate_session/2,
+ register_session/2, register_session/4, invalidate_session/2,
insert_crls/2, insert_crls/3, delete_crls/1, delete_crls/2,
invalidate_session/3, name/1]).
@@ -42,6 +42,8 @@
-include("ssl_handshake.hrl").
-include("ssl_internal.hrl").
+-include("ssl_api.hrl").
+
-include_lib("kernel/include/file.hrl").
-record(state, {
@@ -127,7 +129,13 @@ cache_pem_file(File, DbHandle) ->
[Content] ->
{ok, Content};
undefined ->
- ssl_pem_cache:insert(File)
+ case ssl_pkix_db:decode_pem_file(File) of
+ {ok, Content} ->
+ ssl_pem_cache:insert(File, Content),
+ {ok, Content};
+ Error ->
+ Error
+ end
end.
%%--------------------------------------------------------------------
@@ -142,7 +150,7 @@ lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
ssl_pkix_db:lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer).
%%--------------------------------------------------------------------
--spec new_session_id(integer()) -> session_id().
+-spec new_session_id(integer()) -> ssl:session_id().
%%
%% Description: Creates a session id for the server.
%%--------------------------------------------------------------------
@@ -164,9 +172,11 @@ clean_cert_db(Ref, File) ->
%%
%% Description: Make the session available for reuse.
%%--------------------------------------------------------------------
--spec register_session(host(), inet:port_number(), #session{}) -> ok.
-register_session(Host, Port, Session) ->
- cast({register_session, Host, Port, Session}).
+-spec register_session(ssl:host(), inet:port_number(), #session{}, unique | true) -> ok.
+register_session(Host, Port, Session, true) ->
+ call({register_session, Host, Port, Session});
+register_session(Host, Port, Session, unique = Save) ->
+ cast({register_session, Host, Port, Session, Save}).
-spec register_session(inet:port_number(), #session{}) -> ok.
register_session(Port, Session) ->
@@ -177,7 +187,7 @@ register_session(Port, Session) ->
%% a the session has been marked "is_resumable = false" for some while
%% it will be safe to remove the data from the session database.
%%--------------------------------------------------------------------
--spec invalidate_session(host(), inet:port_number(), #session{}) -> ok.
+-spec invalidate_session(ssl:host(), inet:port_number(), #session{}) -> ok.
invalidate_session(Host, Port, Session) ->
load_mitigation(),
cast({invalidate_session, Host, Port, Session}).
@@ -295,7 +305,10 @@ handle_call({{new_session_id, Port}, _},
_, #state{session_cache_cb = CacheCb,
session_cache_server = Cache} = State) ->
Id = new_id(Port, ?GEN_UNIQUE_ID_MAX_TRIES, Cache, CacheCb),
- {reply, Id, State}.
+ {reply, Id, State};
+handle_call({{register_session, Host, Port, Session},_}, _, State0) ->
+ State = client_register_session(Host, Port, Session, State0),
+ {reply, ok, State}.
%%--------------------------------------------------------------------
-spec handle_cast(msg(), #state{}) -> {noreply, #state{}}.
@@ -305,8 +318,12 @@ handle_call({{new_session_id, Port}, _},
%%
%% Description: Handling cast messages
%%--------------------------------------------------------------------
-handle_cast({register_session, Host, Port, Session}, State0) ->
- State = ssl_client_register_session(Host, Port, Session, State0),
+handle_cast({register_session, Host, Port, Session, unique}, State0) ->
+ State = client_register_unique_session(Host, Port, Session, State0),
+ {noreply, State};
+
+handle_cast({register_session, Host, Port, Session, true}, State0) ->
+ State = client_register_session(Host, Port, Session, State0),
{noreply, State};
handle_cast({register_session, Port, Session}, State0) ->
@@ -534,10 +551,10 @@ clean_cert_db(Ref, CertDb, RefDb, FileMapDb, File) ->
ok
end.
-ssl_client_register_session(Host, Port, Session, #state{session_cache_client = Cache,
- session_cache_cb = CacheCb,
- session_cache_client_max = Max,
- session_client_invalidator = Pid0} = State) ->
+client_register_unique_session(Host, Port, Session, #state{session_cache_client = Cache,
+ session_cache_cb = CacheCb,
+ session_cache_client_max = Max,
+ session_client_invalidator = Pid0} = State) ->
TimeStamp = erlang:monotonic_time(),
NewSession = Session#session{time_stamp = TimeStamp},
@@ -551,6 +568,17 @@ ssl_client_register_session(Host, Port, Session, #state{session_cache_client = C
register_unique_session(Sessions, NewSession, {Host, Port}, State)
end.
+client_register_session(Host, Port, Session, #state{session_cache_client = Cache,
+ session_cache_cb = CacheCb,
+ session_cache_client_max = Max,
+ session_client_invalidator = Pid0} = State) ->
+ TimeStamp = erlang:monotonic_time(),
+ NewSession = Session#session{time_stamp = TimeStamp},
+ Pid = do_register_session({{Host, Port},
+ NewSession#session.session_id},
+ NewSession, Max, Pid0, Cache, CacheCb),
+ State#state{session_client_invalidator = Pid}.
+
server_register_session(Port, Session, #state{session_cache_server_max = Max,
session_cache_server = Cache,
session_cache_cb = CacheCb,
diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl
index 115ab4451d..41bca2f7b5 100644
--- a/lib/ssl/src/ssl_pem_cache.erl
+++ b/lib/ssl/src/ssl_pem_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 20016-2017. All Rights Reserved.
+%% Copyright Ericsson AB 20016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
-export([start_link/1,
start_link_dist/1,
name/1,
- insert/1,
+ insert/2,
clear/0]).
% Spawn export
@@ -45,7 +45,7 @@
-record(state, {
pem_cache,
- last_pem_check :: erlang:timestamp(),
+ last_pem_check :: integer(),
clear :: integer()
}).
@@ -90,19 +90,17 @@ start_link_dist(_) ->
%%--------------------------------------------------------------------
--spec insert(binary()) -> {ok, term()} | {error, reason()}.
+-spec insert(binary(), term()) -> ok | {error, reason()}.
%%
%% Description: Cache a pem file and return its content.
%%--------------------------------------------------------------------
-insert(File) ->
- {ok, PemBin} = file:read_file(File),
- Content = public_key:pem_decode(PemBin),
+insert(File, Content) ->
case bypass_cache() of
true ->
- {ok, Content};
+ ok;
false ->
cast({cache_pem, File, Content}),
- {ok, Content}
+ ok
end.
%%--------------------------------------------------------------------
@@ -136,8 +134,9 @@ init([Name]) ->
PemCache = ssl_pkix_db:create_pem_cache(Name),
Interval = pem_check_interval(),
erlang:send_after(Interval, self(), clear_pem_cache),
+ erlang:system_time(second),
{ok, #state{pem_cache = PemCache,
- last_pem_check = os:timestamp(),
+ last_pem_check = erlang:convert_time_unit(os:system_time(), native, second),
clear = Interval
}}.
@@ -185,7 +184,7 @@ handle_cast({invalidate_pem, File}, #state{pem_cache = Db} = State) ->
handle_info(clear_pem_cache, #state{pem_cache = PemCache,
clear = Interval,
last_pem_check = CheckPoint} = State) ->
- NewCheckPoint = os:timestamp(),
+ NewCheckPoint = erlang:convert_time_unit(os:system_time(), native, second),
start_pem_cache_validator(PemCache, CheckPoint),
erlang:send_after(Interval, self(), clear_pem_cache),
{noreply, State#state{last_pem_check = NewCheckPoint}};
@@ -231,24 +230,14 @@ init_pem_cache_validator([CacheName, PemCache, CheckPoint]) ->
CheckPoint, PemCache).
pem_cache_validate({File, _}, CheckPoint) ->
- case file:read_file_info(File, []) of
- {ok, #file_info{mtime = Time}} ->
- case is_before_checkpoint(Time, CheckPoint) of
- true ->
- ok;
- false ->
- invalidate_pem(File)
- end;
+ case file:read_file_info(File, [{time, posix}]) of
+ {ok, #file_info{mtime = Time}} when Time < CheckPoint ->
+ ok;
_ ->
invalidate_pem(File)
end,
CheckPoint.
-is_before_checkpoint(Time, CheckPoint) ->
- calendar:datetime_to_gregorian_seconds(
- calendar:now_to_datetime(CheckPoint)) -
- calendar:datetime_to_gregorian_seconds(Time) > 0.
-
pem_check_interval() ->
case application:get_env(ssl, ssl_pem_cache_clean) of
{ok, Interval} when is_integer(Interval) ->
diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl
index 8828c3a0d8..f7ddbd060e 100644
--- a/lib/ssl/src/ssl_pkix_db.erl
+++ b/lib/ssl/src/ssl_pkix_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -157,7 +157,7 @@ extract_trusted_certs(File) ->
{error, {badmatch, Error}}
end.
--spec decode_pem_file(binary()) -> {ok, term()}.
+-spec decode_pem_file(binary()) -> {ok, term()} | {error, term()}.
decode_pem_file(File) ->
case file:read_file(File) of
{ok, PemBin} ->
@@ -316,11 +316,16 @@ decode_certs(Ref, Cert) ->
end.
new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) ->
- Ref = make_ref(),
- init_ref_db(Ref, File, RefsDb),
- {ok, Content} = ssl_pem_cache:insert(File),
- add_certs_from_pem(Content, Ref, CertsDb),
- {ok, Ref}.
+ case decode_pem_file(File) of
+ {ok, Content} ->
+ Ref = make_ref(),
+ init_ref_db(Ref, File, RefsDb),
+ ok = ssl_pem_cache:insert(File, Content),
+ add_certs_from_pem(Content, Ref, CertsDb),
+ {ok, Ref};
+ Error ->
+ Error
+ end.
add_crls([_,_,_, {_, Mapping} | _], ?NO_DIST_POINT, CRLs) ->
[add_crls(CRL, Mapping) || CRL <- CRLs];
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 659e1485ac..1a36b2dba8 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,14 +45,16 @@
-export([compress/3, uncompress/3, compressions/0]).
%% Payload encryption/decryption
--export([cipher/4, decipher/4, cipher_aead/4, is_correct_mac/2]).
+-export([cipher/4, cipher/5, decipher/4,
+ cipher_aead/4, cipher_aead/5, decipher_aead/5,
+ is_correct_mac/2, nonce_seed/3]).
-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
+-type connection_states() :: map(). %% Map
+-type connection_state() :: map(). %% Map
%%====================================================================
%% Connection state handling
@@ -302,29 +304,49 @@ cipher(Version, Fragment,
#security_parameters{bulk_cipher_algorithm =
BulkCipherAlgo}
} = WriteState0, MacHash) ->
-
+ %%
{CipherFragment, CipherS1} =
ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MacHash, Fragment, Version),
{CipherFragment, WriteState0#{cipher_state => CipherS1}}.
+
+%%--------------------------------------------------------------------
+-spec cipher(ssl_version(), iodata(), #cipher_state{}, MacHash::binary(), #security_parameters{}) ->
+ {CipherFragment::binary(), #cipher_state{}}.
+%%
+%% Description: Payload encryption
+%%--------------------------------------------------------------------
+cipher(Version, Fragment, CipherS0, MacHash,
+ #security_parameters{bulk_cipher_algorithm = BulkCipherAlgo}) ->
+ %%
+ ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MacHash, Fragment, Version).
+
+%%--------------------------------------------------------------------
+-spec cipher_aead(ssl_version(), iodata(), connection_state(), AAD::binary()) ->
+ {CipherFragment::binary(), connection_state()}.
+
+%% Description: Payload encryption
%% %%--------------------------------------------------------------------
-%% -spec cipher_aead(ssl_version(), iodata(), connection_state(), MacHash::binary()) ->
-%% {CipherFragment::binary(), connection_state()}.
-%% %%
-%% %% Description: Payload encryption
-%% %%--------------------------------------------------------------------
-cipher_aead(Version, Fragment,
+cipher_aead(_Version, Fragment,
#{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),
+ do_cipher_aead(BulkCipherAlgo, Fragment, CipherS0, AAD),
{CipherFragment, WriteState0#{cipher_state => CipherS1}}.
%%--------------------------------------------------------------------
+-spec cipher_aead(ssl_version(), iodata(), #cipher_state{}, AAD::binary(), #security_parameters{}) ->
+ {CipherFragment::binary(), #cipher_state{}}.
+
+%% Description: Payload encryption
+%% %%--------------------------------------------------------------------
+cipher_aead(_Version, Fragment, CipherS, AAD,
+ #security_parameters{bulk_cipher_algorithm = BulkCipherAlgo}) ->
+ do_cipher_aead(BulkCipherAlgo, Fragment, CipherS, AAD).
+
+%%--------------------------------------------------------------------
-spec decipher(ssl_version(), binary(), connection_state(), boolean()) ->
{binary(), binary(), connection_state()} | #alert{}.
%%
@@ -344,10 +366,38 @@ decipher(Version, CipherFragment,
#alert{} = Alert ->
Alert
end.
+%%--------------------------------------------------------------------
+-spec decipher_aead(ssl_cipher:cipher_enum(), #cipher_state{}, binary(), binary(), ssl_record:ssl_version()) ->
+ binary() | #alert{}.
+%%
+%% Description: Decrypts the data and checks the associated data (AAD) MAC using
+%% cipher described by cipher_enum() and updating the cipher state.
+%% Use for suites that use authenticated encryption with associated data (AEAD)
+%%-------------------------------------------------------------------
+decipher_aead(Type, #cipher_state{key = Key} = CipherState, AAD0, CipherFragment, _) ->
+ try
+ Nonce = decrypt_nonce(Type, CipherState, CipherFragment),
+ {AAD, CipherText, CipherTag} = aead_ciphertext_split(Type, CipherState, CipherFragment, AAD0),
+ case ssl_cipher:aead_decrypt(Type, Key, Nonce, CipherText, CipherTag, AAD) of
+ Content when is_binary(Content) ->
+ Content;
+ _ ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
+ end
+ catch
+ _:_ ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
+ end.
+
+nonce_seed(?CHACHA20_POLY1305, Seed, CipherState) ->
+ ssl_cipher:nonce_seed(Seed, CipherState);
+nonce_seed(_,_, CipherState) ->
+ CipherState.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+
empty_connection_state(ConnectionEnd, BeastMitigation) ->
SecParams = empty_security_params(ConnectionEnd),
#{security_parameters => SecParams,
@@ -372,11 +422,13 @@ random() ->
Random_28_bytes = ssl_cipher:random_bytes(28),
<<?UINT32(Secs_since_1970), Random_28_bytes/binary>>.
+-compile({inline, [is_correct_mac/2]}).
is_correct_mac(Mac, Mac) ->
true;
is_correct_mac(_M,_H) ->
false.
+-compile({inline, [record_protocol_role/1]}).
record_protocol_role(client) ->
?CLIENT;
record_protocol_role(server) ->
@@ -400,3 +452,36 @@ initial_security_params(ConnectionEnd) ->
compression_algorithm = ?NULL},
ssl_cipher:security_parameters(?TLS_NULL_WITH_NULL_NULL, SecParams).
+-define(end_additional_data(AAD, Len), << (begin(AAD)end)/binary, ?UINT16(begin(Len)end) >>).
+
+do_cipher_aead(?CHACHA20_POLY1305 = Type, Fragment, #cipher_state{key=Key} = CipherState, AAD0) ->
+ AAD = ?end_additional_data(AAD0, erlang:iolist_size(Fragment)),
+ Nonce = encrypt_nonce(Type, CipherState),
+ {Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD),
+ {<<Content/binary, CipherTag/binary>>, CipherState};
+do_cipher_aead(Type, Fragment, #cipher_state{key=Key, nonce = ExplicitNonce} = CipherState, AAD0) ->
+ AAD = ?end_additional_data(AAD0, erlang:iolist_size(Fragment)),
+ Nonce = encrypt_nonce(Type, CipherState),
+ {Content, CipherTag} = ssl_cipher:aead_encrypt(Type, Key, Nonce, Fragment, AAD),
+ {<<ExplicitNonce:64/integer, Content/binary, CipherTag/binary>>, CipherState#cipher_state{nonce = ExplicitNonce + 1}}.
+
+encrypt_nonce(?CHACHA20_POLY1305, #cipher_state{nonce = Nonce, iv = IV}) ->
+ crypto:exor(<<?UINT32(0), Nonce/binary>>, IV);
+encrypt_nonce(?AES_GCM, #cipher_state{iv = IV, nonce = ExplicitNonce}) ->
+ <<Salt:4/bytes, _/binary>> = IV,
+ <<Salt/binary, ExplicitNonce:64/integer>>.
+
+decrypt_nonce(?CHACHA20_POLY1305, #cipher_state{nonce = Nonce, iv = IV}, _) ->
+ crypto:exor(<<Nonce:96/unsigned-big-integer>>, IV);
+decrypt_nonce(?AES_GCM, #cipher_state{iv = <<Salt:4/bytes, _/binary>>}, <<ExplicitNonce:8/bytes, _/binary>>) ->
+ <<Salt/binary, ExplicitNonce/binary>>.
+
+-compile({inline, [aead_ciphertext_split/4]}).
+aead_ciphertext_split(?CHACHA20_POLY1305, #cipher_state{tag_len = Len}, CipherTextFragment, AAD) ->
+ CipherLen = byte_size(CipherTextFragment) - Len,
+ <<CipherText:CipherLen/bytes, CipherTag:Len/bytes>> = CipherTextFragment,
+ {?end_additional_data(AAD, CipherLen), CipherText, CipherTag};
+aead_ciphertext_split(?AES_GCM, #cipher_state{tag_len = Len}, CipherTextFragment, AAD) ->
+ CipherLen = byte_size(CipherTextFragment) - (Len + 8), %% 8 is length of explicit Nonce
+ << _:8/bytes, CipherText:CipherLen/bytes, CipherTag:Len/bytes>> = CipherTextFragment,
+ {?end_additional_data(AAD, CipherLen), CipherText, CipherTag}.
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index ed007f58d7..a927fba0de 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -140,6 +140,8 @@
-define(ALERT, 21).
-define(HANDSHAKE, 22).
-define(APPLICATION_DATA, 23).
+-define(KNOWN_RECORD_TYPE(Type),
+ (is_integer(Type) andalso (20 =< (Type)) andalso ((Type) =< 23))).
-define(MAX_PLAIN_TEXT_LENGTH, 16384).
-define(MAX_COMPRESSED_LENGTH, (?MAX_PLAIN_TEXT_LENGTH+1024)).
-define(MAX_CIPHER_TEXT_LENGTH, (?MAX_PLAIN_TEXT_LENGTH+2048)).
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index c9607489e9..44305c65fe 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -27,6 +27,7 @@
-include("ssl_handshake.hrl").
-include("ssl_internal.hrl").
+-include("ssl_api.hrl").
%% Internal application API
-export([is_new/2, client_id/4, server_id/6, valid_session/2]).
@@ -34,7 +35,7 @@
-type seconds() :: integer().
%%--------------------------------------------------------------------
--spec is_new(session_id(), session_id()) -> boolean().
+-spec is_new(ssl:session_id(), ssl:session_id()) -> boolean().
%%
%% Description: Checks if the session id decided by the server is a
%% new or resumed sesion id.
@@ -47,12 +48,19 @@ is_new(_ClientSuggestion, _ServerDecision) ->
true.
%%--------------------------------------------------------------------
--spec client_id({host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(),
+-spec client_id({ssl:host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(),
undefined | binary()) -> binary().
%%
%% Description: Should be called by the client side to get an id
%% for the client hello message.
%%--------------------------------------------------------------------
+client_id({Host, Port, #ssl_options{reuse_session = SessionId}}, Cache, CacheCb, _) when is_binary(SessionId)->
+ case CacheCb:lookup(Cache, {{Host, Port}, SessionId}) of
+ undefined ->
+ <<>>;
+ #session{} ->
+ SessionId
+ end;
client_id(ClientInfo, Cache, CacheCb, OwnCert) ->
case select_session(ClientInfo, Cache, CacheCb, OwnCert) of
no_session ->
@@ -91,7 +99,8 @@ server_id(Port, SuggestedId, Options, Cert, Cache, CacheCb) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-select_session({_, _, #ssl_options{reuse_sessions=false}}, _Cache, _CacheCb, _OwnCert) ->
+select_session({_, _, #ssl_options{reuse_sessions = Reuse}}, _Cache, _CacheCb, _OwnCert) when Reuse =/= true ->
+ %% If reuse_sessions == true | save a new session should be created
no_session;
select_session({HostIP, Port, SslOpts}, Cache, CacheCb, OwnCert) ->
Sessions = CacheCb:select_session(Cache, {HostIP, Port}),
@@ -132,7 +141,7 @@ is_resumable(SuggestedSessionId, Port, #ssl_options{reuse_session = ReuseFun} =
false -> {false, undefined}
end;
undefined ->
- {false, undefined}
+ {false, undefined}
end.
resumable(new) ->
diff --git a/lib/ssl/src/ssl_session_cache_api.erl b/lib/ssl/src/ssl_session_cache_api.erl
index b68c75a09b..5f96f905b1 100644
--- a/lib/ssl/src/ssl_session_cache_api.erl
+++ b/lib/ssl/src/ssl_session_cache_api.erl
@@ -23,14 +23,20 @@
-module(ssl_session_cache_api).
-include("ssl_handshake.hrl").
-include("ssl_internal.hrl").
+-include("ssl_api.hrl").
--type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}.
+-export_type([session_cache_key/0, session/0, partial_key/0, session_cache_ref/0]).
--callback init(list()) -> db_handle().
--callback terminate(db_handle()) -> any().
--callback lookup(db_handle(), key()) -> #session{} | undefined.
--callback update(db_handle(), key(), #session{}) -> any().
--callback delete(db_handle(), key()) -> any().
--callback foldl(fun(), term(), db_handle()) -> term().
--callback select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}].
--callback size(db_handle()) -> integer().
+-type session_cache_ref() :: any().
+-type session_cache_key() :: {partial_key(), ssl:session_id()}.
+-opaque session() :: #session{}.
+-opaque partial_key() :: {ssl:host(), inet:port_number()} | inet:port_number().
+
+-callback init(list()) -> session_cache_ref().
+-callback terminate(session_cache_ref()) -> any().
+-callback lookup(session_cache_ref(), session_cache_key()) -> #session{} | undefined.
+-callback update(session_cache_ref(), session_cache_key(), #session{}) -> any().
+-callback delete(session_cache_ref(), session_cache_key()) -> any().
+-callback foldl(fun(), term(), session_cache_ref()) -> term().
+-callback select_session(session_cache_ref(), {ssl:host(), inet:port_number()} | inet:port_number()) -> [#session{}].
+-callback size(session_cache_ref()) -> integer().
diff --git a/lib/ssl/src/ssl_v3.erl b/lib/ssl/src/ssl_v3.erl
index 82d165f995..4eab60b440 100644
--- a/lib/ssl/src/ssl_v3.erl
+++ b/lib/ssl/src/ssl_v3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -131,7 +131,7 @@ setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
{ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
ServerWriteKey, ClientIV, ServerIV}.
--spec suites() -> [ssl_cipher:cipher_suite()].
+-spec suites() -> [ssl_cipher_format:cipher_suite()].
suites() ->
[
diff --git a/lib/ssl/src/tls.erl b/lib/ssl/src/tls.erl
deleted file mode 100644
index aa41cd1ba6..0000000000
--- a/lib/ssl/src/tls.erl
+++ /dev/null
@@ -1,112 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : Reflect TLS specific API options (fairly simple wrapper at the moment)
-
--module(tls).
-
--include("ssl_api.hrl").
--include("ssl_internal.hrl").
-
--export([connect/2, connect/3, listen/2, accept/1, accept/2,
- handshake/1, handshake/2, handshake/3]).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Connect to an TLS server.
-%%--------------------------------------------------------------------
-
--spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
- {error, reason()}.
-
-connect(Socket, Options) when is_port(Socket) ->
- connect(Socket, Options, infinity).
-
--spec connect(host() | port(), [connect_option()] | inet:port_number(),
- timeout() | list()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Socket, SslOptions, Timeout) when is_port(Socket) ->
- TLSOpts = [{protocol, tls} | SslOptions],
- ssl:connect(Socket, TLSOpts, Timeout);
-connect(Host, Port, Options) ->
- connect(Host, Port, Options, infinity).
-
--spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Host, Port, Options, Timeout) ->
- TLSOpts = [{protocol, tls} | Options],
- ssl:connect(Host, Port, TLSOpts, Timeout).
-
-%%--------------------------------------------------------------------
--spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
-
-%%
-%% Description: Creates an ssl listen socket.
-%%--------------------------------------------------------------------
-listen(Port, Options) ->
- TLSOpts = [{protocol, tls} | Options],
- ssl:listen(Port, TLSOpts).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs transport accept on an ssl listen socket
-%%--------------------------------------------------------------------
--spec accept(#sslsocket{}) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(ListenSocket) ->
- accept(ListenSocket, infinity).
-
--spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(Socket, Timeout) ->
- ssl:transport_accept(Socket, Timeout).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs accept on an ssl listen socket. e.i. performs
-%% ssl handshake.
-%%--------------------------------------------------------------------
-
--spec handshake(#sslsocket{}) -> ok | {error, reason()}.
-
-handshake(ListenSocket) ->
- handshake(ListenSocket, infinity).
-
-
--spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(#sslsocket{} = Socket, Timeout) ->
- ssl:ssl_accept(Socket, Timeout);
-
-handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- handshake(ListenSocket, SslOptions, infinity).
-
-
--spec handshake(port(), [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(Socket, SslOptions, Timeout) when is_port(Socket) ->
- ssl:ssl_accept(Socket, SslOptions, Timeout).
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index a3002830d1..b88c7292a7 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
%%
%% %CopyrightEnd%
%%
-
%%
%%----------------------------------------------------------------------
%% Purpose: Handles an ssl connection, e.i. both the setup
@@ -43,30 +42,36 @@
%% Internal application API
%% Setup
--export([start_fsm/8, start_link/7, init/1]).
+-export([start_fsm/8, start_link/8, init/1, pids/1]).
%% State transition handling
--export([next_record/1, next_event/3, next_event/4, handle_common_event/4]).
+-export([next_event/3, next_event/4,
+ handle_protocol_record/3]).
%% Handshake handling
--export([renegotiate/2, send_handshake/2,
+-export([renegotiation/2, renegotiate/2, send_handshake/2,
queue_handshake/2, queue_change_cipher/2,
- reinit_handshake_data/1, select_sni_extension/1, empty_connection_state/2]).
+ reinit/1, reinit_handshake_data/1, select_sni_extension/1,
+ empty_connection_state/2]).
%% Alert and close handling
--export([encode_alert/3, send_alert/2, close/5, protocol_name/0]).
+-export([send_alert/2, send_alert_in_connection/2,
+ send_sync_alert/2,
+ close/5, protocol_name/0]).
%% Data handling
--export([encode_data/3, passive_receive/2, next_record_if_active/1, send/3,
- socket/5, setopts/3, getopts/3]).
+-export([socket/4, setopts/3, getopts/3]).
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
hello/3, user_hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
- connection/3, death_row/3]).
+ connection/3]).
%% gen_statem callbacks
-export([callback_mode/0, terminate/3, code_change/4, format_status/2]).
+
+-define(DIST_CNTRL_SPAWN_OPTS, [{priority, max}]).
+
%%====================================================================
%% Internal application API
%%====================================================================
@@ -74,12 +79,13 @@
%% Setup
%%====================================================================
start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker} = Opts,
- User, {CbModule, _,_, _} = CbInfo,
+ User, {CbModule, _,_, _, _} = CbInfo,
Timeout) ->
try
- {ok, Pid} = tls_connection_sup:start_child([Role, Host, Port, Socket,
+ {ok, Sender} = tls_sender:start(),
+ {ok, Pid} = tls_connection_sup:start_child([Role, Sender, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Tracker),
ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
@@ -87,12 +93,13 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker}
end;
start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_, Tracker} = Opts,
- User, {CbModule, _,_, _} = CbInfo,
+ User, {CbModule, _,_, _, _} = CbInfo,
Timeout) ->
try
- {ok, Pid} = tls_connection_sup:start_child_dist([Role, Host, Port, Socket,
+ {ok, Sender} = tls_sender:start([{spawn_opt, ?DIST_CNTRL_SPAWN_OPTS}]),
+ {ok, Pid} = tls_connection_sup:start_child_dist([Role, Sender, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Tracker),
ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
@@ -100,120 +107,204 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_, Tracker} =
end.
%%--------------------------------------------------------------------
--spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
+-spec start_link(atom(), pid(), ssl:host(), inet:port_number(), port(), list(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, reason()}.
%%
%% Description: Creates a gen_statem process which calls Module:init/1 to
%% initialize.
%%--------------------------------------------------------------------
-start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
- {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]])}.
+start_link(Role, Sender, Host, Port, Socket, Options, User, CbInfo) ->
+ {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Sender, Host, Port, Socket, Options, User, CbInfo]])}.
-init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
+init([Role, Sender, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo]) ->
process_flag(trap_exit, true),
- State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ link(Sender),
+ case SslOpts#ssl_options.erl_dist of
+ true ->
+ process_flag(priority, max);
+ _ ->
+ ok
+ end,
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Sender,
+ Host, Port, Socket, Options, User, CbInfo),
try
State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
- gen_statem:enter_loop(?MODULE, [], init, State)
+ initialize_tls_sender(State),
+ gen_statem:enter_loop(?MODULE, [], init, State)
catch throw:Error ->
- gen_statem:enter_loop(?MODULE, [], error, {Error, State0})
+ EState = State0#state{protocol_specific = Map#{error => Error}},
+ gen_statem:enter_loop(?MODULE, [], error, EState)
end.
+
+pids(#state{protocol_specific = #{sender := Sender}}) ->
+ [self(), Sender].
+
%%====================================================================
%% State transition handling
%%====================================================================
-next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
- {no_record, State#state{unprocessed_handshake_events = N-1}};
-
-next_record(#state{protocol_buffers =
- #protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}
- = Buffers,
- connection_states = ConnStates0,
- ssl_options = #ssl_options{padding_check = Check}} = State) ->
- case tls_record:decode_cipher_text(CT, ConnStates0, Check) of
- {Plain, ConnStates} ->
- {Plain, State#state{protocol_buffers =
- Buffers#protocol_buffers{tls_cipher_texts = Rest},
- connection_states = ConnStates}};
- #alert{} = Alert ->
- {Alert, State}
- end;
-next_record(#state{protocol_buffers = #protocol_buffers{tls_packets = [], tls_cipher_texts = []},
- socket = Socket,
- close_tag = CloseTag,
- transport_cb = Transport} = State) ->
- case tls_socket:setopts(Transport, Socket, [{active,once}]) of
- ok ->
- {no_record, State};
- _ ->
+next_record(_, #state{handshake_env =
+ #handshake_env{unprocessed_handshake_events = N} = HsEnv}
+ = State) when N > 0 ->
+ {no_record, State#state{handshake_env =
+ HsEnv#handshake_env{unprocessed_handshake_events = N-1}}};
+next_record(_, #state{protocol_buffers =
+ #protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts},
+ connection_states = ConnectionStates,
+ ssl_options = #ssl_options{padding_check = Check}} = State) ->
+ next_record(State, CipherTexts, ConnectionStates, Check);
+next_record(connection, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []},
+ protocol_specific = #{active_n_toggle := true}
+ } = State) ->
+ %% If ssl application user is not reading data wait to activate socket
+ flow_ctrl(State);
+
+next_record(_, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []},
+ protocol_specific = #{active_n_toggle := true}
+ } = State) ->
+ activate_socket(State);
+next_record(_, State) ->
+ {no_record, State}.
+
+
+flow_ctrl(#state{user_data_buffer = {_,Size,_},
+ socket_options = #socket_options{active = false},
+ bytes_to_read = undefined} = State) when Size =/= 0 ->
+ {no_record, State};
+flow_ctrl(#state{user_data_buffer = {_,Size,_},
+ socket_options = #socket_options{active = false},
+ bytes_to_read = 0} = State) when Size =/= 0 ->
+ {no_record, State};
+flow_ctrl(#state{user_data_buffer = {_,Size,_},
+ socket_options = #socket_options{active = false},
+ bytes_to_read = BytesToRead} = State) when (Size >= BytesToRead) andalso
+ (BytesToRead > 0) ->
+ {no_record, State};
+flow_ctrl(State) ->
+ activate_socket(State).
+
+
+activate_socket(#state{protocol_specific = #{active_n_toggle := true, active_n := N} = ProtocolSpec,
+ static_env = #static_env{socket = Socket,
+ close_tag = CloseTag,
+ transport_cb = Transport}
+ } = State) ->
+ case tls_socket:setopts(Transport, Socket, [{active, N}]) of
+ ok ->
+ {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}};
+ _ ->
self() ! {CloseTag, Socket},
- {no_record, State}
+ {no_record, State}
+ end.
+
+%% Decipher next record and concatenate consecutive ?APPLICATION_DATA records into one
+%%
+next_record(State, CipherTexts, ConnectionStates, Check) ->
+ next_record(State, CipherTexts, ConnectionStates, Check, []).
+%%
+next_record(State, [#ssl_tls{type = ?APPLICATION_DATA} = CT|CipherTexts], ConnectionStates0, Check, Acc) ->
+ case tls_record:decode_cipher_text(CT, ConnectionStates0, Check) of
+ {#ssl_tls{fragment = Fragment}, ConnectionStates} ->
+ next_record(State, CipherTexts, ConnectionStates, Check, [Fragment|Acc]);
+ #alert{} = Alert ->
+ Alert
end;
-next_record(State) ->
- {no_record, State}.
+next_record(State, [CT|CipherTexts], ConnectionStates0, Check, []) ->
+ case tls_record:decode_cipher_text(CT, ConnectionStates0, Check) of
+ {Record, ConnectionStates} ->
+ next_record_done(State, CipherTexts, ConnectionStates, Record);
+ #alert{} = Alert ->
+ Alert
+ end;
+next_record(State, CipherTexts, ConnectionStates, _Check, Acc) ->
+ %% Not ?APPLICATION_DATA but we have a nonempty Acc
+ %% -> build an ?APPLICATION_DATA record with the accumulated fragments
+ next_record_done(State, CipherTexts, ConnectionStates,
+ #ssl_tls{type = ?APPLICATION_DATA, fragment = iolist_to_binary(lists:reverse(Acc))}).
+
+next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, ConnectionStates, Record) ->
+ {Record,
+ State#state{protocol_buffers = Buffers#protocol_buffers{tls_cipher_texts = CipherTexts},
+ connection_states = ConnectionStates}}.
next_event(StateName, Record, State) ->
next_event(StateName, Record, State, []).
-
-next_event(connection = StateName, no_record, State0, Actions) ->
- case next_record_if_active(State0) of
- {no_record, State} ->
- ssl_connection:hibernate_after(StateName, State, Actions);
- {#ssl_tls{} = Record, State} ->
- {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
- {#alert{} = Alert, State} ->
- {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
+%%
+next_event(StateName, no_record, State0, Actions) ->
+ case next_record(StateName, State0) of
+ {no_record, State} ->
+ {next_state, StateName, State, Actions};
+ {Record, State} ->
+ next_event(StateName, Record, State, Actions)
end;
-next_event(StateName, Record, State, Actions) ->
- case Record of
- no_record ->
- {next_state, StateName, State, Actions};
- #ssl_tls{} = Record ->
- {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
- #alert{} = Alert ->
- {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
- end.
+next_event(StateName, #ssl_tls{} = Record, State, Actions) ->
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
+next_event(StateName, #alert{} = Alert, State, Actions) ->
+ {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}.
+
-handle_common_event(internal, #alert{} = Alert, StateName,
- #state{negotiated_version = Version} = State) ->
- ssl_connection:handle_own_alert(Alert, Version, StateName, State);
+%%% TLS record protocol level application data messages
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName,
+ #state{start_or_recv_from = From,
+ socket_options = #socket_options{active = false}} = State0) when From =/= undefined ->
+ case ssl_connection:read_application_data(Data, State0) of
+ {stop, _, _} = Stop->
+ Stop;
+ {Record, #state{start_or_recv_from = Caller} = State1} ->
+ TimerAction = case Caller of
+ undefined -> %% Passive recv complete cancel timer
+ [{{timeout, recv}, infinity, timeout}];
+ _ ->
+ []
+ end,
+ {next_state, StateName, State, Actions} = next_event(StateName, Record, State1, TimerAction),
+ ssl_connection:hibernate_after(StateName, State, Actions)
+ end;
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, State0) ->
+ case ssl_connection:read_application_data(Data, State0) of
+ {stop, _, _} = Stop->
+ Stop;
+ {Record, State1} ->
+ {next_state, StateName, State, Actions} = next_event(StateName, Record, State1),
+ ssl_connection:hibernate_after(StateName, State, Actions)
+ end;
%%% TLS record protocol level handshake messages
-handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
+handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data},
StateName, #state{protocol_buffers =
#protocol_buffers{tls_handshake_buffer = Buf0} = Buffers,
- negotiated_version = Version,
+ connection_env = #connection_env{negotiated_version = Version},
ssl_options = Options} = State0) ->
try
{Packets, Buf} = tls_handshake:get_tls_handshake(Version,Data,Buf0, Options),
- State1 =
+ State =
State0#state{protocol_buffers =
Buffers#protocol_buffers{tls_handshake_buffer = Buf}},
case Packets of
[] ->
assert_buffer_sanity(Buf, Options),
- {Record, State} = next_record(State1),
- next_event(StateName, Record, State);
+ next_event(StateName, no_record, State);
_ ->
Events = tls_handshake_events(Packets),
case StateName of
connection ->
- ssl_connection:hibernate_after(StateName, State1, Events);
+ ssl_connection:hibernate_after(StateName, State, Events);
_ ->
+ HsEnv = State#state.handshake_env,
{next_state, StateName,
- State1#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
+ State#state{protocol_buffers = Buffers,
+ handshake_env =
+ HsEnv#handshake_env{unprocessed_handshake_events
+ = unprocessed_events(Events)}}, Events}
end
end
catch throw:#alert{} = Alert ->
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) ->
- {next_state, StateName, State, [{next_event, internal, {application_data, Data}}]};
%%% TLS record protocol level change cipher messages
-handle_common_event(internal, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
+handle_protocol_record(#ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
{next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
%%% TLS record protocol level Alert messages
-handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
- #state{negotiated_version = Version} = State) ->
+handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
+ #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
try decode_alerts(EncAlerts) of
Alerts = [_|_] ->
handle_alerts(Alerts, {next_state, StateName, State});
@@ -229,70 +320,79 @@ handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, Sta
end;
%% Ignore unknown TLS record level protocol messages
-handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
- {next_state, StateName, State}.
+handle_protocol_record(#ssl_tls{type = _Unknown}, StateName, State) ->
+ {next_state, StateName, State, []}.
%%====================================================================
%% Handshake handling
%%====================================================================
-renegotiate(#state{role = client} = State, Actions) ->
+renegotiation(Pid, WriteState) ->
+ gen_statem:call(Pid, {user_renegotiate, WriteState}).
+
+renegotiate(#state{static_env = #static_env{role = client},
+ handshake_env = HsEnv} = 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},
+ {next_state, connection, State#state{handshake_env = HsEnv#handshake_env{tls_handshake_history = Hs0}},
[{next_event, internal, #hello_request{}} | Actions]};
-
-renegotiate(#state{role = server,
- socket = Socket,
- transport_cb = Transport,
- negotiated_version = Version,
+renegotiate(#state{static_env = #static_env{role = server,
+ socket = Socket,
+ transport_cb = Transport},
+ handshake_env = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
connection_states = ConnectionStates0} = State0, Actions) ->
HelloRequest = ssl_handshake:hello_request(),
Frag = tls_handshake:encode_handshake(HelloRequest, Version),
Hs0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates} =
tls_record:encode_handshake(Frag, Version, ConnectionStates0),
- send(Transport, Socket, BinMsg),
- State1 = State0#state{connection_states =
+ tls_socket:send(Transport, Socket, BinMsg),
+ State = State0#state{connection_states =
ConnectionStates,
- tls_handshake_history = Hs0},
- {Record, State} = next_record(State1),
- next_event(hello, Record, State, Actions).
+ handshake_env = HsEnv#handshake_env{tls_handshake_history = Hs0}},
+ next_event(hello, no_record, State, Actions).
send_handshake(Handshake, State) ->
send_handshake_flight(queue_handshake(Handshake, State)).
-queue_handshake(Handshake, #state{negotiated_version = Version,
- tls_handshake_history = Hist0,
- flight_buffer = Flight0,
+queue_handshake(Handshake, #state{handshake_env = #handshake_env{tls_handshake_history = Hist0} = HsEnv,
+ connection_env = #connection_env{negotiated_version = Version},
+ flight_buffer = Flight0,
connection_states = ConnectionStates0} = State0) ->
{BinHandshake, ConnectionStates, Hist} =
encode_handshake(Handshake, Version, ConnectionStates0, Hist0),
State0#state{connection_states = ConnectionStates,
- tls_handshake_history = Hist,
+ handshake_env = HsEnv#handshake_env{tls_handshake_history = Hist},
flight_buffer = Flight0 ++ [BinHandshake]}.
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
+send_handshake_flight(#state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
flight_buffer = Flight} = State0) ->
- send(Transport, Socket, Flight),
+ tls_socket:send(Transport, Socket, Flight),
{State0#state{flight_buffer = []}, []}.
-queue_change_cipher(Msg, #state{negotiated_version = Version,
- flight_buffer = Flight0,
- connection_states = ConnectionStates0} = State0) ->
+queue_change_cipher(Msg, #state{connection_env = #connection_env{negotiated_version = Version},
+ flight_buffer = Flight0,
+ connection_states = ConnectionStates0} = State0) ->
{BinChangeCipher, ConnectionStates} =
encode_change_cipher(Msg, Version, ConnectionStates0),
State0#state{connection_states = ConnectionStates,
flight_buffer = Flight0 ++ [BinChangeCipher]}.
-reinit_handshake_data(State) ->
+reinit(#state{protocol_specific = #{sender := Sender},
+ connection_env = #connection_env{negotiated_version = Version},
+ connection_states = #{current_write := Write}} = State) ->
+ tls_sender:update_connection_state(Sender, Write, Version),
+ reinit_handshake_data(State).
+
+reinit_handshake_data(#state{handshake_env = HsEnv} =State) ->
%% premaster_secret, public_key_info and tls_handshake_info
%% are only needed during the handshake phase.
%% To reduce memory foot print of a connection reinitialize them.
State#state{
- premaster_secret = undefined,
- public_key_info = undefined,
- tls_handshake_history = ssl_handshake:init_handshake_history()
+ handshake_env = HsEnv#handshake_env{tls_handshake_history = ssl_handshake:init_handshake_history(),
+ public_key_info = undefined,
+ premaster_secret = undefined}
}.
select_sni_extension(#client_hello{extensions = HelloExtensions}) ->
@@ -306,15 +406,6 @@ empty_connection_state(ConnectionEnd, BeastMitigation) ->
%%====================================================================
%% Alert and close handling
%%====================================================================
-send_alert(Alert, #state{negotiated_version = Version,
- socket = Socket,
- transport_cb = Transport,
- connection_states = ConnectionStates0} = State0) ->
- {BinMsg, ConnectionStates} =
- encode_alert(Alert, Version, ConnectionStates0),
- send(Transport, Socket, BinMsg),
- State0#state{connection_states = ConnectionStates}.
-
%%--------------------------------------------------------------------
-spec encode_alert(#alert{}, ssl_record:ssl_version(), ssl_record:connection_states()) ->
{iolist(), ssl_record:connection_states()}.
@@ -323,6 +414,36 @@ send_alert(Alert, #state{negotiated_version = Version,
%%--------------------------------------------------------------------
encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
tls_record:encode_alert_record(Alert, Version, ConnectionStates).
+
+send_alert(Alert, #state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport},
+ connection_env = #connection_env{negotiated_version = Version},
+ connection_states = ConnectionStates0} = StateData0) ->
+ {BinMsg, ConnectionStates} =
+ encode_alert(Alert, Version, ConnectionStates0),
+ tls_socket:send(Transport, Socket, BinMsg),
+ StateData0#state{connection_states = ConnectionStates}.
+
+%% If an ALERT sent in the connection state, should cause the TLS
+%% connection to end, we need to synchronize with the tls_sender
+%% process so that the ALERT if possible (that is the tls_sender process is
+%% not blocked) is sent before the connection process terminates and
+%% thereby closes the transport socket.
+send_alert_in_connection(#alert{level = ?FATAL} = Alert, State) ->
+ send_sync_alert(Alert, State);
+send_alert_in_connection(#alert{description = ?CLOSE_NOTIFY} = Alert, State) ->
+ send_sync_alert(Alert, State);
+send_alert_in_connection(Alert,
+ #state{protocol_specific = #{sender := Sender}}) ->
+ tls_sender:send_alert(Sender, Alert).
+send_sync_alert(
+ Alert, #state{protocol_specific = #{sender := Sender}} = State) ->
+ try tls_sender:send_and_ack_alert(Sender, Alert)
+ catch
+ _:_ ->
+ throw({stop, {shutdown, own_alert}, State})
+ end.
+
%% User closes or recursive call!
close({close, Timeout}, Socket, Transport = gen_tcp, _,_) ->
tls_socket:setopts(Transport, Socket, [{active, false}]),
@@ -354,31 +475,9 @@ protocol_name() ->
%%====================================================================
%% Data handling
%%====================================================================
-encode_data(Data, Version, ConnectionStates0)->
- tls_record:encode_data(Data, Version, ConnectionStates0).
-
-passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
- case Buffer of
- <<>> ->
- {Record, State} = next_record(State0),
- next_event(StateName, Record, State);
- _ ->
- {Record, State} = ssl_connection:read_application_data(<<>>, State0),
- next_event(StateName, Record, State)
- end.
-next_record_if_active(State =
- #state{socket_options =
- #socket_options{active = false}}) ->
- {no_record ,State};
-next_record_if_active(State) ->
- next_record(State).
-
-send(Transport, Socket, Data) ->
- tls_socket:send(Transport, Socket, Data).
-
-socket(Pid, Transport, Socket, Connection, Tracker) ->
- tls_socket:socket(Pid, Transport, Socket, Connection, Tracker).
+socket(Pids, Transport, Socket, Tracker) ->
+ tls_socket:socket(Pids, Transport, Socket, ?MODULE, Tracker).
setopts(Transport, Socket, Other) ->
tls_socket:setopts(Transport, Socket, Other).
@@ -396,16 +495,19 @@ getopts(Transport, Socket, Tag) ->
%%--------------------------------------------------------------------
init({call, From}, {start, Timeout},
- #state{host = Host, port = Port, role = client,
+ #state{static_env = #static_env{role = client,
+ host = Host,
+ port = Port,
+ transport_cb = Transport,
+ socket = Socket,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ handshake_env = #handshake_env{renegotiation = {Renegotiation, _}} = HsEnv,
+ connection_env = CEnv,
ssl_options = SslOpts,
session = #session{own_certificate = Cert} = Session0,
- transport_cb = Transport, socket = Socket,
- connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _},
- session_cache = Cache,
- session_cache_cb = CacheCb
+ connection_states = ConnectionStates0
} = State0) ->
- Timer = ssl_connection:start_or_recv_cancel_timer(Timeout, From),
Hello = tls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Cache, CacheCb, Renegotiation, Cert),
@@ -414,16 +516,14 @@ init({call, From}, {start, Timeout},
Handshake0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates, Handshake} =
encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
- send(Transport, Socket, BinMsg),
- State1 = State0#state{connection_states = ConnectionStates,
- negotiated_version = Version, %% Requested version
- session =
- Session0#session{session_id = Hello#client_hello.session_id},
- tls_handshake_history = Handshake,
- start_or_recv_from = From,
- timer = Timer},
- {Record, State} = next_record(State1),
- next_event(hello, Record, State);
+ tls_socket:send(Transport, Socket, BinMsg),
+ State = State0#state{connection_states = ConnectionStates,
+ connection_env = CEnv#connection_env{negotiated_version = Version}, %% Requested version
+ session =
+ Session0#session{session_id = Hello#client_hello.session_id},
+ handshake_env = HsEnv#handshake_env{tls_handshake_history = Handshake},
+ start_or_recv_from = From},
+ next_event(hello, no_record, State, [{{timeout, handshake}, Timeout, close}]);
init(Type, Event, State) ->
gen_handshake(?FUNCTION_NAME, Type, Event, State).
@@ -432,17 +532,13 @@ init(Type, Event, State) ->
{start, timeout()} | term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-
-error({call, From}, {start, _Timeout}, {Error, State}) ->
- ssl_connection:stop_and_reply(
- normal, {reply, From, {error, Error}}, State);
error({call, From}, {start, _Timeout},
#state{protocol_specific = #{error := Error}} = State) ->
- ssl_connection:stop_and_reply(
- normal, {reply, From, {error, Error}}, State);
-error({call, _} = Call, Msg, {Error, #state{protocol_specific = Map} = State}) ->
- gen_handshake(?FUNCTION_NAME, Call, Msg,
- State#state{protocol_specific = Map#{error => Error}});
+ {stop_and_reply, {shutdown, normal},
+ [{reply, From, {error, Error}}], State};
+
+error({call, _} = Call, Msg, State) ->
+ gen_handshake(?FUNCTION_NAME, Call, Msg, State);
error(_, _, _) ->
{keep_state_and_data, [postpone]}.
@@ -452,29 +548,38 @@ error(_, _, _) ->
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-hello(internal, #client_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
- start_or_recv_from = From} = State) ->
- {next_state, user_hello, State#state{start_or_recv_from = undefined,
- hello = Hello},
+hello(internal, #client_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ handshake_env = HsEnv,
+ start_or_recv_from = From} = State) ->
+ {next_state, user_hello, State#state{start_or_recv_from = undefined,
+ handshake_env = HsEnv#handshake_env{hello = Hello}},
[{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
-hello(internal, #server_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
- start_or_recv_from = From} = State) ->
+hello(internal, #server_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ handshake_env = HsEnv,
+ start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
- hello = Hello},
+ handshake_env = HsEnv#handshake_env{hello = Hello}},
[{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
hello(internal, #client_hello{client_version = ClientVersion} = Hello,
#state{connection_states = ConnectionStates0,
- port = Port, session = #session{own_certificate = Cert} = Session0,
- renegotiation = {Renegotiation, _},
- session_cache = Cache,
- session_cache_cb = CacheCb,
- negotiated_protocol = CurrentProtocol,
- key_algorithm = KeyExAlg,
+ static_env = #static_env{
+ port = Port,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ handshake_env = #handshake_env{kex_algorithm = KeyExAlg,
+ renegotiation = {Renegotiation, _},
+ negotiated_protocol = CurrentProtocol} = HsEnv,
+ connection_env = CEnv,
+ session = #session{own_certificate = Cert} = Session0,
ssl_options = SslOpts} = State) ->
case tls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of
#alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, ClientVersion, hello, State);
+ ssl_connection:handle_own_alert(Alert, ClientVersion, hello,
+ State#state{connection_env =
+ CEnv#connection_env{negotiated_version = ClientVersion}});
{Version, {Type, Session},
ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
Protocol = case Protocol0 of
@@ -483,21 +588,24 @@ hello(internal, #client_hello{client_version = ClientVersion} = Hello,
end,
gen_handshake(?FUNCTION_NAME, internal, {common_client_hello, Type, ServerHelloExt},
State#state{connection_states = ConnectionStates,
- negotiated_version = Version,
- hashsign_algorithm = HashSign,
- client_hello_version = ClientVersion,
- session = Session,
- negotiated_protocol = Protocol})
+ connection_env = CEnv#connection_env{negotiated_version = Version},
+ handshake_env = HsEnv#handshake_env{
+ hashsign_algorithm = HashSign,
+ client_hello_version = ClientVersion,
+ negotiated_protocol = Protocol},
+ session = Session
+ })
end;
hello(internal, #server_hello{} = Hello,
#state{connection_states = ConnectionStates0,
- negotiated_version = ReqVersion,
- role = client,
- renegotiation = {Renegotiation, _},
+ connection_env = #connection_env{negotiated_version = ReqVersion} = CEnv,
+ static_env = #static_env{role = client},
+ handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
ssl_options = SslOptions} = State) ->
case tls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
- #alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, ReqVersion, hello, State);
+ #alert{} = Alert -> %%TODO
+ ssl_connection:handle_own_alert(Alert, ReqVersion, hello,
+ State#state{connection_env = CEnv#connection_env{negotiated_version = ReqVersion}});
{Version, NewId, ConnectionStates, ProtoExt, Protocol} ->
ssl_connection:handle_session(Hello,
Version, NewId, ConnectionStates, ProtoExt, Protocol, State)
@@ -544,63 +652,143 @@ cipher(Type, Event, State) ->
%%--------------------------------------------------------------------
connection(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
+connection({call, From}, {user_renegotiate, WriteState},
+ #state{connection_states = ConnectionStates} = State) ->
+ {next_state, ?FUNCTION_NAME, State#state{connection_states = ConnectionStates#{current_write => WriteState}},
+ [{next_event,{call, From}, renegotiate}]};
+connection({call, From},
+ {close, {Pid, _Timeout}},
+ #state{connection_env = #connection_env{terminated = closed} =CEnv} = State) ->
+ {next_state, downgrade, State#state{connection_env =
+ CEnv#connection_env{terminated = true,
+ downgrade = {Pid, From}}},
+ [{next_event, internal, ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY)}]};
+connection({call, From},
+ {close,{Pid, Timeout}},
+ #state{connection_states = ConnectionStates,
+ protocol_specific = #{sender := Sender},
+ connection_env = CEnv
+ } = State0) ->
+ case tls_sender:downgrade(Sender, Timeout) of
+ {ok, Write} ->
+ %% User downgrades connection
+ %% When downgrading an TLS connection to a transport connection
+ %% we must recive the close alert from the peer before releasing the
+ %% transport socket.
+ State = send_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
+ State0#state{connection_states =
+ ConnectionStates#{current_write => Write}}),
+ {next_state, downgrade, State#state{connection_env =
+ CEnv#connection_env{downgrade = {Pid, From},
+ terminated = true}},
+ [{timeout, Timeout, downgrade}]};
+ {error, timeout} ->
+ {stop_and_reply, {shutdown, downgrade_fail}, [{reply, From, {error, timeout}}]}
+ end;
connection(internal, #hello_request{},
- #state{role = client, host = Host, port = Port,
+ #state{static_env = #static_env{role = client,
+ host = Host,
+ port = Port,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ handshake_env = #handshake_env{renegotiation = {Renegotiation, peer}},
session = #session{own_certificate = Cert} = Session0,
- session_cache = Cache, session_cache_cb = CacheCb,
- ssl_options = SslOpts,
- connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _}} = State0) ->
- Hello = tls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
- Cache, CacheCb, Renegotiation, Cert),
- {State1, Actions} = send_handshake(Hello, State0),
- {Record, State} =
- next_record(
- State1#state{session = Session0#session{session_id
- = Hello#client_hello.session_id}}),
- next_event(hello, Record, State, Actions);
+ ssl_options = SslOpts,
+ protocol_specific = #{sender := Pid},
+ connection_states = ConnectionStates} = State0) ->
+ try tls_sender:peer_renegotiate(Pid) of
+ {ok, Write} ->
+ Hello = tls_handshake:client_hello(Host, Port, ConnectionStates, SslOpts,
+ Cache, CacheCb, Renegotiation, Cert),
+ {State, Actions} = send_handshake(Hello, State0#state{connection_states = ConnectionStates#{current_write => Write}}),
+ next_event(hello, no_record, State#state{session = Session0#session{session_id
+ = Hello#client_hello.session_id}}, Actions)
+ catch
+ _:_ ->
+ {stop, {shutdown, sender_blocked}, State0}
+ end;
+connection(internal, #hello_request{},
+ #state{static_env = #static_env{role = client,
+ host = Host,
+ port = Port,
+ session_cache = Cache,
+ session_cache_cb = CacheCb},
+ handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
+ session = #session{own_certificate = Cert} = Session0,
+ ssl_options = SslOpts,
+ connection_states = ConnectionStates} = State0) ->
+ Hello = tls_handshake:client_hello(Host, Port, ConnectionStates, SslOpts,
+ Cache, CacheCb, Renegotiation, Cert),
+ {State, Actions} = send_handshake(Hello, State0),
+ next_event(hello, no_record, State#state{session = Session0#session{session_id
+ = Hello#client_hello.session_id}}, Actions);
connection(internal, #client_hello{} = Hello,
- #state{role = server, allow_renegotiate = true} = State0) ->
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{allow_renegotiate = true}= HsEnv,
+ connection_states = CS,
+ protocol_specific = #{sender := Sender}
+ } = State) ->
%% Mitigate Computational DoS attack
%% http://www.educatedguesswork.org/2011/10/ssltls_and_computational_dos.html
%% http://www.thc.org/thc-ssl-dos/ Rather than disabling client
%% initiated renegotiation we will disallow many client initiated
%% renegotiations immediately after each other.
erlang:send_after(?WAIT_TO_ALLOW_RENEGOTIATION, self(), allow_renegotiate),
- {Record, State} = next_record(State0#state{allow_renegotiate = false,
- renegotiation = {true, peer}}),
- next_event(hello, Record, State, [{next_event, internal, Hello}]);
+ {ok, Write} = tls_sender:renegotiate(Sender),
+ next_event(hello, no_record, State#state{connection_states = CS#{current_write => Write},
+ handshake_env = HsEnv#handshake_env{renegotiation = {true, peer},
+ allow_renegotiate = false}
+ },
+ [{next_event, internal, Hello}]);
connection(internal, #client_hello{},
- #state{role = server, allow_renegotiate = false} = State0) ->
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{allow_renegotiate = false}} = State0) ->
Alert = ?ALERT_REC(?WARNING, ?NO_RENEGOTIATION),
- State1 = send_alert(Alert, State0),
- {Record, State} = ssl_connection:prepare_connection(State1, ?MODULE),
- next_event(?FUNCTION_NAME, Record, State);
+ send_alert_in_connection(Alert, State0),
+ State = reinit_handshake_data(State0),
+ next_event(?FUNCTION_NAME, no_record, State);
+
connection(Type, Event, State) ->
ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
%%--------------------------------------------------------------------
--spec death_row(gen_statem:event_type(), term(), #state{}) ->
- gen_statem:state_function_result().
-%%--------------------------------------------------------------------
-death_row(Type, Event, State) ->
- ssl_connection:death_row(Type, Event, State, ?MODULE).
-
-%%--------------------------------------------------------------------
-spec downgrade(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
+downgrade(internal, #alert{description = ?CLOSE_NOTIFY},
+ #state{static_env = #static_env{transport_cb = Transport,
+ socket = Socket},
+ connection_env = #connection_env{downgrade = {Pid, From}}} = State) ->
+ tls_socket:setopts(Transport, Socket, [{active, false}, {packet, 0}, {mode, binary}]),
+ Transport:controlling_process(Socket, Pid),
+ {stop_and_reply, {shutdown, downgrade},[{reply, From, {ok, Socket}}], State};
+downgrade(timeout, downgrade, #state{ connection_env = #connection_env{downgrade = {_, From}}} = State) ->
+ {stop_and_reply, {shutdown, normal},[{reply, From, {error, timeout}}], State};
+downgrade(info, {CloseTag, Socket},
+ #state{static_env = #static_env{socket = Socket,
+ close_tag = CloseTag},
+ connection_env = #connection_env{downgrade = {_, From}}} =
+ State) ->
+ {stop_and_reply, {shutdown, normal},[{reply, From, {error, CloseTag}}], State};
+downgrade(info, Info, State) ->
+ handle_info(Info, ?FUNCTION_NAME, State);
downgrade(Type, Event, State) ->
- ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
-
+ ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
%--------------------------------------------------------------------
%% gen_statem callbacks
%%--------------------------------------------------------------------
callback_mode() ->
state_functions.
+terminate({shutdown, {sender_died, Reason}}, _StateName,
+ #state{static_env = #static_env{socket = Socket,
+ transport_cb = Transport}}
+ = State) ->
+ ssl_connection:handle_trusted_certs_db(State),
+ close(Reason, Socket, Transport, undefined, undefined);
terminate(Reason, StateName, State) ->
- catch ssl_connection:terminate(Reason, StateName, State).
+ catch ssl_connection:terminate(Reason, StateName, State),
+ ensure_sender_terminate(Reason, State).
format_status(Type, Data) ->
ssl_connection:format_status(Type, Data).
@@ -611,9 +799,10 @@ code_change(_OldVsn, StateName, State, _) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
- {CbModule, DataTag, CloseTag, ErrorTag}) ->
- #ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
+initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
+ {CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
+ #ssl_options{beast_mitigation = BeastMitigation,
+ erl_dist = IsErlDist} = SSLOptions,
ConnectionStates = tls_record:init_connection_states(Role, BeastMitigation),
SessionCacheCb = case application:get_env(ssl, session_cb) of
@@ -622,43 +811,85 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
_ ->
ssl_session_cache
end,
-
- Monitor = erlang:monitor(process, User),
-
- #state{socket_options = SocketOptions,
- ssl_options = SSLOptions,
- session = #session{is_resumable = new},
- transport_cb = CbModule,
- data_tag = DataTag,
- close_tag = CloseTag,
- error_tag = ErrorTag,
- role = Role,
- host = Host,
- port = Port,
- socket = Socket,
- connection_states = ConnectionStates,
- protocol_buffers = #protocol_buffers{},
- user_application = {Monitor, User},
- user_data_buffer = <<>>,
- session_cache_cb = SessionCacheCb,
- renegotiation = {false, first},
- allow_renegotiate = SSLOptions#ssl_options.client_renegotiation,
- start_or_recv_from = undefined,
- protocol_cb = ?MODULE,
- tracker = Tracker,
- flight_buffer = []
- }.
-
-next_tls_record(Data, StateName, #state{protocol_buffers =
- #protocol_buffers{tls_record_buffer = Buf0,
- tls_cipher_texts = CT0} = Buffers}
- = State0) ->
- case tls_record:get_tls_records(Data,
- acceptable_record_versions(StateName, State0),
- Buf0) of
+ InternalActiveN = case application:get_env(ssl, internal_active_n) of
+ {ok, N} when is_integer(N) andalso (not IsErlDist) ->
+ N;
+ _ ->
+ ?INTERNAL_ACTIVE_N
+ end,
+ UserMonitor = erlang:monitor(process, User),
+ InitStatEnv = #static_env{
+ role = Role,
+ transport_cb = CbModule,
+ protocol_cb = ?MODULE,
+ data_tag = DataTag,
+ close_tag = CloseTag,
+ error_tag = ErrorTag,
+ passive_tag = PassiveTag,
+ host = Host,
+ port = Port,
+ socket = Socket,
+ session_cache_cb = SessionCacheCb,
+ tracker = Tracker
+ },
+ #state{
+ static_env = InitStatEnv,
+ handshake_env = #handshake_env{
+ tls_handshake_history = ssl_handshake:init_handshake_history(),
+ renegotiation = {false, first},
+ allow_renegotiate = SSLOptions#ssl_options.client_renegotiation
+ },
+ connection_env = #connection_env{user_application = {UserMonitor, User}},
+ socket_options = SocketOptions,
+ ssl_options = SSLOptions,
+ session = #session{is_resumable = new},
+ connection_states = ConnectionStates,
+ protocol_buffers = #protocol_buffers{},
+ user_data_buffer = {[],0,[]},
+ start_or_recv_from = undefined,
+ flight_buffer = [],
+ protocol_specific = #{sender => Sender,
+ active_n => InternalActiveN,
+ active_n_toggle => true
+ }
+ }.
+
+initialize_tls_sender(#state{static_env = #static_env{
+ role = Role,
+ transport_cb = Transport,
+ socket = Socket,
+ tracker = Tracker
+ },
+ connection_env = #connection_env{negotiated_version = Version},
+ socket_options = SockOpts,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt},
+ connection_states = #{current_write := ConnectionWriteState},
+ protocol_specific = #{sender := Sender}}) ->
+ Init = #{current_write => ConnectionWriteState,
+ role => Role,
+ socket => Socket,
+ socket_options => SockOpts,
+ tracker => Tracker,
+ transport_cb => Transport,
+ negotiated_version => Version,
+ renegotiate_at => RenegotiateAt},
+ tls_sender:initialize(Sender, Init).
+
+next_tls_record(Data, StateName,
+ #state{protocol_buffers =
+ #protocol_buffers{tls_record_buffer = Buf0,
+ tls_cipher_texts = CT0} = Buffers} = State0) ->
+ Versions =
+ case StateName of
+ hello ->
+ [tls_record:protocol_version(Vsn) || Vsn <- ?ALL_AVAILABLE_VERSIONS];
+ _ ->
+ State0#state.connection_env#connection_env.negotiated_version
+ end,
+ case tls_record:get_tls_records(Data, Versions, Buf0) of
{Records, Buf1} ->
CT1 = CT0 ++ Records,
- next_record(State0#state{protocol_buffers =
+ next_record(StateName, State0#state{protocol_buffers =
Buffers#protocol_buffers{tls_record_buffer = Buf1,
tls_cipher_texts = CT1}});
#alert{} = Alert ->
@@ -666,10 +897,6 @@ next_tls_record(Data, StateName, #state{protocol_buffers =
end.
-acceptable_record_versions(hello, _) ->
- [tls_record:protocol_version(Vsn) || Vsn <- ?ALL_AVAILABLE_VERSIONS];
-acceptable_record_versions(_, #state{negotiated_version = Version}) ->
- [Version].
handle_record_alert(Alert, _) ->
Alert.
@@ -680,26 +907,35 @@ tls_handshake_events(Packets) ->
%% raw data from socket, upack records
handle_info({Protocol, _, Data}, StateName,
- #state{data_tag = Protocol} = State0) ->
+ #state{static_env = #static_env{data_tag = Protocol}} = State0) ->
case next_tls_record(Data, StateName, State0) of
{Record, State} ->
next_event(StateName, Record, State);
#alert{} = Alert ->
ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
- ssl_connection:stop({shutdown, own_alert}, State0)
+ {stop, {shutdown, own_alert}, State0}
end;
+handle_info({PassiveTag, Socket}, StateName,
+ #state{static_env = #static_env{socket = Socket,
+ passive_tag = PassiveTag},
+ protocol_specific = PS
+ } = State) ->
+ next_event(StateName, no_record,
+ State#state{protocol_specific = PS#{active_n_toggle => true}});
handle_info({CloseTag, Socket}, StateName,
- #state{socket = Socket, close_tag = CloseTag,
+ #state{static_env = #static_env{socket = Socket, close_tag = CloseTag},
+ connection_env = #connection_env{negotiated_version = Version},
socket_options = #socket_options{active = Active},
protocol_buffers = #protocol_buffers{tls_cipher_texts = CTs},
- negotiated_version = Version} = State) ->
+ user_data_buffer = {_,BufferSize,_},
+ protocol_specific = PS} = State) ->
%% Note that as of TLS 1.1,
%% failure to properly close a connection no longer requires that a
%% session not be resumed. This is a change from TLS 1.0 to conform
%% with widespread implementation practice.
- case (Active == false) andalso (CTs =/= []) of
+ case (Active == false) andalso ((CTs =/= []) or (BufferSize =/= 0)) of
false ->
case Version of
{1, N} when N >= 1 ->
@@ -713,13 +949,17 @@ handle_info({CloseTag, Socket}, StateName,
end,
ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
- ssl_connection:stop({shutdown, transport_closed}, State);
+ {stop, {shutdown, transport_closed}, State};
true ->
%% Fixes non-delivery of final TLS record in {active, once}.
%% Basically allows the application the opportunity to set {active, once} again
- %% and then receive the final message.
- next_event(StateName, no_record, State)
+ %% and then receive the final message. Set internal active_n to zero
+ %% to ensure socket close message is sent if there is not enough data to deliver.
+ next_event(StateName, no_record, State#state{protocol_specific = PS#{active_n_toggle => true}})
end;
+handle_info({'EXIT', Sender, Reason}, _,
+ #state{protocol_specific = #{sender := Sender}} = State) ->
+ {stop, {shutdown, {sender_died, Reason}}, State};
handle_info(Msg, StateName, State) ->
ssl_connection:StateName(info, Msg, State, ?MODULE).
@@ -727,6 +967,14 @@ handle_alerts([], Result) ->
Result;
handle_alerts(_, {stop, _, _} = Stop) ->
Stop;
+handle_alerts([#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} | _Alerts],
+ {next_state, connection = StateName, #state{connection_env = CEnv,
+ socket_options = #socket_options{active = false},
+ user_data_buffer = {_,BufferSize,_},
+ protocol_buffers = #protocol_buffers{tls_cipher_texts = CTs}} =
+ State}) when (BufferSize =/= 0) orelse
+ (CTs =/= []) ->
+ {next_state, StateName, State#state{connection_env = CEnv#connection_env{terminated = true}}};
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}) ->
@@ -746,7 +994,7 @@ decode_alerts(Bin) ->
ssl_alert:decode(Bin).
gen_handshake(StateName, Type, Event,
- #state{negotiated_version = Version} = State) ->
+ #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
try ssl_connection:StateName(Type, Event, State, ?MODULE) of
Result ->
Result
@@ -757,7 +1005,7 @@ gen_handshake(StateName, Type, Event,
Version, StateName, State)
end.
-gen_info(Event, connection = StateName, #state{negotiated_version = Version} = State) ->
+gen_info(Event, connection = StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
try handle_info(Event, StateName, State) of
Result ->
Result
@@ -768,7 +1016,7 @@ gen_info(Event, connection = StateName, #state{negotiated_version = Version} =
Version, StateName, State)
end;
-gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
+gen_info(Event, StateName, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
try handle_info(Event, StateName, State) of
Result ->
Result
@@ -788,7 +1036,8 @@ unprocessed_events(Events) ->
erlang:length(Events)-1.
-assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>, #ssl_options{max_handshake_size = Max}) when
+assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>,
+ #ssl_options{max_handshake_size = Max}) when
Length =< Max ->
case size(Rest) of
N when N < Length ->
@@ -808,3 +1057,16 @@ assert_buffer_sanity(Bin, _) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
malformed_handshake_data))
end.
+
+ensure_sender_terminate(downgrade, _) ->
+ ok; %% Do not terminate sender during downgrade phase
+ensure_sender_terminate(_, #state{protocol_specific = #{sender := Sender}}) ->
+ %% Make sure TLS sender dies when connection process is terminated normally
+ %% This is needed if the tls_sender is blocked in prim_inet:send
+ Kill = fun() ->
+ receive
+ after 5000 ->
+ catch (exit(Sender, kill))
+ end
+ end,
+ spawn(Kill).
diff --git a/lib/ssl/src/tls_connection.hrl b/lib/ssl/src/tls_connection.hrl
index 0af2258932..9063b1b736 100644
--- a/lib/ssl/src/tls_connection.hrl
+++ b/lib/ssl/src/tls_connection.hrl
@@ -30,7 +30,6 @@
-include("tls_record.hrl").
-record(protocol_buffers, {
- tls_packets = [], %% :: [#ssl_tls{}], % Not yet handled decode SSL/TLS packets.
tls_record_buffer = <<>>, %% :: binary(), % Buffer of incomplete records
tls_handshake_buffer = <<>>, %% :: binary(), % Buffer of incomplete handshakes
tls_cipher_texts = [] %%:: [binary()]
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index f1eecb2875..c2b0d8e039 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -30,6 +30,7 @@
-include("ssl_alert.hrl").
-include("ssl_internal.hrl").
-include("ssl_cipher.hrl").
+-include("ssl_api.hrl").
-include_lib("public_key/include/public_key.hrl").
%% Handshake handling
@@ -47,7 +48,7 @@
%% Handshake handling
%%====================================================================
%%--------------------------------------------------------------------
--spec client_hello(host(), inet:port_number(), ssl_record:connection_states(),
+-spec client_hello(ssl:host(), inet:port_number(), ssl_record:connection_states(),
#ssl_options{}, integer(), atom(), boolean(), der_cert()) ->
#client_hello{}.
%%
@@ -81,13 +82,13 @@ client_hello(Host, Port, ConnectionStates,
-spec hello(#server_hello{} | #client_hello{}, #ssl_options{},
ssl_record:connection_states() | {inet:port_number(), #session{}, db_handle(),
atom(), ssl_record:connection_states(),
- binary() | undefined, ssl_cipher:key_algo()},
+ binary() | undefined, ssl:kex_algo()},
boolean()) ->
- {tls_record:tls_version(), session_id(),
+ {tls_record:tls_version(), ssl:session_id(),
ssl_record:connection_states(), alpn | npn, binary() | undefined}|
{tls_record:tls_version(), {resumed | new, #session{}},
ssl_record:connection_states(), binary() | undefined,
- #hello_extensions{}, {ssl_cipher:hash(), ssl_cipher:sign_algo()} |
+ #hello_extensions{}, {ssl:hash(), ssl:sign_algo()} |
undefined} | #alert{}.
%%
%% Description: Handles a received hello message
@@ -126,6 +127,9 @@ hello(#client_hello{client_version = ClientVersion,
handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
end
catch
+ error:{case_clause,{asn1, Asn1Reason}} ->
+ %% ASN-1 decode of certificate somehow failed
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {failed_to_decode_own_certificate, Asn1Reason});
_:_ ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data)
end.
@@ -153,7 +157,7 @@ encode_handshake(Package, Version) ->
%%--------------------------------------------------------------------
-spec get_tls_handshake(tls_record:tls_version(), binary(), binary() | iolist(),
#ssl_options{}) ->
- {[tls_handshake()], binary()}.
+ {[{tls_handshake(), binary()}], binary()}.
%%
%% Description: Given buffered and new data from ssl_record, collects
%% and returns it as a list of handshake messages, also returns leftover
@@ -196,7 +200,7 @@ handle_client_hello(Version,
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_ciphers);
_ ->
- #{key_exchange := KeyExAlg} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg,
SupportedHashSigns, Version) of
#alert{} = Alert ->
@@ -220,8 +224,6 @@ handle_client_hello_extensions(Version, Type, Random, CipherSuites,
HelloExt, Version, SslOpts,
Session0, ConnectionStates0,
Renegotiation) of
- #alert{} = Alert ->
- Alert;
{Session, ConnectionStates, Protocol, ServerHelloExt} ->
{Version, {Type, Session}, ConnectionStates, Protocol,
ServerHelloExt, HashSign}
@@ -232,14 +234,14 @@ handle_client_hello_extensions(Version, Type, Random, CipherSuites,
handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation) ->
- case ssl_handshake:handle_server_hello_extensions(tls_record, Random, CipherSuite,
+ try ssl_handshake:handle_server_hello_extensions(tls_record, Random, CipherSuite,
Compression, HelloExt, Version,
SslOpt, ConnectionStates0,
- Renegotiation) of
- #alert{} = Alert ->
- Alert;
+ Renegotiation) of
{ConnectionStates, ProtoExt, Protocol} ->
{Version, SessionId, ConnectionStates, ProtoExt, Protocol}
+ catch throw:Alert ->
+ Alert
end.
%%--------------------------------------------------------------------
enc_handshake(#hello_request{}, _Version) ->
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index f1aca8c801..38022030ee 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -75,25 +75,22 @@ init_connection_states(Role, BeastMitigation) ->
pending_write => Pending}.
%%--------------------------------------------------------------------
--spec get_tls_records(binary(), [tls_version()], binary()) -> {[binary()], binary()} | #alert{}.
+-spec get_tls_records(
+ binary(), [tls_version()] | tls_version(),
+ Buffer0 :: binary() | {'undefined' | #ssl_tls{}, {[binary()],non_neg_integer(),[binary()]}}) ->
+ {Records :: [#ssl_tls{}],
+ Buffer :: {'undefined' | #ssl_tls{}, {[binary()],non_neg_integer(),[binary()]}}} |
+ #alert{}.
%%
%% 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, Versions, Buffer) ->
- BinData = list_to_binary([Buffer, Data]),
- case erlang:byte_size(BinData) of
- N when N >= 3 ->
- case assert_version(BinData, Versions) of
- true ->
- get_tls_records_aux(BinData, []);
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end;
- _ ->
- get_tls_records_aux(BinData, [])
- end.
+
+get_tls_records(Data, Versions, Buffer) when is_binary(Buffer) ->
+ parse_tls_records(Versions, {[Data],byte_size(Data),[]}, undefined);
+get_tls_records(Data, Versions, {Hdr, {Front,Size,Rear}}) ->
+ parse_tls_records(Versions, {Front,Size + byte_size(Data),[Data|Rear]}, Hdr).
%%====================================================================
%% Encoding
@@ -113,8 +110,8 @@ encode_handshake(Frag, Version,
ConnectionStates) ->
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),
- encode_iolist(?HANDSHAKE, Data, Version, ConnectionStates);
+ Data = split_iovec(erlang:iolist_to_iovec(Frag), Version, BCA, BeastMitigation),
+ encode_fragments(?HANDSHAKE, Version, Data, ConnectionStates);
_ ->
encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates)
end.
@@ -140,18 +137,18 @@ encode_change_cipher_spec(Version, ConnectionStates) ->
encode_plain_text(?CHANGE_CIPHER_SPEC, Version, ?byte(?CHANGE_CIPHER_SPEC_PROTO), ConnectionStates).
%%--------------------------------------------------------------------
--spec encode_data(binary(), tls_version(), ssl_record:connection_states()) ->
- {iolist(), ssl_record:connection_states()}.
+-spec encode_data([binary()], tls_version(), ssl_record:connection_states()) ->
+ {[[binary()]], ssl_record:connection_states()}.
%%
%% Description: Encodes data to send on the ssl-socket.
%%--------------------------------------------------------------------
-encode_data(Frag, Version,
+encode_data(Data, Version,
#{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),
- encode_iolist(?APPLICATION_DATA, Data, Version, ConnectionStates).
+ Fragments = split_iovec(Data, Version, BCA, BeastMitigation),
+ encode_fragments(?APPLICATION_DATA, Version, Fragments, ConnectionStates).
%%====================================================================
%% Decoding
@@ -163,56 +160,59 @@ encode_data(Frag, Version,
%%
%% Description: Decode cipher text
%%--------------------------------------------------------------------
-decode_cipher_text(#ssl_tls{type = Type, version = Version,
- fragment = CipherFragment} = CipherText,
+decode_cipher_text(CipherText,
#{current_read :=
- #{compression_state := CompressionS0,
- sequence_number := Seq,
- cipher_state := CipherS0,
+ #{sequence_number := Seq,
security_parameters :=
- #security_parameters{
- cipher_type = ?AEAD,
- bulk_cipher_algorithm =
- BulkCipherAlgo,
- compression_algorithm = CompAlg}
- } = ReadState0} = ConnnectionStates0, _) ->
- AAD = calc_aad(Type, Version, ReadState0),
- case ssl_cipher:decipher_aead(BulkCipherAlgo, CipherS0, Seq, AAD, CipherFragment, Version) of
- {PlainFragment, CipherS1} ->
- {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
- PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#{
+ #security_parameters{cipher_type = ?AEAD,
+ bulk_cipher_algorithm = BulkCipherAlgo},
+ cipher_state := CipherS0
+ }
+ } = ConnectionStates0, _) ->
+ SeqBin = <<?UINT64(Seq)>>,
+ #ssl_tls{type = Type, version = {MajVer,MinVer} = Version, fragment = Fragment} = CipherText,
+ StartAdditionalData = <<SeqBin/binary, ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>,
+ CipherS = ssl_record:nonce_seed(BulkCipherAlgo, SeqBin, CipherS0),
+ case ssl_record:decipher_aead(
+ BulkCipherAlgo, CipherS, StartAdditionalData, Fragment, Version)
+ of
+ PlainFragment when is_binary(PlainFragment) ->
+ #{current_read :=
+ #{security_parameters := SecParams,
+ compression_state := CompressionS0} = ReadState0} = ConnectionStates0,
+ {Plain, CompressionS} = ssl_record:uncompress(SecParams#security_parameters.compression_algorithm,
+ PlainFragment, CompressionS0),
+ ConnectionStates = ConnectionStates0#{
current_read => ReadState0#{
- cipher_state => CipherS1,
+ cipher_state => CipherS,
sequence_number => Seq + 1,
- compression_state => CompressionS1}},
- {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
+ compression_state => CompressionS}},
+ {CipherText#ssl_tls{fragment = Plain}, ConnectionStates};
#alert{} = Alert ->
Alert
end;
-decode_cipher_text(#ssl_tls{type = Type, version = Version,
+decode_cipher_text(#ssl_tls{version = Version,
fragment = CipherFragment} = CipherText,
- #{current_read :=
- #{compression_state := CompressionS0,
- sequence_number := Seq,
- security_parameters :=
- #security_parameters{compression_algorithm = CompAlg}
- } = ReadState0} = ConnnectionStates0, PaddingCheck) ->
+ #{current_read := ReadState0} = ConnnectionStates0, PaddingCheck) ->
case ssl_record:decipher(Version, CipherFragment, ReadState0, PaddingCheck) of
{PlainFragment, Mac, ReadState1} ->
- MacHash = ssl_cipher:calc_mac_hash(Type, Version, PlainFragment, ReadState1),
+ MacHash = ssl_cipher:calc_mac_hash(CipherText#ssl_tls.type, Version, PlainFragment, ReadState1),
case ssl_record:is_correct_mac(Mac, MacHash) of
true ->
+ #{sequence_number := Seq,
+ compression_state := CompressionS0,
+ security_parameters :=
+ #security_parameters{compression_algorithm = CompAlg}} = ReadState0,
{Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#{
- current_read => ReadState1#{
- 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)
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end;
#alert{} = Alert ->
Alert
@@ -394,113 +394,224 @@ initial_connection_state(ConnectionEnd, BeastMitigation) ->
server_verify_data => undefined
}.
-assert_version(<<?BYTE(_), ?BYTE(MajVer), ?BYTE(MinVer), _/binary>>, Versions) ->
- is_acceptable_version({MajVer, MinVer}, Versions).
-
-get_tls_records_aux(<<?BYTE(?APPLICATION_DATA),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Length), Data:Length/binary, Rest/binary>>,
- Acc) ->
- get_tls_records_aux(Rest, [#ssl_tls{type = ?APPLICATION_DATA,
- version = {MajVer, MinVer},
- fragment = Data} | Acc]);
-get_tls_records_aux(<<?BYTE(?HANDSHAKE),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Length),
- Data:Length/binary, Rest/binary>>, Acc) ->
- get_tls_records_aux(Rest, [#ssl_tls{type = ?HANDSHAKE,
- version = {MajVer, MinVer},
- fragment = Data} | Acc]);
-get_tls_records_aux(<<?BYTE(?ALERT),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Length), Data:Length/binary,
- Rest/binary>>, Acc) ->
- get_tls_records_aux(Rest, [#ssl_tls{type = ?ALERT,
- version = {MajVer, MinVer},
- fragment = Data} | Acc]);
-get_tls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Length), Data:Length/binary, Rest/binary>>,
- Acc) ->
- get_tls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC,
- version = {MajVer, MinVer},
- fragment = Data} | Acc]);
-get_tls_records_aux(<<0:1, _CT:7, ?BYTE(_MajVer), ?BYTE(_MinVer),
- ?UINT16(Length), _/binary>>,
- _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
- ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
-get_tls_records_aux(Data, Acc) ->
- case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
- true ->
- {lists:reverse(Acc), Data};
- false ->
- ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
- end.
-%%--------------------------------------------------------------------
-encode_plain_text(Type, Version, Data, #{current_write := Write0} = ConnectionStates) ->
- {CipherFragment, Write1} = do_encode_plain_text(Type, Version, Data, Write0),
- {CipherText, Write} = encode_tls_cipher_text(Type, Version, CipherFragment, Write1),
- {CipherText, ConnectionStates#{current_write => Write}}.
-
-encode_tls_cipher_text(Type, {MajVer, MinVer}, Fragment, #{sequence_number := Seq} = Write) ->
- Length = erlang:iolist_size(Fragment),
- {[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, Fragment],
- Write#{sequence_number => Seq +1}}.
-
-encode_iolist(Type, Data, Version, ConnectionStates0) ->
- {ConnectionStates, EncodedMsg} =
- lists:foldl(fun(Text, {CS0, Encoded}) ->
- {Enc, CS1} =
- encode_plain_text(Type, Version, Text, CS0),
- {CS1, [Enc | Encoded]}
- end, {ConnectionStates0, []}, Data),
- {lists:reverse(EncodedMsg), ConnectionStates}.
-%%--------------------------------------------------------------------
-do_encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
- security_parameters :=
- #security_parameters{
- cipher_type = ?AEAD,
- compression_algorithm = CompAlg}
- } = WriteState0) ->
- {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#{compression_state => CompS1},
- AAD = calc_aad(Type, Version, WriteState1),
- ssl_record:cipher_aead(Version, Comp, WriteState1, AAD);
-do_encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
- security_parameters :=
- #security_parameters{compression_algorithm = CompAlg}
- }= WriteState0) ->
- {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#{compression_state => CompS1},
- MacHash = ssl_cipher:calc_mac_hash(Type, Version, Comp, WriteState1),
- ssl_record:cipher(Version, Comp, WriteState1, MacHash);
-do_encode_plain_text(_,_,_,CS) ->
+
+parse_tls_records(Versions, Q, undefined) ->
+ decode_tls_records(Versions, Q, [], undefined, undefined, undefined);
+parse_tls_records(Versions, Q, #ssl_tls{type = Type, version = Version, fragment = Length}) ->
+ decode_tls_records(Versions, Q, [], Type, Version, Length).
+
+%% Generic code path
+decode_tls_records(Versions, {_,Size,_} = Q0, Acc, undefined, _Version, _Length) ->
+ if
+ 5 =< Size ->
+ {<<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer), ?UINT16(Length)>>, Q} = binary_from_front(5, Q0),
+ validate_tls_records_type(Versions, Q, Acc, Type, {MajVer,MinVer}, Length);
+ 3 =< Size ->
+ {<<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer)>>, Q} = binary_from_front(3, Q0),
+ validate_tls_records_type(Versions, Q, Acc, Type, {MajVer,MinVer}, undefined);
+ 1 =< Size ->
+ {<<?BYTE(Type)>>, Q} = binary_from_front(1, Q0),
+ validate_tls_records_type(Versions, Q, Acc, Type, undefined, undefined);
+ true ->
+ validate_tls_records_type(Versions, Q0, Acc, undefined, undefined, undefined)
+ end;
+decode_tls_records(Versions, {_,Size,_} = Q0, Acc, Type, undefined, _Length) ->
+ if
+ 4 =< Size ->
+ {<<?BYTE(MajVer),?BYTE(MinVer), ?UINT16(Length)>>, Q} = binary_from_front(4, Q0),
+ validate_tls_record_version(Versions, Q, Acc, Type, {MajVer,MinVer}, Length);
+ 2 =< Size ->
+ {<<?BYTE(MajVer),?BYTE(MinVer)>>, Q} = binary_from_front(2, Q0),
+ validate_tls_record_version(Versions, Q, Acc, Type, {MajVer,MinVer}, undefined);
+ true ->
+ validate_tls_record_version(Versions, Q0, Acc, Type, undefined, undefined)
+ end;
+decode_tls_records(Versions, {_,Size,_} = Q0, Acc, Type, Version, undefined) ->
+ if
+ 2 =< Size ->
+ {<<?UINT16(Length)>>, Q} = binary_from_front(2, Q0),
+ validate_tls_record_length(Versions, Q, Acc, Type, Version, Length);
+ true ->
+ validate_tls_record_length(Versions, Q0, Acc, Type, Version, undefined)
+ end;
+decode_tls_records(Versions, Q, Acc, Type, Version, Length) ->
+ validate_tls_record_length(Versions, Q, Acc, Type, Version, Length).
+
+validate_tls_records_type(_Versions, Q, Acc, undefined, _Version, _Length) ->
+ {lists:reverse(Acc),
+ {undefined, Q}};
+validate_tls_records_type(Versions, Q, Acc, Type, Version, Length) ->
+ if
+ ?KNOWN_RECORD_TYPE(Type) ->
+ validate_tls_record_version(Versions, Q, Acc, Type, Version, Length);
+ true ->
+ %% Not ?KNOWN_RECORD_TYPE(Type)
+ ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
+ end.
+
+validate_tls_record_version(_Versions, Q, Acc, Type, undefined, _Length) ->
+ {lists:reverse(Acc),
+ {#ssl_tls{type = Type, version = undefined, fragment = undefined}, Q}};
+validate_tls_record_version(Versions, Q, Acc, Type, Version, Length) ->
+ if
+ is_list(Versions) ->
+ case is_acceptable_version(Version, Versions) of
+ true ->
+ validate_tls_record_length(Versions, Q, Acc, Type, Version, Length);
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+ Version =:= Versions ->
+ %% Exact version match
+ validate_tls_record_length(Versions, Q, Acc, Type, Version, Length);
+ true ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end.
+
+validate_tls_record_length(_Versions, Q, Acc, Type, Version, undefined) ->
+ {lists:reverse(Acc),
+ {#ssl_tls{type = Type, version = Version, fragment = undefined}, Q}};
+validate_tls_record_length(Versions, {_,Size0,_} = Q0, Acc, Type, Version, Length) ->
+ if
+ Length =< ?MAX_CIPHER_TEXT_LENGTH ->
+ if
+ Length =< Size0 ->
+ %% Complete record
+ {Fragment, Q} = binary_from_front(Length, Q0),
+ Record = #ssl_tls{type = Type, version = Version, fragment = Fragment},
+ decode_tls_records(Versions, Q, [Record|Acc], undefined, undefined, undefined);
+ true ->
+ {lists:reverse(Acc),
+ {#ssl_tls{type = Type, version = Version, fragment = Length}, Q0}}
+ end;
+ true ->
+ ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW)
+ end.
+
+
+binary_from_front(SplitSize, {Front,Size,Rear}) ->
+ binary_from_front(SplitSize, Front, Size, Rear, []).
+%%
+binary_from_front(SplitSize, [], Size, [_] = Rear, Acc) ->
+ %% Optimize a simple case
+ binary_from_front(SplitSize, Rear, Size, [], Acc);
+binary_from_front(SplitSize, [], Size, Rear, Acc) ->
+ binary_from_front(SplitSize, lists:reverse(Rear), Size, [], Acc);
+binary_from_front(SplitSize, [Bin|Front], Size, Rear, []) ->
+ %% Optimize a frequent case
+ BinSize = byte_size(Bin),
+ if
+ SplitSize < BinSize ->
+ {RetBin, Rest} = erlang:split_binary(Bin, SplitSize),
+ {RetBin, {[Rest|Front],Size - SplitSize,Rear}};
+ BinSize < SplitSize ->
+ binary_from_front(SplitSize - BinSize, Front, Size, Rear, [Bin]);
+ true -> % Perfect fit
+ {Bin, {Front,Size - SplitSize,Rear}}
+ end;
+binary_from_front(SplitSize, [Bin|Front], Size, Rear, Acc) ->
+ BinSize = byte_size(Bin),
+ if
+ SplitSize < BinSize ->
+ {Last, Rest} = erlang:split_binary(Bin, SplitSize),
+ RetBin = iolist_to_binary(lists:reverse(Acc, [Last])),
+ {RetBin, {[Rest|Front],Size - byte_size(RetBin),Rear}};
+ BinSize < SplitSize ->
+ binary_from_front(SplitSize - BinSize, Front, Size, Rear, [Bin|Acc]);
+ true -> % Perfect fit
+ RetBin = iolist_to_binary(lists:reverse(Acc, [Bin])),
+ {RetBin, {Front,Size - byte_size(RetBin),Rear}}
+ end.
+
+%%--------------------------------------------------------------------
+encode_plain_text(Type, Version, Data, ConnectionStates0) ->
+ {[CipherText],ConnectionStates} = encode_fragments(Type, Version, [Data], ConnectionStates0),
+ {CipherText,ConnectionStates}.
+%%--------------------------------------------------------------------
+encode_fragments(Type, Version, Data,
+ #{current_write := #{compression_state := CompS,
+ cipher_state := CipherS,
+ sequence_number := Seq}} = ConnectionStates) ->
+ encode_fragments(Type, Version, Data, ConnectionStates, CompS, CipherS, Seq, []).
+%%
+encode_fragments(_Type, _Version, [], #{current_write := WriteS} = CS,
+ CompS, CipherS, Seq, CipherFragments) ->
+ {lists:reverse(CipherFragments),
+ CS#{current_write := WriteS#{compression_state := CompS,
+ cipher_state := CipherS,
+ sequence_number := Seq}}};
+encode_fragments(Type, Version, [Text|Data],
+ #{current_write := #{security_parameters :=
+ #security_parameters{cipher_type = ?AEAD,
+ bulk_cipher_algorithm = BCAlg,
+ compression_algorithm = CompAlg} = SecPars}} = CS,
+ CompS0, CipherS0, Seq, CipherFragments) ->
+ {CompText, CompS} = ssl_record:compress(CompAlg, Text, CompS0),
+ SeqBin = <<?UINT64(Seq)>>,
+ CipherS1 = ssl_record:nonce_seed(BCAlg, SeqBin, CipherS0),
+ {MajVer, MinVer} = Version,
+ VersionBin = <<?BYTE(MajVer), ?BYTE(MinVer)>>,
+ StartAdditionalData = <<SeqBin/binary, ?BYTE(Type), VersionBin/binary>>,
+ {CipherFragment,CipherS} = ssl_record:cipher_aead(Version, CompText, CipherS1, StartAdditionalData, SecPars),
+ Length = byte_size(CipherFragment),
+ CipherHeader = <<?BYTE(Type), VersionBin/binary, ?UINT16(Length)>>,
+ encode_fragments(Type, Version, Data, CS, CompS, CipherS, Seq + 1,
+ [[CipherHeader, CipherFragment] | CipherFragments]);
+encode_fragments(Type, Version, [Text|Data],
+ #{current_write := #{security_parameters :=
+ #security_parameters{compression_algorithm = CompAlg,
+ mac_algorithm = MacAlgorithm} = SecPars,
+ mac_secret := MacSecret}} = CS,
+ CompS0, CipherS0, Seq, CipherFragments) ->
+ {CompText, CompS} = ssl_record:compress(CompAlg, Text, CompS0),
+ MacHash = ssl_cipher:calc_mac_hash(Type, Version, CompText, MacAlgorithm, MacSecret, Seq),
+ {CipherFragment,CipherS} = ssl_record:cipher(Version, CompText, CipherS0, MacHash, SecPars),
+ Length = byte_size(CipherFragment),
+ {MajVer, MinVer} = Version,
+ CipherHeader = <<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>,
+ encode_fragments(Type, Version, Data, CS, CompS, CipherS, Seq + 1,
+ [[CipherHeader, CipherFragment] | CipherFragments]);
+encode_fragments(_Type, _Version, _Data, CS, _CompS, _CipherS, _Seq, _CipherFragments) ->
exit({cs, CS}).
%%--------------------------------------------------------------------
-calc_aad(Type, {MajVer, MinVer},
- #{sequence_number := SeqNo}) ->
- <<?UINT64(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are
%% not vulnerable to this attack.
-split_bin(<<FirstByte:8, Rest/binary>>, ChunkSize, Version, BCA, one_n_minus_one) when
- BCA =/= ?RC4 andalso ({3, 1} == Version orelse
- {3, 0} == Version) ->
- do_split_bin(Rest, ChunkSize, [[FirstByte]]);
+split_iovec(Data, Version, BCA, one_n_minus_one)
+ when (BCA =/= ?RC4) andalso ({3, 1} == Version orelse
+ {3, 0} == Version) ->
+ {Part, RestData} = split_iovec(Data, 1, []),
+ [Part|split_iovec(RestData)];
%% 0/n splitting countermeasure for clients that are incompatible with 1/n-1
%% splitting.
-split_bin(Bin, ChunkSize, Version, BCA, zero_n) when
- BCA =/= ?RC4 andalso ({3, 1} == Version orelse
- {3, 0} == Version) ->
- do_split_bin(Bin, ChunkSize, [[<<>>]]);
-split_bin(Bin, ChunkSize, _, _, _) ->
- do_split_bin(Bin, ChunkSize, []).
-
-do_split_bin(<<>>, _, Acc) ->
- lists:reverse(Acc);
-do_split_bin(Bin, ChunkSize, Acc) ->
- case Bin of
- <<Chunk:ChunkSize/binary, Rest/binary>> ->
- do_split_bin(Rest, ChunkSize, [Chunk | Acc]);
- _ ->
- lists:reverse(Acc, [Bin])
- end.
+split_iovec(Data, Version, BCA, zero_n)
+ when (BCA =/= ?RC4) andalso ({3, 1} == Version orelse
+ {3, 0} == Version) ->
+ {Part, RestData} = split_iovec(Data, 0, []),
+ [Part|split_iovec(RestData)];
+split_iovec(Data, _Version, _BCA, _BeatMitigation) ->
+ split_iovec(Data).
+
+split_iovec([]) ->
+ [];
+split_iovec(Data) ->
+ {Part,Rest} = split_iovec(Data, ?MAX_PLAIN_TEXT_LENGTH, []),
+ [Part|split_iovec(Rest)].
+%%
+split_iovec([Bin|Data] = Bin_Data, SplitSize, Acc) ->
+ BinSize = byte_size(Bin),
+ if
+ BinSize =< SplitSize ->
+ split_iovec(Data, SplitSize - BinSize, [Bin|Acc]);
+ SplitSize == 0 ->
+ {lists:reverse(Acc), Bin_Data};
+ SplitSize < BinSize ->
+ {Last, Rest} = erlang:split_binary(Bin, SplitSize),
+ {lists:reverse(Acc, [Last]), [Rest|Data]}
+ end;
+split_iovec([], _SplitSize, Acc) ->
+ {lists:reverse(Acc),[]}.
+
%%--------------------------------------------------------------------
lowest_list_protocol_version(Ver, []) ->
Ver;
diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl
new file mode 100644
index 0000000000..c07b7f49cd
--- /dev/null
+++ b/lib/ssl/src/tls_sender.erl
@@ -0,0 +1,516 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(tls_sender).
+
+-behaviour(gen_statem).
+
+-include("ssl_internal.hrl").
+-include("ssl_alert.hrl").
+-include("ssl_handshake.hrl").
+-include("ssl_api.hrl").
+
+%% API
+-export([start/0, start/1, initialize/2, send_data/2, send_alert/2,
+ send_and_ack_alert/2, setopts/2, renegotiate/1, peer_renegotiate/1, downgrade/2,
+ update_connection_state/3, dist_tls_socket/1, dist_handshake_complete/3]).
+
+%% gen_statem callbacks
+-export([callback_mode/0, init/1, terminate/3, code_change/4]).
+-export([init/3, connection/3, handshake/3, death_row/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(static,
+ {connection_pid,
+ role,
+ socket,
+ socket_options,
+ tracker,
+ transport_cb,
+ negotiated_version,
+ renegotiate_at,
+ connection_monitor,
+ dist_handle
+ }).
+
+-record(data,
+ {static = #static{},
+ connection_states = #{}
+ }).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%--------------------------------------------------------------------
+-spec start() -> {ok, Pid :: pid()} |
+ ignore |
+ {error, Error :: term()}.
+-spec start(list()) -> {ok, Pid :: pid()} |
+ ignore |
+ {error, Error :: term()}.
+
+%% Description: Start sender process to avoid dead lock that
+%% may happen when a socket is busy (busy port) and the
+%% same process is sending and receiving
+%%--------------------------------------------------------------------
+start() ->
+ gen_statem:start(?MODULE, [], []).
+start(SpawnOpts) ->
+ gen_statem:start(?MODULE, [], SpawnOpts).
+
+%%--------------------------------------------------------------------
+-spec initialize(pid(), map()) -> ok.
+%% Description: So TLS connection process can initialize it sender
+%% process.
+%%--------------------------------------------------------------------
+initialize(Pid, InitMsg) ->
+ gen_statem:call(Pid, {self(), InitMsg}).
+
+%%--------------------------------------------------------------------
+-spec send_data(pid(), iodata()) -> ok | {error, term()}.
+%% Description: Send application data
+%%--------------------------------------------------------------------
+send_data(Pid, AppData) ->
+ %% Needs error handling for external API
+ call(Pid, {application_data, AppData}).
+
+%%--------------------------------------------------------------------
+-spec send_alert(pid(), #alert{}) -> _.
+%% Description: TLS connection process wants to send an Alert
+%% in the connection state.
+%%--------------------------------------------------------------------
+send_alert(Pid, Alert) ->
+ gen_statem:cast(Pid, Alert).
+
+%%--------------------------------------------------------------------
+-spec send_and_ack_alert(pid(), #alert{}) -> _.
+%% Description: TLS connection process wants to send an Alert
+%% in the connection state and recive an ack.
+%%--------------------------------------------------------------------
+send_and_ack_alert(Pid, Alert) ->
+ gen_statem:call(Pid, {ack_alert, Alert}, ?DEFAULT_TIMEOUT).
+%%--------------------------------------------------------------------
+-spec setopts(pid(), [{packet, integer() | atom()}]) -> ok | {error, term()}.
+%% Description: Send application data
+%%--------------------------------------------------------------------
+setopts(Pid, Opts) ->
+ call(Pid, {set_opts, Opts}).
+
+%%--------------------------------------------------------------------
+-spec renegotiate(pid()) -> {ok, WriteState::map()} | {error, closed}.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when handshaking.
+%%--------------------------------------------------------------------
+renegotiate(Pid) ->
+ %% Needs error handling for external API
+ call(Pid, renegotiate).
+
+%%--------------------------------------------------------------------
+-spec peer_renegotiate(pid()) -> {ok, WriteState::map()} | {error, term()}.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when handshaking.
+%%--------------------------------------------------------------------
+peer_renegotiate(Pid) ->
+ gen_statem:call(Pid, renegotiate, ?DEFAULT_TIMEOUT).
+
+%%--------------------------------------------------------------------
+-spec update_connection_state(pid(), WriteState::map(), tls_record:tls_version()) -> ok.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when sending application data.
+%%--------------------------------------------------------------------
+update_connection_state(Pid, NewState, Version) ->
+ gen_statem:cast(Pid, {new_write, NewState, Version}).
+
+%%--------------------------------------------------------------------
+-spec downgrade(pid(), integer()) -> {ok, ssl_record:connection_state()}
+ | {error, timeout}.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when sending application data.
+%%--------------------------------------------------------------------
+downgrade(Pid, Timeout) ->
+ try gen_statem:call(Pid, downgrade, Timeout) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ {error, timeout}
+ end.
+%%--------------------------------------------------------------------
+-spec dist_handshake_complete(pid(), node(), term()) -> ok.
+%% Description: Erlang distribution callback
+%%--------------------------------------------------------------------
+dist_handshake_complete(ConnectionPid, Node, DHandle) ->
+ gen_statem:call(ConnectionPid, {dist_handshake_complete, Node, DHandle}).
+%%--------------------------------------------------------------------
+-spec dist_tls_socket(pid()) -> {ok, #sslsocket{}}.
+%% Description: To enable distribution startup to get a proper "#sslsocket{}"
+%%--------------------------------------------------------------------
+dist_tls_socket(Pid) ->
+ gen_statem:call(Pid, dist_get_tls_socket).
+
+%%%===================================================================
+%%% gen_statem callbacks
+%%%===================================================================
+%%--------------------------------------------------------------------
+-spec callback_mode() -> gen_statem:callback_mode_result().
+%%--------------------------------------------------------------------
+callback_mode() ->
+ state_functions.
+
+
+-define(HANDLE_COMMON,
+ ?FUNCTION_NAME(Type, Msg, StateData) ->
+ handle_common(Type, Msg, StateData)).
+%%--------------------------------------------------------------------
+-spec init(Args :: term()) ->
+ gen_statem:init_result(atom()).
+%%--------------------------------------------------------------------
+init(_) ->
+ %% Note: Should not trap exits so that this process
+ %% will be terminated if tls_connection process is
+ %% killed brutally
+ {ok, init, #data{}}.
+
+%%--------------------------------------------------------------------
+-spec init(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+init({call, From}, {Pid, #{current_write := WriteState,
+ role := Role,
+ socket := Socket,
+ socket_options := SockOpts,
+ tracker := Tracker,
+ transport_cb := Transport,
+ negotiated_version := Version,
+ renegotiate_at := RenegotiateAt}},
+ #data{connection_states = ConnectionStates, static = Static0} = StateData0) ->
+ Monitor = erlang:monitor(process, Pid),
+ StateData =
+ StateData0#data{connection_states = ConnectionStates#{current_write => WriteState},
+ static = Static0#static{connection_pid = Pid,
+ connection_monitor = Monitor,
+ role = Role,
+ socket = Socket,
+ socket_options = SockOpts,
+ tracker = Tracker,
+ transport_cb = Transport,
+ negotiated_version = Version,
+ renegotiate_at = RenegotiateAt}},
+ {next_state, handshake, StateData, [{reply, From, ok}]};
+init(_, _, _) ->
+ %% Just in case anything else sneeks through
+ {keep_state_and_data, [postpone]}.
+
+%%--------------------------------------------------------------------
+-spec connection(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+connection({call, From}, {application_data, AppData},
+ #data{static = #static{socket_options = #socket_options{packet = Packet}}} =
+ StateData) ->
+ case encode_packet(Packet, AppData) of
+ {error, _} = Error ->
+ {next_state, ?FUNCTION_NAME, StateData, [{reply, From, Error}]};
+ Data ->
+ send_application_data(Data, From, ?FUNCTION_NAME, StateData)
+ end;
+connection({call, From}, {ack_alert, #alert{} = Alert}, StateData0) ->
+ StateData = send_tls_alert(Alert, StateData0),
+ {next_state, ?FUNCTION_NAME, StateData,
+ [{reply,From,ok}]};
+connection({call, From}, renegotiate,
+ #data{connection_states = #{current_write := Write}} = StateData) ->
+ {next_state, handshake, StateData, [{reply, From, {ok, Write}}]};
+connection({call, From}, downgrade, #data{connection_states =
+ #{current_write := Write}} = StateData) ->
+ {next_state, death_row, StateData, [{reply,From, {ok, Write}}]};
+connection({call, From}, {set_opts, Opts}, StateData) ->
+ handle_set_opts(From, Opts, StateData);
+connection({call, From}, dist_get_tls_socket,
+ #data{static = #static{transport_cb = Transport,
+ socket = Socket,
+ connection_pid = Pid,
+ tracker = Tracker}} = StateData) ->
+ TLSSocket = tls_connection:socket([Pid, self()], Transport, Socket, Tracker),
+ {next_state, ?FUNCTION_NAME, StateData, [{reply, From, {ok, TLSSocket}}]};
+connection({call, From}, {dist_handshake_complete, _Node, DHandle},
+ #data{static = #static{connection_pid = Pid} = Static} = StateData) ->
+ ok = erlang:dist_ctrl_input_handler(DHandle, Pid),
+ ok = ssl_connection:dist_handshake_complete(Pid, DHandle),
+ %% From now on we execute on normal priority
+ process_flag(priority, normal),
+ {keep_state, StateData#data{static = Static#static{dist_handle = DHandle}},
+ [{reply,From,ok}|
+ case dist_data(DHandle) of
+ [] ->
+ [];
+ Data ->
+ [{next_event, internal,
+ {application_packets,{self(),undefined},erlang:iolist_to_iovec(Data)}}]
+ end]};
+connection(internal, {application_packets, From, Data}, StateData) ->
+ send_application_data(Data, From, ?FUNCTION_NAME, StateData);
+%%
+connection(cast, #alert{} = Alert, StateData0) ->
+ StateData = send_tls_alert(Alert, StateData0),
+ {next_state, ?FUNCTION_NAME, StateData};
+connection(cast, {new_write, WritesState, Version},
+ #data{connection_states = ConnectionStates, static = Static} = StateData) ->
+ {next_state, connection,
+ StateData#data{connection_states =
+ ConnectionStates#{current_write => WritesState},
+ static = Static#static{negotiated_version = Version}}};
+%%
+connection(info, dist_data, #data{static = #static{dist_handle = DHandle}}) ->
+ {keep_state_and_data,
+ case dist_data(DHandle) of
+ [] ->
+ [];
+ Data ->
+ [{next_event, internal,
+ {application_packets,{self(),undefined},erlang:iolist_to_iovec(Data)}}]
+ end};
+connection(info, tick, StateData) ->
+ consume_ticks(),
+ Data = [<<0:32>>], % encode_packet(4, <<>>)
+ From = {self(), undefined},
+ send_application_data(Data, From, ?FUNCTION_NAME, StateData);
+connection(info, {send, From, Ref, Data}, _StateData) ->
+ %% This is for testing only!
+ %%
+ %% Needed by some OTP distribution
+ %% test suites...
+ From ! {Ref, ok},
+ {keep_state_and_data,
+ [{next_event, {call, {self(), undefined}},
+ {application_data, erlang:iolist_to_iovec(Data)}}]};
+?HANDLE_COMMON.
+
+%%--------------------------------------------------------------------
+-spec handshake(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+handshake({call, From}, {set_opts, Opts}, StateData) ->
+ handle_set_opts(From, Opts, StateData);
+handshake({call, _}, _, _) ->
+ %% Postpone all calls to the connection state
+ {keep_state_and_data, [postpone]};
+handshake(internal, {application_packets,_,_}, _) ->
+ {keep_state_and_data, [postpone]};
+handshake(cast, {new_write, WritesState, Version},
+ #data{connection_states = ConnectionStates, static = Static} = StateData) ->
+ {next_state, connection,
+ StateData#data{connection_states = ConnectionStates#{current_write => WritesState},
+ static = Static#static{negotiated_version = Version}}};
+handshake(info, dist_data, _) ->
+ {keep_state_and_data, [postpone]};
+handshake(info, tick, _) ->
+ %% Ignore - data is sent anyway during handshake
+ consume_ticks(),
+ keep_state_and_data;
+handshake(info, {send, _, _, _}, _) ->
+ %% Testing only, OTP distribution test suites...
+ {keep_state_and_data, [postpone]};
+?HANDLE_COMMON.
+
+%%--------------------------------------------------------------------
+-spec death_row(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+death_row(state_timeout, Reason, _State) ->
+ {stop, {shutdown, Reason}};
+death_row(_Type, _Msg, _State) ->
+ %% Waste all other events
+ keep_state_and_data.
+
+%%--------------------------------------------------------------------
+-spec terminate(Reason :: term(), State :: term(), Data :: term()) ->
+ any().
+%%--------------------------------------------------------------------
+terminate(_Reason, _State, _Data) ->
+ void.
+
+%%--------------------------------------------------------------------
+-spec code_change(
+ OldVsn :: term() | {down,term()},
+ State :: term(), Data :: term(), Extra :: term()) ->
+ {ok, NewState :: term(), NewData :: term()} |
+ (Reason :: term()).
+%% Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, Data, _Extra) ->
+ {ok, State, Data}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+handle_set_opts(
+ From, Opts, #data{static = #static{socket_options = SockOpts} = Static} = StateData) ->
+ {keep_state, StateData#data{static = Static#static{socket_options = set_opts(SockOpts, Opts)}},
+ [{reply, From, ok}]}.
+
+handle_common(
+ {call, From}, {set_opts, Opts},
+ #data{static = #static{socket_options = SockOpts} = Static} = StateData) ->
+ {keep_state, StateData#data{static = Static#static{socket_options = set_opts(SockOpts, Opts)}},
+ [{reply, From, ok}]};
+handle_common(
+ info, {'DOWN', Monitor, _, _, Reason},
+ #data{static = #static{connection_monitor = Monitor,
+ dist_handle = Handle}} = StateData) when Handle =/= undefined ->
+ {next_state, death_row, StateData,
+ [{state_timeout, 5000, Reason}]};
+handle_common(
+ info, {'DOWN', Monitor, _, _, _},
+ #data{static = #static{connection_monitor = Monitor}} = StateData) ->
+ {stop, normal, StateData};
+handle_common(info, Msg, _) ->
+ Report =
+ io_lib:format("TLS sender: Got unexpected info: ~p ~n", [Msg]),
+ error_logger:info_report(Report),
+ keep_state_and_data;
+handle_common(Type, Msg, _) ->
+ Report =
+ io_lib:format(
+ "TLS sender: Got unexpected event: ~p ~n", [{Type,Msg}]),
+ error_logger:error_report(Report),
+ keep_state_and_data.
+
+send_tls_alert(#alert{} = Alert,
+ #data{static = #static{negotiated_version = Version,
+ socket = Socket,
+ transport_cb = Transport},
+ connection_states = ConnectionStates0} = StateData0) ->
+ {BinMsg, ConnectionStates} =
+ tls_record:encode_alert_record(Alert, Version, ConnectionStates0),
+ tls_socket:send(Transport, Socket, BinMsg),
+ StateData0#data{connection_states = ConnectionStates}.
+
+send_application_data(Data, From, StateName,
+ #data{static = #static{connection_pid = Pid,
+ socket = Socket,
+ dist_handle = DistHandle,
+ negotiated_version = Version,
+ transport_cb = Transport,
+ renegotiate_at = RenegotiateAt},
+ connection_states = ConnectionStates0} = StateData0) ->
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ ssl_connection:internal_renegotiation(Pid, ConnectionStates0),
+ {next_state, handshake, StateData0,
+ [{next_event, internal, {application_packets, From, Data}}]};
+ false ->
+ {Msgs, ConnectionStates} = tls_record:encode_data(Data, Version, ConnectionStates0),
+ StateData = StateData0#data{connection_states = ConnectionStates},
+ case tls_socket:send(Transport, Socket, Msgs) of
+ ok when DistHandle =/= undefined ->
+ {next_state, StateName, StateData, []};
+ Reason when DistHandle =/= undefined ->
+ {next_state, death_row, StateData, [{state_timeout, 5000, Reason}]};
+ ok ->
+ {next_state, StateName, StateData, [{reply, From, ok}]};
+ Result ->
+ {next_state, StateName, StateData, [{reply, From, Result}]}
+ end
+ end.
+
+-compile({inline, encode_packet/2}).
+encode_packet(Packet, Data) ->
+ Len = iolist_size(Data),
+ case Packet of
+ 1 when Len < (1 bsl 8) -> [<<Len:8>>|Data];
+ 2 when Len < (1 bsl 16) -> [<<Len:16>>|Data];
+ 4 when Len < (1 bsl 32) -> [<<Len:32>>|Data];
+ N when N =:= 1; N =:= 2; N =:= 4 ->
+ {error,
+ {badarg, {packet_to_large, Len, (1 bsl (Packet bsl 3)) - 1}}};
+ _ ->
+ Data
+ end.
+
+set_opts(SocketOptions, [{packet, N}]) ->
+ SocketOptions#socket_options{packet = N}.
+
+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.
+
+call(FsmPid, Event) ->
+ try gen_statem:call(FsmPid, Event)
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{normal, _} ->
+ {error, closed};
+ exit:{{shutdown, _},_} ->
+ {error, closed}
+ end.
+
+%%-------------- Erlang distribution helpers ------------------------------
+
+dist_data(DHandle) ->
+ case erlang:dist_ctrl_get_data(DHandle) of
+ none ->
+ erlang:dist_ctrl_get_data_notification(DHandle),
+ [];
+ %% This is encode_packet(4, Data) without Len check
+ %% since the emulator will always deliver a Data
+ %% smaller than 4 GB, and the distribution will
+ %% therefore always have to use {packet,4}
+ Data when is_binary(Data) ->
+ Len = byte_size(Data),
+ [[<<Len:32>>,Data]|dist_data(DHandle)];
+ [BA,BB] = Data ->
+ Len = byte_size(BA) + byte_size(BB),
+ [[<<Len:32>>|Data]|dist_data(DHandle)];
+ Data when is_list(Data) ->
+ Len = iolist_size(Data),
+ [[<<Len:32>>|Data]|dist_data(DHandle)]
+ end.
+
+
+%% Empty the inbox from distribution ticks - do not let them accumulate
+consume_ticks() ->
+ receive tick ->
+ consume_ticks()
+ after 0 ->
+ ok
+ end.
diff --git a/lib/ssl/src/tls_socket.erl b/lib/ssl/src/tls_socket.erl
index 154281f1c2..6c32e6fa04 100644
--- a/lib/ssl/src/tls_socket.erl
+++ b/lib/ssl/src/tls_socket.erl
@@ -32,6 +32,7 @@
emulated_socket_options/2, get_emulated_opts/1,
set_emulated_opts/2, get_all_opts/1, handle_call/3, handle_cast/2,
handle_info/2, code_change/3]).
+-export([update_active_n/2]).
-record(state, {
emulated_opts,
@@ -45,18 +46,20 @@
send(Transport, Socket, Data) ->
Transport:send(Socket, Data).
-listen(Transport, Port, #config{transport_info = {Transport, _, _, _},
+listen(Transport, Port, #config{transport_info = {Transport, _, _, _, _},
inet_user = Options,
ssl = SslOpts, emulated = EmOpts} = Config) ->
case Transport:listen(Port, Options ++ internal_inet_values()) of
{ok, ListenSocket} ->
{ok, Tracker} = inherit_tracker(ListenSocket, EmOpts, SslOpts),
- {ok, #sslsocket{pid = {ListenSocket, Config#config{emulated = Tracker}}}};
+ Socket = #sslsocket{pid = {ListenSocket, Config#config{emulated = Tracker}}},
+ check_active_n(EmOpts, Socket),
+ {ok, Socket};
Err = {error, _} ->
Err
end.
-accept(ListenSocket, #config{transport_info = {Transport,_,_,_} = CbInfo,
+accept(ListenSocket, #config{transport_info = {Transport,_,_,_,_} = CbInfo,
connection_cb = ConnectionCb,
ssl = SslOpts,
emulated = Tracker}, Timeout) ->
@@ -64,11 +67,12 @@ accept(ListenSocket, #config{transport_info = {Transport,_,_,_} = CbInfo,
{ok, Socket} ->
{ok, EmOpts} = get_emulated_opts(Tracker),
{ok, Port} = tls_socket:port(Transport, Socket),
- ConnArgs = [server, "localhost", Port, Socket,
+ {ok, Sender} = tls_sender:start(),
+ ConnArgs = [server, Sender, "localhost", Port, Socket,
{SslOpts, emulated_socket_options(EmOpts, #socket_options{}), Tracker}, self(), CbInfo],
case tls_connection_sup:start_child(ConnArgs) of
{ok, Pid} ->
- ssl_connection:socket_control(ConnectionCb, Socket, Pid, Transport, Tracker);
+ ssl_connection:socket_control(ConnectionCb, Socket, [Pid, Sender], Transport, Tracker);
{error, Reason} ->
{error, Reason}
end;
@@ -76,7 +80,7 @@ accept(ListenSocket, #config{transport_info = {Transport,_,_,_} = CbInfo,
{error, Reason}
end.
-upgrade(Socket, #config{transport_info = {Transport,_,_,_}= CbInfo,
+upgrade(Socket, #config{transport_info = {Transport,_,_,_,_}= CbInfo,
ssl = SslOptions,
emulated = EmOpts, connection_cb = ConnectionCb}, Timeout) ->
ok = setopts(Transport, Socket, tls_socket:internal_inet_values()),
@@ -94,7 +98,7 @@ connect(Address, Port,
#config{transport_info = CbInfo, inet_user = UserOpts, ssl = SslOpts,
emulated = EmOpts, inet_ssl = SocketOpts, connection_cb = ConnetionCb},
Timeout) ->
- {Transport, _, _, _} = CbInfo,
+ {Transport, _, _, _, _} = CbInfo,
try Transport:connect(Address, Port, SocketOpts, Timeout) of
{ok, Socket} ->
ssl_connection:connect(ConnetionCb, Address, Port, Socket,
@@ -112,18 +116,20 @@ connect(Address, Port,
{error, {options, {socket_options, UserOpts}}}
end.
-socket(Pid, Transport, Socket, ConnectionCb, Tracker) ->
- #sslsocket{pid = Pid,
+socket(Pids, Transport, Socket, ConnectionCb, Tracker) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb, Tracker}}.
-setopts(gen_tcp, #sslsocket{pid = {ListenSocket, #config{emulated = Tracker}}}, Options) ->
+setopts(gen_tcp, Socket = #sslsocket{pid = {ListenSocket, #config{emulated = Tracker}}}, Options) ->
{SockOpts, EmulatedOpts} = split_options(Options),
ok = set_emulated_opts(Tracker, EmulatedOpts),
+ check_active_n(EmulatedOpts, Socket),
inet:setopts(ListenSocket, SockOpts);
-setopts(_, #sslsocket{pid = {ListenSocket, #config{transport_info = {Transport,_,_,_},
+setopts(_, Socket = #sslsocket{pid = {ListenSocket, #config{transport_info = {Transport,_,_,_,_},
emulated = Tracker}}}, Options) ->
{SockOpts, EmulatedOpts} = split_options(Options),
ok = set_emulated_opts(Tracker, EmulatedOpts),
+ check_active_n(EmulatedOpts, Socket),
Transport:setopts(ListenSocket, SockOpts);
%%% Following clauses will not be called for emulated options, they are handled in the connection process
setopts(gen_tcp, Socket, Options) ->
@@ -131,6 +137,31 @@ setopts(gen_tcp, Socket, Options) ->
setopts(Transport, Socket, Options) ->
Transport:setopts(Socket, Options).
+check_active_n(EmulatedOpts, Socket = #sslsocket{pid = {_, #config{emulated = Tracker}}}) ->
+ %% We check the resulting options to send an ssl_passive message if necessary.
+ case proplists:lookup(active, EmulatedOpts) of
+ %% The provided value is out of bound.
+ {_, N} when is_integer(N), N < -32768 ->
+ throw(einval);
+ {_, N} when is_integer(N), N > 32767 ->
+ throw(einval);
+ {_, N} when is_integer(N) ->
+ case get_emulated_opts(Tracker, [active]) of
+ [{_, false}] ->
+ self() ! {ssl_passive, Socket},
+ ok;
+ %% The result of the addition is out of bound.
+ [{_, A}] when is_integer(A), A < -32768 ->
+ throw(einval);
+ [{_, A}] when is_integer(A), A > 32767 ->
+ throw(einval);
+ _ ->
+ ok
+ end;
+ _ ->
+ ok
+ end.
+
getopts(gen_tcp, #sslsocket{pid = {ListenSocket, #config{emulated = Tracker}}}, Options) ->
{SockOptNames, EmulatedOptNames} = split_options(Options),
EmulatedOpts = get_emulated_opts(Tracker, EmulatedOptNames),
@@ -208,7 +239,7 @@ start_link(Port, SockOpts, SslOpts) ->
init([Port, Opts, SslOpts]) ->
process_flag(trap_exit, true),
true = link(Port),
- {ok, #state{emulated_opts = Opts, port = Port, ssl_opts = SslOpts}}.
+ {ok, #state{emulated_opts = do_set_emulated_opts(Opts, []), port = Port, ssl_opts = SslOpts}}.
%%--------------------------------------------------------------------
-spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}}.
@@ -303,9 +334,24 @@ split_options([Name | Opts], Emu, SocketOptNames, EmuOptNames) ->
do_set_emulated_opts([], Opts) ->
Opts;
+do_set_emulated_opts([{active, N0} | Rest], Opts) when is_integer(N0) ->
+ N = update_active_n(N0, proplists:get_value(active, Opts, false)),
+ do_set_emulated_opts(Rest, [{active, N} | proplists:delete(active, Opts)]);
do_set_emulated_opts([{Name,_} = Opt | Rest], Opts) ->
do_set_emulated_opts(Rest, [Opt | proplists:delete(Name, Opts)]).
+update_active_n(New, Current) ->
+ if
+ is_integer(Current), New + Current =< 0 ->
+ false;
+ is_integer(Current) ->
+ New + Current;
+ New =< 0 ->
+ false;
+ true ->
+ New
+ end.
+
get_socket_opts(_, [], _) ->
[];
get_socket_opts(ListenSocket, SockOptNames, Cb) ->
@@ -365,6 +411,9 @@ validate_inet_option(header, Value)
when not is_integer(Value) ->
throw({error, {options, {header,Value}}});
validate_inet_option(active, Value)
+ when Value >= -32768, Value =< 32767 ->
+ ok;
+validate_inet_option(active, Value)
when Value =/= true, Value =/= false, Value =/= once ->
throw({error, {options, {active,Value}}});
validate_inet_option(_, _) ->
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index d6b500748e..1bfd9a8b6d 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -192,7 +192,7 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, {Major, Minor},
Fragment]),
Mac.
--spec suites(1|2|3) -> [ssl_cipher:cipher_suite()].
+-spec suites(1|2|3) -> [ssl_cipher_format:cipher_suite()].
suites(Minor) when Minor == 1; Minor == 2 ->
[
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 9dfb2eba53..a10f71a3de 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -29,7 +29,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Application version
# ----------------------------------------------------
include ../vsn.mk
-VSN=$(GS_VSN)
+VSN=$(SSL_VSN)
# ----------------------------------------------------
# Target Specs
diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl
index 8fe7c54549..7f3371da9a 100644
--- a/lib/ssl/test/make_certs.erl
+++ b/lib/ssl/test/make_certs.erl
@@ -189,6 +189,18 @@ gencrl(Root, CA, C, CrlHours) ->
Env = [{"ROOTDIR", filename:absname(Root)}],
cmd(Cmd, Env).
+%% This function sets the number of seconds until the next CRL is due.
+gencrl_sec(Root, CA, C, CrlSecs) ->
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ CACRLFile = filename:join([Root, CA, "crl.pem"]),
+ Cmd = [C#config.openssl_cmd, " ca"
+ " -gencrl ",
+ " -crlsec ", integer_to_list(CrlSecs),
+ " -out ", CACRLFile,
+ " -config ", CACnfFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+
can_generate_expired_crls(C) ->
%% OpenSSL can generate CRLs with an expiration date in the past,
%% if we pass a negative number for -crlhours. However, LibreSSL
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index 3c8eda1812..c64358960c 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -43,10 +43,10 @@ all() ->
groups() ->
[
- {'tlsv1.2', [], test_cases()},
+ {'tlsv1.2', [], [mix_sign | test_cases()]},
{'tlsv1.1', [], test_cases()},
{'tlsv1', [], test_cases()},
- {'dtlsv1.2', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
{'dtlsv1', [], test_cases()}
].
@@ -212,53 +212,61 @@ client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
ecc_default_order(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa,
+ Config, DefaultCurve),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [],
- case ssl_test_lib:supported_eccs([{eccs, [sect571r1]}]) of
- true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
+ true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
ecc_default_order_custom_curves(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa,
+ Config, DefaultCurve),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
ecc_client_order(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa,
+ Config, DefaultCurve),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, false}],
- case ssl_test_lib:supported_eccs([{eccs, [sect571r1]}]) of
- true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
+ true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
ecc_client_order_custom_curves(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa,
+ Config, DefaultCurve),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
@@ -274,12 +282,13 @@ ecc_unknown_curve(Config) ->
client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdh_rsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
@@ -287,26 +296,28 @@ client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdh_rsa, ecdhe_rsa, Config),
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_rsa, ecdhe_ecdsa, Config),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
@@ -314,41 +325,45 @@ client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_rsa, ecdhe_rsa, Config),
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]},
- {client_chain, Default}],
- ecdhe_rsa, ecdh_rsa, Config),
+ {client_chain, Default}],
+ ecdhe_rsa, ecdh_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
-
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
+ Expected = secp256r1, %% The certificate curve
+
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(Expected, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
@@ -356,25 +371,27 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_ecdsa, ecdhe_rsa, Config),
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
false -> {skip, "unsupported named curves"}
@@ -382,13 +399,38 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
+ DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_rsa, ecdhe_ecdsa, Config),
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
- ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
false -> {skip, "unsupported named curves"}
end.
+
+mix_sign(Config) ->
+ mix_sign_rsa_peer(Config),
+ mix_sign_ecdsa_peer(Config).
+
+mix_sign_ecdsa_peer(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_ecc} |Config]),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config).
+
+
+mix_sign_rsa_peer(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_rsa} |Config]),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_RSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_rsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_RSA} | SOpts], Config).
+
diff --git a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
index 5a08b152a6..81a7dfd2da 100644
--- a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
@@ -57,13 +57,13 @@ all_groups() ->
groups() ->
case ssl_test_lib:openssl_sane_dtls() of
true ->
- [{'tlsv1.2', [], test_cases()},
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
{'tlsv1.1', [], test_cases()},
{'tlsv1', [], test_cases()},
- {'dtlsv1.2', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
{'dtlsv1', [], test_cases()}];
false ->
- [{'tlsv1.2', [], test_cases()},
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
{'tlsv1.1', [], test_cases()},
{'tlsv1', [], test_cases()}]
end.
@@ -202,6 +202,17 @@ client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
+
+mix_sign(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], [{client_type, erlang},
+ {server_type, openssl} | Config]).
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
index 27062d4801..dfc780479e 100644
--- a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
@@ -153,41 +153,41 @@ protocols_must_be_a_binary_list(Config) when is_list(Config) ->
empty_client(Config) when is_list(Config) ->
run_failing_handshake(Config,
- [{alpn_advertised_protocols, []}],
- [{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ [{alpn_advertised_protocols, []}],
+ [{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}],
+ no_application_protocol).
%--------------------------------------------------------------------------------
empty_server(Config) when is_list(Config) ->
run_failing_handshake(Config,
- [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
- [{alpn_preferred_protocols, []}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
+ [{alpn_preferred_protocols, []}],
+ no_application_protocol).
%--------------------------------------------------------------------------------
empty_client_empty_server(Config) when is_list(Config) ->
run_failing_handshake(Config,
- [{alpn_advertised_protocols, []}],
- [{alpn_preferred_protocols, []}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ [{alpn_advertised_protocols, []}],
+ [{alpn_preferred_protocols, []}],
+ no_application_protocol).
%--------------------------------------------------------------------------------
no_matching_protocol(Config) when is_list(Config) ->
run_failing_handshake(Config,
- [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
- [{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
+ [{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}],
+ no_application_protocol).
%--------------------------------------------------------------------------------
client_alpn_and_server_alpn(Config) when is_list(Config) ->
run_handshake(Config,
- [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
- [{alpn_preferred_protocols, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}],
- {ok, <<"http/1.1">>}).
+ [{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
+ [{alpn_preferred_protocols, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}],
+ {ok, <<"http/1.1">>}).
%--------------------------------------------------------------------------------
@@ -262,52 +262,12 @@ client_renegotiate(Config) when is_list(Config) ->
%--------------------------------------------------------------------------------
session_reused(Config) when is_list(Config)->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"http/1.0">>]}] ++ ClientOpts0,
ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}] ++ ServerOpts0,
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {options, ServerOpts}]),
-
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result_msg, []}},
- {options, ClientOpts}]),
-
- SessionInfo =
- receive
- {Server, Info} ->
- Info
- end,
-
- Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
-
- %% Make sure session is registered
- ct:sleep(?SLEEP),
-
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- receive
- {Client1, SessionInfo} ->
- ok;
- {Client1, Other} ->
- ct:fail(Other)
- end,
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- ssl_test_lib:close(Client1).
-
+ ssl_test_lib:reuse_session(ClientOpts, ServerOpts, Config).
%--------------------------------------------------------------------------------
alpn_not_supported_client(Config) when is_list(Config) ->
@@ -337,23 +297,23 @@ alpn_not_supported_server(Config) when is_list(Config)->
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-run_failing_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedResult) ->
+run_failing_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedAlert) ->
ClientOpts = ClientExtraOpts ++ ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = ServerExtraOpts ++ ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {?MODULE, placeholder, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- ExpectedResult
- = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, placeholder, []}},
- {options, ClientOpts}]).
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, placeholder, []}},
+ {options, ClientOpts}]),
+ ssl_test_lib:check_client_alert(Server, Client, ExpectedAlert).
run_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) ->
Data = "hello world",
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 959de60f57..4452adaea7 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -147,8 +147,7 @@ options_tests_tls() ->
tls_tcp_reuseaddr].
api_tests() ->
- [connection_info,
- secret_connection_info,
+ [secret_connection_info,
connection_information,
peercert,
peercert_with_client_cert,
@@ -165,8 +164,10 @@ api_tests() ->
accept_pool,
prf,
socket_options,
+ active_n,
cipher_suites,
handshake_continue,
+ handshake_continue_timeout,
hello_client_cancel,
hello_server_cancel
].
@@ -243,7 +244,12 @@ error_handling_tests()->
[close_transport_accept,
recv_active,
recv_active_once,
- recv_error_handling
+ recv_active_n,
+ recv_error_handling,
+ call_in_error_state,
+ close_in_error_state,
+ abuse_transport_accept_socket,
+ controlling_process_transport_accept_socket
].
error_handling_tests_tls()->
@@ -476,6 +482,8 @@ init_per_testcase(TestCase, Config) when TestCase == tls_ssl_accept_timeout;
TestCase == tls_client_closes_socket;
TestCase == tls_closed_in_active_once;
TestCase == tls_downgrade ->
+ ssl:stop(),
+ ssl:start(),
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 15}),
Config;
@@ -567,11 +575,10 @@ alerts(Config) when is_list(Config) ->
Alerts = [?ALERT_REC(?WARNING, ?CLOSE_NOTIFY) |
[?ALERT_REC(?FATAL, Desc) || Desc <- Descriptions]],
lists:foreach(fun(Alert) ->
- case ssl_alert:alert_txt(Alert) of
- Txt when is_list(Txt) ->
- ok;
- Other ->
- ct:fail({unexpected, Other})
+ try ssl_alert:alert_txt(Alert)
+ catch
+ C:E:T ->
+ ct:fail({unexpected, {C, E, T}})
end
end, Alerts).
%%--------------------------------------------------------------------
@@ -610,7 +617,16 @@ new_options_in_accept(Config) when is_list(Config) ->
[_ , _ | ServerSslOpts] = ssl_test_lib:ssl_options(server_opts, Config), %% Remove non ssl opts
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Version = ssl_test_lib:protocol_options(Config, [{tls, sslv3}, {dtls, dtlsv1}]),
- Cipher = ssl_test_lib:protocol_options(Config, [{tls, {rsa,rc4_128,sha}}, {dtls, {rsa,aes_128_cbc,sha}}]),
+ Cipher = ssl_test_lib:protocol_options(Config, [{tls, #{key_exchange =>rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf
+ }},
+ {dtls, #{key_exchange =>rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf
+ }}]),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{ssl_extra_opts, [{versions, [Version]},
@@ -640,8 +656,8 @@ new_options_in_accept(Config) when is_list(Config) ->
handshake_continue() ->
[{doc, "Test API function ssl:handshake_continue/3"}].
handshake_continue(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -667,6 +683,34 @@ handshake_continue(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+%%------------------------------------------------------------------
+handshake_continue_timeout() ->
+ [{doc, "Test API function ssl:handshake_continue/3 with short timeout"}].
+handshake_continue_timeout(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {timeout, 1},
+ {options, ssl_test_lib:ssl_options([{reuseaddr, true}, {handshake, hello}],
+ Config)},
+ {continue_options, proplists:delete(reuseaddr, ServerOpts)}
+ ]),
+
+ Port = ssl_test_lib:inet_port(Server),
+
+
+ {connect_failed, _} = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Server, {error,timeout}),
+ ssl_test_lib:close(Server).
+
+
%%--------------------------------------------------------------------
hello_client_cancel() ->
[{doc, "Test API function ssl:handshake_cancel/1 on the client side"}].
@@ -688,19 +732,12 @@ hello_client_cancel(Config) when is_list(Config) ->
{from, self()},
{options, ssl_test_lib:ssl_options([{handshake, hello}], Config)},
{continue_options, cancel}]),
- receive
- {Server, {error, {tls_alert, "user canceled"}}} ->
- ok;
- {Server, {error, closed}} ->
- ct:pal("Did not receive the ALERT"),
- ok
- end.
-
+ ssl_test_lib:check_server_alert(Server, user_canceled).
%%--------------------------------------------------------------------
hello_server_cancel() ->
[{doc, "Test API function ssl:handshake_cancel/1 on the server side"}].
hello_server_cancel(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -739,46 +776,11 @@ prf(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-connection_info() ->
- [{doc,"Test the API function ssl:connection_information/2"}].
-connection_info(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
- {options, ServerOpts}]),
-
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
- {options,
- [{ciphers,[{dhe_rsa, aes_128_cbc, sha}]} |
- ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- Version = ssl_test_lib:protocol_version(Config),
-
- ServerMsg = ClientMsg = {ok, {Version, {dhe_rsa, aes_128_cbc, sha}}},
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
secret_connection_info() ->
[{doc,"Test the API function ssl:connection_information/2"}].
secret_connection_info(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -859,42 +861,30 @@ controlling_process(Config) when is_list(Config) ->
ClientMsg = "Server hello",
ServerMsg = "Client hello",
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE,
- controlling_process_result, [self(),
- ServerMsg]}},
- {options, ServerOpts}]),
+ Server = ssl_test_lib:start_server([
+ {node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ controlling_process_result, [self(),
+ ServerMsg]}},
+ {options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
+ {Client, CSocket} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
{mfa, {?MODULE,
controlling_process_result, [self(),
ClientMsg]}},
{options, ClientOpts}]),
-
+
ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
+ [self(), Client, Server]),
- receive
- {ssl, _, "S"} ->
- receive_s_rizzo_duong_beast();
- {ssl, _, ServerMsg} ->
- receive
- {ssl, _, ClientMsg} ->
- ok
- end;
- {ssl, _, "C"} ->
- receive_c_rizzo_duong_beast();
- {ssl, _, ClientMsg} ->
- receive
- {ssl, _, ServerMsg} ->
- ok
- end;
- Unexpected ->
- ct:fail(Unexpected)
- end,
+ ServerMsg = ssl_test_lib:active_recv(CSocket, length(ServerMsg)),
+ %% We do not have the TLS server socket but all messages form the client
+ %% socket are now read, so ramining are form the server socket
+ ClientMsg = ssl_active_recv(length(ClientMsg)),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
@@ -1118,16 +1108,19 @@ tls_closed_in_active_once(Config) when is_list(Config) ->
end.
tls_closed_in_active_once_loop(Socket) ->
- ssl:setopts(Socket, [{active, once}]),
- receive
- {ssl, Socket, _} ->
- tls_closed_in_active_once_loop(Socket);
- {ssl_closed, Socket} ->
- ok
- after 5000 ->
- no_ssl_closed_received
+ case ssl:setopts(Socket, [{active, once}]) of
+ ok ->
+ receive
+ {ssl, Socket, _} ->
+ tls_closed_in_active_once_loop(Socket);
+ {ssl_closed, Socket} ->
+ ok
+ after 5000 ->
+ no_ssl_closed_received
+ end;
+ {error, closed} ->
+ ok
end.
-
%%--------------------------------------------------------------------
connect_dist() ->
[{doc,"Test a simple connect as is used by distribution"}].
@@ -1206,16 +1199,15 @@ fallback(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(Server),
- Client =
- ssl_test_lib:start_client_error([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {from, self()}, {options,
- [{fallback, true},
- {versions, ['tlsv1']}
- | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, {error,{tls_alert,"inappropriate fallback"}},
- Client, {error,{tls_alert,"inappropriate fallback"}}).
+ Client =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {from, self()}, {options,
+ [{fallback, true},
+ {versions, ['tlsv1']}
+ | ClientOpts]}]),
+ ssl_test_lib:check_server_alert(Server, Client, inappropriate_fallback).
+
%%--------------------------------------------------------------------
cipher_format() ->
@@ -1476,8 +1468,8 @@ cipher_suites_mix() ->
cipher_suites_mix(Config) when is_list(Config) ->
CipherSuites = [{dhe_rsa,aes_128_cbc,sha256,sha256}, {dhe_rsa,aes_128_cbc,sha}],
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -1866,14 +1858,12 @@ eccs() ->
eccs(Config) when is_list(Config) ->
[_|_] = All = ssl:eccs(),
- [] = SSL3 = ssl:eccs({3,0}),
- [_|_] = Tls = ssl:eccs({3,1}),
- [_|_] = Tls1 = ssl:eccs({3,2}),
- [_|_] = Tls2 = ssl:eccs({3,3}),
[] = SSL3 = ssl:eccs(sslv3),
[_|_] = Tls = ssl:eccs(tlsv1),
[_|_] = Tls1 = ssl:eccs('tlsv1.1'),
[_|_] = Tls2 = ssl:eccs('tlsv1.2'),
+ [_|_] = Tls1 = ssl:eccs('dtlsv1'),
+ [_|_] = Tls2 = ssl:eccs('dtlsv1.2'),
%% ordering is currently unverified by the test
true = lists:sort(All) =:= lists:usort(SSL3 ++ Tls ++ Tls1 ++ Tls2),
ok.
@@ -1987,7 +1977,7 @@ recv_active(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
recv_active_once() ->
- [{doc,"Test recv on active socket"}].
+ [{doc,"Test recv on active (once) socket"}].
recv_active_once(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
@@ -2012,6 +2002,178 @@ recv_active_once(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+recv_active_n() ->
+ [{doc,"Test recv on active (n) socket"}].
+
+recv_active_n(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, try_recv_active_once, []}},
+ {options, [{active, 1} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, try_recv_active_once, []}},
+ {options, [{active, 1} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+%% Test case adapted from gen_tcp_misc_SUITE.
+active_n() ->
+ [{doc,"Test {active,N} option"}].
+
+active_n(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ Port = ssl_test_lib:inet_port(node()),
+ N = 3,
+ LS = ok(ssl:listen(Port, [{active,N}|ServerOpts])),
+ [{active,N}] = ok(ssl:getopts(LS, [active])),
+ active_n_common(LS, N),
+ Self = self(),
+ spawn_link(fun() ->
+ S0 = ok(ssl:transport_accept(LS)),
+ {ok, S} = ssl:handshake(S0),
+ ok = ssl:setopts(S, [{active,N}]),
+ [{active,N}] = ok(ssl:getopts(S, [active])),
+ ssl:controlling_process(S, Self),
+ Self ! {server, S}
+ end),
+ C = ok(ssl:connect("localhost", Port, [{active,N}|ClientOpts])),
+ [{active,N}] = ok(ssl:getopts(C, [active])),
+ S = receive
+ {server, S0} -> S0
+ after
+ 1000 ->
+ exit({error, connect})
+ end,
+ active_n_common(C, N),
+ active_n_common(S, N),
+ ok = ssl:setopts(C, [{active,N}]),
+ ok = ssl:setopts(S, [{active,N}]),
+ ReceiveMsg = fun(Socket, Msg) ->
+ receive
+ {ssl,Socket,Msg} ->
+ ok;
+ {ssl,Socket,Begin} ->
+ receive
+ {ssl,Socket,End} ->
+ Msg = Begin ++ End,
+ ok
+ after 1000 ->
+ exit(timeout)
+ end
+ after 1000 ->
+ exit(timeout)
+ end
+ end,
+ repeat(3, fun(I) ->
+ Msg = "message "++integer_to_list(I),
+ ok = ssl:send(C, Msg),
+ ReceiveMsg(S, Msg),
+ ok = ssl:send(S, Msg),
+ ReceiveMsg(C, Msg)
+ end),
+ receive
+ {ssl_passive,S} ->
+ [{active,false}] = ok(ssl:getopts(S, [active]))
+ after
+ 1000 ->
+ exit({error,ssl_passive})
+ end,
+ receive
+ {ssl_passive,C} ->
+ [{active,false}] = ok(ssl:getopts(C, [active]))
+ after
+ 1000 ->
+ exit({error,ssl_passive})
+ end,
+ LS2 = ok(ssl:listen(0, [{active,0}])),
+ receive
+ {ssl_passive,LS2} ->
+ [{active,false}] = ok(ssl:getopts(LS2, [active]))
+ after
+ 1000 ->
+ exit({error,ssl_passive})
+ end,
+ ok = ssl:close(LS2),
+ ok = ssl:close(C),
+ ok = ssl:close(S),
+ ok = ssl:close(LS),
+ ok.
+
+active_n_common(S, N) ->
+ ok = ssl:setopts(S, [{active,-N}]),
+ receive
+ {ssl_passive, S} -> ok
+ after
+ 1000 ->
+ error({error,ssl_passive_failure})
+ end,
+ [{active,false}] = ok(ssl:getopts(S, [active])),
+ ok = ssl:setopts(S, [{active,0}]),
+ receive
+ {ssl_passive, S} -> ok
+ after
+ 1000 ->
+ error({error,ssl_passive_failure})
+ end,
+ ok = ssl:setopts(S, [{active,32767}]),
+ {error,{options,_}} = ssl:setopts(S, [{active,1}]),
+ {error,{options,_}} = ssl:setopts(S, [{active,-32769}]),
+ ok = ssl:setopts(S, [{active,-32768}]),
+ receive
+ {ssl_passive, S} -> ok
+ after
+ 1000 ->
+ error({error,ssl_passive_failure})
+ end,
+ [{active,false}] = ok(ssl:getopts(S, [active])),
+ ok = ssl:setopts(S, [{active,N}]),
+ ok = ssl:setopts(S, [{active,true}]),
+ [{active,true}] = ok(ssl:getopts(S, [active])),
+ receive
+ _ -> error({error,active_n})
+ after
+ 0 ->
+ ok
+ end,
+ ok = ssl:setopts(S, [{active,N}]),
+ ok = ssl:setopts(S, [{active,once}]),
+ [{active,once}] = ok(ssl:getopts(S, [active])),
+ receive
+ _ -> error({error,active_n})
+ after
+ 0 ->
+ ok
+ end,
+ {error,{options,_}} = ssl:setopts(S, [{active,32768}]),
+ ok = ssl:setopts(S, [{active,false}]),
+ [{active,false}] = ok(ssl:getopts(S, [active])),
+ ok.
+
+ok({ok,V}) -> V.
+
+repeat(N, Fun) ->
+ repeat(N, N, Fun).
+
+repeat(N, T, Fun) when is_integer(N), N > 0 ->
+ Fun(T-N),
+ repeat(N-1, T, Fun);
+repeat(_, _, _) ->
+ ok.
+
+%%--------------------------------------------------------------------
dh_params() ->
[{doc,"Test to specify DH-params file in server."}].
@@ -2136,15 +2298,21 @@ tls_downgrade(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, tls_downgrade_result, []}},
+ {mfa, {?MODULE, tls_downgrade_result, [self()]}},
{options, [{active, false} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, tls_downgrade_result, []}},
+ {mfa, {?MODULE, tls_downgrade_result, [self()]}},
{options, [{active, false} |ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ready, Client, ready),
+
+ Server ! go,
+ Client ! go,
+
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
@@ -2382,8 +2550,8 @@ invalid_options() ->
[{doc,"Test what happens when we give invalid options"}].
invalid_options(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Check = fun(Client, Server, {versions, [sslv2, sslv3]} = Option) ->
@@ -2398,27 +2566,28 @@ invalid_options(Config) when is_list(Config) ->
{error, {options, Option}})
end,
- TestOpts = [{versions, [sslv2, sslv3]},
- {verify, 4},
- {verify_fun, function},
- {fail_if_no_peer_cert, 0},
- {verify_client_once, 1},
- {depth, four},
- {certfile, 'cert.pem'},
- {keyfile,'key.pem' },
- {password, foo},
- {cacertfile, ""},
- {dhfile,'dh.pem' },
- {ciphers, [{foo, bar, sha, ignore}]},
- {reuse_session, foo},
- {reuse_sessions, 0},
- {renegotiate_at, "10"},
- {mode, depech},
- {packet, 8.0},
- {packet_size, "2"},
- {header, a},
- {active, trice},
- {key, 'key.pem' }],
+ TestOpts =
+ [{versions, [sslv2, sslv3]},
+ {verify, 4},
+ {verify_fun, function},
+ {fail_if_no_peer_cert, 0},
+ {verify_client_once, 1},
+ {depth, four},
+ {certfile, 'cert.pem'},
+ {keyfile,'key.pem' },
+ {password, foo},
+ {cacertfile, ""},
+ {dhfile,'dh.pem' },
+ {ciphers, [{foo, bar, sha, ignore}]},
+ {reuse_session, foo},
+ {reuse_sessions, 0},
+ {renegotiate_at, "10"},
+ {mode, depech},
+ {packet, 8.0},
+ {packet_size, "2"},
+ {header, a},
+ {active, trice},
+ {key, 'key.pem' }],
[begin
Server =
@@ -2668,14 +2837,13 @@ default_reject_anonymous(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {options,
- [{ciphers,[CipherSuite]} |
- ClientOpts]}]),
+ {host, Hostname},
+ {from, self()},
+ {options,
+ [{ciphers,[CipherSuite]} |
+ ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}},
- Client, {error, {tls_alert, "insufficient security"}}).
+ ssl_test_lib:check_server_alert(Server, Client, insufficient_security).
%%--------------------------------------------------------------------
ciphers_ecdsa_signed_certs() ->
@@ -2711,175 +2879,69 @@ ciphers_ecdh_rsa_signed_certs_openssl_names(Config) when is_list(Config) ->
reuse_session() ->
[{doc,"Test reuse of sessions (short handshake)"}].
reuse_session(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client0 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]),
- SessionInfo =
- receive
- {Server, Info} ->
- Info
- end,
-
- Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
-
- %% Make sure session is registered
- ct:sleep(?SLEEP),
-
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, ClientOpts}]),
- receive
- {Client1, SessionInfo} ->
- ok;
- {Client1, Other} ->
- ct:log("Expected: ~p, Unexpected: ~p~n",
- [SessionInfo, Other]),
- ct:fail(session_not_reused)
- end,
-
- Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
-
- Client2 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, [{reuse_sessions, false}
- | ClientOpts]}]),
- receive
- {Client2, SessionInfo} ->
- ct:fail(
- session_reused_when_session_reuse_disabled_by_client);
- {Client2, _} ->
- ok
- end,
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- ssl_test_lib:close(Server),
-
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {options, [{reuse_sessions, false} | ServerOpts]}]),
-
- Port1 = ssl_test_lib:inet_port(Server1),
- Client3 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port1}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- SessionInfo1 =
- receive
- {Server1, Info1} ->
- Info1
- end,
-
- Server1 ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
-
- %% Make sure session is registered
- ct:sleep(?SLEEP),
-
- Client4 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port1}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- receive
- {Client4, SessionInfo1} ->
- ct:fail(
- session_reused_when_session_reuse_disabled_by_server);
- {Client4, _Other} ->
- ct:log("OTHER: ~p ~n", [_Other]),
- ok
- end,
-
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client0),
- ssl_test_lib:close(Client1),
- ssl_test_lib:close(Client2),
- ssl_test_lib:close(Client3),
- ssl_test_lib:close(Client4).
-
+ ssl_test_lib:reuse_session(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
reuse_session_expired() ->
[{doc,"Test sessions is not reused when it has expired"}].
reuse_session_expired(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+
+ Server0 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client0 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]),
- SessionInfo =
- receive
- {Server, Info} ->
- Info
- end,
-
- Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {tcp_options, [{active, false}]},
+ {options, ServerOpts}]),
+ Port0 = ssl_test_lib:inet_port(Server0),
- %% Make sure session is registered
- ct:sleep(?SLEEP),
-
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, ClientOpts}]),
+ Client0 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_sessions, save} | ClientOpts]}]),
+ Server0 ! listen,
+
+ Client1 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, ClientOpts}]),
+
+ SID = receive
+ {Client0, Id0} ->
+ Id0
+ end,
+
receive
- {Client1, SessionInfo} ->
- ok;
- {Client1, Other} ->
- ct:log("Expected: ~p, Unexpected: ~p~n",
- [SessionInfo, Other]),
- ct:fail(session_not_reused)
+ {Client1, SID} ->
+ ok
+ after ?SLEEP ->
+ ct:fail(session_not_reused)
end,
- Server ! listen,
-
+ Server0 ! listen,
+
%% Make sure session is unregistered due to expiration
- ct:sleep((?EXPIRE+1)),
- [{session_id, Id} |_] = SessionInfo,
+ ct:sleep((?EXPIRE*2)),
- make_sure_expired(Hostname, Port, Id),
+ make_sure_expired(Hostname, Port0, SID),
Client2 =
ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
+ {port, Port0}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
{from, self()}, {options, ClientOpts}]),
receive
- {Client2, SessionInfo} ->
+ {Client2, SID} ->
ct:fail(session_reused_when_session_expired);
{Client2, _} ->
ok
end,
process_flag(trap_exit, false),
- ssl_test_lib:close(Server),
+ ssl_test_lib:close(Server0),
ssl_test_lib:close(Client0),
ssl_test_lib:close(Client1),
ssl_test_lib:close(Client2).
@@ -2888,16 +2950,16 @@ make_sure_expired(Host, Port, Id) ->
{status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
[_, _,_, _, Prop] = StatusInfo,
State = ssl_test_lib:state(Prop),
- Cache = element(2, State),
+ ClientCache = element(2, State),
- case ssl_session_cache:lookup(Cache, {{Host, Port}, Id}) of
+ case ssl_session_cache:lookup(ClientCache, {{Host, Port}, Id}) of
undefined ->
- ok;
+ ok;
#session{is_resumable = false} ->
- ok;
+ ok;
_ ->
ct:sleep(?SLEEP),
- make_sure_expired(Host, Port, Id)
+ make_sure_expired(Host, Port, Id)
end.
%%--------------------------------------------------------------------
@@ -3293,7 +3355,7 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, DsaServerOpts}]),
+ {options, [{reuseaddr, true} | DsaServerOpts]}]),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
@@ -3354,7 +3416,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, NewServerOpts1}]),
+ {options, [{reuseaddr, true} | NewServerOpts1]}]),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
@@ -3475,16 +3537,50 @@ tls_tcp_reuseaddr(Config) when is_list(Config) ->
honor_server_cipher_order() ->
[{doc,"Test API honor server cipher order."}].
honor_server_cipher_order(Config) when is_list(Config) ->
- ClientCiphers = [{dhe_rsa, aes_128_cbc, sha}, {dhe_rsa, aes_256_cbc, sha}],
- ServerCiphers = [{dhe_rsa, aes_256_cbc, sha}, {dhe_rsa, aes_128_cbc, sha}],
-honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, {dhe_rsa, aes_256_cbc, sha}).
+ ClientCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}],
+ ServerCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac =>sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}],
+ honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}).
honor_client_cipher_order() ->
[{doc,"Test API honor server cipher order."}].
honor_client_cipher_order(Config) when is_list(Config) ->
- ClientCiphers = [{dhe_rsa, aes_128_cbc, sha}, {dhe_rsa, aes_256_cbc, sha}],
- ServerCiphers = [{dhe_rsa, aes_256_cbc, sha}, {dhe_rsa, aes_128_cbc, sha}],
-honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, {dhe_rsa, aes_128_cbc, sha}).
+ ClientCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}],
+ ServerCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac =>sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}],
+honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}).
honor_cipher_order(Config, Honor, ServerCiphers, ClientCiphers, Expected) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
@@ -3594,14 +3690,13 @@ no_common_signature_algs(Config) when is_list(Config) ->
| ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {options, [{signature_algs, [{sha384, rsa}]}
- | ClientOpts]}]),
+ {host, Hostname},
+ {from, self()},
+ {options, [{signature_algs, [{sha384, rsa}]}
+ | ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}},
- Client, {error, {tls_alert, "insufficient security"}}).
-
+ ssl_test_lib:check_server_alert(Server, Client, insufficient_security).
+
%%--------------------------------------------------------------------
tls_dont_crash_on_handshake_garbage() ->
@@ -3631,7 +3726,7 @@ tls_dont_crash_on_handshake_garbage(Config) ->
<<22, 3,3, 5:16, 92,64,37,228,209>> % garbage
]),
% Send unexpected change_cipher_spec
- ok = gen_tcp:send(Socket, <<20, 0,0,12, 111,40,244,7,137,224,16,109,197,110,249,152>>),
+ ok = gen_tcp:send(Socket, <<20, 3,3, 12:16, 111,40,244,7,137,224,16,109,197,110,249,152>>),
% Ensure we receive an alert, not sudden disconnect
{ok, <<21, _/binary>>} = drop_handshakes(Socket, 1000).
@@ -3663,7 +3758,7 @@ hibernate(Config) ->
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=Pid}} = ssl_test_lib:start_client([return_socket,
+ {Client, #sslsocket{pid=[Pid|_]}} = ssl_test_lib:start_client([return_socket,
{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -3706,7 +3801,7 @@ hibernate_right_away(Config) ->
Server1 = ssl_test_lib:start_server(StartServerOpts),
Port1 = ssl_test_lib:inet_port(Server1),
- {Client1, #sslsocket{pid = Pid1}} = ssl_test_lib:start_client(StartClientOpts ++
+ {Client1, #sslsocket{pid = [Pid1|_]}} = ssl_test_lib:start_client(StartClientOpts ++
[{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]),
ssl_test_lib:check_result(Server1, ok, Client1, ok),
@@ -3718,7 +3813,7 @@ hibernate_right_away(Config) ->
Server2 = ssl_test_lib:start_server(StartServerOpts),
Port2 = ssl_test_lib:inet_port(Server2),
- {Client2, #sslsocket{pid = Pid2}} = ssl_test_lib:start_client(StartClientOpts ++
+ {Client2, #sslsocket{pid = [Pid2|_]}} = ssl_test_lib:start_client(StartClientOpts ++
[{port, Port2}, {options, [{hibernate_after, 1}|ClientOpts]}]),
ssl_test_lib:check_result(Server2, ok, Client2, ok),
@@ -3751,7 +3846,7 @@ listen_socket(Config) ->
{error, enotconn} = ssl:peername(ListenSocket),
{error, enotconn} = ssl:peercert(ListenSocket),
{error, enotconn} = ssl:renegotiate(ListenSocket),
- {error, enotconn} = ssl:prf(ListenSocket, 'master_secret', <<"Label">>, client_random, 256),
+ {error, enotconn} = ssl:prf(ListenSocket, 'master_secret', <<"Label">>, [client_random], 256),
{error, enotconn} = ssl:shutdown(ListenSocket, read_write),
ok = ssl:close(ListenSocket).
@@ -3954,18 +4049,18 @@ tls_tcp_error_propagation_in_active_mode(Config) when is_list(Config) ->
{mfa, {ssl_test_lib, no_result, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=Pid} = SslSocket} = ssl_test_lib:start_client([return_socket,
- {node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, receive_msg, []}},
- {options, ClientOpts}]),
-
+ {Client, #sslsocket{pid=[Pid|_]} = SslSocket} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, receive_msg, []}},
+ {options, ClientOpts}]),
+
{status, _, _, StatusInfo} = sys:get_status(Pid),
[_, _,_, _, Prop] = StatusInfo,
State = ssl_test_lib:state(Prop),
- Socket = element(11, State),
-
+ StaticEnv = element(2, State),
+ Socket = element(11, StaticEnv),
%% Fake tcp error
Pid ! {tcp_error, Socket, etimedout},
@@ -3993,6 +4088,108 @@ recv_error_handling(Config) when is_list(Config) ->
ssl:close(SslSocket),
ssl_test_lib:check_result(Server, ok).
+
+
+%%--------------------------------------------------------------------
+call_in_error_state() ->
+ [{doc,"Special case of call error handling"}].
+call_in_error_state(Config) when is_list(Config) ->
+ ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)],
+ Pid = spawn_link(?MODULE, run_error_server, [[self() | ServerOpts]]),
+ receive
+ {Pid, Port} ->
+ spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]])
+ end,
+ receive
+ {error, closed} ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end.
+
+run_client_error([Port, Opts]) ->
+ ssl:connect("localhost", Port, Opts).
+
+run_error_server([ Pid | Opts]) ->
+ {ok, Listen} = ssl:listen(0, Opts),
+ {ok,{_, Port}} = ssl:sockname(Listen),
+ Pid ! {self(), Port},
+ {ok, Socket} = ssl:transport_accept(Listen),
+ Pid ! ssl:controlling_process(Socket, self()).
+
+%%--------------------------------------------------------------------
+
+close_in_error_state() ->
+ [{doc,"Special case of closing socket in error state"}].
+close_in_error_state(Config) when is_list(Config) ->
+ ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)],
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ _ = spawn_link(?MODULE, run_error_server_close, [[self() | ServerOpts]]),
+ receive
+ {_Pid, Port} ->
+ spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]])
+ end,
+ receive
+ ok ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end.
+%%--------------------------------------------------------------------
+abuse_transport_accept_socket() ->
+ [{doc,"Only ssl:handshake and ssl:controlling_process is allowed for transport_accept:sockets"}].
+abuse_transport_accept_socket(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server_transport_abuse_socket([{node, ServerNode},
+ {port, 0},
+ {from, self()},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+%%--------------------------------------------------------------------
+controlling_process_transport_accept_socket() ->
+ [{doc,"Only ssl:handshake and ssl:controlling_process is allowed for transport_accept:sockets"}].
+controlling_process_transport_accept_socket(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server_transport_control([{node, ServerNode},
+ {port, 0},
+ {from, self()},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ _Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options, ClientOpts}]),
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server).
+
+%%--------------------------------------------------------------------
+run_error_server_close([Pid | Opts]) ->
+ {ok, Listen} = ssl:listen(0, Opts),
+ {ok,{_, Port}} = ssl:sockname(Listen),
+ Pid ! {self(), Port},
+ {ok, Socket} = ssl:transport_accept(Listen),
+ Pid ! ssl:close(Socket).
+
%%--------------------------------------------------------------------
rizzo() ->
@@ -4013,6 +4210,8 @@ rizzo(Config) when is_list(Config) ->
{cipher,
fun(rc4_128) ->
false;
+ (chacha20_poly1305) ->
+ false;
(_) ->
true
end}]),
@@ -4055,6 +4254,9 @@ rizzo_one_n_minus_one(Config) when is_list(Config) ->
{cipher,
fun(rc4_128) ->
false;
+ %% TODO: remove this clause when chacha is fixed!
+ (chacha20_poly1305) ->
+ false;
(_) ->
true
end}]),
@@ -4196,8 +4398,7 @@ tls_versions_option(Config) when is_list(Config) ->
{Server, _} ->
ok
end,
-
- ssl_test_lib:check_result(ErrClient, {error, {tls_alert, "protocol version"}}).
+ ssl_test_lib:check_client_alert(ErrClient, protocol_version).
%%--------------------------------------------------------------------
@@ -4212,17 +4413,17 @@ unordered_protocol_versions_server(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ClientOpts}]),
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+
+ ServerMsg = ClientMsg = {ok,'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
@@ -4237,18 +4438,17 @@ unordered_protocol_versions_client(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ServerOpts }]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]),
-
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+
+ ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
@@ -4373,8 +4573,8 @@ tcp_send_recv_result(Socket) ->
ok.
basic_verify_test_no_close(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -4517,19 +4717,24 @@ recv_close(Socket) ->
send_recv_result_active_rizzo(Socket) ->
ssl:send(Socket, "Hello world"),
- receive
- {ssl, Socket, "H"} ->
- receive
- {ssl, Socket, "ello world"} ->
- ok
- end
- end.
+ "Hello world" = ssl_test_lib:active_recv(Socket, 11),
+ ok.
send_recv_result_active_no_rizzo(Socket) ->
ssl:send(Socket, "Hello world"),
+ "Hello world" = ssl_test_lib:active_recv(Socket, 11),
+ ok.
+
+
+ssl_active_recv(N) ->
+ ssl_active_recv(N, []).
+
+ssl_active_recv(0, Acc) ->
+ Acc;
+ssl_active_recv(N, Acc) ->
receive
- {ssl, Socket, "Hello world"} ->
- ok
+ {ssl, _, Bytes} ->
+ ssl_active_recv(N-length(Bytes), Acc ++ Bytes)
end.
result_ok(_Socket) ->
@@ -4553,16 +4758,7 @@ renegotiate_reuse_session(Socket, Data) ->
renegotiate(Socket, Data).
renegotiate_immediately(Socket) ->
- receive
- {ssl, Socket, "Hello world"} ->
- ok;
- %% Handle 1/n-1 splitting countermeasure Rizzo/Duong-Beast
- {ssl, Socket, "H"} ->
- receive
- {ssl, Socket, "ello world"} ->
- ok
- end
- end,
+ _ = ssl_test_lib:active_recv(Socket, 11),
ok = ssl:renegotiate(Socket),
{error, renegotiation_rejected} = ssl:renegotiate(Socket),
ct:sleep(?RENEGOTIATION_DISABLE_TIME + ?SLEEP),
@@ -4572,16 +4768,7 @@ renegotiate_immediately(Socket) ->
ok.
renegotiate_rejected(Socket) ->
- receive
- {ssl, Socket, "Hello world"} ->
- ok;
- %% Handle 1/n-1 splitting countermeasure Rizzo/Duong-Beast
- {ssl, Socket, "H"} ->
- receive
- {ssl, Socket, "ello world"} ->
- ok
- end
- end,
+ _ = ssl_test_lib:active_recv(Socket, 11),
{error, renegotiation_rejected} = ssl:renegotiate(Socket),
{error, renegotiation_rejected} = ssl:renegotiate(Socket),
ct:sleep(?RENEGOTIATION_DISABLE_TIME +1),
@@ -4756,17 +4943,11 @@ session_loop(Sess) ->
erlang_ssl_receive(Socket, Data) ->
- receive
- {ssl, Socket, Data} ->
- io:format("Received ~p~n",[Data]),
- ok;
- {ssl, Socket, Byte} when length(Byte) == 1 -> %% Handle 1/n-1 splitting countermeasure Rizzo/Duong-Beast
- io:format("Received ~p~n",[Byte]),
- erlang_ssl_receive(Socket, tl(Data));
- Other ->
- ct:fail({unexpected_message, Other})
- after timer:seconds(?SEC_RENEGOTIATION_TIMEOUT) * test_server:timetrap_scale_factor() ->
- ct:fail({did_not_get, Data})
+ case ssl_test_lib:active_recv(Socket, length(Data)) of
+ Data ->
+ ok;
+ Other ->
+ ct:fail({{expected, Data}, {got, Other}})
end.
receive_msg(_) ->
@@ -4783,28 +4964,6 @@ controlling_process_result(Socket, Pid, Msg) ->
ssl:send(Socket, Msg),
no_result_msg.
-receive_s_rizzo_duong_beast() ->
- receive
- {ssl, _, "erver hello"} ->
- receive
- {ssl, _, "C"} ->
- receive
- {ssl, _, "lient hello"} ->
- ok
- end
- end
- end.
-receive_c_rizzo_duong_beast() ->
- receive
- {ssl, _, "lient hello"} ->
- receive
- {ssl, _, "S"} ->
- receive
- {ssl, _, "erver hello"} ->
- ok
- end
- end
- end.
controller_dies_result(_Socket, _Pid, _Msg) ->
receive Result -> Result end.
@@ -4890,16 +5049,16 @@ run_suites(Ciphers, Config, Type) ->
{ClientOpts, ServerOpts} =
case Type of
rsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ ssl_test_lib:ssl_options(server_rsa_opts, Config)]};
dsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_dsa_verify_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_dsa_opts, Config)]};
anonymous ->
%% No certs in opts!
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options([], Config)]};
psk ->
@@ -4921,62 +5080,71 @@ run_suites(Ciphers, Config, Type) ->
ssl_test_lib:ssl_options(server_psk_anon_hint, Config)]};
srp ->
{ssl_test_lib:ssl_options(client_srp, Config),
- ssl_test_lib:ssl_options(server_srp, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_srp, Config)]};
srp_anon ->
{ssl_test_lib:ssl_options(client_srp, Config),
- ssl_test_lib:ssl_options(server_srp_anon, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_srp_anon, Config)]};
srp_dsa ->
{ssl_test_lib:ssl_options(client_srp_dsa, Config),
- ssl_test_lib:ssl_options(server_srp_dsa, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_srp_dsa, Config)]};
ecdsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_ecdsa_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]};
ecdh_rsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
- ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)};
+ {ssl_test_lib:ssl_options(client_ecdh_rsa_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)]};
rc4_rsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ ssl_test_lib:ssl_options(server_rsa_verify_opts, Config)]};
rc4_ecdh_rsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_ecdh_rsa_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)]};
rc4_ecdsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]};
des_dhe_rsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_verification_opts, Config)]};
des_rsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ ssl_test_lib:ssl_options(server_rsa_verify_opts, Config)]};
chacha_rsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ ssl_test_lib:ssl_options(server_rsa_verify_opts, Config)]};
chacha_ecdsa ->
- {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {ssl_test_lib:ssl_options(client_ecdsa_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]}
end,
- Result = lists:map(fun(Cipher) ->
- cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
- ssl_test_lib:filter_suites(Ciphers, Version)),
- case lists:flatten(Result) of
- [] ->
- ok;
- Error ->
- ct:log("Cipher suite errors: ~p~n", [Error]),
- ct:fail(cipher_suite_failed_see_test_case_log)
- end.
-
+ Suites = ssl_test_lib:filter_suites(Ciphers, Version),
+ ct:pal("ssl_test_lib:filter_suites(~p ~p) -> ~p ", [Ciphers, Version, Suites]),
+ Results0 = lists:map(fun(Cipher) ->
+ cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
+ ssl_test_lib:filter_suites(Ciphers, Version)),
+ Results = lists:flatten(Results0),
+ true = length(Results) == length(Suites),
+ check_cipher_result(Results).
+
+check_cipher_result([]) ->
+ ok;
+check_cipher_result([ok | Rest]) ->
+ check_cipher_result(Rest);
+check_cipher_result([_ |_] = Error) ->
+ ct:fail(Error).
+
erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher:erl_suite_definition(ssl_cipher:openssl_suite(Suite));
+ ssl_cipher_format:suite_definition(ssl_cipher_format:openssl_suite(Suite));
erlang_cipher_suite(Suite) ->
Suite.
@@ -5011,7 +5179,7 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
case Result of
ok ->
- [];
+ [ok];
Error ->
[{ErlangCipherSuite, Error}]
end.
@@ -5028,8 +5196,13 @@ connection_information_result(Socket) ->
end.
connection_info_result(Socket) ->
- {ok, Info} = ssl:connection_information(Socket, [protocol, cipher_suite]),
- {ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}}.
+ {ok, Info} = ssl:connection_information(Socket, [protocol, selected_cipher_suite]),
+ {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}}.
+
+protocol_info_result(Socket) ->
+ {ok, [{protocol, PVersion}]} = ssl:connection_information(Socket, [protocol]),
+ {ok, PVersion}.
+
version_info_result(Socket) ->
{ok, [{version, Version}]} = ssl:connection_information(Socket, [version]),
{ok, Version}.
@@ -5048,23 +5221,28 @@ connect_dist_c(S) ->
{ok, Test} = ssl:recv(S, 0, 10000),
ok.
-tls_downgrade_result(Socket) ->
+tls_downgrade_result(Socket, Pid) ->
ok = ssl_test_lib:send_recv_result(Socket),
+ Pid ! {self(), ready},
+ receive
+ go ->
+ ok
+ end,
case ssl:close(Socket, {self(), 10000}) of
{ok, TCPSocket} ->
- inet:setopts(TCPSocket, [{active, true}]),
+ inet:setopts(TCPSocket, [{active, true}]),
gen_tcp:send(TCPSocket, "Downgraded"),
- receive
- {tcp, TCPSocket, <<"Downgraded">>} ->
- ok;
- {tcp_closed, TCPSocket} ->
- ct:pal("Peer timed out, downgrade aborted"),
- ok;
- Other ->
- {error, Other}
- end;
+ receive
+ {tcp, TCPSocket, <<"Downgraded">>} ->
+ ok;
+ {tcp_closed, TCPSocket} ->
+ ct:fail("Peer timed out, downgrade aborted"),
+ ok;
+ Other ->
+ {error, Other}
+ end;
{error, timeout} ->
- ct:pal("Timed out, downgrade aborted"),
+ ct:fail("Timed out, downgrade aborted"),
ok;
Fail ->
{error, Fail}
@@ -5095,14 +5273,14 @@ get_invalid_inet_option(Socket) ->
tls_shutdown_result(Socket, server) ->
ssl:send(Socket, "Hej"),
- ssl:shutdown(Socket, write),
+ ok = ssl:shutdown(Socket, write),
{ok, "Hej hopp"} = ssl:recv(Socket, 8),
ok;
tls_shutdown_result(Socket, client) ->
- {ok, "Hej"} = ssl:recv(Socket, 3),
ssl:send(Socket, "Hej hopp"),
- ssl:shutdown(Socket, write),
+ ok = ssl:shutdown(Socket, write),
+ {ok, "Hej"} = ssl:recv(Socket, 3),
ok.
tls_shutdown_write_result(Socket, server) ->
@@ -5158,20 +5336,6 @@ try_recv_active_once(Socket) ->
{error, einval} = ssl:recv(Socket, 11),
ok.
-first_rsa_suite([{ecdhe_rsa, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{ecdhe_rsa, _, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([_ | Rest]) ->
- first_rsa_suite(Rest).
wait_for_send(Socket) ->
%% Make sure TLS process processed send message event
diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl
index 3fe6338d69..13097b08b6 100644
--- a/lib/ssl/test/ssl_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_bench_SUITE.erl
@@ -44,6 +44,7 @@ init_per_suite(Config) ->
nonode@nohost ->
{skipped, "Node not distributed"};
_ ->
+ ssl_test_lib:clean_start(),
[{server_node, ssl_bench_test_lib:setup(perf_server)}|Config]
end.
diff --git a/lib/ssl/test/ssl_bench_test_lib.erl b/lib/ssl/test/ssl_bench_test_lib.erl
index e5cbb911bd..47bcd41608 100644
--- a/lib/ssl/test/ssl_bench_test_lib.erl
+++ b/lib/ssl/test/ssl_bench_test_lib.erl
@@ -58,13 +58,13 @@ setup(Name) ->
Path = code:get_path(),
true = rpc:call(Node, code, set_path, [Path]),
ok = rpc:call(Node, ?MODULE, setup_server, [node()]),
- io:format("Client (~p) using ~s~n",[node(), code:which(ssl)]),
+ io:format("Client (~p) using ~ts~n",[node(), code:which(ssl)]),
(Node =:= node()) andalso restrict_schedulers(client),
Node.
setup_server(ClientNode) ->
(ClientNode =:= node()) andalso restrict_schedulers(server),
- io:format("Server (~p) using ~s~n",[node(), code:which(ssl)]),
+ io:format("Server (~p) using ~ts~n",[node(), code:which(ssl)]),
ok.
restrict_schedulers(Type) ->
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 63e9d07d0b..e89104a999 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -88,7 +88,8 @@ tests() ->
critical_extension_verify_client,
critical_extension_verify_server,
critical_extension_verify_none,
- customize_hostname_check
+ customize_hostname_check,
+ incomplete_chain
].
error_handling_tests()->
@@ -297,15 +298,8 @@ server_require_peer_cert_fail(Config) when is_list(Config) ->
{host, Hostname},
{from, self()},
{options, [{active, Active} | BadClientOpts]}]),
- receive
- {Server, {error, {tls_alert, "handshake failure"}}} ->
- receive
- {Client, {error, {tls_alert, "handshake failure"}}} ->
- ok;
- {Client, {error, closed}} ->
- ok
- end
- end.
+
+ ssl_test_lib:check_server_alert(Server, Client, handshake_failure).
%%--------------------------------------------------------------------
server_require_peer_cert_empty_ok() ->
@@ -364,15 +358,8 @@ server_require_peer_cert_partial_chain(Config) when is_list(Config) ->
{options, [{active, Active},
{cacerts, [RootCA]} |
proplists:delete(cacertfile, ClientOpts)]}]),
- receive
- {Server, {error, {tls_alert, "unknown ca"}}} ->
- receive
- {Client, {error, {tls_alert, "unknown ca"}}} ->
- ok;
- {Client, {error, closed}} ->
- ok
- end
- end.
+ ssl_test_lib:check_server_alert(Server, Client, unknown_ca).
+
%%--------------------------------------------------------------------
server_require_peer_cert_allow_partial_chain() ->
[{doc, "Server trusts intermediat CA and accepts a partial chain. (partial_chain option)"}].
@@ -445,17 +432,7 @@ server_require_peer_cert_do_not_allow_partial_chain(Config) when is_list(Config)
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
{options, ClientOpts}]),
-
- receive
- {Server, {error, {tls_alert, "unknown ca"}}} ->
- receive
- {Client, {error, {tls_alert, "unknown ca"}}} ->
- ok;
- {Client, {error, closed}} ->
- ok
- end
- end.
-
+ ssl_test_lib:check_server_alert(Server, Client, unknown_ca).
%%--------------------------------------------------------------------
server_require_peer_cert_partial_chain_fun_fail() ->
[{doc, "If parial_chain fun crashes, treat it as if it returned unkown_ca"}].
@@ -470,7 +447,7 @@ server_require_peer_cert_partial_chain_fun_fail(Config) when is_list(Config) ->
[{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
PartialChain = fun(_CertChain) ->
- ture = false %% crash on purpose
+ true = false %% crash on purpose
end,
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
@@ -486,16 +463,7 @@ server_require_peer_cert_partial_chain_fun_fail(Config) when is_list(Config) ->
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
{options, ClientOpts}]),
-
- receive
- {Server, {error, {tls_alert, "unknown ca"}}} ->
- receive
- {Client, {error, {tls_alert, "unknown ca"}}} ->
- ok;
- {Client, {error, closed}} ->
- ok
- end
- end.
+ ssl_test_lib:check_server_alert(Server, Client, unknown_ca).
%%--------------------------------------------------------------------
verify_fun_always_run_client() ->
@@ -534,14 +502,8 @@ verify_fun_always_run_client(Config) when is_list(Config) ->
[{verify, verify_peer},
{verify_fun, FunAndState}
| ClientOpts]}]),
- %% Server error may be {tls_alert,"handshake failure"} or closed depending on timing
- %% this is not a bug it is a circumstance of how tcp works!
- receive
- {Server, ServerError} ->
- ct:log("Server Error ~p~n", [ServerError])
- end,
- ssl_test_lib:check_result(Client, {error, {tls_alert, "handshake failure"}}).
+ ssl_test_lib:check_client_alert(Server, Client, handshake_failure).
%%--------------------------------------------------------------------
verify_fun_always_run_server() ->
@@ -580,16 +542,8 @@ verify_fun_always_run_server(Config) when is_list(Config) ->
{mfa, {ssl_test_lib,
no_result, []}},
{options, ClientOpts}]),
-
- %% Client error may be {tls_alert, "handshake failure" } or closed depending on timing
- %% this is not a bug it is a circumstance of how tcp works!
- receive
- {Client, ClientError} ->
- ct:log("Client Error ~p~n", [ClientError])
- end,
-
- ssl_test_lib:check_result(Server, {error, {tls_alert, "handshake failure"}}).
-
+
+ ssl_test_lib:check_client_alert(Server, Client, handshake_failure).
%%--------------------------------------------------------------------
cert_expired() ->
@@ -619,8 +573,7 @@ cert_expired(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer}, {active, Active} | ClientOpts]}]),
- tcp_delivery_workaround(Server, {error, {tls_alert, "certificate expired"}},
- Client, {error, {tls_alert, "certificate expired"}}).
+ ssl_test_lib:check_client_alert(Server, Client, certificate_expired).
two_digits_str(N) when N < 10 ->
lists:flatten(io_lib:format("0~p", [N]));
@@ -726,12 +679,8 @@ critical_extension_verify_server(Config) when is_list(Config) ->
{options, [{verify, verify_none}, {active, Active} | ClientOpts]}]),
%% This certificate has a critical extension that we don't
- %% understand. Therefore, verification should fail.
-
- tcp_delivery_workaround(Server, {error, {tls_alert, "unsupported certificate"}},
- Client, {error, {tls_alert, "unsupported certificate"}}),
-
- ssl_test_lib:close(Server).
+ %% understand. Therefore, verification should fail.
+ ssl_test_lib:check_server_alert(Server, Client, unsupported_certificate).
%%--------------------------------------------------------------------
critical_extension_verify_client() ->
@@ -762,12 +711,7 @@ critical_extension_verify_client(Config) when is_list(Config) ->
{mfa, {ssl_test_lib, ReceiveFunction, []}},
{options, [{verify, verify_peer}, {active, Active} | ClientOpts]}]),
- %% This certificate has a critical extension that we don't
- %% understand. Therefore, verification should fail.
- ssl_test_lib:check_result(Server, {error, {tls_alert, "unsupported certificate"}},
- Client, {error, {tls_alert, "unsupported certificate"}}),
-
- ssl_test_lib:close(Server).
+ ssl_test_lib:check_client_alert(Server, Client, unsupported_certificate).
%%--------------------------------------------------------------------
critical_extension_verify_none() ->
@@ -907,10 +851,7 @@ invalid_signature_server(Config) when is_list(Config) ->
{host, Hostname},
{from, self()},
{options, [{verify, verify_peer} | ClientOpts]}]),
-
- tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}},
- Client, {error, {tls_alert, "unknown ca"}}).
-
+ ssl_test_lib:check_server_alert(Server, Client, unknown_ca).
%%--------------------------------------------------------------------
invalid_signature_client() ->
@@ -945,9 +886,7 @@ invalid_signature_client(Config) when is_list(Config) ->
{from, self()},
{options, NewClientOpts}]),
- tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}},
- Client, {error, {tls_alert, "unknown ca"}}).
-
+ ssl_test_lib:check_client_alert(Server, Client, unknown_ca).
%%--------------------------------------------------------------------
@@ -1033,16 +972,7 @@ unknown_server_ca_fail(Config) when is_list(Config) ->
[{verify, verify_peer},
{verify_fun, FunAndState}
| ClientOpts]}]),
- receive
- {Client, {error, {tls_alert, "unknown ca"}}} ->
- receive
- {Server, {error, {tls_alert, "unknown ca"}}} ->
- ok;
- {Server, {error, closed}} ->
- ok
- end
- end.
-
+ ssl_test_lib:check_client_alert(Server, Client, unknown_ca).
%%--------------------------------------------------------------------
unknown_server_ca_accept_verify_none() ->
@@ -1192,51 +1122,42 @@ customize_hostname_check(Config) when is_list(Config) ->
{mfa, {ssl_test_lib, no_result, []}},
{options, ClientOpts}
]),
- ssl_test_lib:check_result(Client1, {error, {tls_alert, "handshake failure"}},
- Server, {error, {tls_alert, "handshake failure"}}),
-
+ ssl_test_lib:check_client_alert(Server, Client1, handshake_failure).
+
+incomplete_chain() ->
+ [{doc,"Test option verify_peer"}].
+incomplete_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(CertChainConf),
+ [ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerConf),
+ ClientCas = proplists:get_value(cacerts, ClientConf),
+
+ Active = proplists:get_value(active, Config),
+ ReceiveFunction = proplists:get_value(receive_function, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active}, {verify, verify_peer},
+ {cacerts, [ServerRoot]} |
+ proplists:delete(cacerts, ServerConf)]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active},
+ {verify, verify_peer},
+ {cacerts, ServerCas ++ ClientCas} |
+ proplists:delete(cacerts, ClientConf)]}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
- receive
- {Server, ServerMsg} ->
- client_msg(Client, ClientMsg);
- {Client, ClientMsg} ->
- server_msg(Server, ServerMsg);
- {Client, {error,closed}} ->
- server_msg(Server, ServerMsg);
- {Server, {error,closed}} ->
- client_msg(Client, ClientMsg)
- end.
-
-client_msg(Client, ClientMsg) ->
- receive
- {Client, ClientMsg} ->
- ok;
- {Client, {error,closed}} ->
- ct:log("client got close"),
- ok;
- {Client, {error, Reason}} ->
- ct:log("client got econnaborted: ~p", [Reason]),
- ok;
- Unexpected ->
- ct:fail(Unexpected)
- end.
-server_msg(Server, ServerMsg) ->
- receive
- {Server, ServerMsg} ->
- ok;
- {Server, {error,closed}} ->
- ct:log("server got close"),
- ok;
- {Server, {error, Reason}} ->
- ct:log("server got econnaborted: ~p", [Reason]),
- ok;
- Unexpected ->
- ct:fail(Unexpected)
- end.
diff --git a/lib/ssl/test/ssl_crl_SUITE.erl b/lib/ssl/test/ssl_crl_SUITE.erl
index 23c5eaf84d..b2fd3874a8 100644
--- a/lib/ssl/test/ssl_crl_SUITE.erl
+++ b/lib/ssl/test/ssl_crl_SUITE.erl
@@ -238,7 +238,7 @@ crl_verify_revoked(Config) when is_list(Config) ->
end,
crl_verify_error(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts,
- "certificate revoked").
+ certificate_revoked).
crl_verify_no_crl() ->
[{doc,"Verify a simple CRL chain when the CRL is missing"}].
@@ -277,10 +277,10 @@ crl_verify_no_crl(Config) when is_list(Config) ->
%% The error "revocation status undetermined" gets turned
%% into "bad certificate".
crl_verify_error(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts,
- "bad certificate");
+ bad_certificate);
peer ->
crl_verify_error(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts,
- "bad certificate");
+ bad_certificate);
best_effort ->
%% In "best effort" mode, we consider the certificate not
%% to be revoked if we can't find the appropriate CRL.
@@ -341,7 +341,7 @@ crl_hash_dir_collision(Config) when is_list(Config) ->
%% First certificate revoked; first fails, second succeeds.
crl_verify_error(Hostname, ServerNode, ServerOpts1, ClientNode, ClientOpts,
- "certificate revoked"),
+ certificate_revoked),
crl_verify_valid(Hostname, ServerNode, ServerOpts2, ClientNode, ClientOpts),
make_certs:revoke(PrivDir, CA2, "collision-client-2", CertsConfig),
@@ -352,9 +352,9 @@ crl_hash_dir_collision(Config) when is_list(Config) ->
%% Second certificate revoked; both fail.
crl_verify_error(Hostname, ServerNode, ServerOpts1, ClientNode, ClientOpts,
- "certificate revoked"),
+ certificate_revoked),
crl_verify_error(Hostname, ServerNode, ServerOpts2, ClientNode, ClientOpts,
- "certificate revoked"),
+ certificate_revoked),
ok.
@@ -383,8 +383,11 @@ crl_hash_dir_expired(Config) when is_list(Config) ->
{verify, verify_peer}],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- %% First make a CRL that expired yesterday.
- make_certs:gencrl(PrivDir, CA, CertsConfig, -24),
+ %% First make a CRL that will expire in one second.
+ make_certs:gencrl_sec(PrivDir, CA, CertsConfig, 1),
+ %% Sleep until the next CRL is due
+ ct:sleep({seconds, 1}),
+
CrlDir = filename:join(PrivDir, "crls"),
populate_crl_hash_dir(PrivDir, CrlDir,
[{CA, "1627b4b0"}],
@@ -397,10 +400,10 @@ crl_hash_dir_expired(Config) when is_list(Config) ->
%% The error "revocation status undetermined" gets turned
%% into "bad certificate".
crl_verify_error(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts,
- "bad certificate");
+ bad_certificate);
peer ->
crl_verify_error(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts,
- "bad certificate");
+ bad_certificate);
best_effort ->
%% In "best effort" mode, we consider the certificate not
%% to be revoked if we can't find the appropriate CRL.
@@ -448,11 +451,8 @@ crl_verify_error(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts, Expec
{host, Hostname},
{from, self()},
{options, ClientOpts}]),
- receive
- {Server, AlertOrClose} ->
- ct:pal("Server Alert or Close ~p", [AlertOrClose])
- end,
- ssl_test_lib:check_result(Client, {error, {tls_alert, ExpectedAlert}}).
+
+ ssl_test_lib:check_client_alert(Server, Client, ExpectedAlert).
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
diff --git a/lib/ssl/test/ssl_dist_bench_SUITE.erl b/lib/ssl/test/ssl_dist_bench_SUITE.erl
index 3c7904cf24..618ad0789e 100644
--- a/lib/ssl/test/ssl_dist_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,6 +32,8 @@
-export(
[setup/1,
roundtrip/1,
+ throughput_0/1,
+ throughput_64/1,
throughput_1024/1,
throughput_4096/1,
throughput_16384/1,
@@ -40,7 +42,7 @@
throughput_1048576/1]).
%% Debug
--export([payload/1]).
+-export([payload/1, roundtrip_runner/3, setup_runner/3, throughput_runner/4]).
%%%-------------------------------------------------------------------
@@ -55,7 +57,9 @@ groups() ->
{setup, [{repeat, 1}], [setup]},
{roundtrip, [{repeat, 1}], [roundtrip]},
{throughput, [{repeat, 1}],
- [throughput_1024,
+ [throughput_0,
+ throughput_64,
+ throughput_1024,
throughput_4096,
throughput_16384,
throughput_65536,
@@ -247,8 +251,9 @@ setup(A, B, Prefix, HA, HB) ->
[] = ssl_apply(HB, erlang, nodes, []),
{SetupTime, CycleTime} =
ssl_apply(HA, fun () -> setup_runner(A, B, Rounds) end),
- [] = ssl_apply(HA, erlang, nodes, []),
- [] = ssl_apply(HB, erlang, nodes, []),
+ ok = ssl_apply(HB, fun () -> setup_wait_nodedown(A, 10000) end),
+ %% [] = ssl_apply(HA, erlang, nodes, []),
+ %% [] = ssl_apply(HB, erlang, nodes, []),
SetupSpeed = round((Rounds*1000000*1000) / SetupTime),
CycleSpeed = round((Rounds*1000000*1000) / CycleTime),
_ = report(Prefix++" Setup", SetupSpeed, "setups/1000s"),
@@ -275,6 +280,22 @@ setup_loop(A, B, T, N) ->
setup_loop(A, B, Time + T, N - 1)
end.
+setup_wait_nodedown(A, Time) ->
+ ok = net_kernel:monitor_nodes(true),
+ case nodes() of
+ [] ->
+ ok;
+ [A] ->
+ receive
+ {nodedown,A} ->
+ ok;
+ Unexpected ->
+ {error,{unexpected,Unexpected}}
+ after Time ->
+ {error,timeout}
+ end
+ end.
+
%%----------------
%% Roundtrip speed
@@ -334,6 +355,18 @@ roundtrip_client(Pid, Mon, StartTime, N) ->
%%-----------------
%% Throughput speed
+throughput_0(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 500000, 0)
+ end, Config).
+
+throughput_64(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 500000, 64)
+ end, Config).
+
throughput_1024(Config) ->
run_nodepair_test(
fun (A, B, Prefix, HA, HB) ->
@@ -373,45 +406,219 @@ throughput_1048576(Config) ->
throughput(A, B, Prefix, HA, HB, Packets, Size) ->
[] = ssl_apply(HA, erlang, nodes, []),
[] = ssl_apply(HB, erlang, nodes, []),
- Time =
+ #{time := Time,
+ client_dist_stats := ClientDistStats,
+ client_msacc_stats := ClientMsaccStats,
+ client_prof := ClientProf,
+ server_msacc_stats := ServerMsaccStats,
+ server_prof := ServerProf,
+ server_gc_before := Server_GC_Before,
+ server_gc_after := Server_GC_After} =
ssl_apply(HA, fun () -> throughput_runner(A, B, Packets, Size) end),
[B] = ssl_apply(HA, erlang, nodes, []),
[A] = ssl_apply(HB, erlang, nodes, []),
- Speed = round((Packets*Size*1000000) / (1024*Time)),
+ ClientMsaccStats =:= undefined orelse
+ msacc:print(ClientMsaccStats),
+ io:format("ClientDistStats: ~p~n", [ClientDistStats]),
+ Overhead =
+ 50 % Distribution protocol headers (empirical) (TLS+=54)
+ + byte_size(erlang:term_to_binary([0|<<>>])), % Benchmark overhead
+ Bytes = Packets * (Size + Overhead),
+ io:format("~w bytes, ~.4g s~n", [Bytes,Time/1000000]),
+ ClientMsaccStats =:= undefined orelse
+ io:format(
+ "Sender core usage ratio: ~.4g ns/byte~n",
+ [msacc:stats(system_runtime, ClientMsaccStats)*1000/Bytes]),
+ ServerMsaccStats =:= undefined orelse
+ begin
+ io:format(
+ "Receiver core usage ratio: ~.4g ns/byte~n",
+ [msacc:stats(system_runtime, ServerMsaccStats)*1000/Bytes]),
+ msacc:print(ServerMsaccStats)
+ end,
+ io:format("******* ClientProf:~n", []), prof_print(ClientProf),
+ io:format("******* ServerProf:~n", []), prof_print(ServerProf),
+ io:format("******* Server GC Before:~n~p~n", [Server_GC_Before]),
+ io:format("******* Server GC After:~n~p~n", [Server_GC_After]),
+ Speed = round((Bytes * 1000000) / (1024 * Time)),
report(Prefix++" Throughput_"++integer_to_list(Size), Speed, "kB/s").
%% Runs on node A and spawns a server on node B
throughput_runner(A, B, Rounds, Size) ->
Payload = payload(Size),
- ClientPid = self(),
[A] = rpc:call(B, erlang, nodes, []),
+ ClientPid = self(),
ServerPid =
erlang:spawn(
B,
fun () -> throughput_server(ClientPid, Rounds) end),
ServerMon = erlang:monitor(process, ServerPid),
- microseconds(
- throughput_client(
- ServerPid, ServerMon, Payload, start_time(), Rounds)).
+ msacc:available() andalso
+ begin
+ msacc:stop(),
+ msacc:reset(),
+ msacc:start(),
+ ok
+ end,
+ prof_start(),
+ #{time := Time} = Result =
+ throughput_client(ServerPid, ServerMon, Payload, Rounds),
+ prof_stop(),
+ MsaccStats =
+ case msacc:available() of
+ true ->
+ MStats = msacc:stats(),
+ msacc:stop(),
+ MStats;
+ false ->
+ undefined
+ end,
+ Prof = prof_end(),
+ [{_Node,Socket}] = dig_dist_node_sockets(),
+ DistStats = inet:getstat(Socket),
+ Result#{time := microseconds(Time),
+ client_dist_stats => DistStats,
+ client_msacc_stats => MsaccStats,
+ client_prof => Prof}.
+
+dig_dist_node_sockets() ->
+ [case DistCtrl of
+ {_Node,Socket} = NodeSocket when is_port(Socket) ->
+ NodeSocket;
+ {Node,DistCtrlPid} when is_pid(DistCtrlPid) ->
+ [{links,DistCtrlLinks}] = process_info(DistCtrlPid, [links]),
+ case [S || S <- DistCtrlLinks, is_port(S)] of
+ [Socket] ->
+ {Node,Socket};
+ [] ->
+ [{monitors,[{process,DistSenderPid}]}] =
+ process_info(DistCtrlPid, [monitors]),
+ [{links,DistSenderLinks}] =
+ process_info(DistSenderPid, [links]),
+ [Socket] = [S || S <- DistSenderLinks, is_port(S)],
+ {Node,Socket}
+ end
+ end || DistCtrl <- erlang:system_info(dist_ctrl)].
+
-throughput_server(_Pid, 0) ->
- ok;
throughput_server(Pid, N) ->
+ GC_Before = get_server_gc_info(),
+ %% dbg:tracer(port, dbg:trace_port(file, "throughput_server_gc.log")),
+ %% dbg:p(TLSDistReceiver, garbage_collection),
+ msacc:available() andalso
+ begin
+ msacc:stop(),
+ msacc:reset(),
+ msacc:start(),
+ ok
+ end,
+ prof_start(),
+ throughput_server_loop(Pid, GC_Before, N).
+
+throughput_server_loop(_Pid, GC_Before, 0) ->
+ prof_stop(),
+ MsaccStats =
+ case msacc:available() of
+ true ->
+ msacc:stop(),
+ MStats = msacc:stats(),
+ msacc:reset(),
+ MStats;
+ false ->
+ undefined
+ end,
+ Prof = prof_end(),
+ %% dbg:flush_trace_port(),
+ exit(#{server_msacc_stats => MsaccStats,
+ server_prof => Prof,
+ server_gc_before => GC_Before,
+ server_gc_after => get_server_gc_info()});
+throughput_server_loop(Pid, GC_Before, N) ->
receive
- [N|_] ->
- throughput_server(Pid, N-1)
+ {Pid, N, _} ->
+ throughput_server_loop(Pid, GC_Before, N-1)
+ end.
+
+get_server_gc_info() ->
+ case whereis(ssl_connection_sup_dist) of
+ undefined ->
+ undefined;
+ SupPid ->
+ [{_Id,TLSDistReceiver,_Type,_Modules}|_] =
+ supervisor:which_children(SupPid),
+ erlang:process_info(
+ TLSDistReceiver, [garbage_collection,garbage_collection_info])
end.
-throughput_client(_Pid, Mon, _Payload, StartTime, 0) ->
+throughput_client(Pid, Mon, Payload, N) ->
+ throughput_client_loop(Pid, Mon, Payload, N, start_time()).
+
+throughput_client_loop(_Pid, Mon, _Payload, 0, StartTime) ->
receive
- {'DOWN', Mon, _, _, normal} ->
- elapsed_time(StartTime);
+ {'DOWN', Mon, _, _, #{} = Result} ->
+ Result#{time => elapsed_time(StartTime)};
{'DOWN', Mon, _, _, Other} ->
exit(Other)
end;
-throughput_client(Pid, Mon, Payload, StartTime, N) ->
- Pid ! [N|Payload],
- throughput_client(Pid, Mon, Payload, StartTime, N - 1).
+throughput_client_loop(Pid, Mon, Payload, N, StartTime) ->
+ Pid ! {self(), N, Payload},
+ throughput_client_loop(Pid, Mon, Payload, N - 1, StartTime).
+
+
+-define(prof, none). % none | cprof | eprof
+
+-if(?prof =:= cprof).
+prof_start() ->
+ cprof:stop(),
+ cprof:start(),
+ ok.
+-elif(?prof =:= eprof).
+prof_start() ->
+ catch eprof:stop(),
+ {ok,_} = eprof:start(),
+ profiling = eprof:start_profiling(processes()),
+ ok.
+-elif(?prof =:= none).
+prof_start() ->
+ ok.
+-endif.
+
+-if(?prof =:= cprof).
+prof_stop() ->
+ cprof:pause(),
+ ok.
+-elif(?prof =:= eprof).
+prof_stop() ->
+ _ = eprof:stop_profiling(),
+ ok.
+-elif(?prof =:= none).
+prof_stop() ->
+ ok.
+-endif.
+
+-if(?prof =:= cprof).
+prof_end() ->
+ Prof = cprof:analyse(),
+ cprof:stop(),
+ Prof.
+-elif(?prof =:= eprof).
+prof_end() ->
+ eprof:dump_data().
+-elif(?prof =:= none).
+prof_end() ->
+ [].
+-endif.
+
+-if(?prof =:= cprof).
+prof_print(Prof) ->
+ io:format("~p.~n", [Prof]).
+-elif(?prof =:= eprof).
+prof_print(Dump) ->
+ eprof:analyze(undefined, total, [], Dump).
+-elif(?prof =:= none).
+prof_print([]) ->
+ ok.
+-endif.
%%%-------------------------------------------------------------------
%%% Test cases helpers
diff --git a/lib/ssl/test/ssl_engine_SUITE.erl b/lib/ssl/test/ssl_engine_SUITE.erl
index 7277dad012..a39a62e550 100644
--- a/lib/ssl/test/ssl_engine_SUITE.erl
+++ b/lib/ssl/test/ssl_engine_SUITE.erl
@@ -46,10 +46,17 @@ init_per_suite(Config) ->
ssl_test_lib:clean_start(),
case crypto:get_test_engine() of
{ok, EngineName} ->
- try crypto:engine_load(<<"dynamic">>,
- [{<<"SO_PATH">>, EngineName},
- <<"LOAD">>],
- []) of
+ try
+ %% The test engine has it's own fake rsa sign/verify that
+ %% you don't want to use, so exclude it from methods to load:
+ Methods =
+ crypto:engine_get_all_methods() -- [engine_method_rsa],
+ crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, EngineName},
+ <<"LOAD">>],
+ [],
+ Methods)
+ of
{ok, Engine} ->
[{engine, Engine} |Config];
{error, Reason} ->
@@ -90,12 +97,14 @@ end_per_testcase(_TestCase, Config) ->
private_key(Config) when is_list(Config) ->
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "client_engine"]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "server_engine"]),
+ Ext = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
#{server_config := ServerConf,
client_config := ClientConf} = GenCertData =
public_key:pkix_test_data(#{server_chain =>
#{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}
+ peer => [{extensions, Ext},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}
]},
client_chain =>
#{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
@@ -117,8 +126,29 @@ private_key(Config) when is_list(Config) ->
EngineServerConf = [{key, #{algorithm => rsa,
engine => Engine,
key_id => ServerKey}} | proplists:delete(key, ServerConf)],
+
+ EngineFileClientConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ClientKey}} |
+ proplists:delete(keyfile, FileClientConf)],
+
+ EngineFileServerConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ServerKey}} |
+ proplists:delete(keyfile, FileServerConf)],
+
%% Test with engine
test_tls_connection(EngineServerConf, EngineClientConf, Config),
+
+ %% Test with engine and rsa keyexchange
+ RSASuites = all_kex_rsa_suites([{tls_version, 'tlsv1.2'} | Config]),
+
+ test_tls_connection([{ciphers, RSASuites}, {versions, ['tlsv1.2']} | EngineServerConf],
+ [{ciphers, RSASuites}, {versions, ['tlsv1.2']} | EngineClientConf], Config),
+
+ %% Test with engine and present file arugments
+ test_tls_connection(EngineFileServerConf, EngineFileClientConf, Config),
+
%% Test that sofware fallback is available
test_tls_connection(ServerConf, [{reuse_sessions, false} |ClientConf], Config).
@@ -145,3 +175,8 @@ test_tls_connection(ServerConf, ClientConf, Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+all_kex_rsa_suites(Config) ->
+ Version = proplists:get_value(tls_version, Config),
+ All = ssl:cipher_suites(all, Version),
+ ssl:filter_cipher_suites(All,[{key_exchange, fun(rsa) -> true;(_) -> false end}]).
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 2c7c62407e..1fa6029963 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -25,6 +25,7 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
+-include("ssl_handshake.hrl").
-include("ssl_internal.hrl").
-include("tls_handshake.hrl").
-include_lib("public_key/include/public_key.hrl").
@@ -40,7 +41,9 @@ all() -> [decode_hello_handshake,
decode_single_hello_sni_extension_correctly,
decode_empty_server_sni_correctly,
select_proper_tls_1_2_rsa_default_hashsign,
- ignore_hassign_extension_pre_tls_1_2].
+ ignore_hassign_extension_pre_tls_1_2,
+ unorded_chain,
+ encode_decode_srp].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
@@ -149,7 +152,7 @@ decode_single_hello_sni_extension_correctly(_Config) ->
Exts = Decoded.
decode_empty_server_sni_correctly(_Config) ->
- Exts = #hello_extensions{sni = ""},
+ Exts = #hello_extensions{sni = #sni{hostname = ""}},
SNI = <<?UINT16(?SNI_EXT),?UINT16(0)>>,
Decoded = ssl_handshake:decode_hello_extensions(SNI),
Exts = Decoded.
@@ -173,6 +176,54 @@ ignore_hassign_extension_pre_tls_1_2(Config) ->
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,2}), {3,2}),
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,0}), {3,0}).
+unorded_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := _ClientConf} = public_key:pkix_test_data(CertChainConf),
+ PeerCert = proplists:get_value(cert, ServerConf),
+ CaCerts = [_, C1, C2] = proplists:get_value(cacerts, ServerConf),
+ {ok, ExtractedCerts} = ssl_pkix_db:extract_trusted_certs({der, CaCerts}),
+ UnordedChain = case public_key:pkix_is_self_signed(C1) of
+ true ->
+ [C1, C2];
+ false ->
+ [C2, C1]
+ end,
+ OrderedChain = [PeerCert | lists:reverse(UnordedChain)],
+ {ok, _, OrderedChain} =
+ ssl_certificate:certificate_chain(PeerCert, ets:new(foo, []), ExtractedCerts, UnordedChain).
+
+encode_decode_srp(_Config) ->
+ Exts = #hello_extensions{
+ srp = #srp{username = <<"foo">>},
+ sni = #sni{hostname = "bar"},
+ renegotiation_info = undefined,
+ signature_algs = undefined,
+ alpn = undefined,
+ next_protocol_negotiation = undefined,
+ ec_point_formats = undefined,
+ elliptic_curves = undefined
+ },
+ EncodedExts = <<0,20, % Length
+ 0,0, % SNI extension
+ 0,8, % Length
+ 0,6, % ServerNameLength
+ 0, % NameType (host_name)
+ 0,3, % HostNameLength
+ 98,97,114, % hostname = "bar"
+ 0,12, % SRP extension
+ 0,4, % Length
+ 3, % srp_I length
+ 102,111,111>>, % username = "foo"
+ EncodedExts = ssl_handshake:encode_hello_extensions(Exts),
+ Exts = ssl_handshake:decode_hello_extensions({client, EncodedExts}).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
is_supported(Hash) ->
Algos = crypto:supports(),
Hashs = proplists:get_value(hashs, Algos),
diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
index 1c7d6b5f9f..878e983bb9 100644
--- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
@@ -64,13 +64,12 @@ next_protocol_not_supported() ->
npn_not_supported_server
].
-init_per_suite(Config) ->
+init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
ssl_test_lib:clean_start(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config),
- proplists:get_value(priv_dir, Config)),
+ Config = ssl_test_lib:make_rsa_cert(Config0),
ssl_test_lib:cert_options(Config)
catch _:_ ->
{skip, "Crypto did not start"}
@@ -196,10 +195,10 @@ client_negotiate_server_does_not_support(Config) when is_list(Config) ->
renegotiate_from_client_after_npn_handshake(Config) when is_list(Config) ->
Data = "hello world",
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ClientOpts = [{client_preferred_next_protocols,
{client, [<<"http/1.0">>], <<"http/1.1">>}}] ++ ClientOpts0,
- ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{next_protocols_advertised,
[<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}] ++ ServerOpts0,
ExpectedProtocol = {ok, <<"http/1.0">>},
@@ -221,7 +220,7 @@ renegotiate_from_client_after_npn_handshake(Config) when is_list(Config) ->
%--------------------------------------------------------------------------------
npn_not_supported_client(Config) when is_list(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
PrefProtocols = {client_preferred_next_protocols,
{client, [<<"http/1.0">>], <<"http/1.1">>}},
ClientOpts = [PrefProtocols] ++ ClientOpts0,
@@ -236,7 +235,7 @@ npn_not_supported_client(Config) when is_list(Config) ->
%--------------------------------------------------------------------------------
npn_not_supported_server(Config) when is_list(Config)->
- ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
AdvProtocols = {next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]},
ServerOpts = [AdvProtocols] ++ ServerOpts0,
@@ -244,63 +243,24 @@ npn_not_supported_server(Config) when is_list(Config)->
%--------------------------------------------------------------------------------
npn_handshake_session_reused(Config) when is_list(Config)->
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ClientOpts = [{client_preferred_next_protocols,
{client, [<<"http/1.0">>], <<"http/1.1">>}}] ++ ClientOpts0,
- ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts =[{next_protocols_advertised,
[<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}] ++ ServerOpts0,
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {options, ServerOpts}]),
-
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result_msg, []}},
- {options, ClientOpts}]),
-
- SessionInfo =
- receive
- {Server, Info} ->
- Info
- end,
-
- Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
-
- %% Make sure session is registered
- ct:sleep(?SLEEP),
-
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- receive
- {Client1, SessionInfo} ->
- ok;
- {Client1, Other} ->
- ct:fail(Other)
- end,
+ ssl_test_lib:reuse_session(ClientOpts, ServerOpts, Config).
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- ssl_test_lib:close(Client1).
-
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
run_npn_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) ->
Data = "hello world",
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ClientOpts = ClientExtraOpts ++ ClientOpts0,
- ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = ServerExtraOpts ++ ServerOpts0,
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 3261244ace..6d26b2df33 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -141,6 +141,7 @@ socket_active_packet_tests() ->
packet_4_active_some_big,
packet_wait_active,
packet_size_active,
+ packet_switch,
%% inet header option should be deprecated!
header_decode_one_byte_active,
header_decode_two_bytes_active,
@@ -702,6 +703,34 @@ packet_size_passive(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+packet_switch() ->
+ [{doc,"Test packet option {packet, 2} followd by {packet, 4}"}].
+
+packet_switch(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, send_switch_packet ,["Hello World", 4]}},
+ {options, [{nodelay, true},{packet, 2} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, recv_switch_packet, ["Hello World", 4]}},
+ {options, [{nodelay, true}, {packet, 2} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
%%--------------------------------------------------------------------
packet_cdr_decode() ->
[{doc,"Test setting the packet option {packet, cdr}, {mode, binary}"}].
@@ -2093,26 +2122,13 @@ active_once_packet(Socket, Data, N) ->
active_once_packet(Socket, Data, N-1).
active_raw(Socket, Data, N) ->
- active_raw(Socket, Data, N, []).
-
-active_raw(_Socket, _, 0, _) ->
+ active_raw(Socket, (length(Data) * N)).
+active_raw(_Socket, 0) ->
ok;
-active_raw(Socket, Data, N, Acc) ->
+active_raw(Socket, N) ->
receive
- {ssl, Socket, Byte} when length(Byte) == 1 ->
- receive
- {ssl, Socket, _} ->
- active_raw(Socket, Data, N -1)
- end;
- {ssl, Socket, Data} ->
- active_raw(Socket, Data, N-1, []);
- {ssl, Socket, Other} ->
- case Acc ++ Other of
- Data ->
- active_raw(Socket, Data, N-1, []);
- NewAcc ->
- active_raw(Socket, Data, NewAcc)
- end
+ {ssl, Socket, Bytes} ->
+ active_raw(Socket, N-length(Bytes))
end.
active_packet(Socket, _, 0) ->
@@ -2286,3 +2302,26 @@ client_reject_packet_opt(Config, PacketOpt) ->
ClientOpts]}]),
ssl_test_lib:check_result(Client, {error, {options, {not_supported, PacketOpt}}}).
+
+
+send_switch_packet(SslSocket, Data, NextPacket) ->
+ ssl:send(SslSocket, Data),
+ receive
+ {ssl, SslSocket, "Hello World"} ->
+ ssl:setopts(SslSocket, [{packet, NextPacket}]),
+ ssl:send(SslSocket, Data),
+ receive
+ {ssl, SslSocket, "Hello World"} ->
+ ok
+ end
+ end.
+recv_switch_packet(SslSocket, Data, NextPacket) ->
+ receive
+ {ssl, SslSocket, "Hello World"} ->
+ ssl:send(SslSocket, Data),
+ ssl:setopts(SslSocket, [{packet, NextPacket}]),
+ receive
+ {ssl, SslSocket, "Hello World"} ->
+ ssl:send(SslSocket, Data)
+ end
+ end.
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index 5939800001..2d0ffd03d7 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -48,30 +48,40 @@ groups() ->
payload_tests() ->
[server_echos_passive_small,
+ server_echos_passive_chunk_small,
server_echos_active_once_small,
server_echos_active_small,
client_echos_passive_small,
+ client_echos_passive_chunk_small,
client_echos_active_once_small,
client_echos_active_small,
server_echos_passive_big,
+ server_echos_passive_chunk_big,
server_echos_active_once_big,
server_echos_active_big,
client_echos_passive_big,
+ client_echos_passive_chunk_big,
client_echos_active_once_big,
client_echos_active_big,
server_echos_passive_huge,
+ server_echos_passive_chunk_huge,
server_echos_active_once_huge,
server_echos_active_huge,
client_echos_passive_huge,
+ client_echos_passive_chunk_huge,
client_echos_active_once_huge,
- client_echos_active_huge].
+ client_echos_active_huge,
+ client_active_once_server_close].
init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
ssl_test_lib:clean_start(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config), proplists:get_value(priv_dir, Config)),
+ {ok, _} =
+ make_certs:all(
+ proplists:get_value(data_dir, Config),
+ proplists:get_value(priv_dir, Config)),
ssl_test_lib:cert_options(Config)
catch _:_ ->
{skip, "Crypto did not start"}
@@ -103,12 +113,15 @@ end_per_group(GroupName, Config) ->
Config
end.
-init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge;
- TestCase == server_echos_active_once_huge;
- TestCase == server_echos_active_huge;
- TestCase == client_echos_passive_huge;
- TestCase == client_echos_active_once_huge;
- TestCase == client_echos_active_huge ->
+init_per_testcase(TestCase, Config)
+ when TestCase == server_echos_passive_huge;
+ TestCase == server_echos_passive_chunk_huge;
+ TestCase == server_echos_active_once_huge;
+ TestCase == server_echos_active_huge;
+ TestCase == client_echos_passive_huge;
+ TestCase == client_echos_passive_chunk_huge;
+ TestCase == client_echos_active_once_huge;
+ TestCase == client_echos_active_huge ->
case erlang:system_info(system_architecture) of
"sparc-sun-solaris2.10" ->
{skip,"Will take to long time on an old Sparc"};
@@ -117,12 +130,15 @@ init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge;
Config
end;
-init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_big;
- TestCase == server_echos_active_once_big;
- TestCase == server_echos_active_big;
- TestCase == client_echos_passive_big;
- TestCase == client_echos_active_once_big;
- TestCase == client_echos_active_big ->
+init_per_testcase(TestCase, Config)
+ when TestCase == server_echos_passive_big;
+ TestCase == server_echos_passive_chunk_big;
+ TestCase == server_echos_active_once_big;
+ TestCase == server_echos_active_big;
+ TestCase == client_echos_passive_big;
+ TestCase == client_echos_passive_chunk_big;
+ TestCase == client_echos_active_once_big;
+ TestCase == client_echos_active_big ->
ct:timetrap({seconds, 60}),
Config;
@@ -144,11 +160,26 @@ server_echos_passive_small(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ server_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
+
+%%--------------------------------------------------------------------
+
+server_echos_passive_chunk_small() ->
+ [{doc, "Client sends 1000 bytes in passive mode to server, that receives them in chunks, "
+ "sends them back, and closes."}].
+
+server_echos_passive_chunk_small(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ server_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
- Str = "1234567890",
-
- server_echos_passive(Str, 1000, ClientOpts, ServerOpts,
- ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
@@ -160,11 +191,10 @@ server_echos_active_once_small(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- server_echos_active_once(Str, 1000, ClientOpts, ServerOpts,
- ClientNode, ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ server_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
@@ -176,11 +206,10 @@ server_echos_active_small(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- server_echos_active(Str, 1000, ClientOpts, ServerOpts,
- ClientNode, ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ server_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_passive_small() ->
@@ -191,11 +220,25 @@ client_echos_passive_small(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ client_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
+
+%%--------------------------------------------------------------------
+client_echos_passive_chunk__small() ->
+ [{doc, "Server sends 1000 bytes in passive mode to client, that receives them in chunks, "
+ "sends them back, and closes."}].
- Str = "1234567890",
+client_echos_passive_chunk_small(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ client_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
- client_echos_passive(Str, 1000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_active_once_small() ->
@@ -206,11 +249,10 @@ client_echos_active_once_small(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- client_echos_active_once(Str, 1000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ client_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_active_small() ->
@@ -221,11 +263,10 @@ client_echos_active_small(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- client_echos_active(Str, 1000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 100),
+ client_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
@@ -237,11 +278,23 @@ server_echos_passive_big(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ server_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
+%%--------------------------------------------------------------------
+server_echos_passive_chunk_big() ->
+ [{doc, "Client sends 50000 bytes to server in passive mode, that receives them, "
+ "sends them back, and closes."}].
- Str = "1234567890",
-
- server_echos_passive(Str, 50000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+server_echos_passive_chunk_big(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ server_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
@@ -253,11 +306,10 @@ server_echos_active_once_big(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- server_echos_active_once(Str, 50000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ server_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
@@ -269,11 +321,10 @@ server_echos_active_big(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- server_echos_active(Str, 50000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ server_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_passive_big() ->
@@ -284,11 +335,26 @@ client_echos_passive_big(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ client_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
+
+
+%%--------------------------------------------------------------------
+client_echos_passive_chunk_big() ->
+ [{doc, "Server sends 50000 bytes to client in passive mode, that receives them, "
+ "sends them back, and closes."}].
- Str = "1234567890",
+client_echos_passive_chunk_big(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ client_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
- client_echos_passive(Str, 50000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_active_once_big() ->
@@ -299,11 +365,10 @@ client_echos_active_once_big(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- client_echos_active_once(Str, 50000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ client_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_active_big() ->
@@ -314,11 +379,10 @@ client_echos_active_big(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- client_echos_active(Str, 50000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 5000),
+ client_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
server_echos_passive_huge() ->
@@ -329,11 +393,24 @@ server_echos_passive_huge(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ server_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
- Str = "1234567890",
-
- server_echos_passive(Str, 500000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+%%--------------------------------------------------------------------
+server_echos_passive_chunk_huge() ->
+ [{doc, "Client sends 500000 bytes to server in passive mode, that receives "
+ " them, sends them back, and closes."}].
+
+server_echos_passive_chunk_huge(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ server_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
server_echos_active_once_huge() ->
@@ -344,11 +421,10 @@ server_echos_active_once_huge(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- server_echos_active_once(Str, 500000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ server_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
server_echos_active_huge() ->
@@ -359,11 +435,10 @@ server_echos_active_huge(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
-
- server_echos_active(Str, 500000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ server_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_passive_huge() ->
@@ -374,11 +449,23 @@ client_echos_passive_huge(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ client_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
+%%--------------------------------------------------------------------
+client_echos_passive_chunk_huge() ->
+ [{doc, "Server sends 500000 bytes to client in passive mode, that receives "
+ "them, sends them back, and closes."}].
- Str = "1234567890",
- client_echos_passive(Str, 500000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
-
+client_echos_passive_chunk_huge(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ client_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_active_once_huge() ->
[{doc, "Server sends 500000 bytes to client in active once mode, that receives "
@@ -388,10 +475,10 @@ client_echos_active_once_huge(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Str = "1234567890",
- client_echos_active_once(Str, 500000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ client_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
%%--------------------------------------------------------------------
client_echos_active_huge() ->
@@ -402,293 +489,325 @@ client_echos_active_huge(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ client_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
+
- Str = "1234567890",
- client_echos_active(Str, 500000, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname).
+%%--------------------------------------------------------------------
+client_active_once_server_close() ->
+ [{doc, "Server sends 500000 bytes and immediately after closes the connection"
+ "Make sure client recives all data if possible"}].
+
+client_active_once_server_close(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %%
+ Data = binary:copy(<<"1234567890">>, 50000),
+ client_active_once_server_close(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname).
+
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-server_echos_passive(Data, Length, ClientOpts, ServerOpts,
- ClientNode, ServerNode, Hostname) ->
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, echoer,
- [Data, Length]}},
- {options,
- [{active, false},{mode, binary}
- | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa,
- {?MODULE, sender,
- [Data,
- Length]}},
- {options,
- [{active, false}, {mode, binary} |
- ClientOpts]}]),
+server_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, echoer, [Length]}},
+ {options, [{active, false}, {mode, binary} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, sender, [Data]}},
+ {options, [{active, false}, {mode, binary} | ClientOpts]}]),
+ %%
ssl_test_lib:check_result(Server, ok, Client, ok),
-
+ %%
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+server_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, echoer_chunk, [Length]}},
+ {options, [{active, false}, {mode, binary} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, sender, [Data]}},
+ {options, [{active, false}, {mode, binary} | ClientOpts]}]),
+ %%
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ %%
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
-server_echos_active_once(Data, Length, ClientOpts, ServerOpts, ClientNode,
- ServerNode, Hostname) ->
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, echoer_once,
- [Data, Length]}},
- {options, [{active, once},
- {mode, binary}|
- ServerOpts]}]),
+server_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, echoer_active_once, [Length]}},
+ {options, [{active, once}, {mode, binary} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa,
- {?MODULE, sender_once,
- [Data, Length]}},
- {options, [{active, once},
- {mode, binary} |
- ClientOpts]}]),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, sender_active_once, [Data]}},
+ {options, [{active, once}, {mode, binary} | ClientOpts]}]),
+ %%
ssl_test_lib:check_result(Server, ok, Client, ok),
-
+ %%
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-server_echos_active(Data, Length, ClientOpts, ServerOpts,
- ClientNode, ServerNode, Hostname) ->
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, echoer_active,
- [Data, Length]}},
- {options,
- [{active, true},
- {mode, binary} | ServerOpts]}]),
+server_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, echoer_active, [Length]}},
+ {options, [{active, true}, {mode, binary} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, sender_active, [Data]}},
+ {options, [{active, true}, {mode, binary} | ClientOpts]}]),
+ %%
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ %%
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_echos_passive(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, sender, [Data]}},
+ {options, [{active, false}, {mode, binary} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa,
- {?MODULE, sender_active,
- [Data,
- Length]}},
- {options,
- [{active, true}, {mode, binary}
- | ClientOpts]}]),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, echoer, [Length]}},
+ {options, [{active, false}, {mode, binary} | ClientOpts]}]),
+ %%
ssl_test_lib:check_result(Server, ok, Client, ok),
-
+ %%
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-client_echos_passive(Data, Length, ClientOpts, ServerOpts,
- ClientNode, ServerNode, Hostname) ->
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, sender,
- [Data, Length]}},
- {options,
- [{active, false}, {mode, binary} |
- ServerOpts]}]),
+
+client_echos_passive_chunk(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, sender, [Data]}},
+ {options, [{active, false}, {mode, binary} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa,
- {?MODULE, echoer,
- [Data,
- Length]}},
- {options,
- [{active, false}, {mode, binary}
- | ClientOpts]}]),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, echoer_chunk, [Length]}},
+ {options, [{active, false}, {mode, binary} | ClientOpts]}]),
+ %%
ssl_test_lib:check_result(Server, ok, Client, ok),
-
+ %%
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-client_echos_active_once(Data, Length,
- ClientOpts, ServerOpts, ClientNode, ServerNode,
- Hostname) ->
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, sender_once,
- [Data, Length]}},
- {options, [{active, once},
- {mode, binary} |
- ServerOpts]}]),
+
+client_echos_active_once(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, sender_active_once, [Data]}},
+ {options, [{active, once}, {mode, binary} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa,
- {?MODULE, echoer_once,
- [Data,
- Length]}},
- {options,[{active, once},
- {mode, binary}
- | ClientOpts]}]),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, echoer_active_once, [Length]}},
+ {options,[{active, once}, {mode, binary} | ClientOpts]}]),
+ %%
ssl_test_lib:check_result(Server, ok, Client, ok),
-
+ %%
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-client_echos_active(Data, Length, ClientOpts, ServerOpts, ClientNode,
- ServerNode,
- Hostname) ->
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa,
- {?MODULE, sender_active,
- [Data, Length]}},
- {options, [{active, true},
- {mode, binary}
- | ServerOpts]}]),
+client_echos_active(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, sender_active, [Data]}},
+ {options, [{active, true}, {mode, binary} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa,
- {?MODULE, echoer_active,
- [Data,
- Length]}},
- {options, [{active, true},
- {mode, binary}
- | ClientOpts]}]),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, echoer_active, [Length]}},
+ {options, [{active, true}, {mode, binary} | ClientOpts]}]),
+ %
ssl_test_lib:check_result(Server, ok, Client, ok),
-
+ %%
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-send(_, _, _, 0,_) ->
+client_active_once_server_close(
+ Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) ->
+ Length = byte_size(Data),
+ Server =
+ ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, send_close, [Data]}},
+ {options, [{active, once}, {mode, binary} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, active_once_recv, [Length]}},
+ {options,[{active, once}, {mode, binary} | ClientOpts]}]),
+ %%
+ ssl_test_lib:check_result(Server, ok, Client, ok).
+
+send(_Socket, _Data, 0, _) ->
ok;
-send(Socket, Data, Size, Repeate,F) ->
- NewData = lists:duplicate(Size div 10, Data),
- ssl:send(Socket, NewData),
- F(),
- send(Socket, Data, Size, Repeate - 1,F).
-
-sender(Socket, Data, Size) ->
- ok = send(Socket, Data, Size, 100, fun() -> do_recv(Socket, Data, Size, <<>>, false) end),
+send(Socket, Data, Count, RecvEcho) ->
+ ok = ssl:send(Socket, Data),
+ RecvEcho(),
+ send(Socket, Data, Count - 1, RecvEcho).
+
+send_close(Socket, Data) ->
+ ok = ssl:send(Socket, Data),
+ ssl:close(Socket).
+
+sender(Socket, Data) ->
ct:log("Sender recv: ~p~n", [ssl:getopts(Socket, [active])]),
- ok.
-
-sender_once(Socket, Data, Size) ->
- send(Socket, Data, Size, 100,
- fun() -> do_active_once(Socket, Data, Size, <<>>, false) end),
- ct:log("Sender active once: ~p~n",
- [ssl:getopts(Socket, [active])]),
- ok.
-
-sender_active(Socket, Data, Size) ->
- F = fun() -> do_active(Socket, Data, Size, <<>>, false) end,
- send(Socket, Data, Size, 100, F),
+ send(Socket, Data, 100,
+ fun() ->
+ ssl_test_lib:recv_disregard(Socket, byte_size(Data))
+ end).
+
+sender_active_once(Socket, Data) ->
+ ct:log("Sender active once: ~p~n", [ssl:getopts(Socket, [active])]),
+ send(Socket, Data, 100,
+ fun() ->
+ ssl_test_lib:active_once_disregard(Socket, byte_size(Data))
+ end).
+
+sender_active(Socket, Data) ->
ct:log("Sender active: ~p~n", [ssl:getopts(Socket, [active])]),
- ok.
+ send(Socket, Data, 100,
+ fun() ->
+ ssl_test_lib:active_disregard(Socket, byte_size(Data))
+ end).
-echoer(Socket, Data, Size) ->
+echoer(Socket, Size) ->
ct:log("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]),
- echo(fun() -> do_recv(Socket, Data, Size, <<>>, true) end, 100).
+ echo_recv(Socket, Size * 100).
-echoer_once(Socket, Data, Size) ->
- ct:log("Echoer active once: ~p ~n",
- [ssl:getopts(Socket, [active])]),
- echo(fun() -> do_active_once(Socket, Data, Size, <<>>, true) end, 100).
+echoer_chunk(Socket, Size) ->
+ ct:log("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]),
+ echo_recv_chunk(Socket, Size, Size * 100).
+
+echoer_active_once(Socket, Size) ->
+ ct:log("Echoer active once: ~p~n", [ssl:getopts(Socket, [active])]),
+ echo_active_once(Socket, Size * 100).
-echoer_active(Socket, Data, Size) ->
+echoer_active(Socket, Size) ->
ct:log("Echoer active: ~p~n", [ssl:getopts(Socket, [active])]),
- echo(fun() -> do_active(Socket, Data, Size, <<>>, true) end, 100).
+ echo_active(Socket, Size * 100).
-echo(_Fun, 0) -> ok;
-echo(Fun, N) ->
- Fun(),
- echo(Fun, N-1).
+%% Receive Size bytes
+echo_recv(_Socket, 0) ->
+ ok;
+echo_recv(Socket, Size) ->
+ {ok, Data} = ssl:recv(Socket, 0),
+ ok = ssl:send(Socket, Data),
+ echo_recv(Socket, Size - byte_size(Data)).
-do_recv(_Socket, _Data, 0, _Acc, true) ->
+
+%% Receive Size bytes
+echo_recv_chunk(_Socket, _, 0) ->
ok;
-do_recv(_Socket, Data, 0, Acc, false) ->
- Data = lists:sublist(binary_to_list(Acc), 10);
+echo_recv_chunk(Socket, ChunkSize, Size) ->
+ {ok, Data} = ssl:recv(Socket, ChunkSize),
+ ok = ssl:send(Socket, Data),
+ echo_recv_chunk(Socket, ChunkSize, Size - ChunkSize).
-do_recv(Socket, Data, Size, Acc, Echo) ->
- {ok, NewData} = ssl:recv(Socket, 0),
- NewSize = size(NewData),
- case Echo of
- true ->
- ssl:send(Socket, NewData),
- NewSize = size(NewData),
- do_recv(Socket, Data, Size - NewSize, [], Echo);
- false ->
- case size(Acc) < 10 of
- true ->
- do_recv(Socket, Data, Size - NewSize,
- <<Acc/binary, NewData/binary>>, Echo);
- false ->
- do_recv(Socket, Data, Size - NewSize, Acc, Echo)
- end
- end.
-do_active_once(_Socket, _Data, 0, _Acc, true) ->
+%% Receive Size bytes
+echo_active_once(_Socket, 0) ->
ok;
-do_active_once(_Socket, Data, 0, Acc, false) ->
- Data = lists:sublist(binary_to_list(Acc), 10);
-
-do_active_once(Socket, Data, Size, Acc, Echo) ->
- receive
- {ssl, Socket, NewData} ->
- NewSize = size(NewData),
- case Echo of
- true ->
- ssl:send(Socket, NewData),
- ssl:setopts(Socket, [{active, once}]),
- do_active_once(Socket, Data, Size - NewSize, [], Echo);
- false ->
- case size(Acc) < 10 of
- true ->
- ssl:setopts(Socket, [{active, once}]),
- do_active_once(Socket, Data, Size - NewSize,
- <<Acc/binary, NewData/binary>>,
- Echo);
- false ->
- ssl:setopts(Socket, [{active, once}]),
- do_active_once(Socket, Data,
- Size - NewSize, Acc, Echo)
- end
- end
+echo_active_once(Socket, Size) ->
+ receive
+ {ssl, Socket, Data} ->
+ ok = ssl:send(Socket, Data),
+ NewSize = Size - byte_size(Data),
+ ssl:setopts(Socket, [{active, once}]),
+ echo_active_once(Socket, NewSize)
end.
-
-do_active(_Socket, _Data, 0, _Acc, true) ->
+
+%% Receive Size bytes
+echo_active(_Socket, 0) ->
ok;
-do_active(_Socket, Data, 0, Acc, false) ->
- Data = lists:sublist(binary_to_list(Acc), 10);
-
-do_active(Socket, Data, Size, Acc, Echo) ->
- receive
- {ssl, Socket, NewData} ->
- NewSize = size(NewData),
- case Echo of
- true ->
- ssl:send(Socket, NewData),
- do_active(Socket, Data, Size - NewSize, [], Echo);
- false ->
- case size(Acc) < 10 of
- true ->
- do_active(Socket, Data, Size - NewSize,
- <<Acc/binary, NewData/binary>>,
- Echo);
- false ->
- do_active(Socket, Data,
- Size - NewSize, Acc, Echo)
- end
- end
- end.
+echo_active(Socket, Size) ->
+ receive
+ {ssl, Socket, Data} ->
+ ok = ssl:send(Socket, Data),
+ echo_active(Socket, Size - byte_size(Data))
+ end.
+
diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl
index 96b15d9b51..6f11e2bbe8 100644
--- a/lib/ssl/test/ssl_pem_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [pem_cleanup].
+ [pem_cleanup, invalid_insert].
groups() ->
[].
@@ -44,11 +44,8 @@ init_per_suite(Config0) ->
try crypto:start() of
ok ->
ssl_test_lib:clean_start(),
- %% make rsa certs using oppenssl
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- Config1 = ssl_test_lib:make_dsa_cert(Config0),
- ssl_test_lib:cert_options(Config1)
+ %% make rsa certs
+ ssl_test_lib:make_rsa_cert(Config0)
catch _:_ ->
{skip, "Crypto did not start"}
end.
@@ -68,6 +65,10 @@ init_per_testcase(pem_cleanup = Case, Config) ->
application:set_env(ssl, ssl_pem_cache_clean, ?CLEANUP_INTERVAL),
ssl:start(),
ct:timetrap({minutes, 1}),
+ Config;
+init_per_testcase(_, Config) ->
+ ssl:start(),
+ ct:timetrap({seconds, 5}),
Config.
end_per_testcase(_TestCase, Config) ->
@@ -82,8 +83,8 @@ pem_cleanup() ->
[{doc, "Test pem cache invalidate mechanism"}].
pem_cleanup(Config)when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = proplists:get_value(client_verification_opts, Config),
- ServerOpts = proplists:get_value(server_verification_opts, Config),
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
@@ -108,7 +109,34 @@ pem_cleanup(Config)when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client),
false = Size == Size1.
-
+
+invalid_insert() ->
+ [{doc, "Test that insert of invalid pem does not cause empty cache entry"}].
+invalid_insert(Config)when is_list(Config) ->
+ process_flag(trap_exit, true),
+
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ BadClientOpts = [{cacertfile, "tmp/does_not_exist.pem"} | proplists:delete(cacertfile, ClientOpts)],
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {from, self()}, {options, BadClientOpts}]),
+ ssl_test_lib:close(Server),
+ 1 = ssl_pkix_db:db_size(get_fileref_db()).
+
+
+
+%%--------------------------------------------------------------------
+%% Internal funcations
+%%--------------------------------------------------------------------
+
get_pem_cache() ->
{status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
[_, _,_, _, Prop] = StatusInfo,
@@ -120,6 +148,16 @@ get_pem_cache() ->
undefined
end.
+get_fileref_db() ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ case element(6, State) of
+ [_CertDb, {FileRefDb,_} | _] ->
+ FileRefDb;
+ _ ->
+ undefined
+ end.
later()->
DateTime = calendar:now_to_local_time(os:timestamp()),
Gregorian = calendar:datetime_to_gregorian_seconds(DateTime),
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 9862b3ce64..7f33fe3204 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,7 +48,8 @@ all() ->
session_cache_process_list,
session_cache_process_mnesia,
client_unique_session,
- max_table_size
+ max_table_size,
+ save_specific_session
].
groups() ->
@@ -60,10 +61,7 @@ init_per_suite(Config0) ->
ok ->
ssl_test_lib:clean_start(),
%% make rsa certs using
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- Config = ssl_test_lib:make_dsa_cert(Config0),
- ssl_test_lib:cert_options(Config)
+ ssl_test_lib:make_rsa_cert(Config0)
catch _:_ ->
{skip, "Crypto did not start"}
end.
@@ -97,7 +95,10 @@ init_per_testcase(session_cleanup, Config) ->
init_per_testcase(client_unique_session, Config) ->
ct:timetrap({seconds, 40}),
Config;
-
+init_per_testcase(save_specific_session, Config) ->
+ ssl_test_lib:clean_start(),
+ ct:timetrap({seconds, 5}),
+ Config;
init_per_testcase(max_table_size, Config) ->
ssl:stop(),
application:load(ssl),
@@ -141,7 +142,7 @@ end_per_testcase(max_table_size, Config) ->
end_per_testcase(default_action, Config);
end_per_testcase(Case, Config) when Case == session_cache_process_list;
Case == session_cache_process_mnesia ->
- ets:delete(ssl_test),
+ catch ets:delete(ssl_test),
Config;
end_per_testcase(_, Config) ->
Config.
@@ -154,8 +155,8 @@ client_unique_session() ->
"sets up many connections"}].
client_unique_session(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = proplists:get_value(client_opts, Config),
- ServerOpts = proplists:get_value(server_opts, Config),
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -164,8 +165,7 @@ client_unique_session(Config) when is_list(Config) ->
{tcp_options, [{active, false}]},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- LastClient = clients_start(Server,
- ClientNode, Hostname, Port, ClientOpts, client_unique_session, 20),
+ LastClient = clients_start(Server, ClientNode, Hostname, Port, ClientOpts, 20),
receive
{LastClient, {ok, _}} ->
ok
@@ -185,8 +185,8 @@ session_cleanup() ->
"does not grow and grow ..."}].
session_cleanup(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
@@ -254,13 +254,75 @@ session_cache_process_mnesia(Config) when is_list(Config) ->
session_cache_process(mnesia,Config).
%%--------------------------------------------------------------------
+save_specific_session() ->
+ [{doc, "Test that we can save a specific client session"
+ }].
+save_specific_session(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {tcp_options, [{active, false}]},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client1 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, ClientOpts}]),
+ Server ! listen,
+
+ Client2 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_sessions, save} | ClientOpts]}]),
+ SessionID1 =
+ receive
+ {Client1, S1} ->
+ S1
+ end,
+
+ SessionID2 =
+ receive
+ {Client2, S2} ->
+ S2
+ end,
+
+ true = SessionID1 =/= SessionID2,
+
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ ClientCache = element(2, State),
+ 2 = ssl_session_cache:size(ClientCache),
+
+ Server ! listen,
+
+ Client3 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_session, SessionID2} | ClientOpts]}]),
+ receive
+ {Client3, SessionID2} ->
+ ok;
+ {Client3, SessionID3}->
+ ct:fail({got, SessionID3, expected, SessionID2});
+ Other ->
+ ct:fail({got,Other})
+ end.
+
+%%--------------------------------------------------------------------
max_table_size() ->
[{doc,"Test max limit on session table"}].
max_table_size(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = proplists:get_value(client_verification_opts, Config),
- ServerOpts = proplists:get_value(server_verification_opts, Config),
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -270,7 +332,7 @@ max_table_size(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
LastClient = clients_start(Server,
- ClientNode, Hostname, Port, ClientOpts, max_table_size, 20),
+ ClientNode, Hostname, Port, ClientOpts, 20),
receive
{LastClient, {ok, _}} ->
ok
@@ -426,25 +488,27 @@ session_loop(Sess) ->
%%--------------------------------------------------------------------
session_cache_process(_Type,Config) when is_list(Config) ->
- ssl_basic_SUITE:reuse_session(Config).
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ssl_test_lib:reuse_session(ClientOpts, ServerOpts, Config).
-clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, Test, 0) ->
+clients_start(_Server, ClientNode, Hostname, Port, ClientOpts, 0) ->
%% Make sure session is registered
ct:sleep(?SLEEP * 2),
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
{mfa, {?MODULE, connection_info_result, []}},
- {from, self()}, {options, test_copts(Test, 0, ClientOpts)}]);
-clients_start(Server, ClientNode, Hostname, Port, ClientOpts, Test, N) ->
+ {from, self()}, {options, ClientOpts}]);
+clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N) ->
spawn_link(ssl_test_lib, start_client,
[[{node, ClientNode},
{port, Port}, {host, Hostname},
{mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, test_copts(Test, N, ClientOpts)}]]),
+ {from, self()}, {options, ClientOpts}]]),
Server ! listen,
wait_for_server(),
- clients_start(Server, ClientNode, Hostname, Port, ClientOpts, Test, N-1).
+ clients_start(Server, ClientNode, Hostname, Port, ClientOpts, N-1).
connection_info_result(Socket) ->
ssl:connection_information(Socket, [protocol, cipher_suite]).
@@ -481,21 +545,3 @@ get_delay_timers() ->
wait_for_server() ->
ct:sleep(100).
-
-
-test_copts(_, 0, ClientOpts) ->
- ClientOpts;
-test_copts(max_table_size, N, ClientOpts) ->
- Version = tls_record:highest_protocol_version([]),
- CipherSuites = %%lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))),
-[ Y|| Y = {Alg,_, _, _} <- lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), Alg =/= ecdhe_ecdsa, Alg =/= ecdh_ecdsa, Alg =/= ecdh_rsa, Alg =/= ecdhe_rsa, Alg =/= dhe_dss, Alg =/= dss],
- case length(CipherSuites) of
- M when M >= N ->
- Cipher = lists:nth(N, CipherSuites),
- ct:pal("~p",[Cipher]),
- [{ciphers, [Cipher]} | ClientOpts];
- _ ->
- ClientOpts
- end;
-test_copts(_, _, ClientOpts) ->
- ClientOpts.
diff --git a/lib/ssl/test/ssl_sni_SUITE.erl b/lib/ssl/test/ssl_sni_SUITE.erl
index 251b6a2639..7629d75100 100644
--- a/lib/ssl/test/ssl_sni_SUITE.erl
+++ b/lib/ssl/test/ssl_sni_SUITE.erl
@@ -236,8 +236,8 @@ dns_name_reuse(Config) ->
{mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, [{verify, verify_peer} | ClientConf]}]),
- ssl_test_lib:check_result(Client1, {error, {tls_alert, "handshake failure"}}),
- ssl_test_lib:close(Client0).
+ ssl_test_lib:check_client_alert(Client1, handshake_failure).
+
%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -370,8 +370,8 @@ unsuccessfull_connect(ServerOptions, ClientOptions, Hostname0, Config) ->
{from, self()},
{options, ClientOptions}]),
- ssl_test_lib:check_result(Server, {error, {tls_alert, "handshake failure"}},
- Client, {error, {tls_alert, "handshake failure"}}).
+ ssl_test_lib:check_server_alert(Server, Client, handshake_failure).
+
host_name(undefined, Hostname) ->
Hostname;
host_name(Hostname, _) ->
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 39acc65f6c..bfed7d6fda 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -26,9 +26,11 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
+-compile(nowarn_export_all).
-record(sslsocket, { fd = nil, pid = nil}).
-define(SLEEP, 1000).
+-define(DEFAULT_CURVE, secp256r1).
%% For now always run locally
run_where(_) ->
@@ -196,6 +198,55 @@ connect(ListenSocket, Node, _, _, Timeout, Opts, _) ->
rpc:call(Node, ssl, ssl_accept, [AcceptSocket, Opts, Timeout]),
AcceptSocket.
+
+start_server_transport_abuse_socket(Args) ->
+ Result = spawn_link(?MODULE, transport_accept_abuse, [Args]),
+ receive
+ {listen, up} ->
+ Result
+ end.
+
+start_server_transport_control(Args) ->
+ Result = spawn_link(?MODULE, transport_switch_control, [Args]),
+ receive
+ {listen, up} ->
+ Result
+ end.
+
+
+transport_accept_abuse(Opts) ->
+ Node = proplists:get_value(node, Opts),
+ Port = proplists:get_value(port, Opts),
+ Options = proplists:get_value(options, Opts),
+ Pid = proplists:get_value(from, Opts),
+ Transport = proplists:get_value(transport, Opts, ssl),
+ ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
+ {ok, ListenSocket} = rpc:call(Node, Transport, listen, [Port, Options]),
+ Pid ! {listen, up},
+ send_selected_port(Pid, Port, ListenSocket),
+ {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
+ [ListenSocket]),
+ {error, _} = rpc:call(Node, ssl, connection_information, [AcceptSocket]),
+ _ = rpc:call(Node, ssl, handshake, [AcceptSocket, infinity]),
+ Pid ! {self(), ok}.
+
+
+transport_switch_control(Opts) ->
+ Node = proplists:get_value(node, Opts),
+ Port = proplists:get_value(port, Opts),
+ Options = proplists:get_value(options, Opts),
+ Pid = proplists:get_value(from, Opts),
+ Transport = proplists:get_value(transport, Opts, ssl),
+ ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
+ {ok, ListenSocket} = rpc:call(Node, Transport, listen, [Port, Options]),
+ Pid ! {listen, up},
+ send_selected_port(Pid, Port, ListenSocket),
+ {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
+ [ListenSocket]),
+ ok = rpc:call(Node, ssl, controlling_process, [AcceptSocket, self()]),
+ Pid ! {self(), ok}.
+
+
remove_close_msg(0) ->
ok;
remove_close_msg(ReconnectTimes) ->
@@ -387,6 +438,55 @@ check_result(Pid, Msg) ->
{got, Unexpected}},
ct:fail(Reason)
end.
+check_server_alert(Pid, Alert) ->
+ receive
+ {Pid, {error, {tls_alert, {Alert, STxt}}}} ->
+ check_server_txt(STxt),
+ ok
+ end.
+check_server_alert(Server, Client, Alert) ->
+ receive
+ {Server, {error, {tls_alert, {Alert, STxt}}}} ->
+ check_server_txt(STxt),
+ receive
+ {Client, {error, {tls_alert, {Alert, CTxt}}}} ->
+ check_client_txt(CTxt),
+ ok;
+ {Client, {error, closed}} ->
+ ok
+ end
+ end.
+check_client_alert(Pid, Alert) ->
+ receive
+ {Pid, {error, {tls_alert, {Alert, CTxt}}}} ->
+ check_client_txt(CTxt),
+ ok
+ end.
+check_client_alert(Server, Client, Alert) ->
+ receive
+ {Client, {error, {tls_alert, {Alert, CTxt}}}} ->
+ check_client_txt(CTxt),
+ receive
+ {Server, {error, {tls_alert, {Alert, STxt}}}} ->
+ check_server_txt(STxt),
+ ok;
+ {Server, {error, closed}} ->
+ ok
+ end
+ end.
+check_server_txt("TLS server" ++ _) ->
+ ok;
+check_server_txt("DTLS server" ++ _) ->
+ ok;
+check_server_txt(Txt) ->
+ ct:fail({expected_server, {got, Txt}}).
+
+check_client_txt("TLS client" ++ _) ->
+ ok;
+check_client_txt("DTLS client" ++ _) ->
+ ok;
+check_client_txt(Txt) ->
+ ct:fail({expected_server, {got, Txt}}).
wait_for_result(Server, ServerMsg, Client, ClientMsg) ->
receive
@@ -473,7 +573,7 @@ cert_options(Config) ->
{client_verification_opts, [{cacertfile, ServerCaCertFile},
{certfile, ClientCertFile},
{keyfile, ClientKeyFile},
- {ssl_imp, new}]},
+ {verify, verify_peer}]},
{client_verification_opts_digital_signature_only, [{cacertfile, ServerCaCertFile},
{certfile, ClientCertFileDigitalSignatureOnly},
{keyfile, ClientKeyFile},
@@ -568,9 +668,12 @@ make_rsa_cert_chains(UserConf, Config, Suffix) ->
}.
make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) ->
+ make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config, ?DEFAULT_CURVE).
+%%
+make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config, Curve) ->
ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
- CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
+ CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain, Curve),
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]),
GenCertData = public_key:pkix_test_data(CertChainConf),
@@ -585,12 +688,27 @@ default_cert_chain_conf() ->
%% Use only default options
[[],[],[]].
+
gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) ->
+ gen_conf(ClientChainType, ServerChainType, UserClient, UserServer, ?DEFAULT_CURVE).
+%%
+gen_conf(mix, mix, UserClient, UserServer, _) ->
ClientTag = conf_tag("client"),
ServerTag = conf_tag("server"),
- DefaultClient = chain_spec(client, ClientChainType),
- DefaultServer = chain_spec(server, ServerChainType),
+ DefaultClient = default_cert_chain_conf(),
+ DefaultServer = default_cert_chain_conf(),
+
+ ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
+ ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
+
+ new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]);
+gen_conf(ClientChainType, ServerChainType, UserClient, UserServer, Curve) ->
+ ClientTag = conf_tag("client"),
+ ServerTag = conf_tag("server"),
+
+ DefaultClient = chain_spec(client, ClientChainType, Curve),
+ DefaultServer = chain_spec(server, ServerChainType, Curve),
ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
@@ -612,43 +730,43 @@ proplist_to_map([Head | Rest]) ->
conf_tag(Role) ->
list_to_atom(Role ++ "_chain").
-chain_spec(_Role, ecdh_rsa) ->
+chain_spec(_Role, ecdh_rsa, Curve) ->
Digest = {digest, appropriate_sha(crypto:supports())},
- CurveOid = hd(tls_v1:ecc_curves(0)),
+ CurveOid = pubkey_cert_records:namedCurves(Curve),
[[Digest, {key, {namedCurve, CurveOid}}],
[Digest, {key, hardcode_rsa_key(1)}],
[Digest, {key, {namedCurve, CurveOid}}]];
-chain_spec(_Role, ecdhe_ecdsa) ->
+chain_spec(_Role, ecdhe_ecdsa, Curve) ->
Digest = {digest, appropriate_sha(crypto:supports())},
- CurveOid = hd(tls_v1:ecc_curves(0)),
+ CurveOid = pubkey_cert_records:namedCurves(Curve),
[[Digest, {key, {namedCurve, CurveOid}}],
[Digest, {key, {namedCurve, CurveOid}}],
[Digest, {key, {namedCurve, CurveOid}}]];
-chain_spec(_Role, ecdh_ecdsa) ->
+chain_spec(_Role, ecdh_ecdsa, Curve) ->
Digest = {digest, appropriate_sha(crypto:supports())},
- CurveOid = hd(tls_v1:ecc_curves(0)),
+ CurveOid = pubkey_cert_records:namedCurves(Curve),
[[Digest, {key, {namedCurve, CurveOid}}],
[Digest, {key, {namedCurve, CurveOid}}],
[Digest, {key, {namedCurve, CurveOid}}]];
-chain_spec(_Role, ecdhe_rsa) ->
+chain_spec(_Role, ecdhe_rsa, _) ->
Digest = {digest, appropriate_sha(crypto:supports())},
[[Digest, {key, hardcode_rsa_key(1)}],
[Digest, {key, hardcode_rsa_key(2)}],
[Digest, {key, hardcode_rsa_key(3)}]];
-chain_spec(_Role, ecdsa) ->
+chain_spec(_Role, ecdsa, Curve) ->
Digest = {digest, appropriate_sha(crypto:supports())},
- CurveOid = hd(tls_v1:ecc_curves(0)),
+ CurveOid = pubkey_cert_records:namedCurves(Curve),
[[Digest, {key, {namedCurve, CurveOid}}],
[Digest, {key, {namedCurve, CurveOid}}],
[Digest, {key, {namedCurve, CurveOid}}]];
-chain_spec(_Role, rsa) ->
+chain_spec(_Role, rsa, _) ->
Digest = {digest, appropriate_sha(crypto:supports())},
[[Digest, {key, hardcode_rsa_key(1)}],
[Digest, {key, hardcode_rsa_key(2)}],
[Digest, {key, hardcode_rsa_key(3)}]];
-chain_spec(_Role, dsa) ->
+chain_spec(_Role, dsa, _) ->
Digest = {digest, appropriate_sha(crypto:supports())},
[[Digest, {key, hardcode_dsa_key(1)}],
[Digest, {key, hardcode_dsa_key(2)}],
@@ -678,6 +796,46 @@ merge_spec(User, Default, [Conf | Rest], Acc) ->
merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
end.
+make_mix_cert(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = pubkey_cert_records:namedCurves(?DEFAULT_CURVE),
+ Mix = proplists:get_value(mix, Config, peer_ecc),
+ ClientChainType =ServerChainType = mix,
+ {ClientChain, ServerChain} = mix(Mix, Digest, CurveOid, Ext),
+ CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix" ++ atom_to_list(Mix)]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix" ++ atom_to_list(Mix)]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
+
+mix(peer_ecc, Digest, CurveOid, Ext) ->
+ ClientChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, {namedCurve, CurveOid}}, {extensions, Ext}]
+ ],
+ ServerChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, {namedCurve, CurveOid}},{extensions, Ext}]
+ ],
+ {ClientChain, ServerChain};
+
+mix(peer_rsa, Digest, CurveOid, Ext) ->
+ ClientChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(1)}, {extensions, Ext}]
+ ],
+ ServerChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(2)},{extensions, Ext}]
+ ],
+ {ClientChain, ServerChain}.
+
make_ecdsa_cert(Config) ->
CryptoSupport = crypto:supports(),
case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of
@@ -724,7 +882,8 @@ make_rsa_cert(Config) ->
Config
end.
appropriate_sha(CryptoSupport) ->
- case proplists:get_bool(sha256, CryptoSupport) of
+ Hashes = proplists:get_value(hashs, CryptoSupport),
+ case lists:member(sha256, Hashes) of
true ->
sha256;
false ->
@@ -963,9 +1122,7 @@ ecc_test(Expect, COpts, SOpts, CECCOpts, SECCOpts, Config) ->
ecc_test_error(COpts, SOpts, CECCOpts, SECCOpts, Config) ->
{Server, Port} = start_server_ecc_error(erlang, SOpts, SECCOpts, Config),
Client = start_client_ecc_error(erlang, Port, COpts, CECCOpts, Config),
- Error = {error, {tls_alert, "insufficient security"}},
- check_result(Server, Error, Client, Error).
-
+ check_server_alert(Server, Client, insufficient_security).
start_client(openssl, Port, ClientOpts, Config) ->
Cert = proplists:get_value(certfile, ClientOpts),
@@ -973,11 +1130,11 @@ start_client(openssl, Port, ClientOpts, Config) ->
CA = proplists:get_value(cacertfile, ClientOpts),
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client", "-verify", "2", "-port", integer_to_list(Port),
+ Args0 = ["s_client", "-verify", "2", "-port", integer_to_list(Port),
ssl_test_lib:version_flag(Version),
"-cert", Cert, "-CAfile", CA,
"-key", Key, "-host","localhost", "-msg", "-debug"],
-
+ Args = maybe_force_ipv4(Args0),
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
OpenSslPort;
@@ -991,6 +1148,18 @@ start_client(erlang, Port, ClientOpts, Config) ->
{mfa, {ssl_test_lib, check_key_exchange_send_active, [KeyEx]}},
{options, [{verify, verify_peer} | ClientOpts]}]).
+%% Workaround for running tests on machines where openssl
+%% s_client would use an IPv6 address with localhost. As
+%% this test suite and the ssl application is not prepared
+%% for that we have to force s_client to use IPv4 if
+%% OpenSSL supports IPv6.
+maybe_force_ipv4(Args0) ->
+ case is_ipv6_supported() of
+ true ->
+ Args0 ++ ["-4"];
+ false ->
+ Args0
+ end.
start_client_ecc(erlang, Port, ClientOpts, Expect, ECCOpts, Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1097,8 +1266,6 @@ check_ecc(SSL, Role, Expect) ->
{ok, Data} = ssl:connection_information(SSL),
case lists:keyfind(ecc, 1, Data) of
{ecc, {named_curve, Expect}} -> ok;
- false when Expect == undefined -> ok;
- false when Expect == secp256r1 andalso Role == client_no_ecc -> ok;
Other -> {error, Role, Expect, Other}
end.
@@ -1186,13 +1353,13 @@ common_ciphers(crypto) ->
common_ciphers(openssl) ->
OpenSslSuites =
string:tokens(string:strip(os:cmd("openssl ciphers"), right, $\n), ":"),
- [ssl_cipher:erl_suite_definition(S)
+ [ssl_cipher_format:suite_definition(S)
|| S <- ssl_cipher:suites(tls_record:highest_protocol_version([])),
- lists:member(ssl_cipher:openssl_suite_name(S), OpenSslSuites)
+ lists:member(ssl_cipher_format:openssl_suite_name(S), OpenSslSuites)
].
available_suites(Version) ->
- [ssl_cipher:erl_suite_definition(Suite) ||
+ [ssl_cipher_format:suite_definition(Suite) ||
Suite <- ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
@@ -1265,7 +1432,7 @@ string_regex_filter(_Str, _Search) ->
false.
ecdh_dh_anonymous_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:anonymous_suites(Version)],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:anonymous_suites(Version)],
[{key_exchange,
fun(dh_anon) ->
true;
@@ -1274,22 +1441,42 @@ ecdh_dh_anonymous_suites(Version) ->
(_) ->
false
end}]).
+psk_suites({3,_} = Version) ->
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []);
psk_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []).
+ ssl:filter_cipher_suites(psk_suites(dtls_v1:corresponding_tls_version(Version)),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]).
-psk_anon_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
+psk_anon_suites({3,_} = Version) ->
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
[{key_exchange,
fun(psk) ->
true;
- (psk_dhe) ->
+ (dhe_psk) ->
+ true;
+ (ecdhe_psk) ->
true;
(_) ->
false
+ end}]);
+
+psk_anon_suites(Version) ->
+ ssl:filter_cipher_suites(psk_anon_suites(dtls_v1:corresponding_tls_version(Version)),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
end}]).
+
srp_suites() ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
[{key_exchange,
fun(srp_rsa) ->
true;
@@ -1297,10 +1484,10 @@ srp_suites() ->
false
end}]).
srp_anon_suites() ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites_anon()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites_anon()],
[]).
srp_dss_suites() ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
[{key_exchange,
fun(srp_dss) ->
true;
@@ -1308,14 +1495,14 @@ srp_dss_suites() ->
false
end}]).
chacha_suites(Version) ->
- [ssl_cipher:erl_suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
+ [ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
rc4_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <-ssl_cipher:rc4_suites(Version)], []).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:rc4_suites(Version)], []).
des_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <-ssl_cipher:des_suites(Version)], []).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:des_suites(Version)], []).
tuple_to_map({Kex, Cipher, Mac}) ->
#{key_exchange => Kex,
@@ -1338,24 +1525,15 @@ der_to_pem(File, Entries) ->
cipher_result(Socket, Result) ->
{ok, Info} = ssl:connection_information(Socket),
- Result = {ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}},
+ Result = {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}},
ct:log("~p:~p~nSuccessfull connect: ~p~n", [?MODULE,?LINE, Result]),
%% Importante to send two packets here
%% to properly test "cipher state" handling
ssl:send(Socket, "Hello\n"),
- receive
- {ssl, Socket, "H"} ->
- ssl:send(Socket, " world\n"),
- receive_rizzo_duong_beast();
- {ssl, Socket, "Hello\n"} ->
- ssl:send(Socket, " world\n"),
- receive
- {ssl, Socket, " world\n"} ->
- ok
- end;
- Other ->
- {unexpected, Other}
- end.
+ "Hello\n" = active_recv(Socket, length( "Hello\n")),
+ ssl:send(Socket, " world\n"),
+ " world\n" = active_recv(Socket, length(" world\n")),
+ ok.
session_info_result(Socket) ->
{ok, Info} = ssl:connection_information(Socket, [session_id, cipher_suite]),
@@ -1450,10 +1628,13 @@ check_key_exchange_send_active(Socket, KeyEx) ->
send_recv_result_active(Socket).
check_key_exchange({KeyEx,_, _}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
true;
check_key_exchange({KeyEx,_,_,_}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
true;
check_key_exchange(KeyEx1, KeyEx2, Version) ->
+ ct:pal("Kex: ~p ~p", [KeyEx1, KeyEx2]),
case Version of
'tlsv1.2' ->
v_1_2_check(element(1, KeyEx1), KeyEx2);
@@ -1471,34 +1652,81 @@ v_1_2_check(ecdh_rsa, ecdh_ecdsa) ->
v_1_2_check(_, _) ->
false.
-send_recv_result_active(Socket) ->
- ssl:send(Socket, "Hello world"),
- receive
- {ssl, Socket, "H"} ->
- receive
- {ssl, Socket, "ello world"} ->
- ok
- end;
- {ssl, Socket, "Hello world"} ->
- ok
- end.
-
send_recv_result(Socket) ->
- ssl:send(Socket, "Hello world"),
- {ok,"Hello world"} = ssl:recv(Socket, 11),
+ Data = "Hello world",
+ ssl:send(Socket, Data),
+ {ok, Data} = ssl:recv(Socket, length(Data)),
+ ok.
+
+send_recv_result_active(Socket) ->
+ Data = "Hello world",
+ ssl:send(Socket, Data),
+ Data = active_recv(Socket, length(Data)),
ok.
send_recv_result_active_once(Socket) ->
- ssl:send(Socket, "Hello world"),
- receive
- {ssl, Socket, "H"} ->
- ssl:setopts(Socket, [{active, once}]),
- receive
- {ssl, Socket, "ello world"} ->
- ok
- end;
- {ssl, Socket, "Hello world"} ->
- ok
+ Data = "Hello world",
+ ssl:send(Socket, Data),
+ active_once_recv_list(Socket, length(Data)).
+
+active_recv(Socket, N) ->
+ active_recv(Socket, N, []).
+
+active_recv(_Socket, 0, Acc) ->
+ Acc;
+active_recv(Socket, N, Acc) ->
+ receive
+ {ssl, Socket, Bytes} ->
+ active_recv(Socket, N-length(Bytes), Acc ++ Bytes)
+ end.
+
+active_once_recv(_Socket, 0) ->
+ ok;
+active_once_recv(Socket, N) ->
+ receive
+ {ssl, Socket, Bytes} ->
+ ssl:setopts(Socket, [{active, once}]),
+ active_once_recv(Socket, N-byte_size(Bytes))
+ end.
+
+active_once_recv_list(_Socket, 0) ->
+ ok;
+active_once_recv_list(Socket, N) ->
+ receive
+ {ssl, Socket, Bytes} ->
+ ssl:setopts(Socket, [{active, once}]),
+ active_once_recv_list(Socket, N-length(Bytes))
+ end.
+recv_disregard(_Socket, 0) ->
+ ok;
+recv_disregard(Socket, N) ->
+ {ok, Bytes} = ssl:recv(Socket, 0),
+ recv_disregard(Socket, N-byte_size(Bytes)).
+
+active_disregard(_Socket, 0) ->
+ ok;
+active_disregard(Socket, N) ->
+ receive
+ {ssl, Socket, Bytes} ->
+ active_disregard(Socket, N-byte_size(Bytes))
+ end.
+active_once_disregard(_Socket, 0) ->
+ ok;
+active_once_disregard(Socket, N) ->
+ receive
+ {ssl, Socket, Bytes} ->
+ ssl:setopts(Socket, [{active, once}]),
+ active_once_disregard(Socket, N-byte_size(Bytes))
+ end.
+
+is_ipv6_supported() ->
+ case os:cmd("openssl version") of
+ "OpenSSL 0.9.8" ++ _ -> % Does not support IPv6
+ false;
+ "OpenSSL 1.0" ++ _ -> % Does not support IPv6
+ false;
+ _ ->
+ true
end.
is_sane_ecc(openssl) ->
@@ -1586,8 +1814,10 @@ openssl_dsa_support() ->
true;
"LibreSSL" ++ _ ->
false;
+ "OpenSSL 1.1" ++ _Rest ->
+ false;
"OpenSSL 1.0.1" ++ Rest ->
- hd(Rest) >= s;
+ hd(Rest) >= $s;
_ ->
true
end.
@@ -1624,8 +1854,6 @@ openssl_sane_client_cert() ->
false;
"LibreSSL 2.0" ++ _ ->
false;
- "LibreSSL 2.0" ++ _ ->
- false;
"OpenSSL 1.0.1s-freebsd" ->
false;
"OpenSSL 1.0.0" ++ _ ->
@@ -1640,6 +1868,14 @@ check_sane_openssl_version(Version) ->
case {Version, os:cmd("openssl version")} of
{'sslv3', "OpenSSL 1.0.2" ++ _} ->
false;
+ {'dtlsv1', "OpenSSL 0" ++ _} ->
+ false;
+ {'dtlsv1.2', "OpenSSL 0" ++ _} ->
+ false;
+ {'dtlsv1.2', "OpenSSL 1.0.2" ++ _} ->
+ false;
+ {'dtlsv1', "OpenSSL 1.0.0" ++ _} ->
+ false;
{'dtlsv1', _} ->
not is_fips(openssl);
{'dtlsv1.2', _} ->
@@ -1652,18 +1888,10 @@ check_sane_openssl_version(Version) ->
false;
{'tlsv1.1', "OpenSSL 1.0.0" ++ _} ->
false;
- {'dtlsv1.2', "OpenSSL 1.0.2" ++ _} ->
- false;
- {'dtlsv1', "OpenSSL 1.0.0" ++ _} ->
- false;
{'tlsv1.2', "OpenSSL 0" ++ _} ->
false;
{'tlsv1.1', "OpenSSL 0" ++ _} ->
false;
- {'dtlsv1', "OpenSSL 0" ++ _} ->
- false;
- {'dtlsv1.2', "OpenSSL 0" ++ _} ->
- false;
{_, _} ->
true
end;
@@ -1706,10 +1934,10 @@ version_flag('dtlsv1') ->
"-dtls1".
filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_list(Cipher)->
- filter_suites([ssl_cipher:openssl_suite(S) || S <- Ciphers],
+ filter_suites([ssl_cipher_format:openssl_suite(S) || S <- Ciphers],
AtomVersion);
filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_binary(Cipher)->
- filter_suites([ssl_cipher:erl_suite_definition(S) || S <- Ciphers],
+ filter_suites([ssl_cipher_format:suite_definition(S) || S <- Ciphers],
AtomVersion);
filter_suites(Ciphers0, AtomVersion) ->
Version = tls_version(AtomVersion),
@@ -1721,7 +1949,7 @@ filter_suites(Ciphers0, AtomVersion) ->
++ ssl_cipher:srp_suites_anon()
++ ssl_cipher:rc4_suites(Version),
Supported1 = ssl_cipher:filter_suites(Supported0),
- Supported2 = [ssl_cipher:erl_suite_definition(S) || S <- Supported1],
+ Supported2 = [ssl_cipher_format:suite_definition(S) || S <- Supported1],
[Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported2)].
-define(OPENSSL_QUIT, "Q\n").
@@ -1796,13 +2024,11 @@ do_supports_ssl_tls_version(Port, Acc) ->
case Acc ++ Data of
"unknown option" ++ _ ->
false;
- Error when length(Error) >= 11 ->
- case lists:member("error", string:tokens(Data, ":")) of
- true ->
- false;
- false ->
- do_supports_ssl_tls_version(Port, Error)
- end;
+ "s_client: Option unknown" ++ _->
+ false;
+ Info when length(Info) >= 24 ->
+ ct:pal("~p", [Info]),
+ true;
_ ->
do_supports_ssl_tls_version(Port, Acc ++ Data)
end
@@ -2003,3 +2229,135 @@ hardcode_dsa_key(3) ->
y = 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358,
x = 1457508827177594730669011716588605181448418352823}.
+tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
+ receive
+ {Server, ServerMsg} ->
+ client_msg(Client, ClientMsg);
+ {Client, ClientMsg} ->
+ server_msg(Server, ServerMsg);
+ {Client, {error,closed}} ->
+ server_msg(Server, ServerMsg);
+ {Server, {error,closed}} ->
+ client_msg(Client, ClientMsg)
+ end.
+client_msg(Client, ClientMsg) ->
+ receive
+ {Client, ClientMsg} ->
+ ok;
+ {Client, {error,closed}} ->
+ ct:log("client got close"),
+ ok;
+ {Client, {error, Reason}} ->
+ ct:log("client got econnaborted: ~p", [Reason]),
+ ok;
+ Unexpected ->
+ ct:fail(Unexpected)
+ end.
+server_msg(Server, ServerMsg) ->
+ receive
+ {Server, ServerMsg} ->
+ ok;
+ {Server, {error,closed}} ->
+ ct:log("server got close"),
+ ok;
+ {Server, {error, Reason}} ->
+ ct:log("server got econnaborted: ~p", [Reason]),
+ ok;
+ Unexpected ->
+ ct:fail(Unexpected)
+ end.
+
+session_id(Socket) ->
+ {ok, [{session_id, ID}]} = ssl:connection_information(Socket, [session_id]),
+ ID.
+
+reuse_session(ClientOpts, ServerOpts, Config) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server0 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {tcp_options, [{active, false}]},
+ {options, ServerOpts}]),
+ Port0 = ssl_test_lib:inet_port(Server0),
+
+ Client0 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_sessions, save} | ClientOpts]}]),
+ Server0 ! listen,
+
+ Client1 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, ClientOpts}]),
+
+ SID = receive
+ {Client0, Id0} ->
+ Id0
+ end,
+
+ receive
+ {Client1, SID} ->
+ ok
+ after ?SLEEP ->
+ ct:fail(session_not_reused)
+ end,
+
+ Server0 ! listen,
+
+ Client2 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_sessions, false}
+ | ClientOpts]}]),
+ receive
+ {Client2, SID} ->
+ ct:fail(session_reused_when_session_reuse_disabled_by_client);
+ {Client2, _} ->
+ ok
+ end,
+
+ ssl_test_lib:close(Server0),
+ ssl_test_lib:close(Client0),
+ ssl_test_lib:close(Client1),
+ ssl_test_lib:close(Client2),
+
+ Server1 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {tcp_options, [{active, false}]},
+ {options, [{reuse_sessions, false} |ServerOpts]}]),
+ Port1 = ssl_test_lib:inet_port(Server1),
+
+ Client3 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port1}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_sessions, save} | ClientOpts]}]),
+ SID1 = receive
+ {Client3, Id3} ->
+ Id3
+ end,
+
+ Server1 ! listen,
+
+ Client4 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port1}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, ClientOpts}]),
+
+ receive
+ {Client4, SID1} ->
+ ct:fail(session_reused_when_session_reuse_disabled_by_server);
+ {Client4, _} ->
+ ok
+ end,
+
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client3),
+ ssl_test_lib:close(Client4).
+
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 7fc5e13400..df84411b6d 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -91,6 +91,7 @@ all_versions_tests() ->
erlang_server_openssl_client_anon_with_cert,
erlang_server_openssl_client_reuse_session,
erlang_client_openssl_server_renegotiate,
+ erlang_client_openssl_server_renegotiate_after_client_data,
erlang_client_openssl_server_nowrap_seqnum,
erlang_server_openssl_client_nowrap_seqnum,
erlang_client_openssl_server_no_server_ca_cert,
@@ -259,8 +260,9 @@ special_init(TestCase, Config) when
Config;
special_init(TestCase, Config)
when TestCase == erlang_client_openssl_server_renegotiate;
- TestCase == erlang_client_openssl_server_nowrap_seqnum;
- TestCase == erlang_server_openssl_client_nowrap_seqnum
+ TestCase == erlang_client_openssl_server_nowrap_seqnum;
+ TestCase == erlang_server_openssl_client_nowrap_seqnum;
+ TestCase == erlang_client_openssl_server_renegotiate_after_client_data
->
{ok, Version} = application:get_env(ssl, protocol_version),
check_sane_openssl_renegotaite(Config, Version);
@@ -598,73 +600,84 @@ erlang_client_openssl_server_anon(Config) when is_list(Config) ->
VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Port = ssl_test_lib:inet_port(node()),
- CertFile = proplists:get_value(certfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cert", CertFile, "-key", KeyFile,
- "-cipher", "aNULL", "-msg"],
-
- OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
+ case openssl_has_common_ciphers(Ciphers) of
+ false ->
+ {skip, not_supported_by_openssl};
+ true ->
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Port = ssl_test_lib:inet_port(node()),
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ KeyFile = proplists:get_value(keyfile, ServerOpts),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile,
+ "-cipher", "aNULL", "-msg"],
+
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
{mfa, {?MODULE,
erlang_ssl_receive, [Data]}},
- {options, [{ciphers, Ciphers} | ClientOpts]}]),
-
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close_port(OpensslPort),
- ssl_test_lib:close(Client),
- process_flag(trap_exit, false),
- ok.
+ {options, [{ciphers, Ciphers} | ClientOpts]}]),
+
+ true = port_command(OpensslPort, Data),
+
+ ssl_test_lib:check_result(Client, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close_port(OpensslPort),
+ ssl_test_lib:close(Client),
+ process_flag(trap_exit, false)
+ end.
%%--------------------------------------------------------------------
erlang_server_openssl_client_anon() ->
[{doc,"Test erlang server with openssl client, anonymous"}].
erlang_server_openssl_client_anon(Config) when is_list(Config) ->
+
process_flag(trap_exit, true),
ServerOpts = ssl_test_lib:ssl_options(server_anon_opts, Config),
VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ case openssl_has_common_ciphers(Ciphers) of
+ false ->
+ {skip, not_supported_by_openssl};
+ true ->
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, [{ciphers, Ciphers} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cipher", "aNULL", "-msg"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, Data),
-
- ssl_test_lib:check_result(Server, ok),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false)
+ end.
%%--------------------------------------------------------------------
erlang_server_openssl_client_anon_with_cert() ->
@@ -675,30 +688,35 @@ erlang_server_openssl_client_anon_with_cert(Config) when is_list(Config) ->
VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ case openssl_has_common_ciphers(Ciphers) of
+ false ->
+ {skip, not_supported_by_openssl};
+ true ->
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, [{ciphers, Ciphers} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cipher", "aNULL", "-msg"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, Data),
-
- ssl_test_lib:check_result(Server, ok),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false)
+ end.
%%--------------------------------------------------------------------
erlang_server_openssl_client_reuse_session() ->
@@ -744,8 +762,8 @@ erlang_client_openssl_server_renegotiate() ->
[{doc,"Test erlang client when openssl server issuses a renegotiate"}].
erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -754,12 +772,14 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
+ CaCertFile = proplists:get_value(cacertfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
Args = ["s_server", "-accept", integer_to_list(Port),
ssl_test_lib:version_flag(Version),
+ "-CAfile", CaCertFile,
"-cert", CertFile, "-key", KeyFile, "-msg"],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -784,6 +804,53 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
+%%--------------------------------------------------------------------
+erlang_client_openssl_server_renegotiate_after_client_data() ->
+ [{doc,"Test erlang client when openssl server issuses a renegotiate after reading client data"}].
+erlang_client_openssl_server_renegotiate_after_client_data(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ ErlData = "From erlang to openssl",
+ OpenSslData = "From openssl to erlang",
+
+ Port = ssl_test_lib:inet_port(node()),
+ CaCertFile = proplists:get_value(cacertfile, ServerOpts),
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ KeyFile = proplists:get_value(keyfile, ServerOpts),
+ Version = ssl_test_lib:protocol_version(Config),
+
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-CAfile", CaCertFile,
+ "-cert", CertFile, "-key", KeyFile, "-msg"],
+
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_wait_send, [[ErlData, OpenSslData]]}},
+ {options, ClientOpts}]),
+
+ true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
+ ct:sleep(?SLEEP),
+ true = port_command(OpensslPort, OpenSslData),
+
+ ssl_test_lib:check_result(Client, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close_port(OpensslPort),
+ ssl_test_lib:close(Client),
+ process_flag(trap_exit, false),
+ ok.
%%--------------------------------------------------------------------
@@ -794,7 +861,7 @@ erlang_client_openssl_server_nowrap_seqnum() ->
" to lower treashold substantially."}].
erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -803,12 +870,14 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) ->
N = 10,
Port = ssl_test_lib:inet_port(node()),
+ CaCertFile = proplists:get_value(cacertfile, ServerOpts),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
Args = ["s_server", "-accept", integer_to_list(Port),
ssl_test_lib:version_flag(Version),
+ "-CAfile", CaCertFile,
"-cert", CertFile, "-key", KeyFile, "-msg"],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -837,7 +906,7 @@ erlang_server_openssl_client_nowrap_seqnum() ->
" to lower treashold substantially."}].
erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -1180,7 +1249,7 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
ssl_test_lib:consume_port_exit(OpenSslPort),
- ssl_test_lib:check_result(Server, {error, {tls_alert, "bad record mac"}}),
+ ssl_test_lib:check_server_alert(Server, bad_record_mac),
process_flag(trap_exit, false).
%%--------------------------------------------------------------------
@@ -1586,8 +1655,8 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, OpensslServerOpts, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ClientOpts = ErlangClientOpts ++ ClientOpts0,
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1595,6 +1664,7 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens
Data = "From openssl to erlang",
Port = ssl_test_lib:inet_port(node()),
+ CaCertFile = proplists:get_value(cacertfile, ServerOpts),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = ssl_test_lib:protocol_version(Config),
@@ -1604,10 +1674,12 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens
[] ->
["s_server", "-accept",
integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-CAfile", CaCertFile,
"-cert", CertFile,"-key", KeyFile];
[Opt, Value] ->
["s_server", Opt, Value, "-accept",
integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-CAfile", CaCertFile,
"-cert", CertFile,"-key", KeyFile]
end,
@@ -1632,8 +1704,8 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens
start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = proplists:get_value(server_rsa_opts, Config),
- ClientOpts0 = proplists:get_value(client_rsa_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
+ ClientOpts0 = proplists:get_value(client_rsa_verify_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"spdy/2">>]} | ClientOpts0],
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1641,12 +1713,14 @@ start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callba
Data = "From openssl to erlang",
Port = ssl_test_lib:inet_port(node()),
+ CaCertFile = proplists:get_value(cacertfile, ServerOpts),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
Args = ["s_server", "-msg", "-alpn", "http/1.1,spdy/2", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-CAfile", CaCertFile,
"-cert", CertFile, "-key", KeyFile],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
@@ -1764,8 +1838,8 @@ start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Ca
start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ClientOpts = [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}} | ClientOpts0],
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1773,6 +1847,7 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac
Data = "From openssl to erlang",
Port = ssl_test_lib:inet_port(node()),
+ CaCertFile = proplists:get_value(cacertfile, ServerOpts),
CertFile = proplists:get_value(certfile, ServerOpts),
KeyFile = proplists:get_value(keyfile, ServerOpts),
Version = ssl_test_lib:protocol_version(Config),
@@ -1780,6 +1855,7 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac
Exe = "openssl",
Args = ["s_server", "-msg", "-nextprotoneg", "http/1.1,spdy/2", "-accept", integer_to_list(Port),
ssl_test_lib:version_flag(Version),
+ "-CAfile", CaCertFile,
"-cert", CertFile, "-key", KeyFile],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -1870,6 +1946,11 @@ erlang_ssl_receive(Socket, Data) ->
ct:log("Connection info: ~p~n",
[ssl:connection_information(Socket)]),
receive
+ {ssl, Socket, "R\n"} ->
+ %% Swallow s_client renegotiation command.
+ %% openssl s_client connected commands can appear on
+ %% server side with some openssl versions.
+ erlang_ssl_receive(Socket,Data);
{ssl, Socket, Data} ->
io:format("Received ~p~n",[Data]),
%% open_ssl server sometimes hangs waiting in blocking read
@@ -1908,6 +1989,12 @@ server_sent_garbage(Socket) ->
{error, closed} == ssl:send(Socket, "data")
end.
+
+send_wait_send(Socket, [ErlData, OpenSslData]) ->
+ ssl:send(Socket, ErlData),
+ ct:sleep(?SLEEP),
+ ssl:send(Socket, ErlData),
+ erlang_ssl_receive(Socket, OpenSslData).
check_openssl_sni_support(Config) ->
HelpText = os:cmd("openssl s_client --help"),
@@ -2012,3 +2099,18 @@ no_low_flag("-no_ssl2" = Flag) ->
end;
no_low_flag(Flag) ->
Flag.
+
+
+openssl_has_common_ciphers(Ciphers) ->
+ OCiphers = ssl_test_lib:common_ciphers(openssl),
+ has_common_ciphers(Ciphers, OCiphers).
+
+has_common_ciphers([], OCiphers) ->
+ false;
+has_common_ciphers([Cipher | Rest], OCiphers) ->
+ case lists:member(Cipher, OCiphers) of
+ true ->
+ true;
+ _ ->
+ has_common_ciphers(Rest, OCiphers)
+ end.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 10be907b4f..e9aff31b38 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 9.0
+SSL_VSN = 9.2.3.1
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 2b3860b76a..4541b4a463 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -155,6 +155,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml
index db0ab42372..aa1577a067 100644
--- a/lib/stdlib/doc/src/array.xml
+++ b/lib/stdlib/doc/src/array.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>array.xml</file>
</header>
- <module>array</module>
+ <module since="">array</module>
<modulesummary>Functional, extendible arrays.</modulesummary>
<description>
<p>Functional, extendible arrays. Arrays can have fixed size, or can grow
@@ -137,7 +137,7 @@ A3 = array:fix(A2).</pre>
<funcs>
<func>
- <name name="default" arity="1"/>
+ <name name="default" arity="1" since=""/>
<fsummary>Get the value used for uninitialized entries.</fsummary>
<desc><marker id="default-1"/>
<p>Gets the value used for uninitialized entries.</p>
@@ -146,7 +146,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="fix" arity="1"/>
+ <name name="fix" arity="1" since=""/>
<fsummary>Fix the array size.</fsummary>
<desc><marker id="fix-1"/>
<p>Fixes the array size. This prevents it from growing automatically
@@ -157,7 +157,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="foldl" arity="3"/>
+ <name name="foldl" arity="3" since=""/>
<fsummary>Fold the array elements using the specified function and initial
accumulator value.</fsummary>
<desc><marker id="foldl-3"/>
@@ -172,7 +172,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="foldr" arity="3"/>
+ <name name="foldr" arity="3" since=""/>
<fsummary>Fold the array elements right-to-left using the specified
function and initial accumulator value.</fsummary>
<desc><marker id="foldr-3"/>
@@ -186,7 +186,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since=""/>
<fsummary>Equivalent to <c>from_list(List, undefined)</c>.</fsummary>
<desc><marker id="from_list-1"/>
<p>Equivalent to
@@ -195,7 +195,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="from_list" arity="2"/>
+ <name name="from_list" arity="2" since=""/>
<fsummary>Convert a list to an extendible array.</fsummary>
<desc><marker id="from_list-2"/>
<p>Converts a list to an extendible array. <c><anno>Default</anno></c>
@@ -208,7 +208,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="from_orddict" arity="1"/>
+ <name name="from_orddict" arity="1" since=""/>
<fsummary>Equivalent to <c>from_orddict(Orddict, undefined)</c>.
</fsummary>
<desc><marker id="from_orddict-1"/>
@@ -218,7 +218,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="from_orddict" arity="2"/>
+ <name name="from_orddict" arity="2" since=""/>
<fsummary>Convert an ordered list of pairs <c>{Index, Value}</c> to a
corresponding extendible array.</fsummary>
<desc><marker id="from_orddict-2"/>
@@ -234,7 +234,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="get" arity="2"/>
+ <name name="get" arity="2" since=""/>
<fsummary>Get the value of entry <c>I</c>.</fsummary>
<desc><marker id="get-2"/>
<p>Gets the value of entry <c><anno>I</anno></c>. If
@@ -249,7 +249,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="is_array" arity="1"/>
+ <name name="is_array" arity="1" since=""/>
<fsummary>Returns <c>true</c> if <c>X</c> is an array, otherwise
<c>false</c>.</fsummary>
<desc><marker id="is_array-1"/>
@@ -261,7 +261,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="is_fix" arity="1"/>
+ <name name="is_fix" arity="1" since=""/>
<fsummary>Check if the array has fixed size.</fsummary>
<desc><marker id="is_fix-1"/>
<p>Checks if the array has fixed size. Returns <c>true</c> if the array
@@ -271,7 +271,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="map" arity="2"/>
+ <name name="map" arity="2" since=""/>
<fsummary>Map the specified function onto each array element.</fsummary>
<desc><marker id="map-2"/>
<p>Maps the specified function onto each array element. The elements are
@@ -285,7 +285,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Create a new, extendible array with initial size zero.
</fsummary>
<desc><marker id="new-0"/>
@@ -296,7 +296,7 @@ A3 = array:fix(A2).</pre>
</func>
<func>
- <name name="new" arity="1"/>
+ <name name="new" arity="1" since=""/>
<fsummary>Create a new array according to the specified options.
</fsummary>
<desc><marker id="new-1"/>
@@ -346,7 +346,7 @@ array:new([{size,10},{fixed,false},{default,-1}])</pre>
</func>
<func>
- <name name="new" arity="2"/>
+ <name name="new" arity="2" since=""/>
<fsummary>Create a new array according to the specified size and options.
</fsummary>
<desc><marker id="new-2"/>
@@ -370,7 +370,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="relax" arity="1"/>
+ <name name="relax" arity="1" since=""/>
<fsummary>Make the array resizable.</fsummary>
<desc><marker id="relax-1"/>
<p>Makes the array resizable. (Reverses the effects of
@@ -380,7 +380,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="reset" arity="2"/>
+ <name name="reset" arity="2" since=""/>
<fsummary>Reset entry <c>I</c> to the default value for the array.
</fsummary>
<desc><marker id="reset-2"/>
@@ -399,7 +399,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="resize" arity="1"/>
+ <name name="resize" arity="1" since=""/>
<fsummary>Change the array size to that reported by <c>sparse_size/1</c>.
</fsummary>
<desc><marker id="resize-1"/>
@@ -413,7 +413,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="resize" arity="2"/>
+ <name name="resize" arity="2" since=""/>
<fsummary>Change the array size.</fsummary>
<desc><marker id="resize-2"/>
<p>Change the array size. If <c><anno>Size</anno></c> is not a
@@ -424,7 +424,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="set" arity="3"/>
+ <name name="set" arity="3" since=""/>
<fsummary>Set entry <c>I</c> of the array to <c>Value</c>.</fsummary>
<desc><marker id="set-3"/>
<p>Sets entry <c><anno>I</anno></c> of the array to
@@ -441,7 +441,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since=""/>
<fsummary>Get the number of entries in the array.</fsummary>
<desc><marker id="size-1"/>
<p>Gets the number of entries in the array. Entries are numbered from
@@ -454,7 +454,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="sparse_foldl" arity="3"/>
+ <name name="sparse_foldl" arity="3" since=""/>
<fsummary>Fold the array elements using the specified function and initial
accumulator value, skipping default-valued entries.</fsummary>
<desc><marker id="sparse_foldl-3"/>
@@ -469,7 +469,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="sparse_foldr" arity="3"/>
+ <name name="sparse_foldr" arity="3" since=""/>
<fsummary>Fold the array elements right-to-left using the specified
function and initial accumulator value, skipping default-valued
entries.</fsummary>
@@ -485,7 +485,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="sparse_map" arity="2"/>
+ <name name="sparse_map" arity="2" since=""/>
<fsummary>Map the specified function onto each array element, skipping
default-valued entries.</fsummary>
<desc><marker id="sparse_map-2"/>
@@ -498,7 +498,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="sparse_size" arity="1"/>
+ <name name="sparse_size" arity="1" since=""/>
<fsummary>Get the number of entries in the array up until the last
non-default-valued entry.</fsummary>
<desc><marker id="sparse_size-1"/>
@@ -512,7 +512,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="sparse_to_list" arity="1"/>
+ <name name="sparse_to_list" arity="1" since=""/>
<fsummary>Convert the array to a list, skipping default-valued entries.
</fsummary>
<desc><marker id="sparse_to_list-1"/>
@@ -522,7 +522,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="sparse_to_orddict" arity="1"/>
+ <name name="sparse_to_orddict" arity="1" since=""/>
<fsummary>Convert the array to an ordered list of pairs <c>{Index,
Value}</c>, skipping default-valued entries.</fsummary>
<desc><marker id="sparse_to_orddict-1"/>
@@ -534,7 +534,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert the array to a list.</fsummary>
<desc><marker id="to_list-1"/>
<p>Converts the array to a list.</p>
@@ -545,7 +545,7 @@ array:new(100, {default,0})</pre>
</func>
<func>
- <name name="to_orddict" arity="1"/>
+ <name name="to_orddict" arity="1" since=""/>
<fsummary>Convert the array to an ordered list of pairs <c>{Index,
Value}</c>.</fsummary>
<desc><marker id="to_orddict-1"/>
diff --git a/lib/stdlib/doc/src/assert_hrl.xml b/lib/stdlib/doc/src/assert_hrl.xml
index 4dc7299609..fb27954235 100644
--- a/lib/stdlib/doc/src/assert_hrl.xml
+++ b/lib/stdlib/doc/src/assert_hrl.xml
@@ -46,7 +46,7 @@
is the macro name, for example, <c>assertEqual</c>. <c>Info</c> is a list
of tagged values, such as <c>[{module, M}, {line, L}, ...]</c>, which
gives more information about the location and cause of the exception. All
- entries in the <c>Info</c> list are optional; do not rely programatically
+ entries in the <c>Info</c> list are optional; do not rely programmatically
on any of them being present.</p>
<p>Each assert macro has a corresponding version with an extra argument,
diff --git a/lib/stdlib/doc/src/base64.xml b/lib/stdlib/doc/src/base64.xml
index cfa1ecc006..479072ba4f 100644
--- a/lib/stdlib/doc/src/base64.xml
+++ b/lib/stdlib/doc/src/base64.xml
@@ -29,7 +29,7 @@
<rev></rev>
<file>base64.xml</file>
</header>
- <module>base64</module>
+ <module since="">base64</module>
<modulesummary>Provides base64 encode and decode, see
RFC 2045.</modulesummary>
<description>
@@ -51,10 +51,10 @@
<funcs>
<func>
- <name name="decode" arity="1"/>
- <name name="decode_to_string" arity="1"/>
- <name name="mime_decode" arity="1"/>
- <name name="mime_decode_to_string" arity="1"/>
+ <name name="decode" arity="1" since=""/>
+ <name name="decode_to_string" arity="1" since=""/>
+ <name name="mime_decode" arity="1" since=""/>
+ <name name="mime_decode_to_string" arity="1" since=""/>
<fsummary>Decode a base64 encoded string to data.</fsummary>
<type variable="Base64" name_i="1"/>
<type variable="Data" name_i="1"/>
@@ -69,8 +69,8 @@
</func>
<func>
- <name name="encode" arity="1"/>
- <name name="encode_to_string" arity="1"/>
+ <name name="encode" arity="1" since=""/>
+ <name name="encode_to_string" arity="1" since=""/>
<fsummary>Encode data into base64.</fsummary>
<type variable="Data"/>
<type variable="Base64" name_i="1"/>
diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml
index 26d0724aaf..8bb4cf9101 100644
--- a/lib/stdlib/doc/src/beam_lib.xml
+++ b/lib/stdlib/doc/src/beam_lib.xml
@@ -28,7 +28,7 @@
<date>1999-10-30</date>
<rev>PA1</rev>
</header>
- <module>beam_lib</module>
+ <module since="">beam_lib</module>
<modulesummary>An interface to the BEAM file format.</modulesummary>
<description>
<p>This module provides an interface to files created by
@@ -180,8 +180,8 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
<name name="beam"/>
<desc>
<p>Each of the functions described below accept either the
- module name, the filename, or a binary containing the BEAM
- module.</p>
+ filename (as a string) or a binary containing the BEAM
+ module.</p>
</desc>
</datatype>
<datatype>
@@ -267,7 +267,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
<funcs>
<func>
- <name name="all_chunks" arity="1"/>
+ <name name="all_chunks" arity="1" since="OTP 18.2"/>
<fsummary>Read all chunks from a BEAM file or binary</fsummary>
<desc>
<p>Reads chunk data for all chunks.</p>
@@ -275,7 +275,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
</func>
<func>
- <name name="build_module" arity="1"/>
+ <name name="build_module" arity="1" since="OTP 18.2"/>
<fsummary>Create a BEAM module from a list of chunks.</fsummary>
<desc>
<p>Builds a BEAM module (as a binary) from a list of chunks.</p>
@@ -283,7 +283,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
</func>
<func>
- <name name="chunks" arity="2"/>
+ <name name="chunks" arity="2" since=""/>
<fsummary>Read selected chunks from a BEAM file or binary.</fsummary>
<desc>
<p>Reads chunk data for selected chunks references. The order of
@@ -293,7 +293,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
</func>
<func>
- <name name="chunks" arity="3"/>
+ <name name="chunks" arity="3" since=""/>
<fsummary>Read selected chunks from a BEAM file or binary.</fsummary>
<desc>
<p>Reads chunk data for selected chunks references. The order of
@@ -312,7 +312,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
</func>
<func>
- <name name="clear_crypto_key_fun" arity="0"/>
+ <name name="clear_crypto_key_fun" arity="0" since=""/>
<fsummary>Unregister the current crypto key fun.</fsummary>
<desc>
<p>Unregisters the crypto key fun and terminates the process
@@ -327,7 +327,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
</func>
<func>
- <name name="cmp" arity="2"/>
+ <name name="cmp" arity="2" since=""/>
<fsummary>Compare two BEAM files.</fsummary>
<type name="cmp_rsn"/>
<desc>
@@ -341,7 +341,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
</func>
<func>
- <name name="cmp_dirs" arity="2"/>
+ <name name="cmp_dirs" arity="2" since=""/>
<fsummary>Compare the BEAM files in two directories.</fsummary>
<desc>
<p>Compares the BEAM files in
@@ -359,7 +359,7 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
</func>
<func>
- <name name="crypto_key_fun" arity="1"/>
+ <name name="crypto_key_fun" arity="1" since=""/>
<fsummary>Register a fun that provides a crypto key.</fsummary>
<type name="crypto_fun"/>
<type name="crypto_fun_arg"/>
@@ -398,7 +398,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="diff_dirs" arity="2"/>
+ <name name="diff_dirs" arity="2" since=""/>
<fsummary>Compare the BEAM files in two directories.</fsummary>
<desc>
<p>Compares the BEAM files in two directories as
@@ -409,7 +409,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Return an English description of a BEAM read error reply.
</fsummary>
<desc>
@@ -422,7 +422,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="info" arity="1"/>
+ <name name="info" arity="1" since=""/>
<fsummary>Information about a BEAM file.</fsummary>
<desc>
<p>Returns a list containing some information about a BEAM file
@@ -449,7 +449,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="md5" arity="1"/>
+ <name name="md5" arity="1" since=""/>
<fsummary>Read the module version of the BEAM file.</fsummary>
<desc>
<p>Calculates an MD5 redundancy check for the code of the module
@@ -458,7 +458,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="strip" arity="1"/>
+ <name name="strip" arity="1" since=""/>
<fsummary>Remove chunks not needed by the loader from a BEAM file.
</fsummary>
<desc>
@@ -470,7 +470,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="strip_files" arity="1"/>
+ <name name="strip_files" arity="1" since=""/>
<fsummary>Removes chunks not needed by the loader from BEAM files.
</fsummary>
<desc>
@@ -483,7 +483,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="strip_release" arity="1"/>
+ <name name="strip_release" arity="1" since=""/>
<fsummary>Remove chunks not needed by the loader from all BEAM files of
a release.</fsummary>
<desc>
@@ -497,7 +497,7 @@ CryptoKeyFun(clear) -> term()</code>
</func>
<func>
- <name name="version" arity="1"/>
+ <name name="version" arity="1" since=""/>
<fsummary>Read the module version of the BEAM file.</fsummary>
<desc>
<p>Returns the module version or versions. A version is defined by
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml
index 6a86d6c7ba..f3d4edd30f 100644
--- a/lib/stdlib/doc/src/binary.xml
+++ b/lib/stdlib/doc/src/binary.xml
@@ -34,7 +34,7 @@
<rev>A</rev>
<file>binary.xml</file>
</header>
- <module>binary</module>
+ <module since="OTP R14B">binary</module>
<modulesummary>Library for handling binary data.</modulesummary>
<description>
@@ -79,7 +79,7 @@
<funcs>
<func>
- <name name="at" arity="2"/>
+ <name name="at" arity="2" since="OTP R14B"/>
<fsummary>Return the byte at a specific position in a binary.</fsummary>
<desc>
<p>Returns the byte at position <c><anno>Pos</anno></c> (zero-based) in
@@ -90,7 +90,7 @@
</func>
<func>
- <name name="bin_to_list" arity="1"/>
+ <name name="bin_to_list" arity="1" since="OTP R14B"/>
<fsummary>Convert a binary to a list of integers.</fsummary>
<desc>
<p>Same as <c>bin_to_list(<anno>Subject</anno>, {0,byte_size(<anno>Subject</anno>)})</c>.</p>
@@ -98,7 +98,7 @@
</func>
<func>
- <name name="bin_to_list" arity="2"/>
+ <name name="bin_to_list" arity="2" since="OTP R14B"/>
<fsummary>Convert a binary to a list of integers.</fsummary>
<desc>
<p>Converts <c><anno>Subject</anno></c> to a list of <c>byte()</c>s, each
@@ -118,7 +118,7 @@
</func>
<func>
- <name name="bin_to_list" arity="3"/>
+ <name name="bin_to_list" arity="3" since="OTP R14B"/>
<fsummary>Convert a binary to a list of integers.</fsummary>
<desc>
<p>Same as<c> bin_to_list(<anno>Subject</anno>, {<anno>Pos</anno>, <anno>Len</anno>})</c>.</p>
@@ -126,7 +126,7 @@
</func>
<func>
- <name name="compile_pattern" arity="1"/>
+ <name name="compile_pattern" arity="1" since="OTP R14B"/>
<fsummary>Precompile a binary search pattern.</fsummary>
<desc>
<p>Builds an internal structure representing a compilation of a
@@ -158,7 +158,7 @@
</func>
<func>
- <name name="copy" arity="1"/>
+ <name name="copy" arity="1" since="OTP R14B"/>
<fsummary>Create a duplicate of a binary.</fsummary>
<desc>
<p>Same as <c>copy(<anno>Subject</anno>, 1)</c>.</p>
@@ -166,7 +166,7 @@
</func>
<func>
- <name name="copy" arity="2"/>
+ <name name="copy" arity="2" since="OTP R14B"/>
<fsummary>Duplicate a binary <c>N</c> times and create a new.</fsummary>
<desc>
<p>Creates a binary with the content of <c><anno>Subject</anno></c>
@@ -193,7 +193,7 @@
</func>
<func>
- <name name="decode_unsigned" arity="1"/>
+ <name name="decode_unsigned" arity="1" since="OTP R14B"/>
<fsummary>Decode a whole binary into an integer of arbitrary size.
</fsummary>
<desc>
@@ -202,7 +202,7 @@
</func>
<func>
- <name name="decode_unsigned" arity="2"/>
+ <name name="decode_unsigned" arity="2" since="OTP R14B"/>
<fsummary>Decode a whole binary into an integer of arbitrary size.
</fsummary>
<desc>
@@ -219,7 +219,7 @@
</func>
<func>
- <name name="encode_unsigned" arity="1"/>
+ <name name="encode_unsigned" arity="1" since="OTP R14B"/>
<fsummary>Encode an unsigned integer into the minimal binary.</fsummary>
<desc>
<p>Same as <c>encode_unsigned(<anno>Unsigned</anno>, big)</c>.</p>
@@ -227,7 +227,7 @@
</func>
<func>
- <name name="encode_unsigned" arity="2"/>
+ <name name="encode_unsigned" arity="2" since="OTP R14B"/>
<fsummary>Encode an unsigned integer into the minimal binary.</fsummary>
<desc>
<p>Converts a positive integer to the smallest possible
@@ -243,7 +243,7 @@
</func>
<func>
- <name name="first" arity="1"/>
+ <name name="first" arity="1" since="OTP R14B"/>
<fsummary>Return the first byte of a binary.</fsummary>
<desc>
<p>Returns the first byte of binary <c><anno>Subject</anno></c> as an
@@ -253,7 +253,7 @@
</func>
<func>
- <name name="last" arity="1"/>
+ <name name="last" arity="1" since="OTP R14B"/>
<fsummary>Return the last byte of a binary.</fsummary>
<desc>
<p>Returns the last byte of binary <c><anno>Subject</anno></c> as an
@@ -263,7 +263,7 @@
</func>
<func>
- <name name="list_to_bin" arity="1"/>
+ <name name="list_to_bin" arity="1" since="OTP R14B"/>
<fsummary>Convert a list of integers and binaries to a binary.</fsummary>
<desc>
<p>Works exactly as
@@ -273,7 +273,7 @@
</func>
<func>
- <name name="longest_common_prefix" arity="1"/>
+ <name name="longest_common_prefix" arity="1" since="OTP R14B"/>
<fsummary>Return length of longest common prefix for a set of binaries.
</fsummary>
<desc>
@@ -294,7 +294,7 @@
</func>
<func>
- <name name="longest_common_suffix" arity="1"/>
+ <name name="longest_common_suffix" arity="1" since="OTP R14B"/>
<fsummary>Return length of longest common suffix for a set of binaries.
</fsummary>
<desc>
@@ -315,7 +315,7 @@
</func>
<func>
- <name name="match" arity="2"/>
+ <name name="match" arity="2" since="OTP R14B"/>
<fsummary>Search for the first match of a pattern in a binary.</fsummary>
<desc>
<p>Same as <c>match(<anno>Subject</anno>, <anno>Pattern</anno>, [])</c>.
@@ -324,7 +324,7 @@
</func>
<func>
- <name name="match" arity="3"/>
+ <name name="match" arity="3" since="OTP R14B"/>
<fsummary>Search for the first match of a pattern in a binary.</fsummary>
<type name="part"/>
<desc>
@@ -372,7 +372,7 @@
</func>
<func>
- <name name="matches" arity="2"/>
+ <name name="matches" arity="2" since="OTP R14B"/>
<fsummary>Search for all matches of a pattern in a binary.</fsummary>
<desc>
<p>Same as <c>matches(<anno>Subject</anno>, <anno>Pattern</anno>, [])</c>.
@@ -381,7 +381,7 @@
</func>
<func>
- <name name="matches" arity="3"/>
+ <name name="matches" arity="3" since="OTP R14B"/>
<fsummary>Search for all matches of a pattern in a binary.</fsummary>
<type name="part"/>
<desc>
@@ -425,7 +425,7 @@
</func>
<func>
- <name name="part" arity="2"/>
+ <name name="part" arity="2" since="OTP R14B"/>
<fsummary>Extract a part of a binary.</fsummary>
<desc>
<p>Extracts the part of binary <c><anno>Subject</anno></c> described by
@@ -453,7 +453,7 @@
</func>
<func>
- <name name="part" arity="3"/>
+ <name name="part" arity="3" since="OTP R14B"/>
<fsummary>Extract a part of a binary.</fsummary>
<desc>
<p>Same as <c>part(<anno>Subject</anno>, {<anno>Pos</anno>,
@@ -462,7 +462,7 @@
</func>
<func>
- <name name="referenced_byte_size" arity="1"/>
+ <name name="referenced_byte_size" arity="1" since="OTP R14B"/>
<fsummary>Determine the size of the binary pointed out by a subbinary.
</fsummary>
<desc>
@@ -525,7 +525,7 @@ store(Binary, GBSet) ->
</func>
<func>
- <name name="replace" arity="3"/>
+ <name name="replace" arity="3" since="OTP R14B"/>
<fsummary>Replace bytes in a binary according to a pattern.</fsummary>
<desc>
<p>Same as <c>replace(<anno>Subject</anno>, <anno>Pattern</anno>, <anno>Replacement</anno>,[])</c>.</p>
@@ -533,7 +533,7 @@ store(Binary, GBSet) ->
</func>
<func>
- <name name="replace" arity="4"/>
+ <name name="replace" arity="4" since="OTP R14B"/>
<fsummary>Replace bytes in a binary according to a pattern.</fsummary>
<type_desc variable="OnePos">An integer() =&lt; byte_size(<anno>Replacement</anno>)
</type_desc>
@@ -575,7 +575,7 @@ store(Binary, GBSet) ->
</func>
<func>
- <name name="split" arity="2"/>
+ <name name="split" arity="2" since="OTP R14B"/>
<fsummary>Split a binary according to a pattern.</fsummary>
<desc>
<p>Same as <c>split(<anno>Subject</anno>, <anno>Pattern</anno>,
@@ -584,7 +584,7 @@ store(Binary, GBSet) ->
</func>
<func>
- <name name="split" arity="3"/>
+ <name name="split" arity="3" since="OTP R14B"/>
<fsummary>Split a binary according to a pattern.</fsummary>
<desc>
<p>Splits <c><anno>Subject</anno></c> into a list of binaries based on
diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml
index b6cb6f5aae..29edc373c7 100644
--- a/lib/stdlib/doc/src/c.xml
+++ b/lib/stdlib/doc/src/c.xml
@@ -28,7 +28,7 @@
<date>1996-10-30</date>
<rev>B</rev>
</header>
- <module>c</module>
+ <module since="">c</module>
<modulesummary>Command interface module.</modulesummary>
<description>
<p>This module enables users to enter the short form of
@@ -41,7 +41,7 @@
<funcs>
<func>
- <name name="bt" arity="1"/>
+ <name name="bt" arity="1" since=""/>
<fsummary>Stack backtrace for a process.</fsummary>
<desc>
<p>Stack backtrace for a process. Equivalent to
@@ -50,9 +50,9 @@
</func>
<func>
- <name name="c" arity="1"/>
- <name name="c" arity="2"/>
- <name name="c" arity="3"/>
+ <name name="c" arity="1" since=""/>
+ <name name="c" arity="2" since=""/>
+ <name name="c" arity="3" since="OTP 20.0"/>
<fsummary>Compile and load a file or module.</fsummary>
<desc>
<p>Compiles and then purges and loads the code for a module.
@@ -80,7 +80,7 @@
</func>
<func>
- <name name="cd" arity="1"/>
+ <name name="cd" arity="1" since=""/>
<fsummary>Change working directory.</fsummary>
<desc>
<p>Changes working directory to <c><anno>Dir</anno></c>, which can be a
@@ -94,7 +94,7 @@
</func>
<func>
- <name name="erlangrc" arity="1"/>
+ <name name="erlangrc" arity="1" since="OTP 21.0"/>
<fsummary>Load an erlang resource file.</fsummary>
<desc>
<p>Search <c>PathList</c> and load <c>.erlang</c> resource file if
@@ -103,7 +103,7 @@
</func>
<func>
- <name name="flush" arity="0"/>
+ <name name="flush" arity="0" since=""/>
<fsummary>Flush any messages sent to the shell.</fsummary>
<desc>
<p>Flushes any messages sent to the shell.</p>
@@ -111,7 +111,7 @@
</func>
<func>
- <name name="help" arity="0"/>
+ <name name="help" arity="0" since=""/>
<fsummary>Help information.</fsummary>
<desc>
<p>Displays help information: all valid shell internal commands,
@@ -120,8 +120,8 @@
</func>
<func>
- <name name="i" arity="0"/>
- <name name="ni" arity="0"/>
+ <name name="i" arity="0" since=""/>
+ <name name="ni" arity="0" since=""/>
<fsummary>System information.</fsummary>
<desc>
<p><c>i/0</c> displays system information, listing
@@ -131,7 +131,7 @@
</func>
<func>
- <name name="i" arity="3"/>
+ <name name="i" arity="3" since=""/>
<fsummary>Information about pid &lt;X.Y.Z&gt;.</fsummary>
<desc>
<p>Displays information about a process, Equivalent to
@@ -141,7 +141,7 @@
</func>
<func>
- <name name="l" arity="1"/>
+ <name name="l" arity="1" since=""/>
<fsummary>Load or reload a module.</fsummary>
<desc>
<p>Purges and loads, or reloads, a module by calling
@@ -154,7 +154,7 @@
</func>
<func>
- <name>lc(Files) -> ok</name>
+ <name since="">lc(Files) -> ok</name>
<fsummary>Compile a list of files.</fsummary>
<type>
<v>Files = [File]</v>
@@ -171,7 +171,7 @@
</func>
<func>
- <name name="lm" arity="0"/>
+ <name name="lm" arity="0" since="OTP 20.0"/>
<fsummary>Loads all modified modules.</fsummary>
<desc>
<p>Reloads all currently loaded modules that have changed on disk (see <c>mm()</c>).
@@ -180,7 +180,7 @@
</func>
<func>
- <name name="ls" arity="0"/>
+ <name name="ls" arity="0" since=""/>
<fsummary>List files in the current directory.</fsummary>
<desc>
<p>Lists files in the current directory.</p>
@@ -188,7 +188,7 @@
</func>
<func>
- <name name="ls" arity="1"/>
+ <name name="ls" arity="1" since=""/>
<fsummary>List files in a directory or a single file.</fsummary>
<desc>
<p>Lists files in directory <c><anno>Dir</anno></c> or, if <c>Dir</c>
@@ -197,7 +197,7 @@
</func>
<func>
- <name name="m" arity="0"/>
+ <name name="m" arity="0" since=""/>
<fsummary>Which modules are loaded.</fsummary>
<desc>
<p>Displays information about the loaded modules, including
@@ -206,7 +206,7 @@
</func>
<func>
- <name name="m" arity="1"/>
+ <name name="m" arity="1" since=""/>
<fsummary>Information about a module.</fsummary>
<desc>
<p>Displays information about <c><anno>Module</anno></c>.</p>
@@ -214,7 +214,7 @@
</func>
<func>
- <name name="mm" arity="0"/>
+ <name name="mm" arity="0" since="OTP 20.0"/>
<fsummary>Lists all modified modules.</fsummary>
<desc>
<p>Lists all modified modules. Shorthand for
@@ -223,7 +223,7 @@
</func>
<func>
- <name name="memory" arity="0"/>
+ <name name="memory" arity="0" since=""/>
<fsummary>Memory allocation information.</fsummary>
<desc>
<p>Memory allocation information. Equivalent to
@@ -232,8 +232,8 @@
</func>
<func>
- <name name="memory" arity="1" clause_i="1"/>
- <name name="memory" arity="1" clause_i="2"/>
+ <name name="memory" arity="1" clause_i="1" since=""/>
+ <name name="memory" arity="1" clause_i="2" since=""/>
<fsummary>Memory allocation information.</fsummary>
<desc>
<p>Memory allocation information. Equivalent to
@@ -242,8 +242,8 @@
</func>
<func>
- <name name="nc" arity="1"/>
- <name name="nc" arity="2"/>
+ <name name="nc" arity="1" since=""/>
+ <name name="nc" arity="2" since=""/>
<fsummary>Compile and load code in a file on all nodes.</fsummary>
<desc>
<p>Compiles and then loads the code for a file on all nodes.
@@ -255,7 +255,7 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name name="nl" arity="1"/>
+ <name name="nl" arity="1" since=""/>
<fsummary>Load module on all nodes.</fsummary>
<desc>
<p>Loads <c><anno>Module</anno></c> on all nodes.</p>
@@ -263,7 +263,7 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name name="pid" arity="3"/>
+ <name name="pid" arity="3" since=""/>
<fsummary>Convert <c>X,Y,Z</c> to a pid.</fsummary>
<desc>
<p>Converts <c><anno>X</anno></c>, <c><anno>Y</anno></c>,
@@ -273,7 +273,7 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name name="pwd" arity="0"/>
+ <name name="pwd" arity="0" since=""/>
<fsummary>Print working directory.</fsummary>
<desc>
<p>Prints the name of the working directory.</p>
@@ -281,7 +281,7 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name name="q" arity="0"/>
+ <name name="q" arity="0" since=""/>
<fsummary>Quit - shorthand for <c>init:stop()</c>.</fsummary>
<desc>
<p>This function is shorthand for <c>init:stop()</c>, that is,
@@ -290,8 +290,8 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name name="regs" arity="0"/>
- <name name="nregs" arity="0"/>
+ <name name="regs" arity="0" since=""/>
+ <name name="nregs" arity="0" since=""/>
<fsummary>Information about registered processes.</fsummary>
<desc>
<p><c>regs/0</c> displays information about all registered
@@ -301,7 +301,7 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name name="uptime" arity="0"/>
+ <name name="uptime" arity="0" since="OTP 18.0"/>
<fsummary>Print node uptime.</fsummary>
<desc>
<p>Prints the node uptime (as specified by
@@ -310,7 +310,7 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name>xm(ModSpec) -> void()</name>
+ <name since="">xm(ModSpec) -> void()</name>
<fsummary>Cross-reference check a module.</fsummary>
<type>
<v>ModSpec = Module | Filename</v>
@@ -325,7 +325,7 @@ compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_w
</func>
<func>
- <name>y(File) -> YeccRet</name>
+ <name since="">y(File) -> YeccRet</name>
<fsummary>Generate an LALR-1 parser.</fsummary>
<type>
<v>File = name()</v>
@@ -344,7 +344,7 @@ yecc:file(File)</code>
</func>
<func>
- <name>y(File, Options) -> YeccRet</name>
+ <name since="">y(File, Options) -> YeccRet</name>
<fsummary>Generate an LALR-1 parser.</fsummary>
<type>
<v>File = name()</v>
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml
index 6b4fa7f98a..518a085c89 100644
--- a/lib/stdlib/doc/src/calendar.xml
+++ b/lib/stdlib/doc/src/calendar.xml
@@ -28,7 +28,7 @@
<date>1996-11-05</date>
<rev>B</rev>
</header>
- <module>calendar</module>
+ <module since="">calendar</module>
<modulesummary>Local and universal time, day of the week, date and time
conversions.</modulesummary>
<description>
@@ -128,8 +128,8 @@
<funcs>
<func>
- <name name="date_to_gregorian_days" arity="1"/>
- <name name="date_to_gregorian_days" arity="3"/>
+ <name name="date_to_gregorian_days" arity="1" since=""/>
+ <name name="date_to_gregorian_days" arity="3" since=""/>
<fsummary>Compute the number of days from year 0 up to the specified
date.</fsummary>
<type variable="Date" name_i="1"/>
@@ -143,7 +143,7 @@
</func>
<func>
- <name name="datetime_to_gregorian_seconds" arity="1"/>
+ <name name="datetime_to_gregorian_seconds" arity="1" since=""/>
<fsummary>Compute the number of seconds from year 0 up to the specified
date and time.</fsummary>
<desc>
@@ -153,8 +153,8 @@
</func>
<func>
- <name name="day_of_the_week" arity="1"/>
- <name name="day_of_the_week" arity="3"/>
+ <name name="day_of_the_week" arity="1" since=""/>
+ <name name="day_of_the_week" arity="3" since=""/>
<fsummary>Compute the day of the week.</fsummary>
<type variable="Date" name_i="1"/>
<type variable="Year"/>
@@ -169,7 +169,7 @@
</func>
<func>
- <name name="gregorian_days_to_date" arity="1"/>
+ <name name="gregorian_days_to_date" arity="1" since=""/>
<fsummary>Compute the date from the number of gregorian days.</fsummary>
<desc>
<p>Computes the date from the specified number of gregorian days.</p>
@@ -177,7 +177,7 @@
</func>
<func>
- <name name="gregorian_seconds_to_datetime" arity="1"/>
+ <name name="gregorian_seconds_to_datetime" arity="1" since=""/>
<fsummary>Compute the date and time from the number of gregorian seconds.
</fsummary>
<desc>
@@ -187,7 +187,7 @@
</func>
<func>
- <name name="is_leap_year" arity="1"/>
+ <name name="is_leap_year" arity="1" since=""/>
<fsummary>Check if the year is a leap year.</fsummary>
<desc>
<p>Checks if the specified year is a leap year.</p>
@@ -195,7 +195,7 @@
</func>
<func>
- <name name="iso_week_number" arity="0"/>
+ <name name="iso_week_number" arity="0" since="OTP R14B02"/>
<fsummary>Compute the ISO week number for the actual date.</fsummary>
<desc>
<p>Returns tuple <c>{Year, WeekNum}</c> representing
@@ -206,7 +206,7 @@
</func>
<func>
- <name name="iso_week_number" arity="1"/>
+ <name name="iso_week_number" arity="1" since="OTP R14B02"/>
<fsummary>Compute the ISO week number for the specified date.</fsummary>
<desc>
<p>Returns tuple <c>{Year, WeekNum}</c> representing
@@ -215,7 +215,7 @@
</func>
<func>
- <name name="last_day_of_the_month" arity="2"/>
+ <name name="last_day_of_the_month" arity="2" since=""/>
<fsummary>Compute the number of days in a month.</fsummary>
<desc>
<p>Computes the number of days in a month.</p>
@@ -223,7 +223,7 @@
</func>
<func>
- <name name="local_time" arity="0"/>
+ <name name="local_time" arity="0" since=""/>
<fsummary>Compute local time.</fsummary>
<desc>
<p>Returns the local time reported by
@@ -232,7 +232,7 @@
</func>
<func>
- <name name="local_time_to_universal_time" arity="1"/>
+ <name name="local_time_to_universal_time" arity="1" since=""/>
<fsummary>Convert from local time to universal time (deprecated).
</fsummary>
<desc>
@@ -253,7 +253,7 @@
</func>
<func>
- <name name="local_time_to_universal_time_dst" arity="1"/>
+ <name name="local_time_to_universal_time_dst" arity="1" since=""/>
<fsummary>Convert from local time to universal time(s).</fsummary>
<desc>
<p>Converts from local time to Universal Coordinated Time (UTC).
@@ -285,7 +285,7 @@
</func>
<func>
- <name name="now_to_datetime" arity="1"/>
+ <name name="now_to_datetime" arity="1" since=""/>
<fsummary>Convert now to date and time.</fsummary>
<desc>
<p>Returns Universal Coordinated Time (UTC)
@@ -296,7 +296,7 @@
</func>
<func>
- <name name="now_to_local_time" arity="1"/>
+ <name name="now_to_local_time" arity="1" since=""/>
<fsummary>Convert now to local date and time.</fsummary>
<desc>
<p>Returns local date and time converted from the return value from
@@ -306,7 +306,7 @@
</func>
<func>
- <name name="now_to_universal_time" arity="1"/>
+ <name name="now_to_universal_time" arity="1" since=""/>
<fsummary>Convert now to date and time.</fsummary>
<desc>
<p>Returns Universal Coordinated Time (UTC)
@@ -317,8 +317,8 @@
</func>
<func>
- <name name="rfc3339_to_system_time" arity="1"/>
- <name name="rfc3339_to_system_time" arity="2"/>
+ <name name="rfc3339_to_system_time" arity="1" since="OTP 21.0"/>
+ <name name="rfc3339_to_system_time" arity="2" since="OTP 21.0"/>
<fsummary>Convert from RFC 3339 timestamp to system time.</fsummary>
<type name="rfc3339_string"/>
<type name="rfc3339_time_unit"/>
@@ -343,7 +343,7 @@
</func>
<func>
- <name name="seconds_to_daystime" arity="1"/>
+ <name name="seconds_to_daystime" arity="1" since=""/>
<fsummary>Compute days and time from seconds.</fsummary>
<desc>
<p>Converts a specified number of seconds into days, hours, minutes,
@@ -354,7 +354,7 @@
</func>
<func>
- <name name="seconds_to_time" arity="1"/>
+ <name name="seconds_to_time" arity="1" since=""/>
<fsummary>Compute time from seconds.</fsummary>
<type name="secs_per_day"/>
<desc>
@@ -365,7 +365,7 @@
</func>
<func>
- <name name="system_time_to_local_time" arity="2"/>
+ <name name="system_time_to_local_time" arity="2" since="OTP 21.0"/>
<fsummary>Convert system time to local date and time.</fsummary>
<desc>
<p>Converts a specified system time into local date and time.</p>
@@ -373,8 +373,8 @@
</func>
<func>
- <name name="system_time_to_rfc3339" arity="1"/>
- <name name="system_time_to_rfc3339" arity="2"/>
+ <name name="system_time_to_rfc3339" arity="1" since="OTP 21.0"/>
+ <name name="system_time_to_rfc3339" arity="2" since="OTP 21.0"/>
<fsummary>Convert from system to RFC 3339 timestamp.</fsummary>
<type name="offset"/>
<type name="rfc3339_string"/>
@@ -403,7 +403,11 @@
default is <c>second</c>. If some other unit is given
(<c>millisecond</c>, <c>microsecond</c>, or
<c>nanosecond</c>), the formatted string includes a
- fraction of a second.</p>
+ fraction of a second. The number of fractional second
+ digits is three, six, or nine depending on what time unit
+ is chosen. Notice that trailing zeros are not removed from
+ the fraction.
+ </p>
</item>
</taglist>
<pre>
@@ -422,7 +426,7 @@
</func>
<func>
- <name name="system_time_to_universal_time" arity="2"/>
+ <name name="system_time_to_universal_time" arity="2" since="OTP 21.0"/>
<fsummary>Convert system time to universal date and time.</fsummary>
<desc>
<p>Converts a specified system time into universal date and time.</p>
@@ -430,7 +434,7 @@
</func>
<func>
- <name name="time_difference" arity="2"/>
+ <name name="time_difference" arity="2" since=""/>
<fsummary>Compute the difference between two times (deprecated).
</fsummary>
<desc>
@@ -445,7 +449,7 @@
</func>
<func>
- <name name="time_to_seconds" arity="1"/>
+ <name name="time_to_seconds" arity="1" since=""/>
<fsummary>Compute the number of seconds since midnight up to the
specified time.</fsummary>
<type name="secs_per_day"/>
@@ -456,7 +460,7 @@
</func>
<func>
- <name name="universal_time" arity="0"/>
+ <name name="universal_time" arity="0" since=""/>
<fsummary>Compute universal time.</fsummary>
<desc>
<p>Returns the Universal Coordinated Time (UTC)
@@ -466,7 +470,7 @@
</func>
<func>
- <name name="universal_time_to_local_time" arity="1"/>
+ <name name="universal_time_to_local_time" arity="1" since=""/>
<fsummary>Convert from universal time to local time.</fsummary>
<desc>
<p>Converts from Universal Coordinated Time (UTC) to local time.
@@ -476,8 +480,8 @@
</func>
<func>
- <name name="valid_date" arity="1"/>
- <name name="valid_date" arity="3"/>
+ <name name="valid_date" arity="1" since=""/>
+ <name name="valid_date" arity="3" since=""/>
<fsummary>Check if a date is valid</fsummary>
<type variable="Date" name_i="1"/>
<type variable="Year"/>
diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml
index eb6e32aecf..8e4e002000 100644
--- a/lib/stdlib/doc/src/dets.xml
+++ b/lib/stdlib/doc/src/dets.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>dets.xml</file>
</header>
- <module>dets</module>
+ <module since="">dets</module>
<modulesummary>A disk-based term storage.</modulesummary>
<description>
<p>This module provides a term storage on file. The
@@ -188,7 +188,7 @@
<funcs>
<func>
- <name name="all" arity="0"/>
+ <name name="all" arity="0" since=""/>
<fsummary>Return a list of the names of all open Dets tables on
this node.</fsummary>
<desc>
@@ -197,7 +197,7 @@
</func>
<func>
- <name name="bchunk" arity="2"/>
+ <name name="bchunk" arity="2" since=""/>
<fsummary>Return a chunk of objects stored in a Dets table.
</fsummary>
<desc>
@@ -227,7 +227,7 @@
</func>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close a Dets table.</fsummary>
<desc>
<p>Closes a table. Only processes that have opened a table are
@@ -239,7 +239,7 @@
</func>
<func>
- <name name="delete" arity="2"/>
+ <name name="delete" arity="2" since=""/>
<fsummary>Delete all objects with a specified key from a Dets
table.</fsummary>
<desc>
@@ -249,7 +249,7 @@
</func>
<func>
- <name name="delete_all_objects" arity="1"/>
+ <name name="delete_all_objects" arity="1" since=""/>
<fsummary>Delete all objects from a Dets table.</fsummary>
<desc>
<p>Deletes all objects from a table in almost constant time.
@@ -259,7 +259,7 @@
</func>
<func>
- <name name="delete_object" arity="2"/>
+ <name name="delete_object" arity="2" since=""/>
<fsummary>Delete a specified object from a Dets table.</fsummary>
<desc>
<p>Deletes all instances of a specified object from a table. If a
@@ -270,7 +270,7 @@
</func>
<func>
- <name name="first" arity="1"/>
+ <name name="first" arity="1" since=""/>
<fsummary>Return the first key stored in a Dets table.</fsummary>
<desc>
<p>Returns the first key stored in table <c><anno>Name</anno></c>
@@ -295,8 +295,8 @@
</func>
<func>
- <name name="foldl" arity="3"/>
- <name name="foldr" arity="3"/>
+ <name name="foldl" arity="3" since=""/>
+ <name name="foldr" arity="3" since=""/>
<fsummary>Fold a function over a Dets table.</fsummary>
<desc>
<p>Calls <c><anno>Function</anno></c> on successive elements of
@@ -309,7 +309,7 @@
</func>
<func>
- <name name="from_ets" arity="2"/>
+ <name name="from_ets" arity="2" since=""/>
<fsummary>Replace the objects of a Dets table with the objects
of an ETS table.</fsummary>
<desc>
@@ -322,7 +322,7 @@
</func>
<func>
- <name name="info" arity="1"/>
+ <name name="info" arity="1" since=""/>
<fsummary>Return information about a Dets table.</fsummary>
<desc>
<p>Returns information about table <c><anno>Name</anno></c>
@@ -354,7 +354,7 @@
</func>
<func>
- <name name="info" arity="2"/>
+ <name name="info" arity="2" since=""/>
<fsummary>Return the information associated with a specified item for
a Dets table.</fsummary>
<desc>
@@ -455,8 +455,8 @@
</func>
<func>
- <name name="init_table" arity="2"/>
- <name name="init_table" arity="3"/>
+ <name name="init_table" arity="2" since=""/>
+ <name name="init_table" arity="3" since=""/>
<fsummary>Replace all objects of a Dets table.</fsummary>
<desc>
<p>Replaces the existing objects of table <c><anno>Name</anno></c>
@@ -516,7 +516,7 @@
</func>
<func>
- <name name="insert" arity="2"/>
+ <name name="insert" arity="2" since=""/>
<fsummary>Insert one or more objects into a Dets table.</fsummary>
<desc>
<p>Inserts one or more objects into the table <c><anno>Name</anno></c>.
@@ -527,7 +527,7 @@
</func>
<func>
- <name name="insert_new" arity="2"/>
+ <name name="insert_new" arity="2" since=""/>
<fsummary>Insert one or more objects into a Dets table.</fsummary>
<desc>
<p>Inserts one or more objects into table <c><anno>Name</anno></c>.
@@ -539,7 +539,7 @@
</func>
<func>
- <name name="is_compatible_bchunk_format" arity="2"/>
+ <name name="is_compatible_bchunk_format" arity="2" since=""/>
<fsummary>Test compatibility of chunk data of a table.</fsummary>
<desc>
<p>Returns <c>true</c> if it would be possible to initialize
@@ -554,7 +554,7 @@
</func>
<func>
- <name name="is_dets_file" arity="1"/>
+ <name name="is_dets_file" arity="1" since=""/>
<fsummary>Test for a Dets table.</fsummary>
<desc>
<p>Returns <c>true</c> if file <c><anno>Filename</anno></c>
@@ -563,7 +563,7 @@
</func>
<func>
- <name name="lookup" arity="2"/>
+ <name name="lookup" arity="2" since=""/>
<fsummary>Return all objects with a specified key stored in a
Dets table.</fsummary>
<desc>
@@ -590,7 +590,7 @@ ok
</func>
<func>
- <name name="match" arity="1"/>
+ <name name="match" arity="1" since=""/>
<fsummary>Match a chunk of objects stored in a Dets table and
return a list of variable bindings.</fsummary>
<desc>
@@ -606,7 +606,7 @@ ok
</func>
<func>
- <name name="match" arity="2"/>
+ <name name="match" arity="2" since=""/>
<fsummary>Match the objects stored in a Dets table and return a
list of variable bindings.</fsummary>
<desc>
@@ -622,7 +622,7 @@ ok
</func>
<func>
- <name name="match" arity="3"/>
+ <name name="match" arity="3" since=""/>
<fsummary>Match the first chunk of objects stored in a Dets table
and return a list of variable bindings.</fsummary>
<desc>
@@ -654,7 +654,7 @@ ok
</func>
<func>
- <name name="match_delete" arity="2"/>
+ <name name="match_delete" arity="2" since=""/>
<fsummary>Delete all objects that match a given pattern from a
Dets table.</fsummary>
<desc>
@@ -667,7 +667,7 @@ ok
</func>
<func>
- <name name="match_object" arity="1"/>
+ <name name="match_object" arity="1" since=""/>
<fsummary>Match a chunk of objects stored in a Dets table and
return a list of objects.</fsummary>
<desc>
@@ -683,7 +683,7 @@ ok
</func>
<func>
- <name name="match_object" arity="2"/>
+ <name name="match_object" arity="2" since=""/>
<fsummary>Match the objects stored in a Dets table and return
a list of objects.</fsummary>
<desc>
@@ -702,7 +702,7 @@ ok
</func>
<func>
- <name name="match_object" arity="3"/>
+ <name name="match_object" arity="3" since=""/>
<fsummary>Match the first chunk of objects stored in a Dets table
and return a list of objects.</fsummary>
<desc>
@@ -735,7 +735,7 @@ ok
</func>
<func>
- <name name="member" arity="2"/>
+ <name name="member" arity="2" since=""/>
<fsummary>Test for occurrence of a key in a Dets table.</fsummary>
<desc>
<p>Works like <seealso marker="#lookup/2"><c>lookup/2</c></seealso>,
@@ -746,7 +746,7 @@ ok
</func>
<func>
- <name name="next" arity="2"/>
+ <name name="next" arity="2" since=""/>
<fsummary>Return the next key in a Dets table.</fsummary>
<desc>
<p>Returns either the key following <c><anno>Key1</anno></c> in table
@@ -760,7 +760,7 @@ ok
</func>
<func>
- <name name="open_file" arity="1"/>
+ <name name="open_file" arity="1" since=""/>
<fsummary>Open an existing Dets table.</fsummary>
<desc>
<p>Opens an existing table. If the table is not properly closed,
@@ -770,7 +770,7 @@ ok
</func>
<func>
- <name name="open_file" arity="2"/>
+ <name name="open_file" arity="2" since=""/>
<fsummary>Open a Dets table.</fsummary>
<desc>
<p>Opens a table. An empty Dets table is created if no file
@@ -872,7 +872,7 @@ ok
</func>
<func>
- <name name="pid2name" arity="1"/>
+ <name name="pid2name" arity="1" since=""/>
<fsummary>Return the name of the Dets table handled by a pid.</fsummary>
<desc>
<p>Returns the table name given the pid of a process
@@ -883,7 +883,7 @@ ok
</func>
<func>
- <name name="repair_continuation" arity="2"/>
+ <name name="repair_continuation" arity="2" since=""/>
<fsummary>Repair a continuation from <c>select/1</c> or <c>select/3</c>.
</fsummary>
<desc>
@@ -917,7 +917,7 @@ ok
</func>
<func>
- <name name="safe_fixtable" arity="2"/>
+ <name name="safe_fixtable" arity="2" since=""/>
<fsummary>Fix a Dets table for safe traversal.</fsummary>
<desc>
<p>If <c><anno>Fix</anno></c> is <c>true</c>, table
@@ -945,7 +945,7 @@ ok
</func>
<func>
- <name name="select" arity="1"/>
+ <name name="select" arity="1" since=""/>
<fsummary>Apply a match specification to some objects stored in a
Dets table.</fsummary>
<desc>
@@ -962,7 +962,7 @@ ok
</func>
<func>
- <name name="select" arity="2"/>
+ <name name="select" arity="2" since=""/>
<fsummary>Apply a match specification to all objects stored in a
Dets table.</fsummary>
<desc>
@@ -984,7 +984,7 @@ ok
</func>
<func>
- <name name="select" arity="3"/>
+ <name name="select" arity="3" since=""/>
<fsummary>Apply a match specification to the first chunk of objects
stored in a Dets table.</fsummary>
<desc>
@@ -1019,7 +1019,7 @@ ok
</func>
<func>
- <name name="select_delete" arity="2"/>
+ <name name="select_delete" arity="2" since=""/>
<fsummary>Delete all objects that match a given pattern from a
Dets table.</fsummary>
<desc>
@@ -1036,7 +1036,7 @@ ok
</func>
<func>
- <name name="slot" arity="2"/>
+ <name name="slot" arity="2" since=""/>
<fsummary>Return the list of objects associated with a slot of a
Dets table.</fsummary>
<desc>
@@ -1049,7 +1049,7 @@ ok
</func>
<func>
- <name name="sync" arity="1"/>
+ <name name="sync" arity="1" since=""/>
<fsummary>Ensure that all updates made to a Dets table are written
to disk.</fsummary>
<desc>
@@ -1064,8 +1064,8 @@ ok
</func>
<func>
- <name name="table" arity="1"/>
- <name name="table" arity="2"/>
+ <name name="table" arity="1" since=""/>
+ <name name="table" arity="2" since=""/>
<fsummary>Return a QLC query handle.</fsummary>
<desc>
<p>Returns a Query List
@@ -1140,7 +1140,7 @@ true</pre>
</func>
<func>
- <name name="to_ets" arity="2"/>
+ <name name="to_ets" arity="2" since=""/>
<fsummary>Insert all objects of a Dets table into an ETS
table.</fsummary>
<desc>
@@ -1153,7 +1153,7 @@ true</pre>
</func>
<func>
- <name name="traverse" arity="2"/>
+ <name name="traverse" arity="2" since=""/>
<fsummary>Apply a function to all or some objects stored in a Dets
table.</fsummary>
<desc>
@@ -1192,7 +1192,7 @@ fun(X) -> {continue, X} end.</pre>
</func>
<func>
- <name name="update_counter" arity="3"/>
+ <name name="update_counter" arity="3" since=""/>
<fsummary>Update a counter object stored in a Dets table.
</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/dict.xml b/lib/stdlib/doc/src/dict.xml
index c229a18721..95a98cef12 100644
--- a/lib/stdlib/doc/src/dict.xml
+++ b/lib/stdlib/doc/src/dict.xml
@@ -28,7 +28,7 @@
<date>1997-01-15</date>
<rev>B</rev>
</header>
- <module>dict</module>
+ <module since="">dict</module>
<modulesummary>Key-value dictionary.</modulesummary>
<description>
<p>This module provides a <c>Key</c>-<c>Value</c> dictionary.
@@ -55,7 +55,7 @@
<funcs>
<func>
- <name name="append" arity="3"/>
+ <name name="append" arity="3" since=""/>
<fsummary>Append a value to keys in a dictionary.</fsummary>
<desc>
<p>Appends a new <c><anno>Value</anno></c> to the current list
@@ -65,7 +65,7 @@
</func>
<func>
- <name name="append_list" arity="3"/>
+ <name name="append_list" arity="3" since=""/>
<fsummary>Append new values to keys in a dictionary.</fsummary>
<desc>
<p>Appends a list of values <c><anno>ValList</anno></c> to
@@ -77,7 +77,7 @@
</func>
<func>
- <name name="erase" arity="2"/>
+ <name name="erase" arity="2" since=""/>
<fsummary>Erase a key from a dictionary.</fsummary>
<desc>
<p>Erases all items with a given key from a dictionary.</p>
@@ -85,7 +85,7 @@
</func>
<func>
- <name name="fetch" arity="2"/>
+ <name name="fetch" arity="2" since=""/>
<fsummary>Look up values in a dictionary.</fsummary>
<desc>
<p>Returns the value associated with <c><anno>Key</anno></c>
@@ -98,7 +98,7 @@
</func>
<func>
- <name name="fetch_keys" arity="1"/>
+ <name name="fetch_keys" arity="1" since=""/>
<fsummary>Return all keys in a dictionary.</fsummary>
<desc>
<p>Returns a list of all keys in dictionary <c>Dict</c>.</p>
@@ -106,7 +106,7 @@
</func>
<func>
- <name name="take" arity="2"/>
+ <name name="take" arity="2" since="OTP 20.0"/>
<fsummary>Return value and new dictionary without element with this value.</fsummary>
<desc>
<p>This function returns value from dictionary and a
@@ -116,7 +116,7 @@
</func>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since=""/>
<fsummary>Select elements that satisfy a predicate.</fsummary>
<desc>
<p><c><anno>Dict2</anno></c> is a dictionary of all keys and values in
@@ -127,7 +127,7 @@
</func>
<func>
- <name name="find" arity="2"/>
+ <name name="find" arity="2" since=""/>
<fsummary>Search for a key in a dictionary.</fsummary>
<desc>
<p>Searches for a key in dictionary <c>Dict</c>. Returns
@@ -139,7 +139,7 @@
</func>
<func>
- <name name="fold" arity="3"/>
+ <name name="fold" arity="3" since=""/>
<fsummary>Fold a function over a dictionary.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno></c> on successive keys and values of
@@ -153,7 +153,7 @@
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since=""/>
<fsummary>Convert a list of pairs to a dictionary.</fsummary>
<desc>
<p>Converts the <c><anno>Key</anno></c>-<c><anno>Value</anno></c> list
@@ -162,7 +162,7 @@
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since="OTP 17.0"/>
<fsummary>Return <c>true</c> if the dictionary is empty.</fsummary>
<desc>
<p>Returns <c>true</c> if dictionary <c><anno>Dict</anno></c> has no
@@ -171,7 +171,7 @@
</func>
<func>
- <name name="is_key" arity="2"/>
+ <name name="is_key" arity="2" since=""/>
<fsummary>Test if a key is in a dictionary.</fsummary>
<desc>
<p>Tests if <c><anno>Key</anno></c> is contained in
@@ -180,7 +180,7 @@
</func>
<func>
- <name name="map" arity="2"/>
+ <name name="map" arity="2" since=""/>
<fsummary>Map a function over a dictionary.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno></c> on successive keys and values
@@ -190,7 +190,7 @@
</func>
<func>
- <name name="merge" arity="3"/>
+ <name name="merge" arity="3" since=""/>
<fsummary>Merge two dictionaries.</fsummary>
<desc>
<p>Merges two dictionaries, <c><anno>Dict1</anno></c> and
@@ -209,7 +209,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Create a dictionary.</fsummary>
<desc>
<p>Creates a new dictionary.</p>
@@ -217,7 +217,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since=""/>
<fsummary>Return the number of elements in a dictionary.</fsummary>
<desc>
<p>Returns the number of elements in dictionary
@@ -226,7 +226,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="store" arity="3"/>
+ <name name="store" arity="3" since=""/>
<fsummary>Store a value in a dictionary.</fsummary>
<desc>
<p>Stores a <c><anno>Key</anno></c>-<c><anno>Value</anno></c> pair in
@@ -237,7 +237,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert a dictionary to a list of pairs.</fsummary>
<desc>
<p>Converts dictionary <c>Dict</c> to a list representation.</p>
@@ -245,7 +245,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="update" arity="3"/>
+ <name name="update" arity="3" since=""/>
<fsummary>Update a value in a dictionary.</fsummary>
<desc>
<p>Updates a value in a dictionary by calling <c><anno>Fun</anno></c> on
@@ -255,7 +255,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="update" arity="4"/>
+ <name name="update" arity="4" since=""/>
<fsummary>Update a value in a dictionary.</fsummary>
<desc>
<p>Updates a value in a dictionary by calling <c><anno>Fun</anno></c> on
@@ -269,7 +269,7 @@ append(Key, Val, D) ->
</func>
<func>
- <name name="update_counter" arity="3"/>
+ <name name="update_counter" arity="3" since=""/>
<fsummary>Increment a value in a dictionary.</fsummary>
<desc>
<p>Adds <c><anno>Increment</anno></c> to the value associated with
diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml
index a5252b443b..cf2c0844c9 100644
--- a/lib/stdlib/doc/src/digraph.xml
+++ b/lib/stdlib/doc/src/digraph.xml
@@ -32,7 +32,7 @@
<rev>C</rev>
<file>digraph.xml</file>
</header>
- <module>digraph</module>
+ <module since="">digraph</module>
<modulesummary>Directed graphs.</modulesummary>
<description>
<p>This module provides a version of labeled
@@ -144,9 +144,9 @@
<funcs>
<func>
- <name name="add_edge" arity="3"/>
- <name name="add_edge" arity="4"/>
- <name name="add_edge" arity="5"/>
+ <name name="add_edge" arity="3" since=""/>
+ <name name="add_edge" arity="4" since=""/>
+ <name name="add_edge" arity="5" since=""/>
<fsummary>Add an edge to a digraph.</fsummary>
<type name="add_edge_err_rsn"/>
<desc>
@@ -183,9 +183,9 @@
</func>
<func>
- <name name="add_vertex" arity="1"/>
- <name name="add_vertex" arity="2"/>
- <name name="add_vertex" arity="3"/>
+ <name name="add_vertex" arity="1" since=""/>
+ <name name="add_vertex" arity="2" since=""/>
+ <name name="add_vertex" arity="3" since=""/>
<fsummary>Add or modify a vertex of a digraph.</fsummary>
<desc>
<p><c>add_vertex/3</c> creates (or modifies) vertex
@@ -204,7 +204,7 @@
</func>
<func>
- <name name="del_edge" arity="2"/>
+ <name name="del_edge" arity="2" since=""/>
<fsummary>Delete an edge from a digraph.</fsummary>
<desc>
<p>Deletes edge <c><anno>E</anno></c> from digraph
@@ -213,7 +213,7 @@
</func>
<func>
- <name name="del_edges" arity="2"/>
+ <name name="del_edges" arity="2" since=""/>
<fsummary>Delete edges from a digraph.</fsummary>
<desc>
<p>Deletes the edges in list <c><anno>Edges</anno></c> from digraph
@@ -222,7 +222,7 @@
</func>
<func>
- <name name="del_path" arity="3"/>
+ <name name="del_path" arity="3" since=""/>
<fsummary>Delete paths from a digraph.</fsummary>
<desc>
<p>Deletes edges from digraph <c><anno>G</anno></c> until there are no
@@ -252,7 +252,7 @@
</func>
<func>
- <name name="del_vertex" arity="2"/>
+ <name name="del_vertex" arity="2" since=""/>
<fsummary>Delete a vertex from a digraph.</fsummary>
<desc>
<p>Deletes vertex <c><anno>V</anno></c> from digraph
@@ -265,7 +265,7 @@
</func>
<func>
- <name name="del_vertices" arity="2"/>
+ <name name="del_vertices" arity="2" since=""/>
<fsummary>Delete vertices from a digraph.</fsummary>
<desc>
<p>Deletes the vertices in list <c><anno>Vertices</anno></c> from
@@ -274,7 +274,7 @@
</func>
<func>
- <name name="delete" arity="1"/>
+ <name name="delete" arity="1" since=""/>
<fsummary>Delete a digraph.</fsummary>
<desc>
<p>Deletes digraph <c><anno>G</anno></c>. This call is important
@@ -285,7 +285,7 @@
</func>
<func>
- <name name="edge" arity="2"/>
+ <name name="edge" arity="2" since=""/>
<fsummary>Return the vertices and the label of an edge of a digraph.
</fsummary>
<desc>
@@ -303,7 +303,7 @@
</func>
<func>
- <name name="edges" arity="1"/>
+ <name name="edges" arity="1" since=""/>
<fsummary>Return all edges of a digraph.</fsummary>
<desc>
<p>Returns a list of all edges of digraph <c><anno>G</anno></c>, in
@@ -312,7 +312,7 @@
</func>
<func>
- <name name="edges" arity="2"/>
+ <name name="edges" arity="2" since=""/>
<fsummary>Return the edges emanating from or incident on a vertex of
a digraph.</fsummary>
<desc>
@@ -324,7 +324,7 @@
</func>
<func>
- <name name="get_cycle" arity="2"/>
+ <name name="get_cycle" arity="2" since=""/>
<fsummary>Find one cycle in a digraph.</fsummary>
<desc>
<p>If a <seealso marker="#simple_cycle">simple cycle</seealso> of
@@ -341,7 +341,7 @@
</func>
<func>
- <name name="get_path" arity="3"/>
+ <name name="get_path" arity="3" since=""/>
<fsummary>Find one path in a digraph.</fsummary>
<desc>
<p>Tries to find
@@ -357,7 +357,7 @@
</func>
<func>
- <name name="get_short_cycle" arity="2"/>
+ <name name="get_short_cycle" arity="2" since=""/>
<fsummary>Find one short cycle in a digraph.</fsummary>
<desc>
<p>Tries to find an as short as possible
@@ -375,7 +375,7 @@
</func>
<func>
- <name name="get_short_path" arity="3"/>
+ <name name="get_short_path" arity="3" since=""/>
<fsummary>Find one short path in a digraph.</fsummary>
<desc>
<p>Tries to find an as short as possible
@@ -392,7 +392,7 @@
</func>
<func>
- <name name="in_degree" arity="2"/>
+ <name name="in_degree" arity="2" since=""/>
<fsummary>Return the in-degree of a vertex of a digraph.</fsummary>
<desc>
<p>Returns the <seealso marker="#in_degree">in-degree</seealso> of
@@ -401,7 +401,7 @@
</func>
<func>
- <name name="in_edges" arity="2"/>
+ <name name="in_edges" arity="2" since=""/>
<fsummary>Return all edges incident on a vertex of a digraph.</fsummary>
<desc>
<p>Returns a list of all
@@ -412,7 +412,7 @@
</func>
<func>
- <name name="in_neighbours" arity="2"/>
+ <name name="in_neighbours" arity="2" since=""/>
<fsummary>Return all in-neighbors of a vertex of a digraph.</fsummary>
<desc>
<p>Returns a list of
@@ -423,7 +423,7 @@
</func>
<func>
- <name name="info" arity="1"/>
+ <name name="info" arity="1" since=""/>
<fsummary>Return information about a digraph.</fsummary>
<type name="d_cyclicity"/>
<type name="d_protection"/>
@@ -453,7 +453,7 @@
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Return a protected empty digraph, where cycles are allowed.
</fsummary>
<desc>
@@ -462,7 +462,7 @@
</func>
<func>
- <name name="new" arity="1"/>
+ <name name="new" arity="1" since=""/>
<fsummary>Create a new empty digraph.</fsummary>
<type variable="Type"/>
<type name="d_type"/>
@@ -492,7 +492,7 @@
</func>
<func>
- <name name="no_edges" arity="1"/>
+ <name name="no_edges" arity="1" since=""/>
<fsummary>Return the number of edges of a digraph.</fsummary>
<desc>
<p>Returns the number of edges of digraph <c><anno>G</anno></c>.</p>
@@ -500,7 +500,7 @@
</func>
<func>
- <name name="no_vertices" arity="1"/>
+ <name name="no_vertices" arity="1" since=""/>
<fsummary>Return the number of vertices of a digraph.</fsummary>
<desc>
<p>Returns the number of vertices of digraph <c><anno>G</anno></c>.</p>
@@ -508,7 +508,7 @@
</func>
<func>
- <name name="out_degree" arity="2"/>
+ <name name="out_degree" arity="2" since=""/>
<fsummary>Return the out-degree of a vertex of a digraph.</fsummary>
<desc>
<p>Returns the <seealso marker="#out_degree">out-degree</seealso> of
@@ -517,7 +517,7 @@
</func>
<func>
- <name name="out_edges" arity="2"/>
+ <name name="out_edges" arity="2" since=""/>
<fsummary>Return all edges emanating from a vertex of a digraph.
</fsummary>
<desc>
@@ -529,7 +529,7 @@
</func>
<func>
- <name name="out_neighbours" arity="2"/>
+ <name name="out_neighbours" arity="2" since=""/>
<fsummary>Return all out-neighbors of a vertex of a digraph.</fsummary>
<desc>
<p>Returns a list of
@@ -540,7 +540,7 @@
</func>
<func>
- <name name="vertex" arity="2"/>
+ <name name="vertex" arity="2" since=""/>
<fsummary>Return the label of a vertex of a digraph.</fsummary>
<desc>
<p>Returns <c>{<anno>V</anno>,&nbsp;<anno>Label</anno>}</c>,
@@ -553,7 +553,7 @@
</func>
<func>
- <name name="vertices" arity="1"/>
+ <name name="vertices" arity="1" since=""/>
<fsummary>Return all vertices of a digraph.</fsummary>
<desc>
<p>Returns a list of all vertices of digraph <c><anno>G</anno></c>, in
diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml
index cb316e5b93..13b0aaad9e 100644
--- a/lib/stdlib/doc/src/digraph_utils.xml
+++ b/lib/stdlib/doc/src/digraph_utils.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>digraph_utils.xml</file>
</header>
- <module>digraph_utils</module>
+ <module since="">digraph_utils</module>
<modulesummary>Algorithms for directed graphs.</modulesummary>
<description>
<p>This module provides algorithms based on depth-first traversal of
@@ -154,7 +154,7 @@
<funcs>
<func>
- <name name="arborescence_root" arity="1"/>
+ <name name="arborescence_root" arity="1" since=""/>
<fsummary>Check if a digraph is an arborescence.</fsummary>
<desc>
<p>Returns <c>{yes, <anno>Root</anno>}</c> if <c><anno>Root</anno></c>
@@ -164,7 +164,7 @@
</func>
<func>
- <name name="components" arity="1"/>
+ <name name="components" arity="1" since=""/>
<fsummary>Return the components of a digraph.</fsummary>
<desc>
<p>Returns a list
@@ -177,7 +177,7 @@
</func>
<func>
- <name name="condensation" arity="1"/>
+ <name name="condensation" arity="1" since=""/>
<fsummary>Return a condensed graph of a digraph.</fsummary>
<desc>
<p>Creates a digraph where the vertices are
@@ -202,7 +202,7 @@
</func>
<func>
- <name name="cyclic_strong_components" arity="1"/>
+ <name name="cyclic_strong_components" arity="1" since=""/>
<fsummary>Return the cyclic strong components of a digraph.</fsummary>
<desc>
<p>Returns a list of <seealso marker="#strong_components">strongly
@@ -218,7 +218,7 @@
</func>
<func>
- <name name="is_acyclic" arity="1"/>
+ <name name="is_acyclic" arity="1" since=""/>
<fsummary>Check if a digraph is acyclic.</fsummary>
<desc>
<p>Returns <c>true</c> if and only if digraph
@@ -228,7 +228,7 @@
</func>
<func>
- <name name="is_arborescence" arity="1"/>
+ <name name="is_arborescence" arity="1" since=""/>
<fsummary>Check if a digraph is an arborescence.</fsummary>
<desc>
<p>Returns <c>true</c> if and only if digraph
@@ -238,7 +238,7 @@
</func>
<func>
- <name name="is_tree" arity="1"/>
+ <name name="is_tree" arity="1" since=""/>
<fsummary>Check if a digraph is a tree.</fsummary>
<desc>
<p>Returns <c>true</c> if and only if digraph
@@ -248,7 +248,7 @@
</func>
<func>
- <name name="loop_vertices" arity="1"/>
+ <name name="loop_vertices" arity="1" since=""/>
<fsummary>Return the vertices of a digraph included in some loop.
</fsummary>
<desc>
@@ -258,7 +258,7 @@
</func>
<func>
- <name name="postorder" arity="1"/>
+ <name name="postorder" arity="1" since=""/>
<fsummary>Return the vertices of a digraph in postorder.</fsummary>
<desc>
<p>Returns all vertices of digraph <c><anno>Digraph</anno></c>.
@@ -273,7 +273,7 @@
</func>
<func>
- <name name="preorder" arity="1"/>
+ <name name="preorder" arity="1" since=""/>
<fsummary>Return the vertices of a digraph in preorder.</fsummary>
<desc>
<p>Returns all vertices of digraph <c><anno>Digraph</anno></c>.
@@ -285,7 +285,7 @@
</func>
<func>
- <name name="reachable" arity="2"/>
+ <name name="reachable" arity="2" since=""/>
<fsummary>Return the vertices reachable from some vertices of a digraph.
</fsummary>
<desc>
@@ -300,7 +300,7 @@
</func>
<func>
- <name name="reachable_neighbours" arity="2"/>
+ <name name="reachable_neighbours" arity="2" since=""/>
<fsummary>Return the neighbors reachable from some vertices of a
digraph.</fsummary>
<desc>
@@ -316,7 +316,7 @@
</func>
<func>
- <name name="reaching" arity="2"/>
+ <name name="reaching" arity="2" since=""/>
<fsummary>Return the vertices that reach some vertices of a digraph.
</fsummary>
<desc>
@@ -330,7 +330,7 @@
</func>
<func>
- <name name="reaching_neighbours" arity="2"/>
+ <name name="reaching_neighbours" arity="2" since=""/>
<fsummary>Return the neighbors that reach some vertices of a digraph.
</fsummary>
<desc>
@@ -345,7 +345,7 @@
</func>
<func>
- <name name="strong_components" arity="1"/>
+ <name name="strong_components" arity="1" since=""/>
<fsummary>Return the strong components of a digraph.</fsummary>
<desc>
<p>Returns a list of <seealso marker="#strong_components">strongly
@@ -359,8 +359,8 @@
</func>
<func>
- <name name="subgraph" arity="2"/>
- <name name="subgraph" arity="3"/>
+ <name name="subgraph" arity="2" since=""/>
+ <name name="subgraph" arity="3" since=""/>
<fsummary>Return a subgraph of a digraph.</fsummary>
<desc>
<p>Creates a maximal <seealso marker="#subgraph">subgraph</seealso>
@@ -387,7 +387,7 @@
</func>
<func>
- <name name="topsort" arity="1"/>
+ <name name="topsort" arity="1" since=""/>
<fsummary>Return a topological sorting of the vertices of a digraph.
</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml
index 1dc0161398..110c1cea2c 100644
--- a/lib/stdlib/doc/src/epp.xml
+++ b/lib/stdlib/doc/src/epp.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>epp.xml</file>
</header>
- <module>epp</module>
+ <module since="">epp</module>
<modulesummary>An Erlang code preprocessor.</modulesummary>
<description>
<p>The Erlang code preprocessor includes functions that are used by the
@@ -76,7 +76,7 @@
<funcs>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close the preprocessing of the file associated with <c>Epp</c>.
</fsummary>
<desc>
@@ -85,7 +85,7 @@
</func>
<func>
- <name name="default_encoding" arity="0"/>
+ <name name="default_encoding" arity="0" since="OTP R16B"/>
<fsummary>Return the default encoding of Erlang source files.</fsummary>
<desc>
<p>Returns the default encoding of Erlang source files.</p>
@@ -93,7 +93,7 @@
</func>
<func>
- <name name="encoding_to_string" arity="1"/>
+ <name name="encoding_to_string" arity="1" since="OTP R16B"/>
<fsummary>Return a string representation of an encoding.</fsummary>
<desc>
<p>Returns a string representation of an encoding. The string
@@ -107,7 +107,7 @@
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since="OTP R14B03"/>
<fsummary>Format an error descriptor.</fsummary>
<desc>
<p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns
@@ -120,10 +120,14 @@
</func>
<func>
- <name name="open" arity="1"/>
+ <name name="open" arity="1" since="OTP 17.0"/>
<fsummary>Open a file for preprocessing.</fsummary>
<desc>
<p>Opens a file for preprocessing.</p>
+ <p>If you want to change the file name of the implicit -file()
+ attributes inserted during preprocessing, you can do with
+ <c>{source_name, <anno>SourceName</anno>}</c>. If unset it will
+ default to the name of the opened file.</p>
<p>If <c>extra</c> is specified in
<c><anno>Options</anno></c>, the return value is
<c>{ok, <anno>Epp</anno>, <anno>Extra</anno>}</c> instead
@@ -132,7 +136,7 @@
</func>
<func>
- <name name="open" arity="2"/>
+ <name name="open" arity="2" since=""/>
<fsummary>Open a file for preprocessing.</fsummary>
<desc>
<p>Equivalent to
@@ -141,7 +145,7 @@
</func>
<func>
- <name name="open" arity="3"/>
+ <name name="open" arity="3" since=""/>
<fsummary>Open a file for preprocessing.</fsummary>
<desc>
<p>Equivalent to <c>epp:open([{name, FileName}, {includes, IncludePath},
@@ -150,7 +154,7 @@
</func>
<func>
- <name name="parse_erl_form" arity="1"/>
+ <name name="parse_erl_form" arity="1" since=""/>
<fsummary>Return the next Erlang form from the opened Erlang source file.
</fsummary>
<type name="warning_info"/>
@@ -163,12 +167,16 @@
</func>
<func>
- <name name="parse_file" arity="2"/>
+ <name name="parse_file" arity="2" since="OTP 17.0"/>
<fsummary>Preprocess and parse an Erlang source file.</fsummary>
<desc>
<p>Preprocesses and parses an Erlang source file.
Notice that tuple <c>{eof, <anno>Line</anno>}</c> returned at the
end of the file is included as a "form".</p>
+ <p>If you want to change the file name of the implicit -file()
+ attributes inserted during preprocessing, you can do with
+ <c>{source_name, <anno>SourceName</anno>}</c>. If unset it will
+ default to the name of the opened file.</p>
<p>If <c>extra</c> is specified in
<c><anno>Options</anno></c>, the return value is
<c>{ok, [<anno>Form</anno>], <anno>Extra</anno>}</c> instead
@@ -177,7 +185,7 @@
</func>
<func>
- <name name="parse_file" arity="3"/>
+ <name name="parse_file" arity="3" since=""/>
<fsummary>Preprocess and parse an Erlang source file.</fsummary>
<desc>
<p>Equivalent to <c>epp:parse_file(FileName, [{includes, IncludePath},
@@ -186,8 +194,8 @@
</func>
<func>
- <name name="read_encoding" arity="1"/>
- <name name="read_encoding" arity="2"/>
+ <name name="read_encoding" arity="1" since="OTP R16B"/>
+ <name name="read_encoding" arity="2" since="OTP R16B"/>
<fsummary>Read the encoding from a file.</fsummary>
<desc>
<p>Read the <seealso marker="#encoding">encoding</seealso> from
@@ -201,8 +209,8 @@
</func>
<func>
- <name name="read_encoding_from_binary" arity="1"/>
- <name name="read_encoding_from_binary" arity="2"/>
+ <name name="read_encoding_from_binary" arity="1" since="OTP R16B"/>
+ <name name="read_encoding_from_binary" arity="2" since="OTP R16B"/>
<fsummary>Read the encoding from a binary.</fsummary>
<desc>
<p>Read the <seealso marker="#encoding">encoding</seealso> from
@@ -216,7 +224,7 @@
</func>
<func>
- <name name="set_encoding" arity="1"/>
+ <name name="set_encoding" arity="1" since="OTP R16B"/>
<fsummary>Read and set the encoding of an I/O device.</fsummary>
<desc>
<p>Reads the <seealso marker="#encoding">encoding</seealso> from
@@ -231,7 +239,7 @@
</func>
<func>
- <name name="set_encoding" arity="2"/>
+ <name name="set_encoding" arity="2" since="OTP 17.0"/>
<fsummary>Read and set the encoding of an I/O device.</fsummary>
<desc>
<p>Reads the <seealso marker="#encoding">encoding</seealso> from
diff --git a/lib/stdlib/doc/src/erl_anno.xml b/lib/stdlib/doc/src/erl_anno.xml
index f316f63d98..dff93619ab 100644
--- a/lib/stdlib/doc/src/erl_anno.xml
+++ b/lib/stdlib/doc/src/erl_anno.xml
@@ -34,7 +34,7 @@
<rev>A</rev>
<file>erl_anno.xml</file>
</header>
- <module>erl_anno</module>
+ <module since="OTP 18.0">erl_anno</module>
<modulesummary>Abstract datatype for the annotations of the Erlang Compiler.
</modulesummary>
@@ -135,7 +135,7 @@
<funcs>
<func>
- <name name="column" arity="1"/>
+ <name name="column" arity="1" since="OTP 18.0"/>
<fsummary>Return the column.</fsummary>
<type name="column"></type>
<desc>
@@ -144,7 +144,7 @@
</func>
<func>
- <name name="end_location" arity="1"/>
+ <name name="end_location" arity="1" since="OTP 18.0"/>
<fsummary>Return the end location of the text.</fsummary>
<type name="location"></type>
<desc>
@@ -155,7 +155,7 @@
</func>
<func>
- <name name="file" arity="1"/>
+ <name name="file" arity="1" since="OTP 18.0"/>
<fsummary>Return the filename.</fsummary>
<type name="filename"></type>
<desc>
@@ -165,7 +165,7 @@
</func>
<func>
- <name name="from_term" arity="1"/>
+ <name name="from_term" arity="1" since="OTP 18.0"/>
<fsummary>Return annotations given a term.</fsummary>
<desc>
<p>Returns annotations with representation <anno>Term</anno>.</p>
@@ -174,7 +174,7 @@
</func>
<func>
- <name name="generated" arity="1"/>
+ <name name="generated" arity="1" since="OTP 18.0"/>
<fsummary>Return the generated Boolean.</fsummary>
<type name="generated"></type>
<desc>
@@ -185,7 +185,7 @@
</func>
<func>
- <name name="is_anno" arity="1"/>
+ <name name="is_anno" arity="1" since="OTP 18.0"/>
<fsummary>Test for a collection of annotations.</fsummary>
<desc>
<p>Returns <c>true</c> if <anno>Term</anno> is a collection of
@@ -194,7 +194,7 @@
</func>
<func>
- <name name="line" arity="1"/>
+ <name name="line" arity="1" since="OTP 18.0"/>
<fsummary>Return the line.</fsummary>
<type name="line"></type>
<desc>
@@ -203,7 +203,7 @@
</func>
<func>
- <name name="location" arity="1"/>
+ <name name="location" arity="1" since="OTP 18.0"/>
<fsummary>Return the location.</fsummary>
<type name="location"></type>
<desc>
@@ -212,7 +212,7 @@
</func>
<func>
- <name name="new" arity="1"/>
+ <name name="new" arity="1" since="OTP 18.0"/>
<fsummary>Create a new collection of annotations.</fsummary>
<type name="location"></type>
<desc>
@@ -221,7 +221,7 @@
</func>
<func>
- <name name="set_file" arity="2"/>
+ <name name="set_file" arity="2" since="OTP 18.0"/>
<fsummary>Modify the filename.</fsummary>
<type name="filename"></type>
<desc>
@@ -230,7 +230,7 @@
</func>
<func>
- <name name="set_generated" arity="2"/>
+ <name name="set_generated" arity="2" since="OTP 18.0"/>
<fsummary>Modify the generated marker.</fsummary>
<type name="generated"></type>
<desc>
@@ -240,7 +240,7 @@
</func>
<func>
- <name name="set_line" arity="2"/>
+ <name name="set_line" arity="2" since="OTP 18.0"/>
<fsummary>Modify the line.</fsummary>
<type name="line"></type>
<desc>
@@ -249,7 +249,7 @@
</func>
<func>
- <name name="set_location" arity="2"/>
+ <name name="set_location" arity="2" since="OTP 18.0"/>
<fsummary>Modify the location.</fsummary>
<type name="location"></type>
<desc>
@@ -258,7 +258,7 @@
</func>
<func>
- <name name="set_record" arity="2"/>
+ <name name="set_record" arity="2" since="OTP 18.0"/>
<fsummary>Modify the record marker.</fsummary>
<type name="record"></type>
<desc>
@@ -267,7 +267,7 @@
</func>
<func>
- <name name="set_text" arity="2"/>
+ <name name="set_text" arity="2" since="OTP 18.0"/>
<fsummary>Modify the text.</fsummary>
<type name="text"></type>
<desc>
@@ -276,7 +276,7 @@
</func>
<func>
- <name name="text" arity="1"/>
+ <name name="text" arity="1" since="OTP 18.0"/>
<fsummary>Return the text.</fsummary>
<type name="text"></type>
<desc>
@@ -286,7 +286,7 @@
</func>
<func>
- <name name="to_term" arity="1"/>
+ <name name="to_term" arity="1" since="OTP 18.0"/>
<fsummary>Return the term representing a collection of annotations.
</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml
index 1c0f7f062f..813cbecd89 100644
--- a/lib/stdlib/doc/src/erl_eval.xml
+++ b/lib/stdlib/doc/src/erl_eval.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>erl_eval.xml</file>
</header>
- <module>erl_eval</module>
+ <module since="">erl_eval</module>
<modulesummary>The Erlang meta interpreter.</modulesummary>
<description>
<p>This module provides an interpreter for Erlang expressions. The
@@ -96,7 +96,7 @@
<funcs>
<func>
- <name name="add_binding" arity="3"/>
+ <name name="add_binding" arity="3" since=""/>
<fsummary>Add a binding.</fsummary>
<desc>
<p>Adds binding <c><anno>Name</anno>=<anno>Value</anno></c>
@@ -106,7 +106,7 @@
</func>
<func>
- <name name="binding" arity="2"/>
+ <name name="binding" arity="2" since=""/>
<fsummary>Return bindings.</fsummary>
<desc>
<p>Returns the binding of <c><anno>Name</anno></c>
@@ -115,7 +115,7 @@
</func>
<func>
- <name name="bindings" arity="1"/>
+ <name name="bindings" arity="1" since=""/>
<fsummary>Return bindings.</fsummary>
<desc>
<p>Returns the list of bindings contained in the binding
@@ -124,7 +124,7 @@
</func>
<func>
- <name name="del_binding" arity="2"/>
+ <name name="del_binding" arity="2" since=""/>
<fsummary>Delete a binding.</fsummary>
<desc>
<p>Removes the binding of <c><anno>Name</anno></c>
@@ -134,10 +134,10 @@
</func>
<func>
- <name name="expr" arity="2"/>
- <name name="expr" arity="3"/>
- <name name="expr" arity="4"/>
- <name name="expr" arity="5"/>
+ <name name="expr" arity="2" since=""/>
+ <name name="expr" arity="3" since=""/>
+ <name name="expr" arity="4" since=""/>
+ <name name="expr" arity="5" since=""/>
<fsummary>Evaluate expression.</fsummary>
<desc>
<p>Evaluates <c><anno>Expression</anno></c> with the set of bindings
@@ -157,9 +157,9 @@
</func>
<func>
- <name name="expr_list" arity="2"/>
- <name name="expr_list" arity="3"/>
- <name name="expr_list" arity="4"/>
+ <name name="expr_list" arity="2" since=""/>
+ <name name="expr_list" arity="3" since=""/>
+ <name name="expr_list" arity="4" since=""/>
<fsummary>Evaluate a list of expressions.</fsummary>
<desc>
<p>Evaluates a list of expressions in parallel, using the same
@@ -174,9 +174,9 @@
</func>
<func>
- <name name="exprs" arity="2"/>
- <name name="exprs" arity="3"/>
- <name name="exprs" arity="4"/>
+ <name name="exprs" arity="2" since=""/>
+ <name name="exprs" arity="3" since=""/>
+ <name name="exprs" arity="4" since=""/>
<fsummary>Evaluate expressions.</fsummary>
<desc>
<p>Evaluates <c><anno>Expressions</anno></c> with the set of bindings
@@ -197,7 +197,7 @@
</func>
<func>
- <name name="new_bindings" arity="0"/>
+ <name name="new_bindings" arity="0" since=""/>
<fsummary>Return a bindings structure.</fsummary>
<desc>
<p>Returns an empty binding structure.</p>
diff --git a/lib/stdlib/doc/src/erl_expand_records.xml b/lib/stdlib/doc/src/erl_expand_records.xml
index b6aa75ed03..20e5f1960b 100644
--- a/lib/stdlib/doc/src/erl_expand_records.xml
+++ b/lib/stdlib/doc/src/erl_expand_records.xml
@@ -34,7 +34,7 @@
<rev>PA1</rev>
<file>erl_expand_records.xml</file>
</header>
- <module>erl_expand_records</module>
+ <module since="">erl_expand_records</module>
<modulesummary>Expands records in a module.</modulesummary>
<description>
<p>This module expands records in a module.</p>
@@ -42,7 +42,7 @@
<funcs>
<func>
- <name name="module" arity="2"/>
+ <name name="module" arity="2" since=""/>
<fsummary>Expand all records in a module.</fsummary>
<desc>
<p>Expands all records in a module to use explicit tuple
diff --git a/lib/stdlib/doc/src/erl_id_trans.xml b/lib/stdlib/doc/src/erl_id_trans.xml
index 16952a9582..ec66842ac0 100644
--- a/lib/stdlib/doc/src/erl_id_trans.xml
+++ b/lib/stdlib/doc/src/erl_id_trans.xml
@@ -34,7 +34,7 @@
<rev>B</rev>
<file>erl_id_trans.xml</file>
</header>
- <module>erl_id_trans</module>
+ <module since="">erl_id_trans</module>
<modulesummary>An identity parse transform.</modulesummary>
<description>
<p>This module performs an identity parse transformation of Erlang code.
@@ -46,7 +46,7 @@
<funcs>
<func>
- <name>parse_transform(Forms, Options) -> Forms</name>
+ <name since="">parse_transform(Forms, Options) -> Forms</name>
<fsummary>Transform Erlang forms.</fsummary>
<type>
<v>Forms = [<seealso marker="erl_parse#type-abstract_form">erl_parse:abstract_form()</seealso>
diff --git a/lib/stdlib/doc/src/erl_internal.xml b/lib/stdlib/doc/src/erl_internal.xml
index 17cd0fb240..77551ffed7 100644
--- a/lib/stdlib/doc/src/erl_internal.xml
+++ b/lib/stdlib/doc/src/erl_internal.xml
@@ -34,7 +34,7 @@
<rev>B</rev>
<file>erl_internal.xml</file>
</header>
- <module>erl_internal</module>
+ <module since="">erl_internal</module>
<modulesummary>Internal Erlang definitions.</modulesummary>
<description>
<p>This module defines Erlang BIFs, guard tests, and operators.
@@ -44,7 +44,7 @@
<funcs>
<func>
- <name name="add_predefined_functions" arity="1"/>
+ <name name="add_predefined_functions" arity="1" since="OTP 20.0"/>
<fsummary>Add code for pre-defined functions.</fsummary>
<desc>
<p>Adds to <c><anno>Forms</anno></c> the code for the standard
@@ -54,7 +54,7 @@
</func>
<func>
- <name name="arith_op" arity="2"/>
+ <name name="arith_op" arity="2" since=""/>
<fsummary>Test for an arithmetic operator.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c>
@@ -63,7 +63,7 @@
</func>
<func>
- <name name="bif" arity="2"/>
+ <name name="bif" arity="2" since=""/>
<fsummary>Test for an Erlang BIF.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c>
@@ -73,7 +73,7 @@
</func>
<func>
- <name name="bool_op" arity="2"/>
+ <name name="bool_op" arity="2" since=""/>
<fsummary>Test for a Boolean operator.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c>
@@ -82,7 +82,7 @@
</func>
<func>
- <name name="comp_op" arity="2"/>
+ <name name="comp_op" arity="2" since=""/>
<fsummary>Test for a comparison operator.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c>
@@ -91,7 +91,7 @@
</func>
<func>
- <name name="guard_bif" arity="2"/>
+ <name name="guard_bif" arity="2" since=""/>
<fsummary>Test for an Erlang BIF allowed in guards.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is
@@ -100,7 +100,7 @@
</func>
<func>
- <name name="list_op" arity="2"/>
+ <name name="list_op" arity="2" since=""/>
<fsummary>Test for a list operator.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c>
@@ -109,7 +109,7 @@
</func>
<func>
- <name name="op_type" arity="2"/>
+ <name name="op_type" arity="2" since=""/>
<fsummary>Return operator type.</fsummary>
<desc>
<p>Returns the <c><anno>Type</anno></c> of operator that
@@ -120,7 +120,7 @@
</func>
<func>
- <name name="send_op" arity="2"/>
+ <name name="send_op" arity="2" since=""/>
<fsummary>Test for a send operator.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c>
@@ -129,7 +129,7 @@
</func>
<func>
- <name name="type_test" arity="2"/>
+ <name name="type_test" arity="2" since=""/>
<fsummary>Test for a valid type test.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is
diff --git a/lib/stdlib/doc/src/erl_lint.xml b/lib/stdlib/doc/src/erl_lint.xml
index 77cb7a9916..12eaafc3a8 100644
--- a/lib/stdlib/doc/src/erl_lint.xml
+++ b/lib/stdlib/doc/src/erl_lint.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>erl_lint.xml</file>
</header>
- <module>erl_lint</module>
+ <module since="">erl_lint</module>
<modulesummary>The Erlang code linter.</modulesummary>
<description>
<p>This module is used to check Erlang code for illegal syntax and
@@ -78,7 +78,7 @@
<funcs>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Format an error descriptor.</fsummary>
<desc>
<p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns a string
@@ -90,7 +90,7 @@
</func>
<func>
- <name name="is_guard_test" arity="1"/>
+ <name name="is_guard_test" arity="1" since=""/>
<fsummary>Test for a guard test.</fsummary>
<desc>
<p>Tests if <c><anno>Expr</anno></c> is a legal guard test.
@@ -102,9 +102,9 @@
</func>
<func>
- <name name="module" arity="1"/>
- <name name="module" arity="2"/>
- <name name="module" arity="3"/>
+ <name name="module" arity="1" since=""/>
+ <name name="module" arity="2" since=""/>
+ <name name="module" arity="3" since=""/>
<fsummary>Check a module for errors.</fsummary>
<desc>
<p>Checks all the forms in a module for errors. It returns:</p>
diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml
index 647f36883c..8142e5c0aa 100644
--- a/lib/stdlib/doc/src/erl_parse.xml
+++ b/lib/stdlib/doc/src/erl_parse.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>erl_parse.xml</file>
</header>
- <module>erl_parse</module>
+ <module since="">erl_parse</module>
<modulesummary>The Erlang parser.</modulesummary>
<description>
<p>This module is the basic Erlang parser that converts tokens into
@@ -89,7 +89,7 @@
<funcs>
<func>
- <name name="abstract" arity="1"/>
+ <name name="abstract" arity="1" since=""/>
<fsummary>Convert an Erlang term into an abstract form.</fsummary>
<desc>
<p>Converts the Erlang data structure <c><anno>Data</anno></c> into an
@@ -102,7 +102,7 @@
</func>
<func>
- <name name="abstract" arity="2"/>
+ <name name="abstract" arity="2" since="OTP R16B01"/>
<fsummary>Convert an Erlang term into an abstract form.</fsummary>
<type name="encoding_func"/>
<desc>
@@ -124,7 +124,7 @@
</func>
<func>
- <name name="anno_from_term" arity="1"/>
+ <name name="anno_from_term" arity="1" since="OTP 18.0"/>
<fsummary>Return annotations as terms.</fsummary>
<desc>
<p>Assumes that <c><anno>Term</anno></c> is a term with the same
@@ -140,7 +140,7 @@
</func>
<func>
- <name name="anno_to_term" arity="1"/>
+ <name name="anno_to_term" arity="1" since="OTP 18.0"/>
<fsummary>Return the representation of annotations.</fsummary>
<desc>
<p>Returns a term where each collection of annotations
@@ -154,7 +154,7 @@
</func>
<func>
- <name name="fold_anno" arity="3"/>
+ <name name="fold_anno" arity="3" since="OTP 18.0"/>
<fsummary>Fold a function over the annotations of an <c>erl_parse</c> tree.
</fsummary>
<desc>
@@ -171,7 +171,7 @@
</func>
<func>
- <name>format_error(ErrorDescriptor) -> Chars</name>
+ <name since="">format_error(ErrorDescriptor) -> Chars</name>
<fsummary>Format an error descriptor.</fsummary>
<type>
<v>ErrorDescriptor = <seealso
@@ -188,7 +188,7 @@
</func>
<func>
- <name name="map_anno" arity="2"/>
+ <name name="map_anno" arity="2" since="OTP 18.0"/>
<fsummary>Map a function over the annotations of an <c>erl_parse</c> tree.
</fsummary>
<desc>
@@ -201,7 +201,7 @@
</func>
<func>
- <name name="mapfold_anno" arity="3"/>
+ <name name="mapfold_anno" arity="3" since="OTP 18.0"/>
<fsummary>Map and fold a function over the annotations of an
<c>erl_parse</c> tree.</fsummary>
<desc>
@@ -220,7 +220,7 @@
</func>
<func>
- <name name="new_anno" arity="1"/>
+ <name name="new_anno" arity="1" since="OTP 18.0"/>
<fsummary>Create new annotations.</fsummary>
<desc>
<p>Assumes that <c><anno>Term</anno></c> is a term with the same
@@ -236,7 +236,7 @@
</func>
<func>
- <name name="normalise" arity="1"/>
+ <name name="normalise" arity="1" since=""/>
<fsummary>Convert abstract form to an Erlang term.</fsummary>
<desc>
<p>Converts the abstract form <c><anno>AbsTerm</anno></c> of a
@@ -247,7 +247,7 @@
</func>
<func>
- <name name="parse_exprs" arity="1"/>
+ <name name="parse_exprs" arity="1" since=""/>
<fsummary>Parse Erlang expressions.</fsummary>
<desc>
<p>Parses <c><anno>Tokens</anno></c> as if it was a list of expressions.
@@ -267,7 +267,7 @@
</func>
<func>
- <name name="parse_form" arity="1"/>
+ <name name="parse_form" arity="1" since=""/>
<fsummary>Parse an Erlang form.</fsummary>
<desc>
<p>Parses <c><anno>Tokens</anno></c> as if it was a form. Returns one
@@ -287,7 +287,7 @@
</func>
<func>
- <name name="parse_term" arity="1"/>
+ <name name="parse_term" arity="1" since=""/>
<fsummary>Parse an Erlang term.</fsummary>
<desc>
<p>Parses <c><anno>Tokens</anno></c> as if it was a term. Returns
@@ -307,8 +307,8 @@
</func>
<func>
- <name name="tokens" arity="1"/>
- <name name="tokens" arity="2"/>
+ <name name="tokens" arity="1" since=""/>
+ <name name="tokens" arity="2" since=""/>
<fsummary>Generate a list of tokens for an expression.</fsummary>
<desc>
<p>Generates a list of tokens representing the abstract
diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml
index 77a7f1e8d1..f1c3aa5a41 100644
--- a/lib/stdlib/doc/src/erl_pp.xml
+++ b/lib/stdlib/doc/src/erl_pp.xml
@@ -34,7 +34,7 @@
<rev>B</rev>
<file>erl_pp.xml</file>
</header>
- <module>erl_pp</module>
+ <module since="">erl_pp</module>
<modulesummary>The Erlang pretty printer.</modulesummary>
<description>
<p>The functions in this module are used to generate
@@ -73,8 +73,8 @@
<funcs>
<func>
- <name name="attribute" arity="1"/>
- <name name="attribute" arity="2"/>
+ <name name="attribute" arity="1" since=""/>
+ <name name="attribute" arity="2" since=""/>
<fsummary>Pretty print an attribute.</fsummary>
<desc>
<p>Same as <seealso marker="#form/1"><c>form/1,2</c></seealso>,
@@ -83,10 +83,10 @@
</func>
<func>
- <name name="expr" arity="1"/>
- <name name="expr" arity="2"/>
- <name name="expr" arity="3"/>
- <name name="expr" arity="4"/>
+ <name name="expr" arity="1" since=""/>
+ <name name="expr" arity="2" since=""/>
+ <name name="expr" arity="3" since=""/>
+ <name name="expr" arity="4" since=""/>
<fsummary>Pretty print one <c>Expression</c>.</fsummary>
<desc>
<p>Prints one expression. It is useful for implementing hooks (see
@@ -96,9 +96,9 @@
</func>
<func>
- <name name="exprs" arity="1"/>
- <name name="exprs" arity="2"/>
- <name name="exprs" arity="3"/>
+ <name name="exprs" arity="1" since=""/>
+ <name name="exprs" arity="2" since=""/>
+ <name name="exprs" arity="3" since=""/>
<fsummary>Pretty print <c>Expressions</c>.</fsummary>
<desc>
<p>Same as <seealso marker="#form/1"><c>form/1,2</c></seealso>,
@@ -108,8 +108,8 @@
</func>
<func>
- <name name="form" arity="1"/>
- <name name="form" arity="2"/>
+ <name name="form" arity="1" since=""/>
+ <name name="form" arity="2" since=""/>
<fsummary>Pretty print a form.</fsummary>
<desc>
<p>Pretty prints a
@@ -120,8 +120,8 @@
</func>
<func>
- <name name="function" arity="1"/>
- <name name="function" arity="2"/>
+ <name name="function" arity="1" since=""/>
+ <name name="function" arity="2" since=""/>
<fsummary>Pretty print a function.</fsummary>
<desc>
<p>Same as <seealso marker="#form/1"><c>form/1,2</c></seealso>,
@@ -130,8 +130,8 @@
</func>
<func>
- <name name="guard" arity="1"/>
- <name name="guard" arity="2"/>
+ <name name="guard" arity="1" since=""/>
+ <name name="guard" arity="2" since=""/>
<fsummary>Pretty print a guard.</fsummary>
<desc>
<p>Same as <seealso marker="#form/1"><c>form/1,2</c></seealso>,
diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml
index 137ccd3416..38111f73bc 100644
--- a/lib/stdlib/doc/src/erl_scan.xml
+++ b/lib/stdlib/doc/src/erl_scan.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>erl_scan.xml</file>
</header>
- <module>erl_scan</module>
+ <module since="">erl_scan</module>
<modulesummary>The Erlang token scanner.</modulesummary>
<description>
<p>This module contains functions for tokenizing (scanning) characters into
@@ -74,7 +74,7 @@
<funcs>
<func>
- <name name="category" arity="1"/>
+ <name name="category" arity="1" since="OTP 18.0"/>
<fsummary>Return the category.</fsummary>
<desc>
<p>Returns the category of <c><anno>Token</anno></c>.</p>
@@ -82,7 +82,7 @@
</func>
<func>
- <name name="column" arity="1"/>
+ <name name="column" arity="1" since="OTP 18.0"/>
<fsummary>Return the column.</fsummary>
<desc>
<p>Returns the column of <c><anno>Token</anno></c>'s
@@ -91,7 +91,7 @@
</func>
<func>
- <name name="end_location" arity="1"/>
+ <name name="end_location" arity="1" since="OTP 18.0"/>
<fsummary>Return the end location of the text.</fsummary>
<desc>
<p>Returns the end location of the text of
@@ -101,7 +101,7 @@
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Format an error descriptor.</fsummary>
<desc>
<p>Uses an <c><anno>ErrorDescriptor</anno></c> and returns a string
@@ -113,7 +113,7 @@
</func>
<func>
- <name name="line" arity="1"/>
+ <name name="line" arity="1" since="OTP 18.0"/>
<fsummary>Return the line.</fsummary>
<desc>
<p>Returns the line of <c><anno>Token</anno></c>'s collection
@@ -122,7 +122,7 @@
</func>
<func>
- <name name="location" arity="1"/>
+ <name name="location" arity="1" since="OTP 18.0"/>
<fsummary>Return the location.</fsummary>
<desc>
<p>Returns the location of <c><anno>Token</anno></c>'s
@@ -131,7 +131,7 @@
</func>
<func>
- <name name="reserved_word" arity="1"/>
+ <name name="reserved_word" arity="1" since=""/>
<fsummary>Test for a reserved word.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Atom</anno></c> is an
@@ -140,9 +140,9 @@
</func>
<func>
- <name name="string" arity="1"/>
- <name name="string" arity="2"/>
- <name name="string" arity="3"/>
+ <name name="string" arity="1" since=""/>
+ <name name="string" arity="2" since=""/>
+ <name name="string" arity="3" since=""/>
<fsummary>Scan a string and return the Erlang tokens.</fsummary>
<desc>
<p>Takes the list of characters <c><anno>String</anno></c> and tries to
@@ -229,7 +229,7 @@
</func>
<func>
- <name name="symbol" arity="1"/>
+ <name name="symbol" arity="1" since="OTP 18.0"/>
<fsummary>Return the symbol.</fsummary>
<desc>
<p>Returns the symbol of <c><anno>Token</anno></c>.</p>
@@ -237,7 +237,7 @@
</func>
<func>
- <name name="text" arity="1"/>
+ <name name="text" arity="1" since="OTP 18.0"/>
<fsummary>Return the text.</fsummary>
<desc>
<p>Returns the text of <c><anno>Token</anno></c>'s collection
@@ -247,8 +247,8 @@
</func>
<func>
- <name name="tokens" arity="3"/>
- <name name="tokens" arity="4"/>
+ <name name="tokens" arity="3" since=""/>
+ <name name="tokens" arity="4" since=""/>
<fsummary>Re-entrant scanner.</fsummary>
<type name="char_spec"/>
<type name="return_cont"/>
diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml
index 68fa071090..ea8173748a 100644
--- a/lib/stdlib/doc/src/erl_tar.xml
+++ b/lib/stdlib/doc/src/erl_tar.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>erl_tar.xml</file>
</header>
- <module>erl_tar</module>
+ <module since="">erl_tar</module>
<modulesummary>Unix 'tar' utility for reading and writing tar archives.
</modulesummary>
<description>
@@ -127,7 +127,7 @@
<funcs>
<func>
- <name>add(TarDescriptor, Filename, Options) -> RetValue</name>
+ <name since="">add(TarDescriptor, Filename, Options) -> RetValue</name>
<fsummary>Add a file to an open tar file.</fsummary>
<type>
<v>TarDescriptor = term()</v>
@@ -211,7 +211,7 @@
</func>
<func>
- <name>add(TarDescriptor, FilenameOrBin, NameInArchive, Options) ->
+ <name since="">add(TarDescriptor, FilenameOrBin, NameInArchive, Options) ->
RetValue </name>
<fsummary>Add a file to an open tar file.</fsummary>
<type>
@@ -233,7 +233,7 @@
</func>
<func>
- <name>close(TarDescriptor)</name>
+ <name since="">close(TarDescriptor)</name>
<fsummary>Close an open tar file.</fsummary>
<type>
<v>TarDescriptor = term()</v>
@@ -245,7 +245,7 @@
</func>
<func>
- <name>create(Name, FileList) ->RetValue </name>
+ <name since="">create(Name, FileList) ->RetValue </name>
<fsummary>Create a tar archive.</fsummary>
<type>
<v>Name = filename()</v>
@@ -264,7 +264,7 @@
</func>
<func>
- <name>create(Name, FileList, OptionList)</name>
+ <name since="">create(Name, FileList, OptionList)</name>
<fsummary>Create a tar archive with options.</fsummary>
<type>
<v>Name = filename()</v>
@@ -315,7 +315,7 @@
</func>
<func>
- <name>extract(Name) -> RetValue</name>
+ <name since="">extract(Name) -> RetValue</name>
<fsummary>Extract all files from a tar file.</fsummary>
<type>
<v>Name = filename() | {binary,binary()} | {file,Fd}</v>
@@ -339,7 +339,7 @@
</func>
<func>
- <name>extract(Name, OptionList)</name>
+ <name since="">extract(Name, OptionList)</name>
<fsummary>Extract files from a tar file.</fsummary>
<type>
<v>Name = filename() | {binary,binary()} | {file,Fd}</v>
@@ -411,7 +411,7 @@
</func>
<func>
- <name>format_error(Reason) -> string()</name>
+ <name since="">format_error(Reason) -> string()</name>
<fsummary>Convert error term to a readable string.</fsummary>
<type>
<v>Reason = term()</v>
@@ -423,7 +423,7 @@
</func>
<func>
- <name>init(UserPrivate, AccessMode, Fun) ->
+ <name since="OTP 17.4">init(UserPrivate, AccessMode, Fun) ->
{ok,TarDescriptor} | {error,Reason}</name>
<fsummary>Create a <c>TarDescriptor</c> used in subsequent tar operations
when defining own low-level storage access functions.</fsummary>
@@ -518,7 +518,7 @@ erl_tar:close(TarDesc)</code>
</func>
<func>
- <name>open(Name, OpenModeList) -> RetValue</name>
+ <name since="">open(Name, OpenModeList) -> RetValue</name>
<fsummary>Open a tar file for writing.</fsummary>
<type>
<v>Name = filename()</v>
@@ -565,7 +565,7 @@ erl_tar:close(TarDesc)</code>
</func>
<func>
- <name>table(Name) -> RetValue</name>
+ <name since="">table(Name) -> RetValue</name>
<fsummary>Retrieve the name of all files in a tar file.</fsummary>
<type>
<v>Name = filename()|{binary,binary()}|{file,file_descriptor()}</v>
@@ -578,7 +578,7 @@ erl_tar:close(TarDesc)</code>
</func>
<func>
- <name>table(Name, Options)</name>
+ <name since="">table(Name, Options)</name>
<fsummary>Retrieve name and information of all files in a tar file.
</fsummary>
<type>
@@ -590,7 +590,7 @@ erl_tar:close(TarDesc)</code>
</func>
<func>
- <name>t(Name)</name>
+ <name since="">t(Name)</name>
<fsummary>Print the name of each file in a tar file.</fsummary>
<type>
<v>Name = filename()|{binary,binary()}|{file,file_descriptor()}</v>
@@ -602,7 +602,7 @@ erl_tar:close(TarDesc)</code>
</func>
<func>
- <name>tt(Name)</name>
+ <name since="">tt(Name)</name>
<fsummary>Print name and information for each file in a tar file.
</fsummary>
<type>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index f8c54fb79a..b9ceaa1d69 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>ets</module>
+ <module since="">ets</module>
<modulesummary>Built-in term storage.</modulesummary>
<description>
<p>This module is an interface to the Erlang built-in term storage
@@ -138,23 +138,71 @@
operation. In database terms the isolation level can be seen as
"serializable", as if all isolated operations are carried out serially,
one after the other in a strict order.</p>
+ </section>
- <p>No other support is available within this module that would guarantee
- consistency between objects. However, function
- <seealso marker="#safe_fixtable/2"><c>safe_fixtable/2</c></seealso>
- can be used to guarantee that a sequence of
- <seealso marker="#first/1"><c>first/1</c></seealso> and
- <seealso marker="#next/2"><c>next/2</c></seealso> calls traverse the
- table without errors and that each existing object in the table is
- visited exactly once, even if another (or the same) process
- simultaneously deletes or inserts objects into the table.
- Nothing else is guaranteed; in particular objects that are inserted
- or deleted during such a traversal can be visited once or not at all.
- Functions that internally traverse over a table, like
- <seealso marker="#select/1"><c>select</c></seealso> and
- <seealso marker="#match/1"><c>match</c></seealso>,
- give the same guarantee as
- <seealso marker="#safe_fixtable/2"><c>safe_fixtable</c></seealso>.</p>
+ <section><marker id="traversal"></marker>
+ <title>Table traversal</title>
+ <p>There are different ways to traverse through the objects of a table.</p>
+ <list type="bulleted">
+ <item><p><em>Single-step</em> traversal one key at at time, using
+ <seealso marker="#first/1"><c>first/1</c></seealso>,
+ <seealso marker="#next/2"><c>next/2</c></seealso>,
+ <seealso marker="#last/1"><c>last/1</c></seealso> and
+ <seealso marker="#prev/2"><c>prev/2</c></seealso>.</p>
+ </item>
+ <item><p>Search with simple <em>match patterns</em>, using
+ <seealso marker="#match/1"><c>match/1/2/3</c></seealso>,
+ <seealso marker="#match_delete/2"><c>match_delete/2</c></seealso> and
+ <seealso marker="#match_object/1"><c>match_object/1/2/3</c></seealso>.</p>
+ </item>
+ <item><p>Search with more powerful <em>match specifications</em>, using
+ <seealso marker="#select/1"><c>select/1/2/3</c></seealso>,
+ <seealso marker="#select_count/2"><c>select_count/2</c></seealso>,
+ <seealso marker="#select_delete/2"><c>select_delete/2</c></seealso>,
+ <seealso marker="#select_replace/2"><c>select_replace/2</c></seealso> and
+ <seealso marker="#select_reverse/1"><c>select_reverse/1/2/3</c></seealso>.</p>
+ </item>
+ <item><p><em>Table conversions</em>, using
+ <seealso marker="#tab2file/2"><c>tab2file/2/3</c></seealso> and
+ <seealso marker="#tab2list/1"><c>tab2list/1</c></seealso>.</p>
+ </item>
+ </list>
+ <p>None of these ways of table traversal will guarantee a consistent table snapshot
+ if the table is also updated during the traversal. Moreover, traversals not
+ done in a <em>safe</em> way, on tables where keys are inserted or deleted
+ during the traversal, may yield the following undesired effects:</p>
+ <list type="bulleted">
+ <item><p>Any key may be missed.</p></item>
+ <item><p>Any key may be found more than once.</p></item>
+ <item><p>The traversal may fail with <c>badarg</c> exception if keys are deleted.</p>
+ </item>
+ </list>
+ <p>A table traversal is <em>safe</em> if either</p>
+ <list type="bulleted">
+ <item><p>the table is of type <c>ordered_set</c>.</p>
+ </item>
+ <item><p>the entire table traversal is done within one ETS function
+ call.</p>
+ </item>
+ <item><p>function <seealso marker="#safe_fixtable/2"><c>safe_fixtable/2</c></seealso>
+ is used to keep the table fixated during the entire traversal.</p>
+ </item>
+ </list>
+ <p>Traversals using <c>match</c> and <c>select</c> functions may not need to
+ scan the entire table depending on how the key is specified. A match
+ pattern with a <em>fully bound key</em> (without any match variables) will
+ optimize the operation to a single key lookup without any table traversal
+ at all. For <c>ordered_set</c> a <em>partially bound key</em> will limit the
+ traversal to only scan a subset of the table based on term order. A
+ partially bound key is either a list or a tuple with a prefix that is fully
+ bound. Example:</p>
+<pre>
+1> <input>T = ets:new(t,[ordered_set]), ets:insert(T, {"555-1234", "John Smith"}).</input>
+true
+2> <input>%% Efficient search of all with area code 555</input>
+2> <input>ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}).</input>
+[["1234","John Smith"]]
+</pre>
</section>
<section>
@@ -207,7 +255,7 @@
<funcs>
<func>
- <name name="all" arity="0"/>
+ <name name="all" arity="0" since=""/>
<fsummary>Return a list of all ETS tables.</fsummary>
<desc>
<p>Returns a list of all tables at the node. Named tables are
@@ -222,7 +270,7 @@
</func>
<func>
- <name name="delete" arity="1"/>
+ <name name="delete" arity="1" since=""/>
<fsummary>Delete an entire ETS table.</fsummary>
<desc>
<p>Deletes the entire table <c><anno>Tab</anno></c>.</p>
@@ -230,7 +278,7 @@
</func>
<func>
- <name name="delete" arity="2"/>
+ <name name="delete" arity="2" since=""/>
<fsummary>Delete all objects with a specified key from an ETS
table.</fsummary>
<desc>
@@ -240,7 +288,7 @@
</func>
<func>
- <name name="delete_all_objects" arity="1"/>
+ <name name="delete_all_objects" arity="1" since=""/>
<fsummary>Delete all objects in an ETS table.</fsummary>
<desc>
<p>Delete all objects in the ETS table <c><anno>Tab</anno></c>.
@@ -250,7 +298,7 @@
</func>
<func>
- <name name="delete_object" arity="2"/>
+ <name name="delete_object" arity="2" since=""/>
<fsummary>Deletes a specific from an ETS table.</fsummary>
<desc>
<p>Delete the exact object <c><anno>Object</anno></c> from the
@@ -262,7 +310,7 @@
</func>
<func>
- <name name="file2tab" arity="1"/>
+ <name name="file2tab" arity="1" since=""/>
<fsummary>Read an ETS table from a file.</fsummary>
<desc>
<p>Reads a file produced by <seealso marker="#tab2file/2">
@@ -274,7 +322,7 @@
</func>
<func>
- <name name="file2tab" arity="2"/>
+ <name name="file2tab" arity="2" since=""/>
<fsummary>Read an ETS table from a file.</fsummary>
<desc>
<p>Reads a file produced by <seealso marker="#tab2file/2">
@@ -306,7 +354,7 @@
</func>
<func>
- <name name="first" arity="1"/>
+ <name name="first" arity="1" since=""/>
<fsummary>Return the first key in an ETS table.</fsummary>
<desc>
<p>Returns the first key <c><anno>Key</anno></c> in table
@@ -321,7 +369,7 @@
</func>
<func>
- <name name="foldl" arity="3"/>
+ <name name="foldl" arity="3" since=""/>
<fsummary>Fold a function over an ETS table.</fsummary>
<desc>
<p><c><anno>Acc0</anno></c> is returned if the table is empty.
@@ -337,7 +385,7 @@
</func>
<func>
- <name name="foldr" arity="3"/>
+ <name name="foldr" arity="3" since=""/>
<fsummary>Fold a function over an ETS table.</fsummary>
<desc>
<p><c><anno>Acc0</anno></c> is returned if the table is empty.
@@ -353,7 +401,7 @@
</func>
<func>
- <name name="from_dets" arity="2"/>
+ <name name="from_dets" arity="2" since=""/>
<fsummary>Fill an ETS table with objects from a Dets
table.</fsummary>
<desc>
@@ -367,7 +415,7 @@
</func>
<func>
- <name name="fun2ms" arity="1"/>
+ <name name="fun2ms" arity="1" since=""/>
<fsummary>Pseudo function that transforms fun syntax to a match
specification.</fsummary>
<desc>
@@ -436,7 +484,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="give_away" arity="3"/>
+ <name name="give_away" arity="3" since=""/>
<fsummary>Change owner of a table.</fsummary>
<desc>
<p>Make process <c><anno>Pid</anno></c> the new owner of table
@@ -454,7 +502,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="i" arity="0"/>
+ <name name="i" arity="0" since=""/>
<fsummary>Display information about all ETS tables on a terminal.
</fsummary>
<desc>
@@ -463,7 +511,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="i" arity="1"/>
+ <name name="i" arity="1" since=""/>
<fsummary>Browse an ETS table on a terminal.</fsummary>
<desc>
<p>Browses table <c><anno>Tab</anno></c> on a terminal.</p>
@@ -471,7 +519,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="info" arity="1"/>
+ <name name="info" arity="1" since=""/>
<fsummary>Return information about an <c>table</c>.</fsummary>
<desc>
<p>Returns information about table <c><anno>Tab</anno></c> as a list of
@@ -547,7 +595,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="info" arity="2"/>
+ <name name="info" arity="2" since=""/>
<fsummary>Return the information associated with the specified item for
an ETS table.</fsummary>
<desc>
@@ -619,7 +667,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="init_table" arity="2"/>
+ <name name="init_table" arity="2" since=""/>
<fsummary>Replace all objects of an ETS table.</fsummary>
<desc>
<p>Replaces the existing objects of table <c><anno>Tab</anno></c> with
@@ -649,7 +697,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="insert" arity="2"/>
+ <name name="insert" arity="2" since=""/>
<fsummary>Insert an object into an ETS table.</fsummary>
<desc>
<p>Inserts the object or all of the objects in list
@@ -681,7 +729,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="insert_new" arity="2"/>
+ <name name="insert_new" arity="2" since=""/>
<fsummary>Insert an object into an ETS table if the key is not
already present.</fsummary>
<desc>
@@ -700,7 +748,7 @@ Error: fun containing local Erlang function calls
</func>
<func>
- <name name="is_compiled_ms" arity="1"/>
+ <name name="is_compiled_ms" arity="1" since=""/>
<fsummary>Check if an Erlang term is the result of
<c>match_spec_compile</c>.</fsummary>
<desc>
@@ -732,7 +780,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="last" arity="1"/>
+ <name name="last" arity="1" since=""/>
<fsummary>Return the last key in an ETS table of type
<c>ordered_set</c>.</fsummary>
<desc>
@@ -747,7 +795,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="lookup" arity="2"/>
+ <name name="lookup" arity="2" since=""/>
<fsummary>Return all objects with a specified key in an ETS table.
</fsummary>
<desc>
@@ -787,7 +835,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="lookup_element" arity="3"/>
+ <name name="lookup_element" arity="3" since=""/>
<fsummary>Return the <c>Pos</c>:th element of all objects with a
specified key in an ETS table.</fsummary>
<desc>
@@ -810,7 +858,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="match" arity="1"/>
+ <name name="match" arity="1" since=""/>
<fsummary>Continues matching objects in an ETS table.</fsummary>
<desc>
<p>Continues a match started with
@@ -824,7 +872,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="match" arity="2"/>
+ <name name="match" arity="2" since=""/>
<fsummary>Match the objects in an ETS table against a pattern.
</fsummary>
<desc>
@@ -856,7 +904,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="match" arity="3"/>
+ <name name="match" arity="3" since=""/>
<fsummary>Match the objects in an ETS table against a pattern
and return part of the answers.</fsummary>
<desc>
@@ -871,11 +919,14 @@ ets:is_compiled_ms(Broken).</code>
<seealso marker="#first/1"><c>first/1</c></seealso> and
<seealso marker="#next/2"><c>next/2</c></seealso>.</p>
<p>If the table is empty, <c>'$end_of_table'</c> is returned.</p>
+ <p>Use <seealso marker="#safe_fixtable/2"><c>safe_fixtable/2</c></seealso>
+ to guarantee <seealso marker="#traversal">safe traversal</seealso>
+ for subsequent calls to <seealso marker="#match/1"><c>match/1</c></seealso>.</p>
</desc>
</func>
<func>
- <name name="match_delete" arity="2"/>
+ <name name="match_delete" arity="2" since=""/>
<fsummary>Delete all objects that match a specified pattern from an
ETS table.</fsummary>
<desc>
@@ -886,7 +937,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="match_object" arity="1"/>
+ <name name="match_object" arity="1" since=""/>
<fsummary>Continues matching objects in an ETS table.</fsummary>
<desc>
<p>Continues a match started with
@@ -901,7 +952,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="match_object" arity="2"/>
+ <name name="match_object" arity="2" since=""/>
<fsummary>Match the objects in an ETS table against a pattern.
</fsummary>
<desc>
@@ -920,7 +971,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="match_object" arity="3"/>
+ <name name="match_object" arity="3" since=""/>
<fsummary>Match the objects in an ETS table against a pattern and
return part of the answers.</fsummary>
<desc>
@@ -936,11 +987,15 @@ ets:is_compiled_ms(Broken).</code>
<seealso marker="#first/1"><c>first/1</c></seealso> and
<seealso marker="#next/2"><c>next/2</c></seealso>.</p>
<p>If the table is empty, <c>'$end_of_table'</c> is returned.</p>
+ <p>Use <seealso marker="#safe_fixtable/2"><c>safe_fixtable/2</c></seealso>
+ to guarantee <seealso marker="#traversal">safe traversal</seealso>
+ for subsequent calls to <seealso marker="#match_object/1">
+ <c>match_object/1</c></seealso>.</p>
</desc>
</func>
<func>
- <name name="match_spec_compile" arity="1"/>
+ <name name="match_spec_compile" arity="1" since=""/>
<fsummary>Compile a match specification into its internal representation.
</fsummary>
<desc>
@@ -968,7 +1023,7 @@ ets:is_compiled_ms(Broken).</code>
</func>
<func>
- <name name="match_spec_run" arity="2"/>
+ <name name="match_spec_run" arity="2" since=""/>
<fsummary>Perform matching, using a compiled match specification on a
list of terms.</fsummary>
<desc>
@@ -1005,7 +1060,7 @@ ets:select(Table, MatchSpec),</code>
</func>
<func>
- <name name="member" arity="2"/>
+ <name name="member" arity="2" since=""/>
<fsummary>Tests for occurrence of a key in an ETS table.</fsummary>
<desc>
<p>Works like <seealso marker="#lookup/2"><c>lookup/2</c></seealso>,
@@ -1016,14 +1071,14 @@ ets:select(Table, MatchSpec),</code>
</func>
<func>
- <name name="new" arity="2"/>
+ <name name="new" arity="2" since=""/>
<fsummary>Create a new ETS table.</fsummary>
<desc>
<p>Creates a new table and returns a table identifier that can
be used in subsequent operations. The table identifier can be
sent to other processes so that a table can be shared between
different processes within a node.</p>
- <p>Parameter <c><anno>Options</anno></c> is a list of atoms that
+ <p>Parameter <c><anno>Options</anno></c> is a list of options that
specifies table type, access rights, key position, and whether the
table is named. Default values are used for omitted options.
This means that not specifying any options (<c>[]</c>) is the same
@@ -1180,7 +1235,7 @@ ets:select(Table, MatchSpec),</code>
</func>
<func>
- <name name="next" arity="2"/>
+ <name name="next" arity="2" since=""/>
<fsummary>Return the next key in an ETS table.</fsummary>
<desc>
<p>Returns the next key <c><anno>Key2</anno></c>, following key
@@ -1192,17 +1247,18 @@ ets:select(Table, MatchSpec),</code>
<p>To find the first key in the table, use
<seealso marker="#first/1"><c>first/1</c></seealso>.</p>
<p>Unless a table of type <c>set</c>, <c>bag</c>, or
- <c>duplicate_bag</c> is protected using
+ <c>duplicate_bag</c> is fixated using
<seealso marker="#safe_fixtable/2"><c>safe_fixtable/2</c></seealso>,
- a traversal can fail if
- concurrent updates are made to the table. For table
- type <c>ordered_set</c>, the function returns the next key in
- order, even if the object does no longer exist.</p>
+ a call to <c>next/2</c> will fail if <c><anno>Key1</anno></c> no longer
+ exists in the table. For table type <c>ordered_set</c>, the function
+ always returns the next key after <c><anno>Key1</anno></c> in term
+ order, regardless whether <c><anno>Key1</anno></c> ever existed in the
+ table.</p>
</desc>
</func>
<func>
- <name name="prev" arity="2"/>
+ <name name="prev" arity="2" since=""/>
<fsummary>Return the previous key in an ETS table of type
<c>ordered_set</c>.</fsummary>
<desc>
@@ -1212,13 +1268,13 @@ ets:select(Table, MatchSpec),</code>
table types, the function is synonymous to
<seealso marker="#next/2"><c>next/2</c></seealso>.
If no previous key exists, <c>'$end_of_table'</c> is returned.</p>
- <p>To find the last key in the table, use
+ <p>To find the last key in an <c>ordered_set</c> table, use
<seealso marker="#last/1"><c>last/1</c></seealso>.</p>
</desc>
</func>
<func>
- <name name="rename" arity="2"/>
+ <name name="rename" arity="2" since=""/>
<fsummary>Rename a named ETS table.</fsummary>
<desc>
<p>Renames the named table <c><anno>Tab</anno></c> to the new name
@@ -1228,7 +1284,7 @@ ets:select(Table, MatchSpec),</code>
</func>
<func>
- <name name="repair_continuation" arity="2"/>
+ <name name="repair_continuation" arity="2" since=""/>
<fsummary>Repair a continuation from <c>ets:select/1 or ets:select/3</c>
that has passed through external representation.</fsummary>
<desc>
@@ -1283,11 +1339,20 @@ ets:select(ets:repair_continuation(Broken,MS)).</code>
</func>
<func>
- <name name="safe_fixtable" arity="2"/>
+ <name name="safe_fixtable" arity="2" since=""/>
<fsummary>Fix an ETS table for safe traversal.</fsummary>
<desc>
<p>Fixes a table of type <c>set</c>, <c>bag</c>, or
- <c>duplicate_bag</c> for safe traversal.</p>
+ <c>duplicate_bag</c> for <seealso marker="#traversal">
+ safe traversal</seealso> using
+ <seealso marker="#first/1"><c>first/1</c></seealso> &amp;
+ <seealso marker="#next/2"><c>next/2</c></seealso>,
+ <seealso marker="#match/3"><c>match/3</c></seealso> &amp;
+ <seealso marker="#match/1"><c>match/1</c></seealso>,
+ <seealso marker="#match_object/3"><c>match_object/3</c></seealso> &amp;
+ <seealso marker="#match_object/1"><c>match_object/1</c></seealso>, or
+ <seealso marker="#select/3"><c>select/3</c></seealso> &amp;
+ <seealso marker="#select/1"><c>select/1</c></seealso>.</p>
<p>A process fixes a table by calling
<c>safe_fixtable(<anno>Tab</anno>, true)</c>. The table remains
fixed until the process releases it by calling
@@ -1300,11 +1365,11 @@ ets:select(ets:repair_continuation(Broken,MS)).</code>
<p>When a table is fixed, a sequence of
<seealso marker="#first/1"><c>first/1</c></seealso> and
<seealso marker="#next/2"><c>next/2</c></seealso> calls are
- guaranteed to succeed, and each object in
- the table is returned only once, even if objects
- are removed or inserted during the traversal. The keys for new
- objects inserted during the traversal <em>can</em> be returned by
- <c>next/2</c> (it depends on the internal ordering of the keys).</p>
+ guaranteed to succeed even if keys are removed during the
+ traversal. The keys for objects inserted or deleted during a
+ traversal may or may not be returned by <c>next/2</c> depending on
+ the ordering of keys within the table and if the key exists at the time
+ <c>next/2</c> is called.</p>
<p><em>Example:</em></p>
<code type="none">
clean_all_with_value(Tab,X) ->
@@ -1322,7 +1387,7 @@ clean_all_with_value(Tab,X,Key) ->
true
end,
clean_all_with_value(Tab,X,ets:next(Tab,Key)).</code>
- <p>Notice that no deleted objects are removed from a
+ <p>Notice that deleted objects are not freed from a
fixed table until it has been released. If a process fixes a
table but never releases it, the memory used by the deleted
objects is never freed. The performance of operations on
@@ -1332,14 +1397,14 @@ clean_all_with_value(Tab,X,Key) ->
<c>info(Tab, safe_fixed_monotonic_time)</c></seealso>. A system with
many processes fixing tables can need a monitor that sends alarms
when tables have been fixed for too long.</p>
- <p>Notice that for table type <c>ordered_set</c>,
- <c>safe_fixtable/2</c> is not necessary, as calls to
- <c>first/1</c> and <c>next/2</c> always succeed.</p>
+ <p>Notice that <c>safe_fixtable/2</c> is not necessary for table type
+ <c>ordered_set</c> and for traversals done by a single ETS function call,
+ like <seealso marker="#select/2"><c>select/2</c></seealso>.</p>
</desc>
</func>
<func>
- <name name="select" arity="1"/>
+ <name name="select" arity="1" since=""/>
<fsummary>Continue matching objects in an ETS table.</fsummary>
<desc>
<p>Continues a match started with
@@ -1353,7 +1418,7 @@ clean_all_with_value(Tab,X,Key) ->
</func>
<func>
- <name name="select" arity="2"/>
+ <name name="select" arity="2" since=""/>
<fsummary>Match the objects in an ETS table against a
match specification.</fsummary>
<desc>
@@ -1448,7 +1513,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</func>
<func>
- <name name="select" arity="3"/>
+ <name name="select" arity="3" since=""/>
<fsummary>Match the objects in an ETS table against a match
specification and return part of the answers.</fsummary>
<desc>
@@ -1462,12 +1527,15 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
table, which is still faster than traversing the table object by
object using <seealso marker="#first/1"><c>first/1</c></seealso>
and <seealso marker="#next/2"><c>next/2</c></seealso>.</p>
- <p>If the table is empty, <c>'$end_of_table'</c> is returned.</p>
+ <p>If the table is empty, <c>'$end_of_table'</c> is returned.</p>
+ <p>Use <seealso marker="#safe_fixtable/2"><c>safe_fixtable/2</c></seealso>
+ to guarantee <seealso marker="#traversal">safe traversal</seealso>
+ for subsequent calls to <seealso marker="#select/1"><c>select/1</c></seealso>.</p>
</desc>
</func>
<func>
- <name name="select_count" arity="2"/>
+ <name name="select_count" arity="2" since=""/>
<fsummary>Match the objects in an ETS table against a match
specification and return the number of objects for which the match
specification returned <c>true</c>.</fsummary>
@@ -1486,7 +1554,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</func>
<func>
- <name name="select_delete" arity="2"/>
+ <name name="select_delete" arity="2" since=""/>
<fsummary>Match the objects in an ETS table against a match
specification and delete objects where the match specification
returns <c>true</c>.</fsummary>
@@ -1510,7 +1578,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</func>
<func>
- <name name="select_replace" arity="2"/>
+ <name name="select_replace" arity="2" since="OTP 20.0"/>
<fsummary>Match and replace objects atomically in an ETS table</fsummary>
<desc>
<p>Matches the objects in the table <c><anno>Tab</anno></c> using a
@@ -1519,7 +1587,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
the match specification result.</p>
<p>The match-and-replace operation for each individual object is guaranteed to be
<seealso marker="#concurrency">atomic and isolated</seealso>. The
- <c>select_replace</c> table iteration as a whole, like all other select functions,
+ <c>select_replace</c> table traversal as a whole, like all other select functions,
does not give such guarantees.</p>
<p>The match specifiction must be guaranteed to <em>retain the key</em>
of any matched object. If not, <c>select_replace</c> will fail with <c>badarg</c>
@@ -1549,7 +1617,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="select_reverse" arity="1"/>
+ <name name="select_reverse" arity="1" since="OTP R14B"/>
<fsummary>Continue matching objects in an ETS table.</fsummary>
<desc>
<p>Continues a match started with <seealso marker="#select_reverse/3">
@@ -1582,7 +1650,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="select_reverse" arity="2"/>
+ <name name="select_reverse" arity="2" since="OTP R14B"/>
<fsummary>Match the objects in an ETS table against a
match specification.</fsummary>
<desc>
@@ -1594,7 +1662,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="select_reverse" arity="3"/>
+ <name name="select_reverse" arity="3" since="OTP R14B"/>
<fsummary>Match the objects in an ETS table against a
match specification and return part of the answers.</fsummary>
<desc>
@@ -1612,7 +1680,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="setopts" arity="2"/>
+ <name name="setopts" arity="2" since=""/>
<fsummary>Set table options.</fsummary>
<desc>
<p>Sets table options. The only allowed option to be set after the
@@ -1623,7 +1691,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="slot" arity="2"/>
+ <name name="slot" arity="2" since=""/>
<fsummary>Return all objects in a specified slot of an ETS table.
</fsummary>
<desc>
@@ -1648,7 +1716,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="tab2file" arity="2"/>
+ <name name="tab2file" arity="2" since=""/>
<fsummary>Dump an ETS table to a file.</fsummary>
<desc>
<p>Dumps table <c><anno>Tab</anno></c> to file
@@ -1659,7 +1727,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="tab2file" arity="3"/>
+ <name name="tab2file" arity="3" since=""/>
<fsummary>Dump an ETS table to a file.</fsummary>
<desc>
<p>Dumps table <c><anno>Tab</anno></c> to file
@@ -1706,7 +1774,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="tab2list" arity="1"/>
+ <name name="tab2list" arity="1" since=""/>
<fsummary>Return a list of all objects in an ETS table.</fsummary>
<desc>
<p>Returns a list of all objects in table <c><anno>Tab</anno></c>.</p>
@@ -1714,7 +1782,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="tabfile_info" arity="1"/>
+ <name name="tabfile_info" arity="1" since=""/>
<fsummary>Return a list of all objects in an ETS table.</fsummary>
<desc>
<p>Returns information about the table dumped to file by
@@ -1792,8 +1860,8 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
</func>
<func>
- <name name="table" arity="1"/>
- <name name="table" arity="2"/>
+ <name name="table" arity="1" since=""/>
+ <name name="table" arity="2" since=""/>
<fsummary>Return a QLC query handle.</fsummary>
<desc>
<p>Returns a Query List
@@ -1869,7 +1937,7 @@ true</pre>
</func>
<func>
- <name name="take" arity="2"/>
+ <name name="take" arity="2" since="OTP 18.0"/>
<fsummary>Return and remove all objects with a specified key from an
ETS table.</fsummary>
<desc>
@@ -1884,7 +1952,7 @@ true</pre>
</desc>
</func>
<func>
- <name name="test_ms" arity="2"/>
+ <name name="test_ms" arity="2" since=""/>
<fsummary>Test a match specification for use in <c>select/2</c>.
</fsummary>
<desc>
@@ -1911,7 +1979,7 @@ true</pre>
</func>
<func>
- <name name="to_dets" arity="2"/>
+ <name name="to_dets" arity="2" since=""/>
<fsummary>Fill a Dets table with objects from an ETS table.
</fsummary>
<desc>
@@ -1922,12 +1990,12 @@ true</pre>
</func>
<func>
- <name name="update_counter" arity="3" clause_i="1"/>
- <name name="update_counter" arity="4" clause_i="1"/>
- <name name="update_counter" arity="3" clause_i="2"/>
- <name name="update_counter" arity="4" clause_i="2"/>
- <name name="update_counter" arity="3" clause_i="3"/>
- <name name="update_counter" arity="4" clause_i="3"/>
+ <name name="update_counter" arity="3" clause_i="1" since=""/>
+ <name name="update_counter" arity="4" clause_i="1" since="OTP 18.0"/>
+ <name name="update_counter" arity="3" clause_i="2" since=""/>
+ <name name="update_counter" arity="4" clause_i="2" since="OTP 18.0"/>
+ <name name="update_counter" arity="3" clause_i="3" since=""/>
+ <name name="update_counter" arity="4" clause_i="3" since="OTP 18.0"/>
<fsummary>Update a counter object in an ETS table.</fsummary>
<type variable="Tab"/>
<type variable="Key"/>
@@ -1940,9 +2008,8 @@ true</pre>
<p>This function provides an efficient way to update one or more
counters, without the trouble of having to look up an object, update
the object by incrementing an element, and insert the resulting
- object into the table again. (The update is done atomically,
- that is, no process
- can access the ETS table in the middle of the operation.)</p>
+ object into the table again. The operation is guaranteed to be
+ <seealso marker="#concurrency">atomic and isolated</seealso>.</p>
<p>This function destructively update the object with key
<c><anno>Key</anno></c> in table <c><anno>Tab</anno></c> by adding
<c><anno>Incr</anno></c> to the element at position
@@ -2006,8 +2073,8 @@ true</pre>
</func>
<func>
- <name name="update_element" arity="3" clause_i="1"/>
- <name name="update_element" arity="3" clause_i="2"/>
+ <name name="update_element" arity="3" clause_i="1" since=""/>
+ <name name="update_element" arity="3" clause_i="2" since=""/>
<fsummary>Update the <c>Pos</c>:th element of the object with a
specified key in an ETS table.</fsummary>
<type variable="Tab"/>
@@ -2049,7 +2116,7 @@ true</pre>
</func>
<func>
- <name name="whereis" arity="1"/>
+ <name name="whereis" arity="1" since="OTP 21.0"/>
<fsummary>Retrieves the tid() of a named table.</fsummary>
<desc>
<p>This function returns the
diff --git a/lib/stdlib/doc/src/file_sorter.xml b/lib/stdlib/doc/src/file_sorter.xml
index e988d58c2f..942d98fe61 100644
--- a/lib/stdlib/doc/src/file_sorter.xml
+++ b/lib/stdlib/doc/src/file_sorter.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>file_sorter.xml</file>
</header>
- <module>file_sorter</module>
+ <module since="">file_sorter</module>
<modulesummary>File sorter.</modulesummary>
<description>
<p>This module contains functions for sorting terms on files, merging
@@ -334,8 +334,8 @@ output(L) ->
<funcs>
<func>
- <name name="check" arity="1"/>
- <name name="check" arity="2"/>
+ <name name="check" arity="1" since=""/>
+ <name name="check" arity="2" since=""/>
<fsummary>Check whether terms on files are sorted.</fsummary>
<desc>
<p>Checks files for sortedness. If a file is not sorted, the
@@ -347,8 +347,8 @@ output(L) ->
</func>
<func>
- <name name="keycheck" arity="2"/>
- <name name="keycheck" arity="3"/>
+ <name name="keycheck" arity="2" since=""/>
+ <name name="keycheck" arity="3" since=""/>
<fsummary>Check whether terms on files are sorted by key.</fsummary>
<desc>
<p>Checks files for sortedness. If a file is not sorted, the
@@ -360,8 +360,8 @@ output(L) ->
</func>
<func>
- <name name="keymerge" arity="3"/>
- <name name="keymerge" arity="4"/>
+ <name name="keymerge" arity="3" since=""/>
+ <name name="keymerge" arity="4" since=""/>
<fsummary>Merge terms on files by key.</fsummary>
<desc>
<p>Merges tuples on files. Each input file is assumed to be
@@ -372,7 +372,7 @@ output(L) ->
</func>
<func>
- <name name="keysort" arity="2"/>
+ <name name="keysort" arity="2" since=""/>
<fsummary>Sort terms on files by key.</fsummary>
<desc>
<p>Sorts tuples on files.</p>
@@ -382,8 +382,8 @@ output(L) ->
</func>
<func>
- <name name="keysort" arity="3"/>
- <name name="keysort" arity="4"/>
+ <name name="keysort" arity="3" since=""/>
+ <name name="keysort" arity="4" since=""/>
<fsummary>Sort terms on files by key.</fsummary>
<desc>
<p>Sorts tuples on files. The sort is performed on the
@@ -397,8 +397,8 @@ output(L) ->
</func>
<func>
- <name name="merge" arity="2"/>
- <name name="merge" arity="3"/>
+ <name name="merge" arity="2" since=""/>
+ <name name="merge" arity="3" since=""/>
<fsummary>Merge terms on files.</fsummary>
<desc>
<p>Merges terms on files. Each input file is assumed to be
@@ -409,7 +409,7 @@ output(L) ->
</func>
<func>
- <name name="sort" arity="1"/>
+ <name name="sort" arity="1" since=""/>
<fsummary>Sort terms on files.</fsummary>
<desc>
<p>Sorts terms on files.</p>
@@ -419,8 +419,8 @@ output(L) ->
</func>
<func>
- <name name="sort" arity="2"/>
- <name name="sort" arity="3"/>
+ <name name="sort" arity="2" since=""/>
+ <name name="sort" arity="3" since=""/>
<fsummary>Sort terms on files.</fsummary>
<desc>
<p>Sorts terms on files.</p>
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index 3b5be75bc0..5df415834f 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>filelib.xml</file>
</header>
- <module>filelib</module>
+ <module since="">filelib</module>
<modulesummary>File utilities, such as wildcard matching of filenames.
</modulesummary>
<description>
@@ -94,7 +94,7 @@
<funcs>
<func>
- <name name="ensure_dir" arity="1"/>
+ <name name="ensure_dir" arity="1" since=""/>
<fsummary>Ensure that all parent directories for a file or directory
exist.</fsummary>
<desc>
@@ -108,7 +108,7 @@
</func>
<func>
- <name name="file_size" arity="1"/>
+ <name name="file_size" arity="1" since=""/>
<fsummary>Return the size in bytes of a file.</fsummary>
<desc>
<p>Returns the size of the specified file.</p>
@@ -116,7 +116,7 @@
</func>
<func>
- <name name="fold_files" arity="5"/>
+ <name name="fold_files" arity="5" since=""/>
<fsummary>Fold over all files matching a regular expression.</fsummary>
<desc>
<p>Folds function <c><anno>Fun</anno></c> over all (regular) files
@@ -142,7 +142,7 @@
</func>
<func>
- <name name="is_dir" arity="1"/>
+ <name name="is_dir" arity="1" since=""/>
<fsummary>Test whether <c>Name</c> refers to a directory.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Name</anno></c>
@@ -151,7 +151,7 @@
</func>
<func>
- <name name="is_file" arity="1"/>
+ <name name="is_file" arity="1" since=""/>
<fsummary>Test whether <c>Name</c> refers to a file or directory.
</fsummary>
<desc>
@@ -161,7 +161,7 @@
</func>
<func>
- <name name="is_regular" arity="1"/>
+ <name name="is_regular" arity="1" since=""/>
<fsummary>Test whether <c>Name</c> refers to a (regular) file.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Name</anno></c>
@@ -170,7 +170,7 @@
</func>
<func>
- <name name="last_modified" arity="1"/>
+ <name name="last_modified" arity="1" since=""/>
<fsummary>Return the local date and time when a file was last modified.
</fsummary>
<desc>
@@ -180,7 +180,7 @@
</func>
<func>
- <name name="wildcard" arity="1"/>
+ <name name="wildcard" arity="1" since=""/>
<fsummary>Match filenames using Unix-style wildcards.</fsummary>
<desc>
<p>Returns a list of all files that match Unix-style wildcard string
@@ -252,7 +252,7 @@ filelib:wildcard("lib/**/*.{erl,hrl}")</code>
</func>
<func>
- <name name="wildcard" arity="2"/>
+ <name name="wildcard" arity="2" since=""/>
<fsummary>Match filenames using Unix-style wildcards starting at a
specified directory.</fsummary>
<desc>
@@ -263,8 +263,8 @@ filelib:wildcard("lib/**/*.{erl,hrl}")</code>
</func>
<func>
- <name name="find_file" arity="2"/>
- <name name="find_file" arity="3"/>
+ <name name="find_file" arity="2" since="OTP 20.0"/>
+ <name name="find_file" arity="3" since="OTP 20.0"/>
<fsummary>Find a file relative to a given directory.</fsummary>
<desc>
<p>Looks for a file of the given name by applying suffix rules to
@@ -278,7 +278,7 @@ filelib:wildcard("lib/**/*.{erl,hrl}")</code>
</desc>
</func>
<func>
- <name name="find_source" arity="1"/>
+ <name name="find_source" arity="1" since="OTP 20.0"/>
<fsummary>Find the source file for a given object file.</fsummary>
<desc>
<p>Equivalent to <c>find_source(Base, Dir)</c>, where <c>Dir</c> is
@@ -287,8 +287,8 @@ filelib:wildcard("lib/**/*.{erl,hrl}")</code>
</desc>
</func>
<func>
- <name name="find_source" arity="2"/>
- <name name="find_source" arity="3"/>
+ <name name="find_source" arity="2" since="OTP 20.0"/>
+ <name name="find_source" arity="3" since="OTP 20.0"/>
<fsummary>Find a source file relative to a given directory.</fsummary>
<desc>
<p>Applies file extension specific rules to find the source file for
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index ce19f70df0..ae42846c6b 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -28,7 +28,7 @@
<date>1997-11-13</date>
<rev>B</rev>
</header>
- <module>filename</module>
+ <module since="">filename</module>
<modulesummary>Filename manipulation functions.</modulesummary>
<description>
<p>This module provides functions
@@ -84,15 +84,10 @@
reject such filenames.
</p></warning>
</description>
- <datatypes>
- <datatype>
- <name name="basedir_type"/>
- </datatype>
- </datatypes>
<funcs>
<func>
- <name name="absname" arity="1"/>
+ <name name="absname" arity="1" since=""/>
<fsummary>Convert a filename to an absolute name, relative the working
directory.</fsummary>
<desc>
@@ -124,7 +119,7 @@
</func>
<func>
- <name name="absname" arity="2"/>
+ <name name="absname" arity="2" since=""/>
<fsummary>Convert a filename to an absolute name, relative a specified
directory.</fsummary>
<desc>
@@ -135,7 +130,7 @@
</func>
<func>
- <name name="absname_join" arity="2"/>
+ <name name="absname_join" arity="2" since=""/>
<fsummary>Join an absolute directory with a relative filename.</fsummary>
<desc>
<p>Joins an absolute directory with a relative filename. Similar to
@@ -149,18 +144,37 @@
</func>
<func>
- <name name="basedir" arity="2"/>
- <fsummary>Equivalent to <c>basedir(<anno>Type</anno>,<anno>Application</anno>,#{})</c>.</fsummary>
+ <name name="basedir" arity="2" clause_i="1" since="OTP 19.0"/>
+ <name name="basedir" arity="2" clause_i="2" since="OTP 19.0"/>
+ <fsummary>Equivalent to <c>basedir(<anno>PathType</anno>,
+ <anno>Application</anno>,#{})</c> or
+ <c>basedir(<anno>PathsType</anno>, <anno>Application</anno>,#{})</c>.
+ </fsummary>
+ <type variable="PathType" name_i="1"/>
+ <type name="basedir_path_type"/>
+ <type variable="PathsType" name_i="2"/>
+ <type name="basedir_paths_type"/>
+ <type variable="Application"/>
<desc>
<p>
- Equivalent to <seealso marker="#basedir-3">
- basedir(<anno>Type</anno>, <anno>Application</anno>, #{})</seealso>.
+ Equivalent to <seealso marker="#basedir_3_1">
+ basedir(<anno>PathType</anno>, <anno>Application</anno>, #{})</seealso>
+ or <seealso marker="#basedir_3_2">
+basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seealso>.
</p>
</desc>
</func>
<func>
- <name name="basedir" arity="3"/>
+ <name name="basedir" arity="3" clause_i="1" anchor="basedir_3_1" since="OTP 19.0"/>
+ <name name="basedir" arity="3" clause_i="2" anchor="basedir_3_2" since="OTP 19.0"/>
<fsummary></fsummary>
+ <type variable="PathType" name_i="1"/>
+ <type name="basedir_path_type"/>
+ <type variable="PathsType" name_i="2"/>
+ <type name="basedir_paths_type"/>
+ <type variable="Application"/>
+ <type variable="Opts"/>
+ <type name="basedir_opts"/>
<desc><marker id="basedir-3"/>
<p>
Returns a suitable path, or paths, for a given type. If
@@ -300,7 +314,7 @@ true
</desc>
</func>
<func>
- <name name="basename" arity="1"/>
+ <name name="basename" arity="1" since=""/>
<fsummary>Return the last component of a filename.</fsummary>
<desc>
<p>Returns the last component of <c><anno>Filename</anno></c>, or
@@ -318,7 +332,7 @@ true
</func>
<func>
- <name name="basename" arity="2"/>
+ <name name="basename" arity="2" since=""/>
<fsummary>Return the last component of a filename, stripped of the
specified extension.</fsummary>
<desc>
@@ -343,7 +357,7 @@ true
</func>
<func>
- <name name="dirname" arity="1"/>
+ <name name="dirname" arity="1" since=""/>
<fsummary>Return the directory part of a path name.</fsummary>
<desc>
<p>Returns the directory part of <c><anno>Filename</anno></c>.</p>
@@ -360,7 +374,7 @@ true
</func>
<func>
- <name name="extension" arity="1"/>
+ <name name="extension" arity="1" since=""/>
<fsummary>Return the file extension.</fsummary>
<desc>
<p>Returns the file extension of <c><anno>Filename</anno></c>,
@@ -376,8 +390,8 @@ true
</func>
<func>
- <name name="find_src" arity="1"/>
- <name name="find_src" arity="2"/>
+ <name name="find_src" arity="1" since=""/>
+ <name name="find_src" arity="2" since=""/>
<fsummary>Find the filename and compiler options for a module.</fsummary>
<desc>
<p>Finds the source filename and compiler options for a module.
@@ -424,7 +438,7 @@ true
</func>
<func>
- <name name="flatten" arity="1"/>
+ <name name="flatten" arity="1" since=""/>
<fsummary>Convert a filename to a flat string.</fsummary>
<desc>
<p>Converts a possibly deep list filename consisting of
@@ -434,7 +448,7 @@ true
</func>
<func>
- <name name="join" arity="1"/>
+ <name name="join" arity="1" since=""/>
<fsummary>Join a list of filename components with directory separators.
</fsummary>
<desc>
@@ -462,7 +476,7 @@ true
</func>
<func>
- <name name="join" arity="2"/>
+ <name name="join" arity="2" since=""/>
<fsummary>Join two filename components with directory separators.
</fsummary>
<desc>
@@ -473,7 +487,7 @@ true
</func>
<func>
- <name name="nativename" arity="1"/>
+ <name name="nativename" arity="1" since=""/>
<fsummary>Return the native form of a file path.</fsummary>
<desc>
<p>Converts <c><anno>Path</anno></c> to a form accepted by the command
@@ -492,7 +506,7 @@ true
</func>
<func>
- <name name="pathtype" arity="1"/>
+ <name name="pathtype" arity="1" since=""/>
<fsummary>Return the path type.</fsummary>
<desc>
<p>Returns the path type, which is one of the following:</p>
@@ -522,8 +536,8 @@ true
</func>
<func>
- <name name="rootname" arity="1"/>
- <name name="rootname" arity="2"/>
+ <name name="rootname" arity="1" since=""/>
+ <name name="rootname" arity="2" since=""/>
<fsummary>Remove a filename extension.</fsummary>
<desc>
<p>Removes a filename extension. <c>rootname/2</c> works as
@@ -543,7 +557,7 @@ true
</func>
<func>
- <name name="safe_relative_path" arity="1"/>
+ <name name="safe_relative_path" arity="1" since="OTP 19.3"/>
<fsummary>Sanitize a relative path to avoid directory traversal attacks.</fsummary>
<desc>
<p>Sanitizes the relative path by eliminating ".." and "."
@@ -570,7 +584,7 @@ unsafe</pre>
</func>
<func>
- <name name="split" arity="1"/>
+ <name name="split" arity="1" since=""/>
<fsummary>Split a filename into its path components.</fsummary>
<desc>
<p>Returns a list whose elements are the path components of
diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml
index 03397b4503..a9596c6e4d 100644
--- a/lib/stdlib/doc/src/gb_sets.xml
+++ b/lib/stdlib/doc/src/gb_sets.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>gb_sets</module>
+ <module since="">gb_sets</module>
<modulesummary>General balanced trees.</modulesummary>
<description>
<p>This module provides ordered sets using Prof. Arne Andersson's
@@ -123,8 +123,8 @@
<funcs>
<func>
- <name name="add" arity="2"/>
- <name name="add_element" arity="2"/>
+ <name name="add" arity="2" since=""/>
+ <name name="add_element" arity="2" since=""/>
<fsummary>Add a (possibly existing) element to a set.</fsummary>
<desc>
<p>Returns a new set formed from <c><anno>Set1</anno></c> with
@@ -135,7 +135,7 @@
</func>
<func>
- <name name="balance" arity="1"/>
+ <name name="balance" arity="1" since=""/>
<fsummary>Rebalance tree representation of a set.</fsummary>
<desc>
<p>Rebalances the tree representation of <c><anno>Set1</anno></c>.
@@ -149,7 +149,7 @@
</func>
<func>
- <name name="del_element" arity="2"/>
+ <name name="del_element" arity="2" since=""/>
<fsummary>Remove a (possibly non-existing) element from a set.</fsummary>
<desc>
<p>Returns a new set formed from <c><anno>Set1</anno></c> with
@@ -160,7 +160,7 @@
</func>
<func>
- <name name="delete" arity="2"/>
+ <name name="delete" arity="2" since=""/>
<fsummary>Remove an element from a set.</fsummary>
<desc>
<p>Returns a new set formed from <c><anno>Set1</anno></c> with
@@ -171,7 +171,7 @@
</func>
<func>
- <name name="delete_any" arity="2"/>
+ <name name="delete_any" arity="2" since=""/>
<fsummary>Remove a (possibly non-existing) element from a set.</fsummary>
<desc>
<p>Returns a new set formed from <c><anno>Set1</anno></c> with
@@ -182,7 +182,7 @@
</func>
<func>
- <name name="difference" arity="2"/>
+ <name name="difference" arity="2" since=""/>
<fsummary>Return the difference of two sets.</fsummary>
<desc>
<p>Returns only the elements of <c><anno>Set1</anno></c> that are not
@@ -191,7 +191,7 @@
</func>
<func>
- <name name="empty" arity="0"/>
+ <name name="empty" arity="0" since=""/>
<fsummary>Return an empty set.</fsummary>
<desc>
<p>Returns a new empty set.</p>
@@ -199,7 +199,7 @@
</func>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since=""/>
<fsummary>Filter set elements.</fsummary>
<desc>
<p>Filters elements in <c><anno>Set1</anno></c> using predicate function
@@ -208,7 +208,7 @@
</func>
<func>
- <name name="fold" arity="3"/>
+ <name name="fold" arity="3" since=""/>
<fsummary>Fold over set elements.</fsummary>
<desc>
<p>Folds <c><anno>Function</anno></c> over every element in
@@ -218,7 +218,7 @@
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since=""/>
<fsummary>Convert a list into a set.</fsummary>
<desc>
<p>Returns a set of the elements in <c><anno>List</anno></c>, where
@@ -227,7 +227,7 @@
</func>
<func>
- <name name="from_ordset" arity="1"/>
+ <name name="from_ordset" arity="1" since=""/>
<fsummary>Make a set from an ordset list.</fsummary>
<desc>
<p>Turns an ordered-set list <c><anno>List</anno></c> into a set.
@@ -236,7 +236,7 @@
</func>
<func>
- <name name="insert" arity="2"/>
+ <name name="insert" arity="2" since=""/>
<fsummary>Add a new element to a set.</fsummary>
<desc>
<p>Returns a new set formed from <c><anno>Set1</anno></c> with
@@ -247,7 +247,7 @@
</func>
<func>
- <name name="intersection" arity="1"/>
+ <name name="intersection" arity="1" since=""/>
<fsummary>Return the intersection of a list of sets.</fsummary>
<desc>
<p>Returns the intersection of the non-empty list of sets.</p>
@@ -255,7 +255,7 @@
</func>
<func>
- <name name="intersection" arity="2"/>
+ <name name="intersection" arity="2" since=""/>
<fsummary>Return the intersection of two sets.</fsummary>
<desc>
<p>Returns the intersection of <c><anno>Set1</anno></c> and
@@ -264,7 +264,7 @@
</func>
<func>
- <name name="is_disjoint" arity="2"/>
+ <name name="is_disjoint" arity="2" since=""/>
<fsummary>Check whether two sets are disjoint.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Set1</anno></c> and
@@ -274,7 +274,7 @@
</func>
<func>
- <name name="is_element" arity="2"/>
+ <name name="is_element" arity="2" since=""/>
<fsummary>Test for membership of a set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of
@@ -283,7 +283,7 @@
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since=""/>
<fsummary>Test for empty set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Set</anno></c> is an empty set,
@@ -292,7 +292,7 @@
</func>
<func>
- <name name="is_member" arity="2"/>
+ <name name="is_member" arity="2" since=""/>
<fsummary>Test for membership of a set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of
@@ -301,7 +301,7 @@
</func>
<func>
- <name name="is_set" arity="1"/>
+ <name name="is_set" arity="1" since=""/>
<fsummary>Test for a set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> appears to be a set,
@@ -310,7 +310,7 @@
</func>
<func>
- <name name="is_subset" arity="2"/>
+ <name name="is_subset" arity="2" since=""/>
<fsummary>Test for subset.</fsummary>
<desc>
<p>Returns <c>true</c> when every element of <c><anno>Set1</anno></c> is
@@ -319,7 +319,7 @@
</func>
<func>
- <name name="iterator" arity="1"/>
+ <name name="iterator" arity="1" since=""/>
<fsummary>Return an iterator for a set.</fsummary>
<desc>
<p>Returns an iterator that can be used for traversing the entries of
@@ -336,7 +336,7 @@
</func>
<func>
- <name name="iterator_from" arity="2"/>
+ <name name="iterator_from" arity="2" since="OTP 18.0"/>
<fsummary>Return an iterator for a set starting from a specified element.
</fsummary>
<desc>
@@ -351,7 +351,7 @@
</func>
<func>
- <name name="largest" arity="1"/>
+ <name name="largest" arity="1" since=""/>
<fsummary>Return largest element.</fsummary>
<desc>
<p>Returns the largest element in <c><anno>Set</anno></c>. Assumes that
@@ -360,7 +360,7 @@
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Return an empty set.</fsummary>
<desc>
<p>Returns a new empty set.</p>
@@ -368,7 +368,7 @@
</func>
<func>
- <name name="next" arity="1"/>
+ <name name="next" arity="1" since=""/>
<fsummary>Traverse a set with an iterator.</fsummary>
<desc>
<p>Returns <c>{<anno>Element</anno>, <anno>Iter2</anno>}</c>, where
@@ -381,7 +381,7 @@
</func>
<func>
- <name name="singleton" arity="1"/>
+ <name name="singleton" arity="1" since=""/>
<fsummary>Return a set with one element.</fsummary>
<desc>
<p>Returns a set containing only element <c><anno>Element</anno></c>.
@@ -390,7 +390,7 @@
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since=""/>
<fsummary>Return the number of elements in a set.</fsummary>
<desc>
<p>Returns the number of elements in <c><anno>Set</anno></c>.</p>
@@ -398,7 +398,7 @@
</func>
<func>
- <name name="smallest" arity="1"/>
+ <name name="smallest" arity="1" since=""/>
<fsummary>Return smallest element.</fsummary>
<desc>
<p>Returns the smallest element in <c><anno>Set</anno></c>. Assumes that
@@ -407,7 +407,7 @@
</func>
<func>
- <name name="subtract" arity="2"/>
+ <name name="subtract" arity="2" since=""/>
<fsummary>Return the difference of two sets.</fsummary>
<desc>
<p>Returns only the elements of <c><anno>Set1</anno></c> that are not
@@ -416,7 +416,7 @@
</func>
<func>
- <name name="take_largest" arity="1"/>
+ <name name="take_largest" arity="1" since=""/>
<fsummary>Extract largest element.</fsummary>
<desc>
<p>Returns <c>{<anno>Element</anno>, <anno>Set2</anno>}</c>, where
@@ -428,7 +428,7 @@
</func>
<func>
- <name name="take_smallest" arity="1"/>
+ <name name="take_smallest" arity="1" since=""/>
<fsummary>Extract smallest element.</fsummary>
<desc>
<p>Returns <c>{<anno>Element</anno>, <anno>Set2</anno>}</c>, where
@@ -440,7 +440,7 @@
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert a set into a list.</fsummary>
<desc>
<p>Returns the elements of <c><anno>Set</anno></c> as a list.</p>
@@ -448,7 +448,7 @@
</func>
<func>
- <name name="union" arity="1"/>
+ <name name="union" arity="1" since=""/>
<fsummary>Return the union of a list of sets.</fsummary>
<desc>
<p>Returns the merged (union) set of the list of sets.</p>
@@ -456,7 +456,7 @@
</func>
<func>
- <name name="union" arity="2"/>
+ <name name="union" arity="2" since=""/>
<fsummary>Return the union of two sets.</fsummary>
<desc>
<p>Returns the merged (union) set of <c><anno>Set1</anno></c> and
diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml
index 5cfff021c1..570c9c7cb6 100644
--- a/lib/stdlib/doc/src/gb_trees.xml
+++ b/lib/stdlib/doc/src/gb_trees.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>gb_trees</module>
+ <module since="">gb_trees</module>
<modulesummary>General balanced trees.</modulesummary>
<description>
<p>This module provides Prof. Arne Andersson's General
@@ -75,7 +75,7 @@
<funcs>
<func>
- <name name="balance" arity="1"/>
+ <name name="balance" arity="1" since=""/>
<fsummary>Rebalance a tree.</fsummary>
<desc>
<p>Rebalances <c><anno>Tree1</anno></c>. Notice that this is
@@ -88,7 +88,7 @@
</func>
<func>
- <name name="delete" arity="2"/>
+ <name name="delete" arity="2" since=""/>
<fsummary>Remove a node from a tree.</fsummary>
<desc>
<p>Removes the node with key <c><anno>Key</anno></c> from
@@ -98,7 +98,7 @@
</func>
<func>
- <name name="delete_any" arity="2"/>
+ <name name="delete_any" arity="2" since=""/>
<fsummary>Remove a (possibly non-existing) node from a tree.</fsummary>
<desc>
<p>Removes the node with key <c><anno>Key</anno></c> from
@@ -109,7 +109,7 @@
</func>
<func>
- <name name="take" arity="2"/>
+ <name name="take" arity="2" since="OTP 20.0"/>
<fsummary>Returns a value and new tree without node with key <c>Key</c>.</fsummary>
<desc>
<p>Returns a value <c><anno>Value</anno></c> from node with key <c><anno>Key</anno></c>
@@ -120,7 +120,7 @@
</func>
<func>
- <name name="take_any" arity="2"/>
+ <name name="take_any" arity="2" since="OTP 20.0"/>
<fsummary>Returns a value and new tree without node with key <c>Key</c>.</fsummary>
<desc>
<p>Returns a value <c><anno>Value</anno></c> from node with key <c><anno>Key</anno></c>
@@ -131,7 +131,7 @@
</func>
<func>
- <name name="empty" arity="0"/>
+ <name name="empty" arity="0" since=""/>
<fsummary>Return an empty tree.</fsummary>
<desc>
<p>Returns a new empty tree.</p>
@@ -139,7 +139,7 @@
</func>
<func>
- <name name="enter" arity="3"/>
+ <name name="enter" arity="3" since=""/>
<fsummary>Insert or update key with value in a tree.</fsummary>
<desc>
<p>Inserts <c><anno>Key</anno></c> with value <c><anno>Value</anno></c>
@@ -151,7 +151,7 @@
</func>
<func>
- <name name="from_orddict" arity="1"/>
+ <name name="from_orddict" arity="1" since=""/>
<fsummary>Make a tree from an orddict.</fsummary>
<desc>
<p>Turns an ordered list <c><anno>List</anno></c> of key-value tuples
@@ -160,7 +160,7 @@
</func>
<func>
- <name name="get" arity="2"/>
+ <name name="get" arity="2" since=""/>
<fsummary>Look up a key in a tree, if present.</fsummary>
<desc>
<p>Retrieves the value stored with <c><anno>Key</anno></c> in
@@ -171,7 +171,7 @@
</func>
<func>
- <name name="insert" arity="3"/>
+ <name name="insert" arity="3" since=""/>
<fsummary>Insert a new key and value in a tree.</fsummary>
<desc>
<p>Inserts <c><anno>Key</anno></c> with value <c><anno>Value</anno></c>
@@ -182,7 +182,7 @@
</func>
<func>
- <name name="is_defined" arity="2"/>
+ <name name="is_defined" arity="2" since=""/>
<fsummary>Test for membership of a tree.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Key</anno></c> is present in
@@ -191,7 +191,7 @@
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since=""/>
<fsummary>Test for empty tree.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Tree</anno></c> is an empty tree,
@@ -200,7 +200,7 @@
</func>
<func>
- <name name="iterator" arity="1"/>
+ <name name="iterator" arity="1" since=""/>
<fsummary>Return an iterator for a tree.</fsummary>
<desc>
<p>Returns an iterator that can be used for traversing the
@@ -218,7 +218,7 @@
</func>
<func>
- <name name="iterator_from" arity="2"/>
+ <name name="iterator_from" arity="2" since="OTP 18.0"/>
<fsummary>Return an iterator for a tree starting from a specified key.
</fsummary>
<desc>
@@ -233,7 +233,7 @@
</func>
<func>
- <name name="keys" arity="1"/>
+ <name name="keys" arity="1" since=""/>
<fsummary>Return a list of the keys in a tree.</fsummary>
<desc>
<p>Returns the keys in <c><anno>Tree</anno></c> as an ordered list.</p>
@@ -241,7 +241,7 @@
</func>
<func>
- <name name="largest" arity="1"/>
+ <name name="largest" arity="1" since=""/>
<fsummary>Return largest key and value.</fsummary>
<desc>
<p>Returns <c>{<anno>Key</anno>, <anno>Value</anno>}</c>, where
@@ -253,7 +253,7 @@
</func>
<func>
- <name name="lookup" arity="2"/>
+ <name name="lookup" arity="2" since=""/>
<fsummary>Look up a key in a tree.</fsummary>
<desc>
<p>Looks up <c><anno>Key</anno></c> in <c><anno>Tree</anno></c>.
@@ -263,7 +263,7 @@
</func>
<func>
- <name name="map" arity="2"/>
+ <name name="map" arity="2" since=""/>
<fsummary>Return largest key and value.</fsummary>
<desc>
<p>Maps function F(<anno>K</anno>, <anno>V1</anno>) -> <anno>V2</anno>
@@ -275,7 +275,7 @@
</func>
<func>
- <name name="next" arity="1"/>
+ <name name="next" arity="1" since=""/>
<fsummary>Traverse a tree with an iterator.</fsummary>
<desc>
<p>Returns <c>{<anno>Key</anno>, <anno>Value</anno>,
@@ -288,7 +288,7 @@
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since=""/>
<fsummary>Return the number of nodes in a tree.</fsummary>
<desc>
<p>Returns the number of nodes in <c><anno>Tree</anno></c>.</p>
@@ -296,7 +296,7 @@
</func>
<func>
- <name name="smallest" arity="1"/>
+ <name name="smallest" arity="1" since=""/>
<fsummary>Return smallest key and value.</fsummary>
<desc>
<p>Returns <c>{<anno>Key</anno>, <anno>Value</anno>}</c>, where
@@ -308,7 +308,7 @@
</func>
<func>
- <name name="take_largest" arity="1"/>
+ <name name="take_largest" arity="1" since=""/>
<fsummary>Extract largest key and value.</fsummary>
<desc>
<p>Returns <c>{<anno>Key</anno>, <anno>Value</anno>,
@@ -321,7 +321,7 @@
</func>
<func>
- <name name="take_smallest" arity="1"/>
+ <name name="take_smallest" arity="1" since=""/>
<fsummary>Extract smallest key and value.</fsummary>
<desc>
<p>Returns <c>{<anno>Key</anno>, <anno>Value</anno>,
@@ -334,7 +334,7 @@
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert a tree into a list.</fsummary>
<desc>
<p>Converts a tree into an ordered list of key-value tuples.</p>
@@ -342,7 +342,7 @@
</func>
<func>
- <name name="update" arity="3"/>
+ <name name="update" arity="3" since=""/>
<fsummary>Update a key to new value in a tree.</fsummary>
<desc>
<p>Updates <c><anno>Key</anno></c> to value <c><anno>Value</anno></c>
@@ -352,7 +352,7 @@
</func>
<func>
- <name name="values" arity="1"/>
+ <name name="values" arity="1" since=""/>
<fsummary>Return a list of the values in a tree.</fsummary>
<desc>
<p>Returns the values in <c><anno>Tree</anno></c> as an ordered list,
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index f793ec7fdf..2915c4f507 100644
--- a/lib/stdlib/doc/src/gen_event.xml
+++ b/lib/stdlib/doc/src/gen_event.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>gen_event</module>
+ <module since="">gen_event</module>
<modulesummary>Generic event handling behavior.</modulesummary>
<description>
<p>This behavior module provides event handling functionality. It
@@ -130,7 +130,7 @@ gen_event:stop -----> Module:terminate/2
<funcs>
<func>
- <name>add_handler(EventMgrRef, Handler, Args) -> Result</name>
+ <name since="">add_handler(EventMgrRef, Handler, Args) -> Result</name>
<fsummary>Add an event handler to a generic event manager.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
@@ -178,7 +178,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>add_sup_handler(EventMgrRef, Handler, Args) -> Result</name>
+ <name since="">add_sup_handler(EventMgrRef, Handler, Args) -> Result</name>
<fsummary>Add a supervised event handler to a generic event manager.
</fsummary>
<type>
@@ -241,8 +241,8 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>call(EventMgrRef, Handler, Request) -> Result</name>
- <name>call(EventMgrRef, Handler, Request, Timeout) -> Result</name>
+ <name since="">call(EventMgrRef, Handler, Request) -> Result</name>
+ <name since="">call(EventMgrRef, Handler, Request, Timeout) -> Result</name>
<fsummary>Make a synchronous call to a generic event manager.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
@@ -285,7 +285,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>delete_handler(EventMgrRef, Handler, Args) -> Result</name>
+ <name since="">delete_handler(EventMgrRef, Handler, Args) -> Result</name>
<fsummary>Delete an event handler from a generic event manager.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
@@ -318,8 +318,8 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>notify(EventMgrRef, Event) -> ok</name>
- <name>sync_notify(EventMgrRef, Event) -> ok</name>
+ <name since="">notify(EventMgrRef, Event) -> ok</name>
+ <name since="">sync_notify(EventMgrRef, Event) -> ok</name>
<fsummary>Notify an event manager about an event.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
@@ -349,9 +349,9 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>start() -> Result</name>
- <name>start(EventMgrName | Options) -> Result</name>
- <name>start(EventMgrName, Options) -> Result</name>
+ <name since="">start() -> Result</name>
+ <name since="">start(EventMgrName | Options) -> Result</name>
+ <name since="OTP 20.0">start(EventMgrName, Options) -> Result</name>
<fsummary>Create a stand-alone event manager process.</fsummary>
<type>
<v>EventMgrName = {local,Name} | {global,GlobalName} | {via,Module,ViaName}</v>
@@ -375,9 +375,9 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>start_link() -> Result</name>
- <name>start_link(EventMgrName | Options) -> Result</name>
- <name>start_link(EventMgrName, Options) -> Result</name>
+ <name since="">start_link() -> Result</name>
+ <name since="">start_link(EventMgrName | Options) -> Result</name>
+ <name since="OTP 20.0">start_link(EventMgrName, Options) -> Result</name>
<fsummary>Create a generic event manager process in a supervision tree.
</fsummary>
<type>
@@ -436,8 +436,8 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>stop(EventMgrRef) -> ok</name>
- <name>stop(EventMgrRef, Reason, Timeout) -> ok</name>
+ <name since="">stop(EventMgrRef) -> ok</name>
+ <name since="OTP 18.0">stop(EventMgrRef, Reason, Timeout) -> ok</name>
<fsummary>Terminate a generic event manager.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
@@ -474,7 +474,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>swap_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result</name>
+ <name since="">swap_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result</name>
<fsummary>Replace an event handler in a generic event manager.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
@@ -521,7 +521,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>swap_sup_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result</name>
+ <name since="">swap_sup_handler(EventMgrRef, {Handler1,Args1}, {Handler2,Args2}) -> Result</name>
<fsummary>Replace an event handler in a generic event manager.</fsummary>
<type>
<v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}
@@ -546,7 +546,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>which_handlers(EventMgrRef) -> [Handler]</name>
+ <name since="">which_handlers(EventMgrRef) -> [Handler]</name>
<fsummary>Return all event handlers installed in a generic event manager.
</fsummary>
<type>
@@ -575,7 +575,7 @@ gen_event:stop -----> Module:terminate/2
<funcs>
<func>
- <name>Module:code_change(OldVsn, State, Extra) -> {ok, NewState}</name>
+ <name since="">Module:code_change(OldVsn, State, Extra) -> {ok, NewState}</name>
<fsummary>Update the internal state during upgrade/downgrade.</fsummary>
<type>
<v>OldVsn = Vsn | {down, Vsn}</v>
@@ -611,7 +611,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>Module:format_status(Opt, [PDict, State]) -> Status</name>
+ <name since="OTP R14B">Module:format_status(Opt, [PDict, State]) -> Status</name>
<fsummary>Optional function for providing a term describing the
current event handler state.</fsummary>
<type>
@@ -667,7 +667,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>Module:handle_call(Request, State) -> Result</name>
+ <name since="">Module:handle_call(Request, State) -> Result</name>
<fsummary>Handle a synchronous request.</fsummary>
<type>
<v>Request = term()</v>
@@ -698,7 +698,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>Module:handle_event(Event, State) -> Result</name>
+ <name since="">Module:handle_event(Event, State) -> Result</name>
<fsummary>Handle an event.</fsummary>
<type>
<v>Event = term()</v>
@@ -756,7 +756,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>Module:handle_info(Info, State) -> Result</name>
+ <name since="">Module:handle_info(Info, State) -> Result</name>
<fsummary>Handle an incoming message.</fsummary>
<type>
<v>Info = term()</v>
@@ -775,7 +775,7 @@ gen_event:stop -----> Module:terminate/2
<p>This callback is optional, so callback modules need not
export it. The <c>gen_event</c> module provides a default
implementation of this function that logs about the unexpected
- <c>Info</c> message, drops it and returns <c>{noreply, State}</c>.</p>
+ <c>Info</c> message, drops it and returns <c>{ok, State}</c>.</p>
</note>
<p>This function is called for each installed event handler when
an event manager receives any other message than an event or
@@ -788,7 +788,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>Module:init(InitArgs) -> {ok,State} | {ok,State,hibernate} | {error,Reason}</name>
+ <name since="">Module:init(InitArgs) -> {ok,State} | {ok,State,hibernate} | {error,Reason}</name>
<fsummary>Initialize an event handler.</fsummary>
<type>
<v>InitArgs = Args | {Args,Term}</v>
@@ -825,7 +825,7 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name>Module:terminate(Arg, State) -> term()</name>
+ <name since="">Module:terminate(Arg, State) -> term()</name>
<fsummary>Clean up before deletion.</fsummary>
<type>
<v>Arg = Args | {stop,Reason} | stop | remove_handler</v>
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml
index 106bda85f5..a4554d7657 100644
--- a/lib/stdlib/doc/src/gen_server.xml
+++ b/lib/stdlib/doc/src/gen_server.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>gen_server</module>
+ <module since="">gen_server</module>
<modulesummary>Generic server behavior.</modulesummary>
<description>
<p>This behavior module provides the server of a client-server
@@ -101,8 +101,8 @@ gen_server:abcast -----> Module:handle_cast/2
<funcs>
<func>
- <name>abcast(Name, Request) -> abcast</name>
- <name>abcast(Nodes, Name, Request) -> abcast</name>
+ <name since="">abcast(Name, Request) -> abcast</name>
+ <name since="">abcast(Nodes, Name, Request) -> abcast</name>
<fsummary>Send an asynchronous request to many generic servers.</fsummary>
<type>
<v>Nodes = [Node]</v>
@@ -124,8 +124,8 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>call(ServerRef, Request) -> Reply</name>
- <name>call(ServerRef, Request, Timeout) -> Reply</name>
+ <name since="">call(ServerRef, Request) -> Reply</name>
+ <name since="">call(ServerRef, Request, Timeout) -> Reply</name>
<fsummary>Make a synchronous call to a generic server.</fsummary>
<type>
<v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
@@ -175,7 +175,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>cast(ServerRef, Request) -> ok</name>
+ <name since="">cast(ServerRef, Request) -> ok</name>
<fsummary>Send an asynchronous request to a generic server.</fsummary>
<type>
<v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
@@ -200,10 +200,10 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>enter_loop(Module, Options, State)</name>
- <name>enter_loop(Module, Options, State, ServerName)</name>
- <name>enter_loop(Module, Options, State, Timeout)</name>
- <name>enter_loop(Module, Options, State, ServerName, Timeout)</name>
+ <name since="">enter_loop(Module, Options, State)</name>
+ <name since="">enter_loop(Module, Options, State, ServerName)</name>
+ <name since="">enter_loop(Module, Options, State, Timeout)</name>
+ <name since="">enter_loop(Module, Options, State, ServerName, Timeout)</name>
<fsummary>Enter the <c>gen_server</c> receive loop.</fsummary>
<type>
<v>Module = atom()</v>
@@ -248,9 +248,9 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>multi_call(Name, Request) -> Result</name>
- <name>multi_call(Nodes, Name, Request) -> Result</name>
- <name>multi_call(Nodes, Name, Request, Timeout) -> Result</name>
+ <name since="">multi_call(Name, Request) -> Result</name>
+ <name since="">multi_call(Nodes, Name, Request) -> Result</name>
+ <name since="">multi_call(Nodes, Name, Request, Timeout) -> Result</name>
<fsummary>Make a synchronous call to many generic servers.</fsummary>
<type>
<v>Nodes = [Node]</v>
@@ -307,7 +307,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>reply(Client, Reply) -> Result</name>
+ <name since="">reply(Client, Reply) -> Result</name>
<fsummary>Send a reply to a client.</fsummary>
<type>
<v>Client - see below</v>
@@ -332,8 +332,8 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>start(Module, Args, Options) -> Result</name>
- <name>start(ServerName, Module, Args, Options) -> Result</name>
+ <name since="">start(Module, Args, Options) -> Result</name>
+ <name since="">start(ServerName, Module, Args, Options) -> Result</name>
<fsummary>Create a standalone <c>gen_server</c> process.</fsummary>
<type>
<v>ServerName = {local,Name} | {global,GlobalName}</v>
@@ -361,8 +361,8 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>start_link(Module, Args, Options) -> Result</name>
- <name>start_link(ServerName, Module, Args, Options) -> Result</name>
+ <name since="">start_link(Module, Args, Options) -> Result</name>
+ <name since="">start_link(ServerName, Module, Args, Options) -> Result</name>
<fsummary>Create a <c>gen_server</c> process in a supervision tree.
</fsummary>
<type>
@@ -466,8 +466,8 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>stop(ServerRef) -> ok</name>
- <name>stop(ServerRef, Reason, Timeout) -> ok</name>
+ <name since="OTP 18.0">stop(ServerRef) -> ok</name>
+ <name since="OTP 18.0">stop(ServerRef, Reason, Timeout) -> ok</name>
<fsummary>Synchronously stop a generic server.</fsummary>
<type>
<v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
@@ -508,7 +508,7 @@ gen_server:abcast -----> Module:handle_cast/2
<funcs>
<func>
- <name>Module:code_change(OldVsn, State, Extra) -> {ok, NewState} | {error, Reason}</name>
+ <name since="">Module:code_change(OldVsn, State, Extra) -> {ok, NewState} | {error, Reason}</name>
<fsummary>Update the internal state during upgrade/downgrade.</fsummary>
<type>
<v>OldVsn = Vsn | {down, Vsn}</v>
@@ -550,7 +550,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>Module:format_status(Opt, [PDict, State]) -> Status</name>
+ <name since="OTP R13B04">Module:format_status(Opt, [PDict, State]) -> Status</name>
<fsummary>Optional function for providing a term describing the
current <c>gen_server</c> status.</fsummary>
<type>
@@ -610,7 +610,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>Module:handle_call(Request, From, State) -> Result</name>
+ <name since="">Module:handle_call(Request, From, State) -> Result</name>
<fsummary>Handle a synchronous request.</fsummary>
<type>
<v>Request = term()</v>
@@ -677,7 +677,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>Module:handle_cast(Request, State) -> Result</name>
+ <name since="">Module:handle_cast(Request, State) -> Result</name>
<fsummary>Handle an asynchronous request.</fsummary>
<type>
<v>Request = term()</v>
@@ -703,7 +703,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>Module:handle_continue(Continue, State) -> Result</name>
+ <name since="OTP 21.0">Module:handle_continue(Continue, State) -> Result</name>
<fsummary>Handle a continue instruction.</fsummary>
<type>
<v>Continue = term()</v>
@@ -738,7 +738,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>Module:handle_info(Info, State) -> Result</name>
+ <name since="">Module:handle_info(Info, State) -> Result</name>
<fsummary>Handle an incoming message.</fsummary>
<type>
<v>Info = timeout | term()</v>
@@ -770,7 +770,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>Module:init(Args) -> Result</name>
+ <name since="">Module:init(Args) -> Result</name>
<fsummary>Initialize process and internal state.</fsummary>
<type>
<v>Args = term()</v>
@@ -811,7 +811,7 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
- <name>Module:terminate(Reason, State)</name>
+ <name since="">Module:terminate(Reason, State)</name>
<fsummary>Clean up before termination.</fsummary>
<type>
<v>Reason = normal | shutdown | {shutdown,term()} | term()</v>
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index a808d3af55..aaa26df18d 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>gen_statem</module>
+ <module since="OTP 19.0">gen_statem</module>
<modulesummary>Generic state machine behavior.</modulesummary>
<description>
<p>
@@ -1398,8 +1398,8 @@ handle_event(_, _, State, Data) ->
<funcs>
<func>
- <name name="call" arity="2"/>
- <name name="call" arity="3"/>
+ <name name="call" arity="2" since="OTP 19.0"/>
+ <name name="call" arity="3" since="OTP 19.0"/>
<fsummary>Make a synchronous call to a <c>gen_statem</c>.</fsummary>
<desc>
<p>
@@ -1474,7 +1474,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="cast" arity="2"/>
+ <name name="cast" arity="2" since="OTP 19.0"/>
<fsummary>Send an asynchronous event to a <c>gen_statem</c>.</fsummary>
<desc>
<p>
@@ -1493,7 +1493,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="enter_loop" arity="4"/>
+ <name name="enter_loop" arity="4" since="OTP 19.1"/>
<fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
<p>
@@ -1507,7 +1507,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="enter_loop" arity="5"/>
+ <name name="enter_loop" arity="5" since="OTP 19.0"/>
<fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
<p>
@@ -1531,7 +1531,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="enter_loop" arity="6"/>
+ <name name="enter_loop" arity="6" since="OTP 19.0"/>
<fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
<p>
@@ -1588,8 +1588,8 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="reply" arity="1"/>
- <name name="reply" arity="2"/>
+ <name name="reply" arity="1" since="OTP 19.0"/>
+ <name name="reply" arity="2" since="OTP 19.0"/>
<fsummary>Reply to a caller.</fsummary>
<desc>
<p>
@@ -1621,8 +1621,8 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="start" arity="3"/>
- <name name="start" arity="4"/>
+ <name name="start" arity="3" since="OTP 19.0"/>
+ <name name="start" arity="4" since="OTP 19.0"/>
<fsummary>Create a standalone <c>gen_statem</c> process.</fsummary>
<desc>
<p>
@@ -1642,8 +1642,8 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="start_link" arity="3"/>
- <name name="start_link" arity="4"/>
+ <name name="start_link" arity="3" since="OTP 19.0"/>
+ <name name="start_link" arity="4" since="OTP 19.0"/>
<fsummary>Create a linked <c>gen_statem</c> process.</fsummary>
<desc>
<p>
@@ -1750,7 +1750,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="stop" arity="1"/>
+ <name name="stop" arity="1" since="OTP 19.0"/>
<fsummary>Synchronously stop a generic server.</fsummary>
<desc>
<p>
@@ -1761,7 +1761,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="stop" arity="3"/>
+ <name name="stop" arity="3" since="OTP 19.0"/>
<fsummary>Synchronously stop a generic server.</fsummary>
<desc>
<p>
@@ -1807,7 +1807,7 @@ handle_event(_, _, State, Data) ->
<funcs>
<func>
- <name>Module:callback_mode() -> CallbackMode</name>
+ <name since="OTP 19.1">Module:callback_mode() -> CallbackMode</name>
<fsummary>Update the internal state during upgrade/downgrade.</fsummary>
<type>
<v>
@@ -1858,7 +1858,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name>Module:code_change(OldVsn, OldState, OldData, Extra) ->
+ <name since="OTP 19.0">Module:code_change(OldVsn, OldState, OldData, Extra) ->
Result
</name>
<fsummary>Update the internal state during upgrade/downgrade.</fsummary>
@@ -1947,7 +1947,7 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name>Module:init(Args) -> Result(StateType)</name>
+ <name since="OTP 19.0">Module:init(Args) -> Result(StateType)</name>
<fsummary>
Initializing process and internal state.
</fsummary>
@@ -1989,7 +1989,7 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
</func>
<func>
- <name>Module:format_status(Opt, [PDict,State,Data]) ->
+ <name since="OTP 19.0">Module:format_status(Opt, [PDict,State,Data]) ->
Status
</name>
<fsummary>Optional function for providing a term describing the
@@ -2088,16 +2088,16 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
</func>
<func>
- <name>Module:StateName(enter, OldState, Data) ->
+ <name since="OTP 19.0">Module:StateName(enter, OldState, Data) ->
StateEnterResult(StateName)
</name>
- <name>Module:StateName(EventType, EventContent, Data) ->
+ <name since="OTP 19.0">Module:StateName(EventType, EventContent, Data) ->
StateFunctionResult
</name>
- <name>Module:handle_event(enter, OldState, State, Data) ->
+ <name since="OTP 19.0">Module:handle_event(enter, OldState, State, Data) ->
StateEnterResult(State)
</name>
- <name>Module:handle_event(EventType, EventContent, State, Data) ->
+ <name since="OTP 19.0">Module:handle_event(EventType, EventContent, State, Data) ->
HandleEventResult
</name>
<fsummary>Handle an event.</fsummary>
@@ -2216,7 +2216,7 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
</func>
<func>
- <name>Module:terminate(Reason, State, Data) -> Ignored</name>
+ <name since="OTP 19.0">Module:terminate(Reason, State, Data) -> Ignored</name>
<fsummary>Clean up before termination.</fsummary>
<type>
<v>Reason = normal | shutdown | {shutdown,term()} | term()</v>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index d4a2713840..d69e808586 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>io</module>
+ <module since="">io</module>
<modulesummary>Standard I/O server interface functions.</modulesummary>
<description>
<p>This module provides an interface to standard Erlang I/O servers.
@@ -104,8 +104,8 @@
<funcs>
<func>
- <name name="columns" arity="0"/>
- <name name="columns" arity="1"/>
+ <name name="columns" arity="0" since=""/>
+ <name name="columns" arity="1" since=""/>
<fsummary>Get the number of columns of an I/O device.</fsummary>
<desc>
<p>Retrieves the number of columns of the
@@ -116,12 +116,12 @@
</func>
<func>
- <name name="format" arity="1"/>
- <name name="format" arity="2"/>
- <name name="format" arity="3"/>
- <name name="fwrite" arity="1"/>
- <name name="fwrite" arity="2"/>
- <name name="fwrite" arity="3"/>
+ <name name="format" arity="1" since=""/>
+ <name name="format" arity="2" since=""/>
+ <name name="format" arity="3" since=""/>
+ <name name="fwrite" arity="1" since=""/>
+ <name name="fwrite" arity="2" since=""/>
+ <name name="fwrite" arity="3" since=""/>
<fsummary>Write formatted output.</fsummary>
<desc>
<p>Writes the items in <c><anno>Data</anno></c> (<c>[]</c>) on the
@@ -523,8 +523,8 @@ ok
</func>
<func>
- <name name="fread" arity="2"/>
- <name name="fread" arity="3"/>
+ <name name="fread" arity="2" since=""/>
+ <name name="fread" arity="3" since=""/>
<fsummary>Read formatted input.</fsummary>
<type name="server_no_data"/>
<desc>
@@ -690,8 +690,8 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
</func>
<func>
- <name name="get_chars" arity="2"/>
- <name name="get_chars" arity="3"/>
+ <name name="get_chars" arity="2" since=""/>
+ <name name="get_chars" arity="3" since=""/>
<fsummary>Read a specified number of characters.</fsummary>
<type name="server_no_data"/>
<desc>
@@ -722,8 +722,8 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
</func>
<func>
- <name name="get_line" arity="1"/>
- <name name="get_line" arity="2"/>
+ <name name="get_line" arity="1" since=""/>
+ <name name="get_line" arity="2" since=""/>
<fsummary>Read a line.</fsummary>
<type name="server_no_data"/>
<desc>
@@ -754,8 +754,8 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
</func>
<func>
- <name name="getopts" arity="0"/>
- <name name="getopts" arity="1"/>
+ <name name="getopts" arity="0" since=""/>
+ <name name="getopts" arity="1" since=""/>
<fsummary>Get the supported options and values from an I/O server.
</fsummary>
<desc>
@@ -781,8 +781,8 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
</func>
<func>
- <name name="nl" arity="0"/>
- <name name="nl" arity="1"/>
+ <name name="nl" arity="0" since=""/>
+ <name name="nl" arity="1" since=""/>
<fsummary>Write a newline.</fsummary>
<desc>
<p>Writes new line to the standard output
@@ -791,10 +791,10 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
</func>
<func>
- <name name="parse_erl_exprs" arity="1"/>
- <name name="parse_erl_exprs" arity="2"/>
- <name name="parse_erl_exprs" arity="3"/>
- <name name="parse_erl_exprs" arity="4"/>
+ <name name="parse_erl_exprs" arity="1" since=""/>
+ <name name="parse_erl_exprs" arity="2" since=""/>
+ <name name="parse_erl_exprs" arity="3" since=""/>
+ <name name="parse_erl_exprs" arity="4" since="OTP R16B"/>
<fsummary>Read, tokenize, and parse Erlang expressions.</fsummary>
<type name="parse_ret"/>
<type name="server_no_data"/>
@@ -844,10 +844,10 @@ enter><input>abc("hey".</input>
</func>
<func>
- <name name="parse_erl_form" arity="1"/>
- <name name="parse_erl_form" arity="2"/>
- <name name="parse_erl_form" arity="3"/>
- <name name="parse_erl_form" arity="4"/>
+ <name name="parse_erl_form" arity="1" since=""/>
+ <name name="parse_erl_form" arity="2" since=""/>
+ <name name="parse_erl_form" arity="3" since=""/>
+ <name name="parse_erl_form" arity="4" since="OTP R16B"/>
<fsummary>Read, tokenize, and parse an Erlang form.</fsummary>
<type name="parse_form_ret"/>
<type name="server_no_data"/>
@@ -888,7 +888,7 @@ enter><input>abc("hey".</input>
</func>
<func>
- <name name="printable_range" arity="0"/>
+ <name name="printable_range" arity="0" since="OTP R16B"/>
<fsummary>Get user-requested printable character range.</fsummary>
<desc>
<p>Returns the user-requested range of printable Unicode characters.</p>
@@ -918,8 +918,8 @@ enter><input>abc("hey".</input>
</func>
<func>
- <name name="put_chars" arity="1"/>
- <name name="put_chars" arity="2"/>
+ <name name="put_chars" arity="1" since=""/>
+ <name name="put_chars" arity="2" since=""/>
<fsummary>Write a list of characters.</fsummary>
<desc>
<p>Writes the characters of <c><anno>CharData</anno></c> to the I/O
@@ -928,8 +928,8 @@ enter><input>abc("hey".</input>
</func>
<func>
- <name name="read" arity="1"/>
- <name name="read" arity="2"/>
+ <name name="read" arity="1" since=""/>
+ <name name="read" arity="2" since=""/>
<fsummary>Read a term.</fsummary>
<type name="server_no_data"/>
<desc>
@@ -960,8 +960,8 @@ enter><input>abc("hey".</input>
</func>
<func>
- <name name="read" arity="3"/>
- <name name="read" arity="4"/>
+ <name name="read" arity="3" since=""/>
+ <name name="read" arity="4" since="OTP R16B"/>
<fsummary>Read a term.</fsummary>
<type name="server_no_data"/>
<desc>
@@ -997,8 +997,8 @@ enter><input>abc("hey".</input>
</func>
<func>
- <name name="rows" arity="0"/>
- <name name="rows" arity="1"/>
+ <name name="rows" arity="0" since=""/>
+ <name name="rows" arity="1" since=""/>
<fsummary>Get the number of rows of an I/O device.</fsummary>
<desc>
<p>Retrieves the number of rows of <c><anno>IoDevice</anno></c>
@@ -1009,10 +1009,10 @@ enter><input>abc("hey".</input>
</func>
<func>
- <name name="scan_erl_exprs" arity="1"/>
- <name name="scan_erl_exprs" arity="2"/>
- <name name="scan_erl_exprs" arity="3"/>
- <name name="scan_erl_exprs" arity="4"/>
+ <name name="scan_erl_exprs" arity="1" since=""/>
+ <name name="scan_erl_exprs" arity="2" since=""/>
+ <name name="scan_erl_exprs" arity="3" since=""/>
+ <name name="scan_erl_exprs" arity="4" since="OTP R16B"/>
<fsummary>Read and tokenize Erlang expressions.</fsummary>
<type name="server_no_data"/>
<desc>
@@ -1060,10 +1060,10 @@ enter><input>1.0er.</input>
</func>
<func>
- <name name="scan_erl_form" arity="1"/>
- <name name="scan_erl_form" arity="2"/>
- <name name="scan_erl_form" arity="3"/>
- <name name="scan_erl_form" arity="4"/>
+ <name name="scan_erl_form" arity="1" since=""/>
+ <name name="scan_erl_form" arity="2" since=""/>
+ <name name="scan_erl_form" arity="3" since=""/>
+ <name name="scan_erl_form" arity="4" since="OTP R16B"/>
<fsummary>Read and tokenize an Erlang form.</fsummary>
<type name="server_no_data"/>
<desc>
@@ -1083,8 +1083,8 @@ enter><input>1.0er.</input>
</func>
<func>
- <name name="setopts" arity="1"/>
- <name name="setopts" arity="2"/>
+ <name name="setopts" arity="1" since=""/>
+ <name name="setopts" arity="2" since=""/>
<fsummary>Set options.</fsummary>
<desc>
<p>Set options for the standard I/O device
@@ -1198,8 +1198,8 @@ fun("") -> {yes, "quit", []};
</func>
<func>
- <name name="write" arity="1"/>
- <name name="write" arity="2"/>
+ <name name="write" arity="1" since=""/>
+ <name name="write" arity="2" since=""/>
<fsummary>Write a term.</fsummary>
<desc>
<p>Writes term <c><anno>Term</anno></c> to the standard output
diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml
index a3df2897ac..4d527f8ed3 100644
--- a/lib/stdlib/doc/src/io_lib.xml
+++ b/lib/stdlib/doc/src/io_lib.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>io_lib</module>
+ <module since="">io_lib</module>
<modulesummary>I/O library functions.</modulesummary>
<description>
<p>This module contains functions for converting to and from
@@ -99,7 +99,7 @@
<funcs>
<func>
- <name name="build_text" arity="1"/>
+ <name name="build_text" arity="1" since="OTP 18.0"/>
<fsummary>Build the output text for a preparsed format list.</fsummary>
<desc>
<p>For details, see
@@ -108,7 +108,7 @@
</func>
<func>
- <name name="char_list" arity="1"/>
+ <name name="char_list" arity="1" since=""/>
<fsummary>Test for a list of characters.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
@@ -117,7 +117,7 @@
</func>
<func>
- <name name="deep_char_list" arity="1"/>
+ <name name="deep_char_list" arity="1" since=""/>
<fsummary>Test for a deep list of characters.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a, possibly deep,
@@ -126,7 +126,7 @@
</func>
<func>
- <name name="deep_latin1_char_list" arity="1"/>
+ <name name="deep_latin1_char_list" arity="1" since="OTP R16B"/>
<fsummary>Test for a deep list of characters.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a, possibly deep,
@@ -136,8 +136,8 @@
</func>
<func>
- <name name="format" arity="2"/>
- <name name="fwrite" arity="2"/>
+ <name name="format" arity="2" since=""/>
+ <name name="fwrite" arity="2" since=""/>
<fsummary>Write formatted output.</fsummary>
<desc>
<p>Returns a character list that represents <c><anno>Data</anno></c>
@@ -156,8 +156,8 @@
</func>
<func>
- <name name="format" arity="3"/>
- <name name="fwrite" arity="3"/>
+ <name name="format" arity="3" since="OTP 21.0"/>
+ <name name="fwrite" arity="3" since="OTP 21.0"/>
<fsummary>Write formatted output.</fsummary>
<desc>
<p>Returns a character list that represents <c><anno>Data</anno></c>
@@ -181,7 +181,7 @@
</func>
<func>
- <name name="fread" arity="2"/>
+ <name name="fread" arity="2" since=""/>
<fsummary>Read formatted input.</fsummary>
<desc>
<p>Tries to read <c><anno>String</anno></c> in accordance with the
@@ -222,7 +222,7 @@
</func>
<func>
- <name name="fread" arity="3"/>
+ <name name="fread" arity="3" since=""/>
<fsummary>Re-entrant formatted reader</fsummary>
<desc>
<p>This is the re-entrant formatted reader. The continuation of
@@ -268,7 +268,7 @@
</func>
<func>
- <name name="indentation" arity="2"/>
+ <name name="indentation" arity="2" since=""/>
<fsummary>Indentation after printing string.</fsummary>
<desc>
<p>Returns the indentation if <c><anno>String</anno></c> has been
@@ -277,7 +277,7 @@
</func>
<func>
- <name name="latin1_char_list" arity="1"/>
+ <name name="latin1_char_list" arity="1" since="OTP R16B"/>
<fsummary>Test for a list of ISO Latin-1 characters.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
@@ -286,7 +286,7 @@
</func>
<func>
- <name name="nl" arity="0"/>
+ <name name="nl" arity="0" since=""/>
<fsummary>Write a newline.</fsummary>
<desc>
<p>Returns a character list that represents a new line character.</p>
@@ -294,8 +294,8 @@
</func>
<func>
- <name name="print" arity="1"/>
- <name name="print" arity="4"/>
+ <name name="print" arity="1" since=""/>
+ <name name="print" arity="4" since=""/>
<fsummary>Pretty print a term.</fsummary>
<desc>
<p>Returns a list of characters that represents
@@ -315,7 +315,7 @@
</func>
<func>
- <name name="printable_latin1_list" arity="1"/>
+ <name name="printable_latin1_list" arity="1" since="OTP R16B"/>
<fsummary>Test for a list of printable ISO Latin-1 characters.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
@@ -324,7 +324,7 @@
</func>
<func>
- <name name="printable_list" arity="1"/>
+ <name name="printable_list" arity="1" since=""/>
<fsummary>Test for a list of printable characters.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
@@ -338,7 +338,7 @@
</func>
<func>
- <name name="printable_unicode_list" arity="1"/>
+ <name name="printable_unicode_list" arity="1" since="OTP R16B"/>
<fsummary>Test for a list of printable Unicode characters.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
@@ -347,7 +347,7 @@
</func>
<func>
- <name name="scan_format" arity="2"/>
+ <name name="scan_format" arity="2" since="OTP 18.0"/>
<fsummary>Parse all control sequences in the format string.</fsummary>
<desc>
<p>Returns a list corresponding to the specified format string,
@@ -373,7 +373,7 @@
</func>
<func>
- <name name="unscan_format" arity="1"/>
+ <name name="unscan_format" arity="1" since="OTP 18.0"/>
<fsummary>Revert a preparsed format list to a plain character list
and a list of arguments.</fsummary>
<desc>
@@ -383,9 +383,9 @@
</func>
<func>
- <name name="write" arity="1"/>
- <name name="write" arity="2" clause_i="1"/>
- <name name="write" arity="2" clause_i="2"/>
+ <name name="write" arity="1" since=""/>
+ <name name="write" arity="2" clause_i="1" since=""/>
+ <name name="write" arity="2" clause_i="2" since="OTP 20.0"/>
<fsummary>Write a term.</fsummary>
<desc>
<p>Returns a character list that represents <c><anno>Term</anno></c>.
@@ -411,7 +411,7 @@
</func>
<func>
- <name name="write_atom" arity="1"/>
+ <name name="write_atom" arity="1" since=""/>
<fsummary>Write an atom.</fsummary>
<desc>
<p>Returns the list of characters needed to print atom
@@ -420,7 +420,7 @@
</func>
<func>
- <name name="write_atom_as_latin1" arity="1"/>
+ <name name="write_atom_as_latin1" arity="1" since="OTP 20.0"/>
<fsummary>Write an atom.</fsummary>
<desc>
<p>Returns the list of characters needed to print atom
@@ -430,7 +430,7 @@
</func>
<func>
- <name name="write_char" arity="1"/>
+ <name name="write_char" arity="1" since=""/>
<fsummary>Write a character.</fsummary>
<desc>
<p>Returns the list of characters needed to print a character
@@ -439,7 +439,7 @@
</func>
<func>
- <name name="write_char_as_latin1" arity="1"/>
+ <name name="write_char_as_latin1" arity="1" since="OTP R16B"/>
<fsummary>Write a character.</fsummary>
<desc>
<p>Returns the list of characters needed to print a character
@@ -449,7 +449,7 @@
</func>
<func>
- <name name="write_latin1_char" arity="1"/>
+ <name name="write_latin1_char" arity="1" since="OTP R16B"/>
<fsummary>Write an ISO Latin-1 character.</fsummary>
<desc>
<p>Returns the list of characters needed to print a character
@@ -458,7 +458,7 @@
</func>
<func>
- <name name="write_latin1_string" arity="1"/>
+ <name name="write_latin1_string" arity="1" since="OTP R16B"/>
<fsummary>Write an ISO Latin-1 string.</fsummary>
<desc>
<p>Returns the list of characters needed to print
@@ -467,7 +467,7 @@
</func>
<func>
- <name name="write_string" arity="1"/>
+ <name name="write_string" arity="1" since=""/>
<fsummary>Write a string.</fsummary>
<desc>
<p>Returns the list of characters needed to print
@@ -476,7 +476,7 @@
</func>
<func>
- <name name="write_string_as_latin1" arity="1"/>
+ <name name="write_string_as_latin1" arity="1" since="OTP R16B"/>
<fsummary>Write a string.</fsummary>
<desc>
<p>Returns the list of characters needed to print
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index c3d5d7e07a..2755fb3dce 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2018</year>
+ <year>1996</year><year>2019</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -28,7 +28,7 @@
<date>1996-09-28</date>
<rev>A</rev>
</header>
- <module>lists</module>
+ <module since="">lists</module>
<modulesummary>List processing functions.</modulesummary>
<description>
<p>This module contains functions for list processing.</p>
@@ -63,7 +63,7 @@
<funcs>
<func>
- <name name="all" arity="2"/>
+ <name name="all" arity="2" since=""/>
<fsummary>Return <c>true</c> if all elements in a list satisfy
<c>Pred</c>.</fsummary>
<desc>
@@ -74,7 +74,7 @@
</func>
<func>
- <name name="any" arity="2"/>
+ <name name="any" arity="2" since=""/>
<fsummary>Return <c>true</c> if any of the elements in a list
satisfies <c>Pred</c>.</fsummary>
<desc>
@@ -85,7 +85,7 @@
</func>
<func>
- <name name="append" arity="1"/>
+ <name name="append" arity="1" since=""/>
<fsummary>Append a list of lists.</fsummary>
<desc>
<p>Returns a list in which all the sublists of
@@ -98,7 +98,7 @@
</func>
<func>
- <name name="append" arity="2"/>
+ <name name="append" arity="2" since=""/>
<fsummary>Append two lists.</fsummary>
<desc>
<p>Returns a new list <c><anno>List3</anno></c>, which is made from
@@ -113,7 +113,7 @@
</func>
<func>
- <name name="concat" arity="1"/>
+ <name name="concat" arity="1" since=""/>
<fsummary>Concatenate a list of atoms.</fsummary>
<desc>
<p>Concatenates the text representation of the elements of
@@ -127,7 +127,7 @@
</func>
<func>
- <name name="delete" arity="2"/>
+ <name name="delete" arity="2" since=""/>
<fsummary>Delete an element from a list.</fsummary>
<desc>
<p>Returns a copy of <c><anno>List1</anno></c> where the first element
@@ -137,7 +137,7 @@
</func>
<func>
- <name name="droplast" arity="1"/>
+ <name name="droplast" arity="1" since="OTP 17.0"/>
<fsummary>Drop the last element of a list.</fsummary>
<desc>
<p>Drops the last element of a <c><anno>List</anno></c>. The list is to
@@ -147,7 +147,7 @@
</func>
<func>
- <name name="dropwhile" arity="2"/>
+ <name name="dropwhile" arity="2" since=""/>
<fsummary>Drop elements from a list while a predicate is <c>true</c>.
</fsummary>
<desc>
@@ -159,7 +159,7 @@
</func>
<func>
- <name name="duplicate" arity="2"/>
+ <name name="duplicate" arity="2" since=""/>
<fsummary>Make <c>N</c> copies of element.</fsummary>
<desc>
<p>Returns a list containing <c><anno>N</anno></c> copies of term
@@ -172,7 +172,7 @@
</func>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since=""/>
<fsummary>Select elements that satisfy a predicate.</fsummary>
<desc>
<p><c><anno>List2</anno></c> is a list of all elements
@@ -182,7 +182,7 @@
</func>
<func>
- <name name="filtermap" arity="2"/>
+ <name name="filtermap" arity="2" since="OTP R16B01"/>
<fsummary>Filter and map elements that satisfy a function.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>)</c> on successive
@@ -211,7 +211,7 @@ filtermap(Fun, List1) ->
</func>
<func>
- <name name="flatlength" arity="1"/>
+ <name name="flatlength" arity="1" since=""/>
<fsummary>Length of flattened deep list.</fsummary>
<desc>
<p>Equivalent to <c>length(flatten(<anno>DeepList</anno>))</c>, but
@@ -220,7 +220,7 @@ filtermap(Fun, List1) ->
</func>
<func>
- <name name="flatmap" arity="2"/>
+ <name name="flatmap" arity="2" since=""/>
<fsummary>Map and flatten in one pass.</fsummary>
<desc>
<p>Takes a function from <c><anno>A</anno></c>s to lists of
@@ -241,7 +241,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="flatten" arity="1"/>
+ <name name="flatten" arity="1" since=""/>
<fsummary>Flatten a deep list.</fsummary>
<desc>
<p>Returns a flattened version of <c><anno>DeepList</anno></c>.</p>
@@ -249,7 +249,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="flatten" arity="2"/>
+ <name name="flatten" arity="2" since=""/>
<fsummary>Flatten a deep list.</fsummary>
<desc>
<p>Returns a flattened version of <c><anno>DeepList</anno></c> with tail
@@ -258,7 +258,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="foldl" arity="3"/>
+ <name name="foldl" arity="3" since=""/>
<fsummary>Fold a function over a list.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>, <anno>AccIn</anno>)</c>
@@ -278,7 +278,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="foldr" arity="3"/>
+ <name name="foldr" arity="3" since=""/>
<fsummary>Fold a function over a list.</fsummary>
<desc>
<p>Like <seealso marker="#foldl/3"><c>foldl/3</c></seealso>, but the
@@ -297,7 +297,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="join" arity="2"/>
+ <name name="join" arity="2" since="OTP 19.0"/>
<fsummary>Insert an element between elements in a list</fsummary>
<desc>
<p>Inserts <c><anno>Sep</anno></c> between each element in <c><anno>List1</anno></c>. Has no
@@ -312,7 +312,7 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name name="foreach" arity="2"/>
+ <name name="foreach" arity="2" since=""/>
<fsummary>Apply a function to each element of a list.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>)</c> for each element
@@ -324,7 +324,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keydelete" arity="3"/>
+ <name name="keydelete" arity="3" since=""/>
<fsummary>Delete an element from a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -336,7 +336,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keyfind" arity="3"/>
+ <name name="keyfind" arity="3" since=""/>
<fsummary>Search for an element in a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -349,7 +349,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keymap" arity="3"/>
+ <name name="keymap" arity="3" since=""/>
<fsummary>Map a function over a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -368,7 +368,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keymember" arity="3"/>
+ <name name="keymember" arity="3" since=""/>
<fsummary>Test for membership of a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -379,7 +379,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keymerge" arity="3"/>
+ <name name="keymerge" arity="3" since=""/>
<fsummary>Merge two key-sorted lists of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -395,7 +395,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keyreplace" arity="4"/>
+ <name name="keyreplace" arity="4" since=""/>
<fsummary>Replace an element in a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -407,7 +407,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keysearch" arity="3"/>
+ <name name="keysearch" arity="3" since=""/>
<fsummary>Search for an element in a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -425,7 +425,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keysort" arity="2"/>
+ <name name="keysort" arity="2" since=""/>
<fsummary>Sort a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -436,7 +436,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keystore" arity="4"/>
+ <name name="keystore" arity="4" since=""/>
<fsummary>Store an element in a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -452,7 +452,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="keytake" arity="3"/>
+ <name name="keytake" arity="3" since=""/>
<fsummary>Extract an element from a list of tuples.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -467,7 +467,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="last" arity="1"/>
+ <name name="last" arity="1" since=""/>
<fsummary>Return last element in a list.</fsummary>
<desc>
<p>Returns the last element in <c><anno>List</anno></c>.</p>
@@ -475,7 +475,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="map" arity="2"/>
+ <name name="map" arity="2" since=""/>
<fsummary>Map a function over a list.</fsummary>
<desc>
<p>Takes a function from <c><anno>A</anno></c>s to
@@ -488,7 +488,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="mapfoldl" arity="3"/>
+ <name name="mapfoldl" arity="3" since=""/>
<fsummary>Map and fold in one pass.</fsummary>
<desc>
<p>Combines the operations of
@@ -504,7 +504,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="mapfoldr" arity="3"/>
+ <name name="mapfoldr" arity="3" since=""/>
<fsummary>Map and fold in one pass.</fsummary>
<desc>
<p>Combines the operations of
@@ -514,7 +514,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="max" arity="1"/>
+ <name name="max" arity="1" since=""/>
<fsummary>Return maximum element of a list.</fsummary>
<desc>
<p>Returns the first element of <c><anno>List</anno></c> that compares
@@ -524,7 +524,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="member" arity="2"/>
+ <name name="member" arity="2" since=""/>
<fsummary>Test for membership of a list.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Elem</anno></c> matches some element
@@ -533,7 +533,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="merge" arity="1"/>
+ <name name="merge" arity="1" since=""/>
<fsummary>Merge a list of sorted lists.</fsummary>
<desc>
<p>Returns the sorted list formed by merging all the sublists of
@@ -546,7 +546,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="merge" arity="2"/>
+ <name name="merge" arity="2" since=""/>
<fsummary>Merge two sorted lists.</fsummary>
<desc>
<p>Returns the sorted list formed by merging <c><anno>List1</anno></c>
@@ -559,7 +559,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="merge" arity="3"/>
+ <name name="merge" arity="3" since=""/>
<fsummary>Merge two sorted list.</fsummary>
<desc>
<p>Returns the sorted list formed by merging <c><anno>List1</anno></c>
@@ -577,7 +577,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="merge3" arity="3"/>
+ <name name="merge3" arity="3" since=""/>
<fsummary>Merge three sorted lists.</fsummary>
<desc>
<p>Returns the sorted list formed by merging <c><anno>List1</anno></c>,
@@ -593,7 +593,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="min" arity="1"/>
+ <name name="min" arity="1" since=""/>
<fsummary>Return minimum element of a list.</fsummary>
<desc>
<p>Returns the first element of <c><anno>List</anno></c> that compares
@@ -603,7 +603,7 @@ flatmap(Fun, List1) ->
</func>
<func>
- <name name="nth" arity="2"/>
+ <name name="nth" arity="2" since=""/>
<fsummary>Return the <c>N</c>th element of a list.</fsummary>
<type_desc variable="N">1..length(<anno>List</anno>)</type_desc>
<desc>
@@ -617,7 +617,7 @@ c</pre>
</func>
<func>
- <name name="nthtail" arity="2"/>
+ <name name="nthtail" arity="2" since=""/>
<fsummary>Return the <c>N</c>th tail of a list.</fsummary>
<type_desc variable="N">0..length(<anno>List</anno>)</type_desc>
<desc>
@@ -638,7 +638,7 @@ c</pre>
</func>
<func>
- <name name="partition" arity="2"/>
+ <name name="partition" arity="2" since=""/>
<fsummary>Partition a list into two lists based on a predicate.</fsummary>
<desc>
<p>Partitions <c><anno>List</anno></c> into two lists, where the first
@@ -658,7 +658,7 @@ c</pre>
</func>
<func>
- <name name="prefix" arity="2"/>
+ <name name="prefix" arity="2" since=""/>
<fsummary>Test for list prefix.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>List1</anno></c> is a prefix of
@@ -667,7 +667,7 @@ c</pre>
</func>
<func>
- <name name="reverse" arity="1"/>
+ <name name="reverse" arity="1" since=""/>
<fsummary>Reverse a list.</fsummary>
<desc>
<p>Returns a list with the elements in <c><anno>List1</anno></c>
@@ -676,7 +676,7 @@ c</pre>
</func>
<func>
- <name name="reverse" arity="2"/>
+ <name name="reverse" arity="2" since=""/>
<fsummary>Reverse a list appending a tail.</fsummary>
<desc>
<p>Returns a list with the elements in <c><anno>List1</anno></c>
@@ -689,8 +689,20 @@ c</pre>
</func>
<func>
- <name name="seq" arity="2"/>
- <name name="seq" arity="3"/>
+ <name name="search" arity="2" since="OTP 21.0"/>
+ <fsummary>Find the first element that satisfies a predicate.</fsummary>
+ <desc>
+ <p>If there is a <c><anno>Value</anno></c> in <c><anno>List</anno></c>
+ such that <c><anno>Pred</anno>(<anno>Value</anno>)</c> returns
+ <c>true</c>, returns <c>{value, <anno>Value</anno>}</c>
+ for the first such <c><anno>Value</anno></c>,
+ otherwise returns <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="seq" arity="2" since=""/>
+ <name name="seq" arity="3" since=""/>
<fsummary>Generate a sequence of integers.</fsummary>
<desc>
<p>Returns a sequence of integers that starts with
@@ -736,7 +748,7 @@ length(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr</code>
</func>
<func>
- <name name="sort" arity="1"/>
+ <name name="sort" arity="1" since=""/>
<fsummary>Sort a list.</fsummary>
<desc>
<p>Returns a list containing the sorted elements of
@@ -745,7 +757,7 @@ length(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr</code>
</func>
<func>
- <name name="sort" arity="2"/>
+ <name name="sort" arity="2" since=""/>
<fsummary>Sort a list.</fsummary>
<desc>
<p>Returns a list containing the sorted elements of
@@ -759,7 +771,7 @@ length(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr</code>
</func>
<func>
- <name name="split" arity="2"/>
+ <name name="split" arity="2" since=""/>
<fsummary>Split a list into two lists.</fsummary>
<type_desc variable="N">0..length(<anno>List1</anno>)</type_desc>
<desc>
@@ -771,19 +783,7 @@ length(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr</code>
</func>
<func>
- <name name="search" arity="2"/>
- <fsummary>Find the first element that satisfies a predicate.</fsummary>
- <desc>
- <p>If there is a <c><anno>Value</anno></c> in <c><anno>List</anno></c>
- such that <c><anno>Pred</anno>(<anno>Value</anno>)</c> returns
- <c>true</c>, returns <c>{value, <anno>Value</anno>}</c>
- for the first such <c><anno>Value</anno></c>,
- otherwise returns <c>false</c>.</p>
- </desc>
- </func>
-
- <func>
- <name name="splitwith" arity="2"/>
+ <name name="splitwith" arity="2" since=""/>
<fsummary>Split a list into two lists based on a predicate.</fsummary>
<desc>
<p>Partitions <c><anno>List</anno></c> into two lists according to
@@ -804,7 +804,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="sublist" arity="2"/>
+ <name name="sublist" arity="2" since=""/>
<fsummary>Return a sublist of a certain length, starting at the first
position.</fsummary>
<desc>
@@ -816,7 +816,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="sublist" arity="3"/>
+ <name name="sublist" arity="3" since=""/>
<fsummary>Return a sublist starting at a specified position and with a
specified number of elements.</fsummary>
<type_desc variable="Start">1..(length(<anno>List1</anno>)+1)</type_desc>
@@ -838,7 +838,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="subtract" arity="2"/>
+ <name name="subtract" arity="2" since=""/>
<fsummary>Subtract the element in one list from another list.</fsummary>
<desc>
<p>Returns a new list <c><anno>List3</anno></c> that is a copy of
@@ -850,19 +850,11 @@ splitwith(Pred, List) ->
> <input>lists:subtract("123212", "212").</input>
"312".</pre>
<p><c>lists:subtract(A, B)</c> is equivalent to <c>A -- B</c>.</p>
- <warning>
- <p>The complexity of <c>lists:subtract(A, B)</c> is proportional to
- <c>length(A)*length(B)</c>, meaning that it is very slow if both
- <c>A</c> and <c>B</c> are long lists. (If both lists are long, it
- is a much better choice to use ordered lists and
- <seealso marker="ordsets#subtract/2">
- <c>ordsets:subtract/2</c></seealso>.</p>
- </warning>
</desc>
</func>
<func>
- <name name="suffix" arity="2"/>
+ <name name="suffix" arity="2" since=""/>
<fsummary>Test for list suffix.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>List1</anno></c> is a suffix of
@@ -871,7 +863,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="sum" arity="1"/>
+ <name name="sum" arity="1" since=""/>
<fsummary>Return the sum of elements in a list.</fsummary>
<desc>
<p>Returns the sum of the elements in <c><anno>List</anno></c>.</p>
@@ -879,7 +871,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="takewhile" arity="2"/>
+ <name name="takewhile" arity="2" since=""/>
<fsummary>Take elements from a list while a predicate is <c>true</c>.
</fsummary>
<desc>
@@ -892,7 +884,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="ukeymerge" arity="3"/>
+ <name name="ukeymerge" arity="3" since=""/>
<fsummary>Merge two key-sorted lists of tuples, removing duplicates.
</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
@@ -910,7 +902,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="ukeysort" arity="2"/>
+ <name name="ukeysort" arity="2" since=""/>
<fsummary>Sort a list of tuples, removing duplicates.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
@@ -922,7 +914,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="umerge" arity="1"/>
+ <name name="umerge" arity="1" since=""/>
<fsummary>Merge a list of sorted lists, removing duplicates.</fsummary>
<desc>
<p>Returns the sorted list formed by merging all the sublists
@@ -935,7 +927,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="umerge" arity="2"/>
+ <name name="umerge" arity="2" since=""/>
<fsummary>Merge two sorted lists, removing duplicates.</fsummary>
<desc>
<p>Returns the sorted list formed by merging <c><anno>List1</anno></c>
@@ -949,7 +941,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="umerge" arity="3"/>
+ <name name="umerge" arity="3" since=""/>
<fsummary>Merge two sorted lists, removing duplicates.</fsummary>
<desc>
<p>Returns the sorted list formed by merging <c><anno>List1</anno></c>
@@ -966,7 +958,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="umerge3" arity="3"/>
+ <name name="umerge3" arity="3" since=""/>
<fsummary>Merge three sorted lists, removing duplicates.</fsummary>
<desc>
<p>Returns the sorted list formed by merging <c><anno>List1</anno></c>,
@@ -981,7 +973,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="unzip" arity="1"/>
+ <name name="unzip" arity="1" since=""/>
<fsummary>Unzip a list of two-tuples into two lists.</fsummary>
<desc>
<p>"Unzips" a list of two-tuples into two lists, where the first
@@ -991,7 +983,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="unzip3" arity="1"/>
+ <name name="unzip3" arity="1" since=""/>
<fsummary>Unzip a list of three-tuples into three lists.</fsummary>
<desc>
<p>"Unzips" a list of three-tuples into three lists, where
@@ -1002,7 +994,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="usort" arity="1"/>
+ <name name="usort" arity="1" since=""/>
<fsummary>Sort a list, removing duplicates.</fsummary>
<desc>
<p>Returns a list containing the sorted elements of
@@ -1012,7 +1004,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="usort" arity="2"/>
+ <name name="usort" arity="2" since=""/>
<fsummary>Sort a list, removing duplicates.</fsummary>
<desc>
<p>Returns a list containing the sorted elements of
@@ -1027,7 +1019,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="zip" arity="2"/>
+ <name name="zip" arity="2" since=""/>
<fsummary>Zip two lists into a list of two-tuples.</fsummary>
<desc>
<p>"Zips" two lists of equal length into one list of two-tuples,
@@ -1038,7 +1030,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="zip3" arity="3"/>
+ <name name="zip3" arity="3" since=""/>
<fsummary>Zip three lists into a list of three-tuples.</fsummary>
<desc>
<p>"Zips" three lists of equal length into one list of
@@ -1050,7 +1042,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="zipwith" arity="3"/>
+ <name name="zipwith" arity="3" since=""/>
<fsummary>Zip two lists into one list according to a fun.</fsummary>
<desc>
<p>Combines the elements of two lists of equal length into one list.
@@ -1067,7 +1059,7 @@ splitwith(Pred, List) ->
</func>
<func>
- <name name="zipwith3" arity="4"/>
+ <name name="zipwith3" arity="4" since=""/>
<fsummary>Zip three lists into one list according to a fun.</fsummary>
<desc>
<p>Combines the elements of three lists of equal length into one
diff --git a/lib/stdlib/doc/src/log_mf_h.xml b/lib/stdlib/doc/src/log_mf_h.xml
index edc3d31025..b922006cc0 100644
--- a/lib/stdlib/doc/src/log_mf_h.xml
+++ b/lib/stdlib/doc/src/log_mf_h.xml
@@ -34,7 +34,7 @@
<rev>A</rev>
<file>log_mf_h.xml</file>
</header>
- <module>log_mf_h</module>
+ <module since="">log_mf_h</module>
<modulesummary>An event handler that logs events to disk.</modulesummary>
<description>
<p>This module is a <c>gen_event</c> handler module that can be installed
@@ -60,8 +60,8 @@
<funcs>
<func>
- <name name="init" arity="3"/>
- <name name="init" arity="4"/>
+ <name name="init" arity="3" since=""/>
+ <name name="init" arity="4" since=""/>
<fsummary>Initiate the event handler.</fsummary>
<desc>
<p>Initiates the event handler. Returns <c><anno>Args</anno></c>, which
diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml
index a225dea3b5..e2a62cb397 100644
--- a/lib/stdlib/doc/src/maps.xml
+++ b/lib/stdlib/doc/src/maps.xml
@@ -27,7 +27,7 @@
<date>2014-02-28</date>
<rev>A</rev>
</header>
- <module>maps</module>
+ <module since="OTP 17.0">maps</module>
<modulesummary>Maps processing functions.</modulesummary>
<description>
<p>This module contains functions for maps processing.</p>
@@ -49,7 +49,7 @@
<funcs>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since="OTP 18.0"/>
<fsummary>Select pairs that satisfy a predicate.</fsummary>
<desc>
<p>Returns a map <c><anno>Map</anno></c> for which predicate
@@ -68,7 +68,7 @@
</func>
<func>
- <name name="find" arity="2"/>
+ <name name="find" arity="2" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a tuple <c>{ok, Value}</c>, where <c><anno>Value</anno></c>
@@ -87,7 +87,7 @@
</func>
<func>
- <name name="fold" arity="3"/>
+ <name name="fold" arity="3" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Calls <c>F(K, V, AccIn)</c> for every <c><anno>K</anno></c> to value
@@ -111,7 +111,7 @@
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Takes a list of key-value tuples elements and builds a map. The
@@ -128,7 +128,7 @@
</func>
<func>
- <name name="get" arity="2"/>
+ <name name="get" arity="2" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns value <c><anno>Value</anno></c> associated with
@@ -147,7 +147,7 @@
</func>
<func>
- <name name="get" arity="3"/>
+ <name name="get" arity="3" since="OTP 17.1"/>
<fsummary></fsummary>
<desc>
<p>Returns value <c><anno>Value</anno></c> associated with
@@ -168,7 +168,7 @@ val1
</func>
<func>
- <name name="is_key" arity="2"/>
+ <name name="is_key" arity="2" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns <c>true</c> if map <c><anno>Map</anno></c> contains
@@ -188,7 +188,7 @@ false</code>
</func>
<func>
- <name name="iterator" arity="1"/>
+ <name name="iterator" arity="1" since="OTP 21.0"/>
<fsummary>Create a map iterator.</fsummary>
<desc>
<p>Returns a map iterator <c><anno>Iterator</anno></c> that can
@@ -202,19 +202,19 @@ false</code>
<code type="none">
> M = #{ a => 1, b => 2 }.
#{a => 1,b => 2}
-> I = maps:iterator(M).
-[{a,1},{b,2}]
-> {K1, V1, I2} = maps:next(I).
-{a,1,[{b,2}]}
-> {K2, V2, I3} = maps:next(I2).
-{b,2,[]}
+> I = maps:iterator(M), ok.
+ok
+> {K1, V1, I2} = maps:next(I), {K1, V1}.
+{a,1}
+> {K2, V2, I3} = maps:next(I2),{K2, V2}.
+{b,2}
> maps:next(I3).
none</code>
</desc>
</func>
<func>
- <name name="keys" arity="1"/>
+ <name name="keys" arity="1" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a complete list of keys, in any order, which resides
@@ -230,7 +230,7 @@ none</code>
</func>
<func>
- <name name="map" arity="2"/>
+ <name name="map" arity="2" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Produces a new map <c><anno>Map</anno></c> by calling function
@@ -253,7 +253,7 @@ none</code>
</func>
<func>
- <name name="merge" arity="2"/>
+ <name name="merge" arity="2" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Merges two maps into a single map <c><anno>Map3</anno></c>. If two
@@ -271,7 +271,7 @@ none</code>
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a new empty map.</p>
@@ -283,7 +283,7 @@ none</code>
</func>
<func>
- <name name="next" arity="1"/>
+ <name name="next" arity="1" since="OTP 21.0"/>
<fsummary>Get the next key and value from an iterator.</fsummary>
<desc>
<p>Returns the next key-value association in
@@ -298,21 +298,21 @@ none</code>
<code type="none">
> Map = #{a => 1, b => 2, c => 3}.
#{a => 1,b => 2,c => 3}
-> Iter = maps:iterator(Map).
-[{a,1},{b,2},{c,3}]
-> {_, _, Iter1} = maps:next(Iter).
-{a,1,[{b,2},{c,3}]}
-> {_, _, Iter2} = maps:next(Iter1).
-{b,2,[{c,3}]}
-> {_, _, Iter3} = maps:next(Iter2).
-{c,3,[]}
-> maps:next(Iter3).
+> I = maps:iterator(Map), ok.
+ok
+> {K1, V1, I1} = maps:next(I), {K1, V1}.
+{a,1}
+> {K2, V2, I2} = maps:next(I1), {K2, V2}.
+{b,2}
+> {K3, V3, I3} = maps:next(I2), {K3, V3}.
+{c,3}
+> maps:next(I3).
none</code>
</desc>
</func>
<func>
- <name name="put" arity="3"/>
+ <name name="put" arity="3" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Associates <c><anno>Key</anno></c> with value
@@ -336,7 +336,7 @@ none</code>
</func>
<func>
- <name name="remove" arity="2"/>
+ <name name="remove" arity="2" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Removes the <c><anno>Key</anno></c>, if it exists, and its
@@ -356,7 +356,7 @@ none</code>
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns the number of key-value associations in
@@ -370,7 +370,7 @@ none</code>
</func>
<func>
- <name name="take" arity="2"/>
+ <name name="take" arity="2" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>The function removes the <c><anno>Key</anno></c>, if it
@@ -395,7 +395,7 @@ error</code>
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a list of pairs representing the key-value associations of
@@ -412,7 +412,7 @@ error</code>
</func>
<func>
- <name name="update" arity="3"/>
+ <name name="update" arity="3" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>If <c><anno>Key</anno></c> exists in <c><anno>Map1</anno></c>, the
@@ -432,7 +432,7 @@ error</code>
</func>
<func>
- <name name="update_with" arity="3"/>
+ <name name="update_with" arity="3" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Update a value in a <c><anno>Map1</anno></c> associated
@@ -451,7 +451,7 @@ error</code>
</func>
<func>
- <name name="update_with" arity="4"/>
+ <name name="update_with" arity="4" since="OTP 19.0"/>
<fsummary></fsummary>
<desc>
<p>Update a value in a <c><anno>Map1</anno></c> associated
@@ -471,7 +471,7 @@ error</code>
</func>
<func>
- <name name="values" arity="1"/>
+ <name name="values" arity="1" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a complete list of values, in arbitrary order, contained in
@@ -487,7 +487,7 @@ error</code>
</func>
<func>
- <name name="with" arity="2"/>
+ <name name="with" arity="2" since="OTP 17.3"/>
<fsummary></fsummary>
<desc>
<p>Returns a new map <c><anno>Map2</anno></c> with the keys <c>K1</c>
@@ -504,7 +504,7 @@ error</code>
</func>
<func>
- <name name="without" arity="2"/>
+ <name name="without" arity="2" since="OTP 17.0"/>
<fsummary></fsummary>
<desc>
<p>Returns a new map <c><anno>Map2</anno></c> without keys <c>K1</c>
diff --git a/lib/stdlib/doc/src/math.xml b/lib/stdlib/doc/src/math.xml
index b4f096217a..d89310e2c8 100644
--- a/lib/stdlib/doc/src/math.xml
+++ b/lib/stdlib/doc/src/math.xml
@@ -34,7 +34,7 @@
<rev>B</rev>
<file>math.xml</file>
</header>
- <module>math</module>
+ <module since="">math</module>
<modulesummary>Mathematical functions.</modulesummary>
<description>
<p>This module provides an interface to a number of mathematical
@@ -50,28 +50,28 @@
<funcs>
<func>
- <name name="acos" arity="1"/>
- <name name="acosh" arity="1"/>
- <name name="asin" arity="1"/>
- <name name="asinh" arity="1"/>
- <name name="atan" arity="1"/>
- <name name="atan2" arity="2"/>
- <name name="atanh" arity="1"/>
- <name name="ceil" arity="1"/>
- <name name="cos" arity="1"/>
- <name name="cosh" arity="1"/>
- <name name="exp" arity="1"/>
- <name name="floor" arity="1"/>
- <name name="fmod" arity="2"/>
- <name name="log" arity="1"/>
- <name name="log10" arity="1"/>
- <name name="log2" arity="1"/>
- <name name="pow" arity="2"/>
- <name name="sin" arity="1"/>
- <name name="sinh" arity="1"/>
- <name name="sqrt" arity="1"/>
- <name name="tan" arity="1"/>
- <name name="tanh" arity="1"/>
+ <name name="acos" arity="1" since=""/>
+ <name name="acosh" arity="1" since=""/>
+ <name name="asin" arity="1" since=""/>
+ <name name="asinh" arity="1" since=""/>
+ <name name="atan" arity="1" since=""/>
+ <name name="atan2" arity="2" since=""/>
+ <name name="atanh" arity="1" since=""/>
+ <name name="ceil" arity="1" since="OTP 20.0"/>
+ <name name="cos" arity="1" since=""/>
+ <name name="cosh" arity="1" since=""/>
+ <name name="exp" arity="1" since=""/>
+ <name name="floor" arity="1" since="OTP 20.0"/>
+ <name name="fmod" arity="2" since="OTP 20.0"/>
+ <name name="log" arity="1" since=""/>
+ <name name="log10" arity="1" since=""/>
+ <name name="log2" arity="1" since="OTP 18.0"/>
+ <name name="pow" arity="2" since=""/>
+ <name name="sin" arity="1" since=""/>
+ <name name="sinh" arity="1" since=""/>
+ <name name="sqrt" arity="1" since=""/>
+ <name name="tan" arity="1" since=""/>
+ <name name="tanh" arity="1" since=""/>
<fsummary>Diverse math functions.</fsummary>
<type variable="X" name_i="6"/>
<type variable="Y" name_i="6"/>
@@ -82,7 +82,7 @@
</func>
<func>
- <name name="erf" arity="1"/>
+ <name name="erf" arity="1" since=""/>
<fsummary>Error function.</fsummary>
<desc>
<p>Returns the error function of <c><anno>X</anno></c>, where:</p>
@@ -92,7 +92,7 @@ erf(X) = 2/sqrt(pi)*integral from 0 to X of exp(-t*t) dt.</pre>
</func>
<func>
- <name name="erfc" arity="1"/>
+ <name name="erfc" arity="1" since=""/>
<fsummary>Another error function.</fsummary>
<desc>
<p><c>erfc(X)</c> returns <c>1.0</c> - <c>erf(X)</c>, computed by
@@ -101,7 +101,7 @@ erf(X) = 2/sqrt(pi)*integral from 0 to X of exp(-t*t) dt.</pre>
</func>
<func>
- <name name="pi" arity="0"/>
+ <name name="pi" arity="0" since=""/>
<fsummary>A useful number.</fsummary>
<desc>
<p>A useful number.</p>
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index 0a05fa37c5..65cc150507 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -32,7 +32,7 @@
<rev>C</rev>
<file>ms_transform.xml</file>
</header>
- <module>ms_transform</module>
+ <module since="">ms_transform</module>
<modulesummary>A parse transformation that translates fun syntax into match
specifications.</modulesummary>
<description>
@@ -731,7 +731,7 @@ ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code>
<funcs>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Error formatting function as required by the parse transformation interface.</fsummary>
<desc>
<p>Takes an error code returned by one of the other functions
@@ -741,7 +741,7 @@ ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code>
</func>
<func>
- <name name="parse_transform" arity="2"/>
+ <name name="parse_transform" arity="2" since=""/>
<fsummary>Transforms Erlang abstract format containing calls to
ets/dbg:fun2ms/1 into literal match specifications.</fsummary>
<type_desc variable="Options">Option list, required but not used.
@@ -762,7 +762,7 @@ ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code>
</func>
<func>
- <name name="transform_from_shell" arity="3"/>
+ <name name="transform_from_shell" arity="3" since=""/>
<fsummary>Used when transforming funs created in the shell into
match_specifications.</fsummary>
<type_desc variable="BoundEnvironment">List of variable bindings in the
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 611bfe73e0..7d8f0bf85c 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -31,6 +31,236 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 3.8.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug in gen_statem has been fixed where the internal
+ timeout message could arrive as an info to the callback
+ module during high load due to incorrect use of
+ asynchronous timer cancel.</p>
+ <p>
+ Own Id: OTP-15295</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a performance regression when reading files
+ opened with the <c>compressed</c> flag.</p>
+ <p>
+ Own Id: OTP-15706 Aux Id: ERIERL-336 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug in the Erlang Pretty Printer: long atom
+ names in combination with <c>&lt;&lt;&gt;&gt;</c> could
+ cause a crash. </p>
+ <p>
+ Own Id: OTP-15592 Aux Id: ERL-818 </p>
+ </item>
+ <item>
+ <p> Fix bugs that could cause wrong results or bad
+ performance when formatting lists of characters using the
+ control sequences <c>p</c> or <c>P</c> and limiting the
+ output with the option <c>chars_limit</c>. </p>
+ <p>
+ Own Id: OTP-15639</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improved ETS documentation about safe table traversal and
+ the partially bound key optimization for
+ <c>ordered_set</c>.</p>
+ <p>
+ Own Id: OTP-15545 Aux Id: PR-2103, PR-2139 </p>
+ </item>
+ <item>
+ <p> Optimize <c>calendar:gregorian_days_to_date/1</c>.
+ </p>
+ <p>
+ Own Id: OTP-15572 Aux Id: PR-2121 </p>
+ </item>
+ <item>
+ <p> Optimize functions
+ <c>calendar:rfc3339_to_system_time()</c> and
+ <c>calendar:system_time_to_rfc3339()</c>. </p>
+ <p>
+ Own Id: OTP-15630</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.7.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Optimize pretty printing of terms. The slower
+ behaviour was introduced in Erlang/OTP 20. </p>
+ <p>
+ Own Id: OTP-15573 Aux Id: ERIERL-306 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Document <c>bit_size</c> in match specifications and
+ allow it in <c>ets:fun2ms</c>.</p>
+ <p>
+ Own Id: OTP-15343 Aux Id: PR-1962 </p>
+ </item>
+ <item>
+ <p>The <c>beam()</c> type in <c>beam_lib</c> is defined
+ as <c>module() | file:filename() | binary()</c>. The
+ <c>module()</c> is misleading. Giving the module name as
+ an atom will only work if the BEAM file is in a current
+ directory.</p>
+ <p>To avoid confusion, <c>module()</c> has been removed
+ from the type. That means that there will be a Dialyzer
+ warning for code that call <c>beam_lib</c> with an atom
+ as filename, but the calls will still work.</p>
+ <p>
+ Own Id: OTP-15378 Aux Id: ERL-696 </p>
+ </item>
+ <item>
+ <p>
+ <c>unicode_util</c> crashed on certain emoji grapheme
+ clusters in binary strings.</p>
+ <p>
+ Own Id: OTP-15428 Aux Id: ERL-777 </p>
+ </item>
+ <item>
+ <p>When an external fun was used, warnings for unused
+ variables could be suppressed.</p>
+ <p>
+ Own Id: OTP-15437 Aux Id: ERL-762 </p>
+ </item>
+ <item>
+ <p>
+ Fix reduction count in lists:member/2</p>
+ <p>
+ Own Id: OTP-15474 Aux Id: ERIERL-229 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>When specified, the <c>+{source,Name}</c> option will
+ now override the actual file name in stack traces,
+ instead of only affecting the return value of
+ <c>Mod:module_info()</c>.</p>
+ <p>The <c>+deterministic</c> flag will also affect stack
+ traces now, omitting all path information except the file
+ name, fixing a long-standing issue where deterministic
+ builds required deterministic paths.</p>
+ <p>
+ Own Id: OTP-15245 Aux Id: ERL-706 </p>
+ </item>
+ <item>
+ <p>List subtraction (The <c>--</c> operator) will now
+ yield properly on large inputs.</p>
+ <p>
+ Own Id: OTP-15371</p>
+ </item>
+ <item>
+ <p>
+ <c>calendar:system_time_to_rfc3339/1,2</c> no longer
+ remove trailing zeros from fractions.</p>
+ <p>
+ Own Id: OTP-15464</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The specs of <c>filename:basedir/2,3</c> are
+ corrected.</p>
+ <p>
+ Own Id: OTP-15252 Aux Id: ERL-667 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Let <c>dets:open_file()</c> exit with a <c>badarg</c>
+ message if given a raw file name (a binary). </p>
+ <p>
+ Own Id: OTP-15253 Aux Id: OTP-13229, ERL-55 </p>
+ </item>
+ <item>
+ <p> The <c>Format</c> argument of the formatting
+ functions in modules <c>io</c> and <c>io_lib</c> is
+ accepted even if it is, for example, a list of binaries.
+ This is how it used to be before Erlang/OTP 21.0. </p>
+ <p>
+ Own Id: OTP-15304</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug that could cause a crash when formatting a
+ list of non-characters using the control sequences
+ <c>p</c> or <c>P</c> and limiting the output with the
+ option <c>chars_limit</c>. </p>
+ <p>
+ Own Id: OTP-15159</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -452,6 +682,21 @@
</section>
+<section><title>STDLIB 3.4.5.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>List subtraction (The <c>--</c> operator) will now
+ yield properly on large inputs.</p>
+ <p>
+ Own Id: OTP-15371</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.4.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1606,6 +1851,21 @@
</section>
+<section><title>STDLIB 2.8.0.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>List subtraction (The <c>--</c> operator) will now
+ yield properly on large inputs.</p>
+ <p>
+ Own Id: OTP-15371</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 2.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -7775,4 +8035,3 @@
</section>
</section>
</chapter>
-
diff --git a/lib/stdlib/doc/src/orddict.xml b/lib/stdlib/doc/src/orddict.xml
index 26bbf499c6..27ccccee7e 100644
--- a/lib/stdlib/doc/src/orddict.xml
+++ b/lib/stdlib/doc/src/orddict.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>orddict.xml</file>
</header>
- <module>orddict</module>
+ <module since="">orddict</module>
<modulesummary>Key-value dictionary as ordered list.</modulesummary>
<description>
<p>This module provides a <c>Key</c>-<c>Value</c> dictionary.
@@ -61,7 +61,7 @@
<funcs>
<func>
- <name name="append" arity="3"/>
+ <name name="append" arity="3" since=""/>
<fsummary>Append a value to keys in a dictionary.</fsummary>
<desc>
<p>Appends a new <c><anno>Value</anno></c> to the current list
@@ -73,7 +73,7 @@
</func>
<func>
- <name name="append_list" arity="3"/>
+ <name name="append_list" arity="3" since=""/>
<fsummary>Append new values to keys in a dictionary.</fsummary>
<desc>
<p>Appends a list of values <c><anno>ValList</anno></c> to
@@ -85,7 +85,7 @@
</func>
<func>
- <name name="erase" arity="2"/>
+ <name name="erase" arity="2" since=""/>
<fsummary>Erase a key from a dictionary.</fsummary>
<desc>
<p>Erases all items with a specified key from a dictionary.</p>
@@ -93,7 +93,7 @@
</func>
<func>
- <name name="fetch" arity="2"/>
+ <name name="fetch" arity="2" since=""/>
<fsummary>Look up values in a dictionary.</fsummary>
<desc>
<p>Returns the value associated with <c><anno>Key</anno></c>
@@ -105,7 +105,7 @@
</func>
<func>
- <name name="fetch_keys" arity="1"/>
+ <name name="fetch_keys" arity="1" since=""/>
<fsummary>Return all keys in a dictionary.</fsummary>
<desc>
<p>Returns a list of all keys in a dictionary.</p>
@@ -113,7 +113,7 @@
</func>
<func>
- <name name="take" arity="2"/>
+ <name name="take" arity="2" since="OTP 20.0"/>
<fsummary>Return value and new dictionary without element with this value.</fsummary>
<desc>
<p>This function returns value from dictionary and new dictionary without this value.
@@ -122,7 +122,7 @@
</func>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since=""/>
<fsummary>Select elements that satisfy a predicate.</fsummary>
<desc>
<p><c><anno>Orddict2</anno></c> is a dictionary of all keys and values
@@ -133,7 +133,7 @@
</func>
<func>
- <name name="find" arity="2"/>
+ <name name="find" arity="2" since=""/>
<fsummary>Search for a key in a dictionary.</fsummary>
<desc>
<p>Searches for a key in a dictionary. Returns
@@ -145,7 +145,7 @@
</func>
<func>
- <name name="fold" arity="3"/>
+ <name name="fold" arity="3" since=""/>
<fsummary>Fold a function over a dictionary.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno></c> on successive keys and values of
@@ -157,7 +157,7 @@
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since=""/>
<fsummary>Convert a list of pairs to a dictionary.</fsummary>
<desc>
<p>Converts the <c><anno>Key</anno></c>-<c><anno>Value</anno></c> list
@@ -166,7 +166,7 @@
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since="OTP 17.0"/>
<fsummary>Return true if the dictionary is empty.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Orddict</anno></c> has no elements,
@@ -175,7 +175,7 @@
</func>
<func>
- <name name="is_key" arity="2"/>
+ <name name="is_key" arity="2" since=""/>
<fsummary>Test if a key is in a dictionary.</fsummary>
<desc>
<p>Tests if <c><anno>Key</anno></c> is contained in
@@ -184,7 +184,7 @@
</func>
<func>
- <name name="map" arity="2"/>
+ <name name="map" arity="2" since=""/>
<fsummary>Map a function over a dictionary.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno></c> on successive keys and values of
@@ -193,7 +193,7 @@
</func>
<func>
- <name name="merge" arity="3"/>
+ <name name="merge" arity="3" since=""/>
<fsummary>Merge two dictionaries.</fsummary>
<desc>
<p>Merges two dictionaries, <c><anno>Orddict1</anno></c> and
@@ -212,7 +212,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Create a dictionary.</fsummary>
<desc>
<p>Creates a new dictionary.</p>
@@ -220,7 +220,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since=""/>
<fsummary>Return the number of elements in an ordered dictionary.
</fsummary>
<desc>
@@ -229,7 +229,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="store" arity="3"/>
+ <name name="store" arity="3" since=""/>
<fsummary>Store a value in a dictionary.</fsummary>
<desc>
<p>Stores a <c><anno>Key</anno></c>-<c><anno>Value</anno></c> pair in a
@@ -240,7 +240,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert a dictionary to a list of pairs.</fsummary>
<desc>
<p>Converts a dictionary to a list representation.</p>
@@ -248,7 +248,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="update" arity="3"/>
+ <name name="update" arity="3" since=""/>
<fsummary>Update a value in a dictionary.</fsummary>
<desc>
<p>Updates a value in a dictionary by calling <c><anno>Fun</anno></c>
@@ -258,7 +258,7 @@ merge(Fun, D1, D2) ->
</func>
<func>
- <name name="update" arity="4"/>
+ <name name="update" arity="4" since=""/>
<fsummary>Update a value in a dictionary.</fsummary>
<desc>
<p>Updates a value in a dictionary by calling <c><anno>Fun</anno></c>
@@ -273,7 +273,7 @@ append(Key, Val, D) ->
</func>
<func>
- <name name="update_counter" arity="3"/>
+ <name name="update_counter" arity="3" since=""/>
<fsummary>Increment a value in a dictionary.</fsummary>
<desc>
<p>Adds <c><anno>Increment</anno></c> to the value associated with
diff --git a/lib/stdlib/doc/src/ordsets.xml b/lib/stdlib/doc/src/ordsets.xml
index 11f98c8fb7..fbe334c009 100644
--- a/lib/stdlib/doc/src/ordsets.xml
+++ b/lib/stdlib/doc/src/ordsets.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>ordsets.xml</file>
</header>
- <module>ordsets</module>
+ <module since="">ordsets</module>
<modulesummary>Functions for manipulating sets as ordered lists.
</modulesummary>
<description>
@@ -60,7 +60,7 @@
<funcs>
<func>
- <name name="add_element" arity="2"/>
+ <name name="add_element" arity="2" since=""/>
<fsummary>Add an element to an <c>Ordset</c>.</fsummary>
<desc>
<p>Returns a new ordered set formed from <c><anno>Ordset1</anno></c>
@@ -69,7 +69,7 @@
</func>
<func>
- <name name="del_element" arity="2"/>
+ <name name="del_element" arity="2" since=""/>
<fsummary>Remove an element from an <c>Ordset</c>.</fsummary>
<desc>
<p>Returns <c><anno>Ordset1</anno></c>, but with
@@ -78,7 +78,7 @@
</func>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since=""/>
<fsummary>Filter set elements.</fsummary>
<desc>
<p>Filters elements in <c><anno>Ordset1</anno></c> with boolean function
@@ -87,7 +87,7 @@
</func>
<func>
- <name name="fold" arity="3"/>
+ <name name="fold" arity="3" since=""/>
<fsummary>Fold over set elements.</fsummary>
<desc>
<p>Folds <c><anno>Function</anno></c> over every element in
@@ -97,7 +97,7 @@
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since=""/>
<fsummary>Convert a list into an <c>Ordset</c>.</fsummary>
<desc>
<p>Returns an ordered set of the elements in <c><anno>List</anno></c>.
@@ -106,7 +106,7 @@
</func>
<func>
- <name name="intersection" arity="1"/>
+ <name name="intersection" arity="1" since=""/>
<fsummary>Return the intersection of a list of <c>Ordsets</c></fsummary>
<desc>
<p>Returns the intersection of the non-empty list of sets.</p>
@@ -114,7 +114,7 @@
</func>
<func>
- <name name="intersection" arity="2"/>
+ <name name="intersection" arity="2" since=""/>
<fsummary>Return the intersection of two <c>Ordsets</c>.</fsummary>
<desc>
<p>Returns the intersection of <c><anno>Ordset1</anno></c> and
@@ -123,7 +123,7 @@
</func>
<func>
- <name name="is_disjoint" arity="2"/>
+ <name name="is_disjoint" arity="2" since=""/>
<fsummary>Check whether two <c>Ordsets</c> are disjoint.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Ordset1</anno></c> and
@@ -133,7 +133,7 @@
</func>
<func>
- <name name="is_element" arity="2"/>
+ <name name="is_element" arity="2" since=""/>
<fsummary>Test for membership of an <c>Ordset</c>.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of
@@ -142,7 +142,7 @@
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since="OTP 21.0"/>
<fsummary>Test for empty set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Ordset</anno></c> is an empty set,
@@ -151,7 +151,7 @@
</func>
<func>
- <name name="is_set" arity="1"/>
+ <name name="is_set" arity="1" since=""/>
<fsummary>Test for an <c>Ordset</c>.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Ordset</anno></c> is an ordered set
@@ -160,7 +160,7 @@
</func>
<func>
- <name name="is_subset" arity="2"/>
+ <name name="is_subset" arity="2" since=""/>
<fsummary>Test for subset.</fsummary>
<desc>
<p>Returns <c>true</c> when every element of <c><anno>Ordset1</anno></c>
@@ -170,7 +170,7 @@
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Return an empty set.</fsummary>
<desc>
<p>Returns a new empty ordered set.</p>
@@ -178,7 +178,7 @@
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since=""/>
<fsummary>Return the number of elements in a set.</fsummary>
<desc>
<p>Returns the number of elements in <c><anno>Ordset</anno></c>.</p>
@@ -186,7 +186,7 @@
</func>
<func>
- <name name="subtract" arity="2"/>
+ <name name="subtract" arity="2" since=""/>
<fsummary>Return the difference of two <c>Ordsets</c>.</fsummary>
<desc>
<p>Returns only the elements of <c><anno>Ordset1</anno></c> that are not
@@ -195,7 +195,7 @@
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert an <c>Ordset</c> into a list.</fsummary>
<desc>
<p>Returns the elements of <c><anno>Ordset</anno></c> as a list.</p>
@@ -203,7 +203,7 @@
</func>
<func>
- <name name="union" arity="1"/>
+ <name name="union" arity="1" since=""/>
<fsummary>Return the union of a list of <c>Ordsets</c>.</fsummary>
<desc>
<p>Returns the merged (union) set of the list of sets.</p>
@@ -211,7 +211,7 @@
</func>
<func>
- <name name="union" arity="2"/>
+ <name name="union" arity="2" since=""/>
<fsummary>Return the union of two <c>Ordsets</c>.</fsummary>
<desc>
<p>Returns the merged (union) set of <c><anno>Ordset1</anno></c> and
diff --git a/lib/stdlib/doc/src/pool.xml b/lib/stdlib/doc/src/pool.xml
index 05d12ade28..675ee08bfb 100644
--- a/lib/stdlib/doc/src/pool.xml
+++ b/lib/stdlib/doc/src/pool.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>pool</module>
+ <module since="">pool</module>
<modulesummary>Load distribution facility.</modulesummary>
<description>
<p>This module can be used to run a set of Erlang nodes as a pool
@@ -54,7 +54,7 @@
<funcs>
<func>
- <name name="attach" arity="1"/>
+ <name name="attach" arity="1" since=""/>
<fsummary>Ensure that a pool master is running.</fsummary>
<desc>
<p>Ensures that a pool master is running and includes
@@ -63,7 +63,7 @@
</func>
<func>
- <name name="get_node" arity="0"/>
+ <name name="get_node" arity="0" since=""/>
<fsummary>Return the node with the expected lowest future load.</fsummary>
<desc>
<p>Returns the node with the expected lowest future load.</p>
@@ -71,7 +71,7 @@
</func>
<func>
- <name name="get_nodes" arity="0"/>
+ <name name="get_nodes" arity="0" since=""/>
<fsummary>Return a list of the current member nodes of the pool.
</fsummary>
<desc>
@@ -80,7 +80,7 @@
</func>
<func>
- <name name="pspawn" arity="3"/>
+ <name name="pspawn" arity="3" since=""/>
<fsummary>Spawn a process on the pool node with expected lowest future
load.</fsummary>
<desc>
@@ -90,7 +90,7 @@
</func>
<func>
- <name name="pspawn_link" arity="3"/>
+ <name name="pspawn_link" arity="3" since=""/>
<fsummary>Spawn and link to a process on the pool node with expected
lowest future load.</fsummary>
<desc>
@@ -100,8 +100,8 @@
</func>
<func>
- <name name="start" arity="1"/>
- <name name="start" arity="2"/>
+ <name name="start" arity="1" since=""/>
+ <name name="start" arity="2" since=""/>
<fsummary>>Start a new pool.</fsummary>
<desc>
<p>Starts a new pool. The file <c>.hosts.erlang</c> is read to
@@ -122,7 +122,7 @@
</func>
<func>
- <name name="stop" arity="0"/>
+ <name name="stop" arity="0" since=""/>
<fsummary>Stop the pool and kill all the slave nodes.</fsummary>
<desc>
<p>Stops the pool and kills all the slave nodes.</p>
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index b85fab67d5..aeb9f48735 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>proc_lib</module>
+ <module since="">proc_lib</module>
<modulesummary>Functions for asynchronous and synchronous start of processes
adhering to the OTP design principles.</modulesummary>
<description>
@@ -102,7 +102,7 @@
<funcs>
<func>
- <name name="format" arity="1"/>
+ <name name="format" arity="1" since=""/>
<fsummary>Format a crash report.</fsummary>
<desc>
<p>Equivalent to <seealso marker="#format/2">
@@ -111,7 +111,7 @@
</func>
<func>
- <name name="format" arity="2"/>
+ <name name="format" arity="2" since="OTP R16B"/>
<fsummary>Format a crash report.</fsummary>
<desc>
<note>
@@ -138,7 +138,7 @@
</func>
<func>
- <name name="format" arity="3"/>
+ <name name="format" arity="3" since="OTP 18.1"/>
<fsummary>Format a crash report.</fsummary>
<desc>
<note>
@@ -162,7 +162,7 @@
</func>
<func>
- <name name="hibernate" arity="3"/>
+ <name name="hibernate" arity="3" since=""/>
<fsummary>Hibernate a process until a message is sent to it.</fsummary>
<desc>
<p>This function does the same as (and does call) the
@@ -176,8 +176,8 @@
</func>
<func>
- <name name="init_ack" arity="1"/>
- <name name="init_ack" arity="2"/>
+ <name name="init_ack" arity="1" since=""/>
+ <name name="init_ack" arity="2" since=""/>
<fsummary>Used by a process when it has started.</fsummary>
<desc>
<p>This function must be used by a process that has been started by
@@ -214,7 +214,7 @@ init(Parent) ->
</func>
<func>
- <name name="initial_call" arity="1"/>
+ <name name="initial_call" arity="1" since=""/>
<fsummary>Extract the initial call of a <c>proc_lib</c>spawned process.
</fsummary>
<desc>
@@ -244,10 +244,10 @@ init(Parent) ->
</func>
<func>
- <name name="spawn" arity="1"/>
- <name name="spawn" arity="2"/>
- <name name="spawn" arity="3"/>
- <name name="spawn" arity="4"/>
+ <name name="spawn" arity="1" since=""/>
+ <name name="spawn" arity="2" since=""/>
+ <name name="spawn" arity="3" since=""/>
+ <name name="spawn" arity="4" since=""/>
<fsummary>Spawn a new process.</fsummary>
<type variable="Node"/>
<type variable="Fun" name_i="1"/>
@@ -262,10 +262,10 @@ init(Parent) ->
</func>
<func>
- <name name="spawn_link" arity="1"/>
- <name name="spawn_link" arity="2"/>
- <name name="spawn_link" arity="3"/>
- <name name="spawn_link" arity="4"/>
+ <name name="spawn_link" arity="1" since=""/>
+ <name name="spawn_link" arity="2" since=""/>
+ <name name="spawn_link" arity="3" since=""/>
+ <name name="spawn_link" arity="4" since=""/>
<fsummary>Spawn and link to a new process.</fsummary>
<type variable="Node"/>
<type variable="Fun" name_i="1"/>
@@ -281,10 +281,10 @@ init(Parent) ->
</func>
<func>
- <name name="spawn_opt" arity="2"/>
- <name name="spawn_opt" arity="3"/>
- <name name="spawn_opt" arity="4"/>
- <name name="spawn_opt" arity="5"/>
+ <name name="spawn_opt" arity="2" since=""/>
+ <name name="spawn_opt" arity="3" since=""/>
+ <name name="spawn_opt" arity="4" since=""/>
+ <name name="spawn_opt" arity="5" since=""/>
<fsummary>Spawn a new process with specified options.</fsummary>
<type variable="Node"/>
<type variable="Fun" name_i="1"/>
@@ -306,12 +306,12 @@ init(Parent) ->
</func>
<func>
- <name name="start" arity="3"/>
- <name name="start" arity="4"/>
- <name name="start" arity="5"/>
- <name name="start_link" arity="3"/>
- <name name="start_link" arity="4"/>
- <name name="start_link" arity="5"/>
+ <name name="start" arity="3" since=""/>
+ <name name="start" arity="4" since=""/>
+ <name name="start" arity="5" since=""/>
+ <name name="start_link" arity="3" since=""/>
+ <name name="start_link" arity="4" since=""/>
+ <name name="start_link" arity="5" since=""/>
<fsummary>Start a new process synchronously.</fsummary>
<desc>
<p>Starts a new process synchronously. Spawns the process and
@@ -341,7 +341,7 @@ init(Parent) ->
</func>
<func>
- <name name="stop" arity="1"/>
+ <name name="stop" arity="1" since="OTP 18.0"/>
<fsummary>Terminate a process synchronously.</fsummary>
<type variable="Process"/>
<desc>
@@ -351,7 +351,7 @@ init(Parent) ->
</func>
<func>
- <name name="stop" arity="3"/>
+ <name name="stop" arity="3" since="OTP 18.0"/>
<fsummary>Terminate a process synchronously.</fsummary>
<type variable="Process"/>
<type variable="Reason"/>
@@ -375,7 +375,7 @@ init(Parent) ->
</func>
<func>
- <name name="translate_initial_call" arity="1"/>
+ <name name="translate_initial_call" arity="1" since=""/>
<fsummary>Extract and translate the initial call of a
<c>proc_lib</c>spawned process.</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/proplists.xml b/lib/stdlib/doc/src/proplists.xml
index f9a54bf804..4465103469 100644
--- a/lib/stdlib/doc/src/proplists.xml
+++ b/lib/stdlib/doc/src/proplists.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>proplists.xml</file>
</header>
- <module>proplists</module>
+ <module since="">proplists</module>
<modulesummary>Support functions for property lists.</modulesummary>
<description>
<p>Property lists are ordinary lists containing entries in the form
@@ -57,11 +57,16 @@
<datatype>
<name name="property"/>
</datatype>
+
+ <datatype>
+ <name name="proplist"/>
+ </datatype>
+
</datatypes>
<funcs>
<func>
- <name name="append_values" arity="2"/>
+ <name name="append_values" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Similar to
@@ -79,7 +84,7 @@ append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])</code>
</func>
<func>
- <name name="compact" arity="1"/>
+ <name name="compact" arity="1" since=""/>
<fsummary></fsummary>
<desc>
<p>Minimizes the representation of all entries in the list. This is
@@ -91,7 +96,7 @@ append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])</code>
</func>
<func>
- <name name="delete" arity="2"/>
+ <name name="delete" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Deletes all entries associated with <c><anno>Key</anno></c> from
@@ -100,7 +105,7 @@ append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])</code>
</func>
<func>
- <name name="expand" arity="2"/>
+ <name name="expand" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Expands particular properties to corresponding sets of
@@ -133,7 +138,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="get_all_values" arity="2"/>
+ <name name="get_all_values" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Similar to
@@ -145,7 +150,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="get_bool" arity="2"/>
+ <name name="get_bool" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Returns the value of a boolean key/value option. If
@@ -159,7 +164,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="get_keys" arity="1"/>
+ <name name="get_keys" arity="1" since=""/>
<fsummary></fsummary>
<desc>
<p>Returns an unordered list of the keys used in
@@ -168,7 +173,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="get_value" arity="2"/>
+ <name name="get_value" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Equivalent to
@@ -177,7 +182,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="get_value" arity="3"/>
+ <name name="get_value" arity="3" since=""/>
<fsummary></fsummary>
<desc>
<p>Returns the value of a simple key/value property in
@@ -194,7 +199,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="is_defined" arity="2"/>
+ <name name="is_defined" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>List</anno></c> contains at least
@@ -204,7 +209,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="lookup" arity="2"/>
+ <name name="lookup" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Returns the first entry associated with <c><anno>Key</anno></c> in
@@ -219,7 +224,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="lookup_all" arity="2"/>
+ <name name="lookup_all" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Returns the list of all entries associated with
@@ -231,7 +236,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="normalize" arity="2"/>
+ <name name="normalize" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Passes <c><anno>ListIn</anno></c> through a sequence of
@@ -263,7 +268,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="property" arity="1"/>
+ <name name="property" arity="1" since=""/>
<fsummary></fsummary>
<desc>
<p>Creates a normal form (minimal) representation of a property. If
@@ -276,7 +281,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="property" arity="2"/>
+ <name name="property" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Creates a normal form (minimal) representation of a simple key/value
@@ -289,7 +294,7 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
</func>
<func>
- <name name="split" arity="2"/>
+ <name name="split" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Partitions <c><anno>List</anno></c> into a list of sublists and a
@@ -310,7 +315,7 @@ split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])</code>
</func>
<func>
- <name name="substitute_aliases" arity="2"/>
+ <name name="substitute_aliases" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Substitutes keys of properties. For each entry in
@@ -332,7 +337,7 @@ split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])</code>
</func>
<func>
- <name name="substitute_negations" arity="2"/>
+ <name name="substitute_negations" arity="2" since=""/>
<fsummary></fsummary>
<desc>
<p>Substitutes keys of boolean-valued properties and
@@ -360,7 +365,7 @@ split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])</code>
</func>
<func>
- <name name="unfold" arity="1"/>
+ <name name="unfold" arity="1" since=""/>
<fsummary></fsummary>
<desc>
<p>Unfolds all occurrences of atoms in <c><anno>ListIn</anno></c> to
diff --git a/lib/stdlib/doc/src/qlc.xml b/lib/stdlib/doc/src/qlc.xml
index fe14a6334c..fe60c2e9bb 100644
--- a/lib/stdlib/doc/src/qlc.xml
+++ b/lib/stdlib/doc/src/qlc.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>qlc.xml</file>
</header>
- <module>qlc</module>
+ <module since="">qlc</module>
<modulesummary>Query interface to Mnesia, ETS, Dets, and so on.
</modulesummary>
<description>
@@ -720,7 +720,7 @@ ets:match_spec_run(ets:lookup(86033, {2,2}),
<funcs>
<func>
- <name name="append" arity="1"/>
+ <name name="append" arity="1" since=""/>
<fsummary>Return a query handle.</fsummary>
<desc>
<p>Returns a query handle. When evaluating query handle
@@ -731,7 +731,7 @@ ets:match_spec_run(ets:lookup(86033, {2,2}),
</func>
<func>
- <name name="append" arity="2"/>
+ <name name="append" arity="2" since=""/>
<fsummary>Return a query handle.</fsummary>
<desc>
<p>Returns a query handle. When evaluating query handle
@@ -744,8 +744,8 @@ ets:match_spec_run(ets:lookup(86033, {2,2}),
</func>
<func>
- <name name="cursor" arity="1"/>
- <name name="cursor" arity="2"/>
+ <name name="cursor" arity="1" since=""/>
+ <name name="cursor" arity="2" since=""/>
<fsummary>Create a query cursor.</fsummary>
<desc>
<p>Creates a query cursor and
@@ -777,7 +777,7 @@ ok</pre>
</func>
<func>
- <name name="delete_cursor" arity="1"/>
+ <name name="delete_cursor" arity="1" since=""/>
<fsummary>Delete a query cursor.</fsummary>
<desc>
<p>Deletes a query cursor. Only the owner of the cursor can
@@ -786,10 +786,10 @@ ok</pre>
</func>
<func>
- <name name="e" arity="1"/>
- <name name="e" arity="2"/>
- <name name="eval" arity="1"/>
- <name name="eval" arity="2"/>
+ <name name="e" arity="1" since=""/>
+ <name name="e" arity="2" since=""/>
+ <name name="eval" arity="1" since=""/>
+ <name name="eval" arity="2" since=""/>
<fsummary>Return all answers to a query.</fsummary>
<desc>
<p>Evaluates a query handle in the
@@ -805,8 +805,8 @@ ok</pre>
</func>
<func>
- <name name="fold" arity="3"/>
- <name name="fold" arity="4"/>
+ <name name="fold" arity="3" since=""/>
+ <name name="fold" arity="4" since=""/>
<fsummary>Fold a function over the answers to a query.</fsummary>
<desc>
<p>Calls <c><anno>Function</anno></c> on successive answers to
@@ -830,7 +830,7 @@ ok</pre>
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Return an English description of a an error tuple.</fsummary>
<desc>
<p>Returns a descriptive string in English of an error tuple
@@ -841,8 +841,8 @@ ok</pre>
</func>
<func>
- <name name="info" arity="1"/>
- <name name="info" arity="2"/>
+ <name name="info" arity="1" since=""/>
+ <name name="info" arity="2" since=""/>
<fsummary>Return code describing a query handle.</fsummary>
<desc>
<p>Returns information about a
@@ -946,8 +946,8 @@ end</pre>
</func>
<func>
- <name name="keysort" arity="2"/>
- <name name="keysort" arity="3"/>
+ <name name="keysort" arity="2" since=""/>
+ <name name="keysort" arity="3" since=""/>
<fsummary>Return a query handle.</fsummary>
<desc>
<p>Returns a query handle. When evaluating query handle
@@ -967,8 +967,8 @@ end</pre>
</func>
<func>
- <name name="next_answers" arity="1"/>
- <name name="next_answers" arity="2"/>
+ <name name="next_answers" arity="1" since=""/>
+ <name name="next_answers" arity="2" since=""/>
<fsummary>Return some or all answers to a query.</fsummary>
<desc>
<p>Returns some or all of the remaining answers to a query
@@ -983,8 +983,8 @@ end</pre>
</func>
<func>
- <name name="q" arity="1"/>
- <name name="q" arity="2"/>
+ <name name="q" arity="1" since=""/>
+ <name name="q" arity="2" since=""/>
<fsummary>Return a handle for a query list comprehension.</fsummary>
<desc>
<p>Returns a query handle for a QLC.
@@ -1188,8 +1188,8 @@ ets:match_spec_run(
</func>
<func>
- <name name="sort" arity="1"/>
- <name name="sort" arity="2"/>
+ <name name="sort" arity="1" since=""/>
+ <name name="sort" arity="2" since=""/>
<fsummary>Return a query handle.</fsummary>
<desc>
<p>Returns a query handle. When evaluating query handle
@@ -1208,9 +1208,9 @@ ets:match_spec_run(
</func>
<func>
- <name name="string_to_handle" arity="1"/>
- <name name="string_to_handle" arity="2"/>
- <name name="string_to_handle" arity="3"/>
+ <name name="string_to_handle" arity="1" since=""/>
+ <name name="string_to_handle" arity="2" since=""/>
+ <name name="string_to_handle" arity="3" since=""/>
<fsummary>Return a handle for a query list comprehension.</fsummary>
<desc>
<p>A string version of <seealso marker="#q/1"><c>q/1,2</c></seealso>.
@@ -1238,7 +1238,7 @@ ets:match_spec_run(
</func>
<func>
- <name name="table" arity="2"/>
+ <name name="table" arity="2" since=""/>
<fsummary>Return a query handle for a table.</fsummary>
<desc>
<p>Returns a query handle for a QLC table.
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml
index 9f3aff03a3..83a8afea81 100644
--- a/lib/stdlib/doc/src/queue.xml
+++ b/lib/stdlib/doc/src/queue.xml
@@ -32,7 +32,7 @@
<rev>B</rev>
<file>queue.xml</file>
</header>
- <module>queue</module>
+ <module since="">queue</module>
<modulesummary>Abstract data type for FIFO queues.</modulesummary>
<description>
<p>This module provides (double-ended) FIFO queues
@@ -113,7 +113,7 @@
<funcs>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since=""/>
<fsummary>Filter a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> that is the result of calling
@@ -134,7 +134,7 @@
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since=""/>
<fsummary>Convert a list to a queue.</fsummary>
<desc>
<p>Returns a queue containing the items in <c><anno>L</anno></c> in the
@@ -144,7 +144,7 @@
</func>
<func>
- <name name="in" arity="2"/>
+ <name name="in" arity="2" since=""/>
<fsummary>Insert an item at the rear of a queue.</fsummary>
<desc>
<p>Inserts <c><anno>Item</anno></c> at the rear of queue
@@ -154,7 +154,7 @@
</func>
<func>
- <name name="in_r" arity="2"/>
+ <name name="in_r" arity="2" since=""/>
<fsummary>Insert an item at the front of a queue.</fsummary>
<desc>
<p>Inserts <c><anno>Item</anno></c> at the front of queue
@@ -164,7 +164,7 @@
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since=""/>
<fsummary>Test if a queue is empty.</fsummary>
<desc>
<p>Tests if <c><anno>Q</anno></c> is empty and returns <c>true</c> if
@@ -173,7 +173,7 @@
</func>
<func>
- <name name="is_queue" arity="1"/>
+ <name name="is_queue" arity="1" since=""/>
<fsummary>Test if a term is a queue.</fsummary>
<desc>
<p>Tests if <c><anno>Term</anno></c> is a queue and returns <c>true</c>
@@ -182,7 +182,7 @@
</func>
<func>
- <name name="join" arity="2"/>
+ <name name="join" arity="2" since=""/>
<fsummary>Join two queues.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q3</anno></c> that is the result of joining
@@ -192,7 +192,7 @@
</func>
<func>
- <name name="len" arity="1"/>
+ <name name="len" arity="1" since=""/>
<fsummary>Get the length of a queue.</fsummary>
<desc>
<p>Calculates and returns the length of queue <c><anno>Q</anno></c>.</p>
@@ -200,7 +200,7 @@
</func>
<func>
- <name name="member" arity="2"/>
+ <name name="member" arity="2" since=""/>
<fsummary>Test if an item is in a queue.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Item</anno></c> matches some element
@@ -209,7 +209,7 @@
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Create an empty queue.</fsummary>
<desc>
<p>Returns an empty queue.</p>
@@ -217,7 +217,7 @@
</func>
<func>
- <name name="out" arity="1"/>
+ <name name="out" arity="1" since=""/>
<fsummary>Remove the front item from a queue.</fsummary>
<desc>
<p>Removes the item at the front of queue <c><anno>Q1</anno></c>.
@@ -230,7 +230,7 @@
</func>
<func>
- <name name="out_r" arity="1"/>
+ <name name="out_r" arity="1" since=""/>
<fsummary>Remove the rear item from a queue.</fsummary>
<desc>
<p>Removes the item at the rear of queue <c><anno>Q1</anno></c>.
@@ -242,7 +242,7 @@
</func>
<func>
- <name name="reverse" arity="1"/>
+ <name name="reverse" arity="1" since=""/>
<fsummary>Reverse a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> containing the items of
@@ -251,7 +251,7 @@
</func>
<func>
- <name name="split" arity="2"/>
+ <name name="split" arity="2" since=""/>
<fsummary>Split a queue in two.</fsummary>
<desc>
<p>Splits <c><anno>Q1</anno></c> in two. The <c><anno>N</anno></c>
@@ -261,7 +261,7 @@
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert a queue to a list.</fsummary>
<desc>
<p>Returns a list of the items in the queue in the same order;
@@ -276,7 +276,7 @@
<funcs>
<func>
- <name name="drop" arity="1"/>
+ <name name="drop" arity="1" since=""/>
<fsummary>Remove the front item from a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
@@ -286,7 +286,7 @@
</func>
<func>
- <name name="drop_r" arity="1"/>
+ <name name="drop_r" arity="1" since=""/>
<fsummary>Remove the rear item from a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
@@ -296,7 +296,7 @@
</func>
<func>
- <name name="get" arity="1"/>
+ <name name="get" arity="1" since=""/>
<fsummary>Return the front item of a queue.</fsummary>
<desc>
<p>Returns <c><anno>Item</anno></c> at the front of queue
@@ -306,7 +306,7 @@
</func>
<func>
- <name name="get_r" arity="1"/>
+ <name name="get_r" arity="1" since=""/>
<fsummary>Return the rear item of a queue.</fsummary>
<desc>
<p>Returns <c><anno>Item</anno></c> at the rear of queue
@@ -316,7 +316,7 @@
</func>
<func>
- <name name="peek" arity="1"/>
+ <name name="peek" arity="1" since=""/>
<fsummary>Return the front item of a queue.</fsummary>
<desc>
<p>Returns tuple <c>{value, <anno>Item</anno>}</c>, where
@@ -326,7 +326,7 @@
</func>
<func>
- <name name="peek_r" arity="1"/>
+ <name name="peek_r" arity="1" since=""/>
<fsummary>Return the rear item of a queue.</fsummary>
<desc>
<p>Returns tuple <c>{value, <anno>Item</anno>}</c>, where
@@ -342,7 +342,7 @@
<funcs>
<func>
- <name name="cons" arity="2"/>
+ <name name="cons" arity="2" since=""/>
<fsummary>Insert an item at the head of a queue.</fsummary>
<desc>
<p>Inserts <c><anno>Item</anno></c> at the head of queue
@@ -352,7 +352,7 @@
</func>
<func>
- <name name="daeh" arity="1"/>
+ <name name="daeh" arity="1" since=""/>
<fsummary>Return the tail item of a queue.</fsummary>
<desc>
<p>Returns the tail item of queue <c><anno>Q</anno></c>.</p>
@@ -361,7 +361,7 @@
</func>
<func>
- <name name="head" arity="1"/>
+ <name name="head" arity="1" since=""/>
<fsummary>Return the item at the head of a queue.</fsummary>
<desc>
<p>Returns <c><anno>Item</anno></c> from the head of queue
@@ -371,7 +371,7 @@
</func>
<func>
- <name name="init" arity="1"/>
+ <name name="init" arity="1" since=""/>
<fsummary>Remove the tail item from a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
@@ -381,7 +381,7 @@
</func>
<func>
- <name name="lait" arity="1"/>
+ <name name="lait" arity="1" since=""/>
<fsummary>Remove the tail item from a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
@@ -392,7 +392,7 @@
</func>
<func>
- <name name="last" arity="1"/>
+ <name name="last" arity="1" since=""/>
<fsummary>Return the tail item of a queue.</fsummary>
<desc>
<p>Returns the tail item of queue <c><anno>Q</anno></c>.</p>
@@ -401,7 +401,7 @@
</func>
<func>
- <name name="liat" arity="1"/>
+ <name name="liat" arity="1" since=""/>
<fsummary>Remove the tail item from a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
@@ -411,7 +411,7 @@
</func>
<func>
- <name name="snoc" arity="2"/>
+ <name name="snoc" arity="2" since=""/>
<fsummary>Insert an item at the tail of a queue.</fsummary>
<desc>
<p>Inserts <c><anno>Item</anno></c> as the tail item of queue
@@ -421,7 +421,7 @@
</func>
<func>
- <name name="tail" arity="1"/>
+ <name name="tail" arity="1" since=""/>
<fsummary>Remove the head item from a queue.</fsummary>
<desc>
<p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index 21f680a0ee..27d2d99f3c 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>rand.xml</file>
</header>
- <module>rand</module>
+ <module since="OTP 18.0">rand</module>
<modulesummary>Pseudo random number generation.</modulesummary>
<description>
<p>
@@ -273,7 +273,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<funcs>
<func>
- <name name="export_seed" arity="0"/>
+ <name name="export_seed" arity="0" since="OTP 18.0"/>
<fsummary>Export the random number generation state.</fsummary>
<desc><marker id="export_seed-0"/>
<p>Returns the random number state in an external format.
@@ -282,7 +282,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="export_seed_s" arity="1"/>
+ <name name="export_seed_s" arity="1" since="OTP 18.0"/>
<fsummary>Export the random number generation state.</fsummary>
<desc><marker id="export_seed_s-1"/>
<p>Returns the random number generator state in an external format.
@@ -291,7 +291,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="jump" arity="0"/>
+ <name name="jump" arity="0" since="OTP 20.0"/>
<fsummary>Return the seed after performing jump calculation
to the state in the process dictionary.</fsummary>
<desc><marker id="jump-0" />
@@ -306,7 +306,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="jump" arity="1"/>
+ <name name="jump" arity="1" since="OTP 20.0"/>
<fsummary>Return the seed after performing jump calculation.</fsummary>
<desc><marker id="jump-1" />
<p>Returns the state after performing jump calculation
@@ -318,7 +318,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="normal" arity="0"/>
+ <name name="normal" arity="0" since="OTP 18.0"/>
<fsummary>Return a standard normal distributed random float.</fsummary>
<desc>
<p>Returns a standard normal deviate float (that is, the mean
@@ -328,7 +328,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="normal" arity="2"/>
+ <name name="normal" arity="2" since="OTP 20.0"/>
<fsummary>Return a normal distributed random float.</fsummary>
<desc>
<p>Returns a normal N(Mean, Variance) deviate float
@@ -337,7 +337,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="normal_s" arity="1"/>
+ <name name="normal_s" arity="1" since="OTP 18.0"/>
<fsummary>Return a standard normal distributed random float.</fsummary>
<desc>
<p>Returns, for a specified state, a standard normal
@@ -347,7 +347,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="normal_s" arity="3"/>
+ <name name="normal_s" arity="3" since="OTP 20.0"/>
<fsummary>Return a normal distributed random float.</fsummary>
<desc>
<p>Returns, for a specified state, a normal N(Mean, Variance)
@@ -356,7 +356,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="seed" arity="1"/>
+ <name name="seed" arity="1" since="OTP 18.0"/>
<fsummary>Seed random number generator.</fsummary>
<desc>
<marker id="seed-1"/>
@@ -372,7 +372,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="seed" arity="2"/>
+ <name name="seed" arity="2" since="OTP 18.0"/>
<fsummary>Seed the random number generation.</fsummary>
<desc>
<p>Seeds random number generation with the specified algorithm and
@@ -381,7 +381,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="seed_s" arity="1"/>
+ <name name="seed_s" arity="1" since="OTP 18.0"/>
<fsummary>Seed random number generator.</fsummary>
<desc>
<p>
@@ -396,7 +396,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="seed_s" arity="2"/>
+ <name name="seed_s" arity="2" since="OTP 18.0"/>
<fsummary>Seed the random number generation.</fsummary>
<desc>
<p>Seeds random number generation with the specified algorithm and
@@ -405,7 +405,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</func>
<func>
- <name name="uniform" arity="0"/>
+ <name name="uniform" arity="0" since="OTP 18.0"/>
<fsummary>Return a random float.</fsummary>
<desc><marker id="uniform-0"/>
<p>
@@ -441,7 +441,7 @@ end.</pre>
</func>
<func>
- <name name="uniform_real" arity="0"/>
+ <name name="uniform_real" arity="0" since="OTP 21.0"/>
<fsummary>Return a random float.</fsummary>
<desc><marker id="uniform_real-0"/>
<p>
@@ -477,7 +477,7 @@ end.</pre>
</func>
<func>
- <name name="uniform" arity="1"/>
+ <name name="uniform" arity="1" since="OTP 18.0"/>
<fsummary>Return a random integer.</fsummary>
<desc><marker id="uniform-1"/>
<p>Returns, for a specified integer <c><anno>N</anno> >= 1</c>,
@@ -488,7 +488,7 @@ end.</pre>
</func>
<func>
- <name name="uniform_s" arity="1"/>
+ <name name="uniform_s" arity="1" since="OTP 18.0"/>
<fsummary>Return a random float.</fsummary>
<desc>
<p>
@@ -524,7 +524,7 @@ end.</pre>
</func>
<func>
- <name name="uniform_real_s" arity="1"/>
+ <name name="uniform_real_s" arity="1" since="OTP 21.0"/>
<fsummary>Return a random float.</fsummary>
<desc>
<p>
@@ -586,7 +586,7 @@ end.</pre>
</func>
<func>
- <name name="uniform_s" arity="2"/>
+ <name name="uniform_s" arity="2" since="OTP 18.0"/>
<fsummary>Return a random integer.</fsummary>
<desc>
<p>Returns, for a specified integer <c><anno>N</anno> >= 1</c>
diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml
index 8d090d20b3..f0261ed009 100644
--- a/lib/stdlib/doc/src/random.xml
+++ b/lib/stdlib/doc/src/random.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>random.xml</file>
</header>
- <module>random</module>
+ <module since="">random</module>
<modulesummary>Pseudo-random number generation.</modulesummary>
<description>
<p>This module provides a random number generator. The method is attributed
@@ -73,7 +73,7 @@
<funcs>
<func>
- <name name="seed" arity="0"/>
+ <name name="seed" arity="0" since=""/>
<fsummary>Seed random number generation with default values.</fsummary>
<desc>
<p>Seeds random number generation with default (fixed) values
@@ -82,7 +82,7 @@
</func>
<func>
- <name name="seed" arity="1"/>
+ <name name="seed" arity="1" since=""/>
<fsummary>Seed random number generator.</fsummary>
<desc>
<p><c>seed({<anno>A1</anno>, <anno>A2</anno>, <anno>A3</anno>})</c>
@@ -92,7 +92,7 @@
</func>
<func>
- <name name="seed" arity="3"/>
+ <name name="seed" arity="3" since=""/>
<fsummary>Seed random number generator.</fsummary>
<desc>
<p>Seeds random number generation with integer values in the process
@@ -116,7 +116,7 @@ random:seed(erlang:phash2([node()]),
</func>
<func>
- <name name="seed0" arity="0"/>
+ <name name="seed0" arity="0" since=""/>
<fsummary>Return default state for random number generation.</fsummary>
<desc>
<p>Returns the default state.</p>
@@ -124,7 +124,7 @@ random:seed(erlang:phash2([node()]),
</func>
<func>
- <name name="uniform" arity="0"/>
+ <name name="uniform" arity="0" since=""/>
<fsummary>Return a random float.</fsummary>
<desc>
<p>Returns a random float uniformly distributed between <c>0.0</c>
@@ -133,7 +133,7 @@ random:seed(erlang:phash2([node()]),
</func>
<func>
- <name name="uniform" arity="1"/>
+ <name name="uniform" arity="1" since=""/>
<fsummary>Return a random integer.</fsummary>
<desc>
<p>Returns, for a specified integer <c><anno>N</anno> >= 1</c>,
@@ -144,7 +144,7 @@ random:seed(erlang:phash2([node()]),
</func>
<func>
- <name name="uniform_s" arity="1"/>
+ <name name="uniform_s" arity="1" since=""/>
<fsummary>Return a random float.</fsummary>
<desc>
<p>Returns, for a specified state, a random float uniformly
@@ -153,7 +153,7 @@ random:seed(erlang:phash2([node()]),
</func>
<func>
- <name name="uniform_s" arity="2"/>
+ <name name="uniform_s" arity="2" since=""/>
<fsummary>Return a random integer.</fsummary>
<desc>
<p>Returns, for a specified integer <c><anno>N</anno> >= 1</c> and a
diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml
index 078ca0e38c..b04434492d 100644
--- a/lib/stdlib/doc/src/re.xml
+++ b/lib/stdlib/doc/src/re.xml
@@ -34,7 +34,7 @@
<rev>A</rev>
<file>re.xml</file>
</header>
- <module>re</module>
+ <module since="">re</module>
<modulesummary>Perl-like regular expressions for Erlang.</modulesummary>
<description>
<p>This module contains regular expression matching functions for
@@ -79,7 +79,7 @@
<funcs>
<func>
- <name name="version" arity="0"/>
+ <name name="version" arity="0" since="OTP 20.0"/>
<fsummary>Gives the PCRE version of the system in a string format</fsummary>
<desc>
<p>The return of this function is a string with the PCRE version of the system that was used in the Erlang/OTP compilation.</p>
@@ -87,7 +87,7 @@
</func>
<func>
- <name name="compile" arity="1"/>
+ <name name="compile" arity="1" since=""/>
<fsummary>Compile a regular expression into a match program</fsummary>
<desc>
<p>The same as <c>compile(<anno>Regexp</anno>,[])</c></p>
@@ -95,7 +95,7 @@
</func>
<func>
- <name name="compile" arity="2"/>
+ <name name="compile" arity="2" since=""/>
<fsummary>Compile a regular expression into a match program.</fsummary>
<desc>
<p>Compiles a regular expression, with the syntax
@@ -304,7 +304,7 @@
</func>
<func>
- <name name="inspect" arity="2"/>
+ <name name="inspect" arity="2" since="OTP 17.0"/>
<fsummary>Inspects a compiled regular expression.</fsummary>
<desc>
<p>Takes a compiled regular expression and an item, and returns the
@@ -348,7 +348,7 @@
</func>
<func>
- <name name="replace" arity="3"/>
+ <name name="replace" arity="3" since=""/>
<fsummary>Match a subject against regular expression and replace matching
elements with Replacement.</fsummary>
<desc>
@@ -358,7 +358,7 @@
</func>
<func>
- <name name="replace" arity="4"/>
+ <name name="replace" arity="4" since=""/>
<fsummary>Match a subject against regular expression and replace matching
elements with Replacement.</fsummary>
<desc>
@@ -408,7 +408,7 @@ re:replace("abcd","c","[\\&amp;]",[{return,list}]).</code>
</func>
<func>
- <name name="run" arity="2"/>
+ <name name="run" arity="2" since=""/>
<fsummary>Match a subject against regular expression and capture
subpatterns.</fsummary>
<desc>
@@ -417,7 +417,7 @@ re:replace("abcd","c","[\\&amp;]",[{return,list}]).</code>
</func>
<func>
- <name name="run" arity="3"/>
+ <name name="run" arity="3" since=""/>
<fsummary>Match a subject against regular expression and capture
subpatterns.</fsummary>
<type_desc variable="CompileOpt">See <seealso marker="#compile_options">
@@ -992,7 +992,7 @@ re:run("cacb","c(a|b)",[global,{capture,[1],list}]).</code>
</func>
<func>
- <name name="split" arity="2"/>
+ <name name="split" arity="2" since=""/>
<fsummary>Split a string by tokens specified as a regular expression.
</fsummary>
<desc>
@@ -1001,7 +1001,7 @@ re:run("cacb","c(a|b)",[global,{capture,[1],list}]).</code>
</func>
<func>
- <name name="split" arity="3"/>
+ <name name="split" arity="3" since=""/>
<fsummary>Split a string by tokens specified as a regular expression</fsummary>
<type_desc variable="CompileOpt">See <seealso marker="#compile_options">
<c>compile/2</c></seealso>.</type_desc>
diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml
index 8db3e1e623..07ce41b7a7 100644
--- a/lib/stdlib/doc/src/sets.xml
+++ b/lib/stdlib/doc/src/sets.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>sets.xml</file>
</header>
- <module>sets</module>
+ <module since="">sets</module>
<modulesummary>Functions for set manipulation.</modulesummary>
<description>
<p>Sets are collections of elements with no duplicate elements.
@@ -59,7 +59,7 @@
<funcs>
<func>
- <name name="add_element" arity="2"/>
+ <name name="add_element" arity="2" since=""/>
<fsummary>Add an element to a <c>Set</c>.</fsummary>
<desc>
<p>Returns a new set formed from <c><anno>Set1</anno></c> with
@@ -68,7 +68,7 @@
</func>
<func>
- <name name="del_element" arity="2"/>
+ <name name="del_element" arity="2" since=""/>
<fsummary>Remove an element from a <c>Set</c>.</fsummary>
<desc>
<p>Returns <c><anno>Set1</anno></c>, but with
@@ -77,7 +77,7 @@
</func>
<func>
- <name name="filter" arity="2"/>
+ <name name="filter" arity="2" since=""/>
<fsummary>Filter set elements.</fsummary>
<desc>
<p>Filters elements in <c><anno>Set1</anno></c> with boolean function
@@ -86,7 +86,7 @@
</func>
<func>
- <name name="fold" arity="3"/>
+ <name name="fold" arity="3" since=""/>
<fsummary>Fold over set elements.</fsummary>
<desc>
<p>Folds <c><anno>Function</anno></c> over every element in
@@ -96,7 +96,7 @@
</func>
<func>
- <name name="from_list" arity="1"/>
+ <name name="from_list" arity="1" since=""/>
<fsummary>Convert a list into a <c>Set</c>.</fsummary>
<desc>
<p>Returns a set of the elements in <c><anno>List</anno></c>.</p>
@@ -104,7 +104,7 @@
</func>
<func>
- <name name="intersection" arity="1"/>
+ <name name="intersection" arity="1" since=""/>
<fsummary>Return the intersection of a list of <c>Sets</c>.</fsummary>
<desc>
<p>Returns the intersection of the non-empty list of sets.</p>
@@ -112,7 +112,7 @@
</func>
<func>
- <name name="intersection" arity="2"/>
+ <name name="intersection" arity="2" since=""/>
<fsummary>Return the intersection of two <c>Sets</c>.</fsummary>
<desc>
<p>Returns the intersection of <c><anno>Set1</anno></c> and
@@ -121,7 +121,7 @@
</func>
<func>
- <name name="is_disjoint" arity="2"/>
+ <name name="is_disjoint" arity="2" since=""/>
<fsummary>Check whether two <c>Sets</c> are disjoint.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Set1</anno></c> and
@@ -131,7 +131,7 @@
</func>
<func>
- <name name="is_element" arity="2"/>
+ <name name="is_element" arity="2" since=""/>
<fsummary>Test for membership of a <c>Set</c>.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of
@@ -140,7 +140,7 @@
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since="OTP 21.0"/>
<fsummary>Test for empty set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Set</anno></c> is an empty set,
@@ -149,7 +149,7 @@
</func>
<func>
- <name name="is_set" arity="1"/>
+ <name name="is_set" arity="1" since=""/>
<fsummary>Test for a <c>Set</c>.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Set</anno></c> is a set of
@@ -158,7 +158,7 @@
</func>
<func>
- <name name="is_subset" arity="2"/>
+ <name name="is_subset" arity="2" since=""/>
<fsummary>Test for subset.</fsummary>
<desc>
<p>Returns <c>true</c> when every element of <c><anno>Set1</anno></c> is
@@ -167,7 +167,7 @@
</func>
<func>
- <name name="new" arity="0"/>
+ <name name="new" arity="0" since=""/>
<fsummary>Return an empty set.</fsummary>
<desc>
<p>Returns a new empty set.</p>
@@ -175,7 +175,7 @@
</func>
<func>
- <name name="size" arity="1"/>
+ <name name="size" arity="1" since=""/>
<fsummary>Return the number of elements in a set.</fsummary>
<desc>
<p>Returns the number of elements in <c><anno>Set</anno></c>.</p>
@@ -183,7 +183,7 @@
</func>
<func>
- <name name="subtract" arity="2"/>
+ <name name="subtract" arity="2" since=""/>
<fsummary>Return the difference of two <c>Sets</c>.</fsummary>
<desc>
<p>Returns only the elements of <c><anno>Set1</anno></c> that are not
@@ -192,7 +192,7 @@
</func>
<func>
- <name name="to_list" arity="1"/>
+ <name name="to_list" arity="1" since=""/>
<fsummary>Convert a <c>Set</c>into a list.</fsummary>
<desc>
<p>Returns the elements of <c><anno>Set</anno></c> as a list.
@@ -201,7 +201,7 @@
</func>
<func>
- <name name="union" arity="1"/>
+ <name name="union" arity="1" since=""/>
<fsummary>Return the union of a list of <c>Sets</c>.</fsummary>
<desc>
<p>Returns the merged (union) set of the list of sets.</p>
@@ -209,7 +209,7 @@
</func>
<func>
- <name name="union" arity="2"/>
+ <name name="union" arity="2" since=""/>
<fsummary>Return the union of two <c>Sets</c>.</fsummary>
<desc>
<p>Returns the merged (union) set of <c><anno>Set1</anno></c> and
diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml
index 2593d3690b..50a0968531 100644
--- a/lib/stdlib/doc/src/shell.xml
+++ b/lib/stdlib/doc/src/shell.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>shell.xml</file>
</header>
- <module>shell</module>
+ <module since="">shell</module>
<modulesummary>The Erlang shell.</modulesummary>
<description>
<p>This module provides an Erlang shell.</p>
@@ -874,7 +874,7 @@ q - quit erlang
<funcs>
<func>
- <name>catch_exception(Bool) -> boolean()</name>
+ <name since="">catch_exception(Bool) -> boolean()</name>
<fsummary>Set the exception handling of the shell.</fsummary>
<type>
<v>Bool = boolean()</v>
@@ -892,7 +892,7 @@ q - quit erlang
</func>
<func>
- <name name="history" arity="1"/>
+ <name name="history" arity="1" since=""/>
<fsummary>Set the number of previous commands to keep.</fsummary>
<desc>
<p>Sets the number of previous commands to keep in the
@@ -902,7 +902,7 @@ q - quit erlang
</func>
<func>
- <name name="prompt_func" arity="1"/>
+ <name name="prompt_func" arity="1" since="OTP R13B04"/>
<fsummary>Set the shell prompt.</fsummary>
<desc>
<p>Sets the shell prompt function to <c><anno>PromptFunc</anno></c>.
@@ -911,7 +911,7 @@ q - quit erlang
</func>
<func>
- <name name="results" arity="1"/>
+ <name name="results" arity="1" since=""/>
<fsummary>Set the number of previous results to keep.</fsummary>
<desc>
<p>Sets the number of results from previous commands to keep in
@@ -921,7 +921,7 @@ q - quit erlang
</func>
<func>
- <name name="start_restricted" arity="1"/>
+ <name name="start_restricted" arity="1" since=""/>
<fsummary>Exit a normal shell and starts a restricted shell.</fsummary>
<desc>
<p>Exits a normal shell and starts a restricted shell.
@@ -936,7 +936,7 @@ q - quit erlang
</func>
<func>
- <name name="stop_restricted" arity="0"/>
+ <name name="stop_restricted" arity="0" since=""/>
<fsummary>Exit a restricted shell and starts a normal shell.</fsummary>
<desc>
<p>Exits a restricted shell and starts a normal shell. The function
@@ -945,7 +945,7 @@ q - quit erlang
</func>
<func>
- <name name="strings" arity="1"/>
+ <name name="strings" arity="1" since="OTP R16B"/>
<fsummary>Set the shell's string recognition flag.</fsummary>
<desc>
<p>Sets pretty printing of lists to <c><anno>Strings</anno></c>.
diff --git a/lib/stdlib/doc/src/slave.xml b/lib/stdlib/doc/src/slave.xml
index e53ec8231b..80fb28b548 100644
--- a/lib/stdlib/doc/src/slave.xml
+++ b/lib/stdlib/doc/src/slave.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>slave</module>
+ <module since="">slave</module>
<modulesummary>Functions for starting and controlling slave nodes.
</modulesummary>
<description>
@@ -68,7 +68,7 @@
<funcs>
<func>
- <name>pseudo([Master | ServerList]) -> ok</name>
+ <name since="">pseudo([Master | ServerList]) -> ok</name>
<fsummary>Start a number of pseudo servers.</fsummary>
<type>
<v>Master = node()</v>
@@ -84,7 +84,7 @@
</func>
<func>
- <name name="pseudo" arity="2"/>
+ <name name="pseudo" arity="2" since=""/>
<fsummary>Start a number of pseudo servers.</fsummary>
<desc>
<p>Starts a number of pseudo servers. A pseudo server is a
@@ -102,7 +102,7 @@ rpc:call(N, slave, pseudo, [node(), [pxw_server]]).</code>
</func>
<func>
- <name name="relay" arity="1"/>
+ <name name="relay" arity="1" since=""/>
<fsummary>Run a pseudo server.</fsummary>
<desc>
<p>Runs a pseudo server. This function never returns any value
@@ -113,9 +113,9 @@ rpc:call(N, slave, pseudo, [node(), [pxw_server]]).</code>
</func>
<func>
- <name name="start" arity="1"/>
- <name name="start" arity="2"/>
- <name name="start" arity="3"/>
+ <name name="start" arity="1" since=""/>
+ <name name="start" arity="2" since=""/>
+ <name name="start" arity="3" since=""/>
<fsummary>Start a slave node on a host.</fsummary>
<desc>
<p>Starts a slave node on host <c><anno>Host</anno></c>. Host names
@@ -178,9 +178,9 @@ slave:start(H, Name, Arg).</code>
</func>
<func>
- <name name="start_link" arity="1"/>
- <name name="start_link" arity="2"/>
- <name name="start_link" arity="3"/>
+ <name name="start_link" arity="1" since=""/>
+ <name name="start_link" arity="2" since=""/>
+ <name name="start_link" arity="3" since=""/>
<fsummary>Start and link to a slave node on a host.</fsummary>
<desc>
<p>Starts a slave node in the same way as <c>start/1,2,3</c>,
@@ -193,7 +193,7 @@ slave:start(H, Name, Arg).</code>
</func>
<func>
- <name name="stop" arity="1"/>
+ <name name="stop" arity="1" since=""/>
<fsummary>Stop (kill) a node.</fsummary>
<desc>
<p>Stops (kills) a node.</p>
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index 4cf1984d46..a0759d2f52 100644
--- a/lib/stdlib/doc/src/sofs.xml
+++ b/lib/stdlib/doc/src/sofs.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>sofs.xml</file>
</header>
- <module>sofs</module>
+ <module since="">sofs</module>
<modulesummary>Functions for manipulating sets of sets.</modulesummary>
<description>
<p>This module provides operations on finite sets and
@@ -456,8 +456,8 @@ fun(S) -> sofs:partition(1, S) end
<funcs>
<func>
- <name name="a_function" arity="1"/>
- <name name="a_function" arity="2"/>
+ <name name="a_function" arity="1" since=""/>
+ <name name="a_function" arity="2" since=""/>
<fsummary>Create a function.</fsummary>
<desc>
<p>Creates a <seealso marker="#function">function</seealso>.
@@ -470,7 +470,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="canonical_relation" arity="1"/>
+ <name name="canonical_relation" arity="1" since=""/>
<fsummary>Return the canonical map.</fsummary>
<desc>
<p>Returns the binary relation containing the elements
@@ -490,7 +490,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="composite" arity="2"/>
+ <name name="composite" arity="2" since=""/>
<fsummary>Return the composite of two functions.</fsummary>
<desc>
<p>Returns the <seealso marker="#composite">composite</seealso> of
@@ -506,7 +506,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="constant_function" arity="2"/>
+ <name name="constant_function" arity="2" since=""/>
<fsummary>Create the function that maps each element of a
set onto another set.</fsummary>
<desc>
@@ -522,7 +522,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="converse" arity="1"/>
+ <name name="converse" arity="1" since=""/>
<fsummary>Return the converse of a binary relation.</fsummary>
<desc>
<p>Returns the <seealso marker="#converse">converse</seealso>
@@ -536,7 +536,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="difference" arity="2"/>
+ <name name="difference" arity="2" since=""/>
<fsummary>Return the difference of two sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#difference">difference</seealso> of
@@ -545,8 +545,8 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="digraph_to_family" arity="1"/>
- <name name="digraph_to_family" arity="2"/>
+ <name name="digraph_to_family" arity="1" since=""/>
+ <name name="digraph_to_family" arity="2" since=""/>
<fsummary>Create a family from a directed graph.</fsummary>
<desc>
<p>Creates a <seealso marker="#family">family</seealso> from
@@ -565,7 +565,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="domain" arity="1"/>
+ <name name="domain" arity="1" since=""/>
<fsummary>Return the domain of a binary relation.</fsummary>
<desc>
<p>Returns the <seealso marker="#domain">domain</seealso> of
@@ -579,7 +579,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="drestriction" arity="2"/>
+ <name name="drestriction" arity="2" since=""/>
<fsummary>Return a restriction of a binary relation.</fsummary>
<desc>
<p>Returns the difference between the binary relation
@@ -598,7 +598,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="drestriction" arity="3"/>
+ <name name="drestriction" arity="3" since=""/>
<fsummary>Return a restriction of a relation.</fsummary>
<desc>
<p>Returns a subset of <c><anno>Set1</anno></c> containing those
@@ -618,7 +618,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="empty_set" arity="0"/>
+ <name name="empty_set" arity="0" since=""/>
<fsummary>Return the untyped empty set.</fsummary>
<desc>
<p>Returns the <seealso marker="#sets_definition">untyped empty
@@ -628,7 +628,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="extension" arity="3"/>
+ <name name="extension" arity="3" since=""/>
<fsummary>Extend the domain of a binary relation.</fsummary>
<desc>
<p>Returns the <seealso marker="#extension">extension</seealso> of
@@ -648,8 +648,8 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family" arity="1"/>
- <name name="family" arity="2"/>
+ <name name="family" arity="1" since=""/>
+ <name name="family" arity="2" since=""/>
<fsummary>Create a family of subsets.</fsummary>
<desc>
<p>Creates a <seealso marker="#family">family of subsets</seealso>.
@@ -662,7 +662,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_difference" arity="2"/>
+ <name name="family_difference" arity="2" since=""/>
<fsummary>Return the difference of two families.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> and <c><anno>Family2</anno></c>
@@ -683,7 +683,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_domain" arity="1"/>
+ <name name="family_domain" arity="1" since=""/>
<fsummary>Return a family of domains.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> is
@@ -704,7 +704,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_field" arity="1"/>
+ <name name="family_field" arity="1" since=""/>
<fsummary>Return a family of fields.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> is
@@ -728,7 +728,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_intersection" arity="1"/>
+ <name name="family_intersection" arity="1" since=""/>
<fsummary>Return the intersection of a family
of sets of sets.</fsummary>
<desc>
@@ -752,7 +752,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_intersection" arity="2"/>
+ <name name="family_intersection" arity="2" since=""/>
<fsummary>Return the intersection of two families.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> and <c><anno>Family2</anno></c>
@@ -772,7 +772,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_projection" arity="2"/>
+ <name name="family_projection" arity="2" since=""/>
<fsummary>Return a family of modified subsets.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> is
@@ -791,7 +791,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_range" arity="1"/>
+ <name name="family_range" arity="1" since=""/>
<fsummary>Return a family of ranges.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> is
@@ -812,7 +812,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_specification" arity="2"/>
+ <name name="family_specification" arity="2" since=""/>
<fsummary>Select a subset of a family using a predicate.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> is
@@ -837,8 +837,8 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_to_digraph" arity="1"/>
- <name name="family_to_digraph" arity="2"/>
+ <name name="family_to_digraph" arity="1" since=""/>
+ <name name="family_to_digraph" arity="2" since=""/>
<fsummary>Create a directed graph from a family.</fsummary>
<desc>
<p>Creates a directed graph from
@@ -863,7 +863,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_to_relation" arity="1"/>
+ <name name="family_to_relation" arity="1" since=""/>
<fsummary>Create a binary relation from a family.</fsummary>
<desc>
<p>If <c><anno>Family</anno></c> is
@@ -881,7 +881,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_union" arity="1"/>
+ <name name="family_union" arity="1" since=""/>
<fsummary>Return the union of a family of sets of sets.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> is
@@ -904,7 +904,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="family_union" arity="2"/>
+ <name name="family_union" arity="2" since=""/>
<fsummary>Return the union of two families.</fsummary>
<desc>
<p>If <c><anno>Family1</anno></c> and <c><anno>Family2</anno></c>
@@ -926,7 +926,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="field" arity="1"/>
+ <name name="field" arity="1" since=""/>
<fsummary>Return the field of a binary relation.</fsummary>
<desc>
<p>Returns the <seealso marker="#field">field</seealso> of the
@@ -942,7 +942,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="from_external" arity="2"/>
+ <name name="from_external" arity="2" since=""/>
<fsummary>Create a set.</fsummary>
<desc>
<p>Creates a set from the <seealso marker="#external_set">external
@@ -955,7 +955,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="from_sets" arity="1" clause_i="1"/>
+ <name name="from_sets" arity="1" clause_i="1" since=""/>
<fsummary>Create a set out of a list of sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#sets_definition">unordered
@@ -971,7 +971,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="from_sets" arity="1" clause_i="2"/>
+ <name name="from_sets" arity="1" clause_i="2" since=""/>
<fsummary>Create an ordered set out of a tuple of sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#sets_definition">ordered
@@ -981,8 +981,8 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="from_term" arity="1"/>
- <name name="from_term" arity="2"/>
+ <name name="from_term" arity="1" since=""/>
+ <name name="from_term" arity="2" since=""/>
<fsummary>Create a set.</fsummary>
<desc>
<p><marker id="from_term"></marker>Creates an element
@@ -1031,7 +1031,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="image" arity="2"/>
+ <name name="image" arity="2" since=""/>
<fsummary>Return the image of a set under a binary relation.</fsummary>
<desc>
<p>Returns the <seealso marker="#image">image</seealso> of
@@ -1047,7 +1047,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="intersection" arity="1"/>
+ <name name="intersection" arity="1" since=""/>
<fsummary>Return the intersection of a set of sets.</fsummary>
<desc>
<p>Returns
@@ -1059,7 +1059,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="intersection" arity="2"/>
+ <name name="intersection" arity="2" since=""/>
<fsummary>Return the intersection of two sets.</fsummary>
<desc>
<p>Returns
@@ -1069,7 +1069,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="intersection_of_family" arity="1"/>
+ <name name="intersection_of_family" arity="1" since=""/>
<fsummary>Return the intersection of a family.</fsummary>
<desc>
<p>Returns the intersection of
@@ -1086,7 +1086,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="inverse" arity="1"/>
+ <name name="inverse" arity="1" since=""/>
<fsummary>Return the inverse of a function.</fsummary>
<desc>
<p>Returns the <seealso marker="#inverse">inverse</seealso>
@@ -1100,7 +1100,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="inverse_image" arity="2"/>
+ <name name="inverse_image" arity="2" since=""/>
<fsummary>Return the inverse image of a set under
a binary relation.</fsummary>
<desc>
@@ -1117,7 +1117,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="is_a_function" arity="1"/>
+ <name name="is_a_function" arity="1" since=""/>
<fsummary>Test for a function.</fsummary>
<desc>
<p>Returns <c>true</c> if the binary relation <c><anno>BinRel</anno></c>
@@ -1127,7 +1127,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="is_disjoint" arity="2"/>
+ <name name="is_disjoint" arity="2" since=""/>
<fsummary>Test for disjoint sets.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Set1</anno></c>
@@ -1138,7 +1138,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="is_empty_set" arity="1"/>
+ <name name="is_empty_set" arity="1" since=""/>
<fsummary>Test for an empty set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>AnySet</anno></c> is an empty
@@ -1147,7 +1147,7 @@ fun(S) -> sofs:partition(1, S) end
</func>
<func>
- <name name="is_equal" arity="2"/>
+ <name name="is_equal" arity="2" since=""/>
<fsummary>Test two sets for equality.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>AnySet1</anno></c>
@@ -1164,7 +1164,7 @@ true</pre>
</func>
<func>
- <name name="is_set" arity="1"/>
+ <name name="is_set" arity="1" since=""/>
<fsummary>Test for an unordered set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>AnySet</anno></c> is
@@ -1175,7 +1175,7 @@ true</pre>
</func>
<func>
- <name name="is_sofs_set" arity="1"/>
+ <name name="is_sofs_set" arity="1" since=""/>
<fsummary>Test for an unordered set.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is
@@ -1185,7 +1185,7 @@ true</pre>
</func>
<func>
- <name name="is_subset" arity="2"/>
+ <name name="is_subset" arity="2" since=""/>
<fsummary>Test two sets for subset.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Set1</anno></c> is
@@ -1195,7 +1195,7 @@ true</pre>
</func>
<func>
- <name name="is_type" arity="1"/>
+ <name name="is_type" arity="1" since=""/>
<fsummary>Test for a type.</fsummary>
<desc>
<p>Returns <c>true</c> if term <c><anno>Term</anno></c> is
@@ -1204,7 +1204,7 @@ true</pre>
</func>
<func>
- <name name="join" arity="4"/>
+ <name name="join" arity="4" since=""/>
<fsummary>Return the join of two relations.</fsummary>
<desc>
<p>Returns the <seealso marker="#natural_join">natural
@@ -1221,7 +1221,7 @@ true</pre>
</func>
<func>
- <name name="multiple_relative_product" arity="2"/>
+ <name name="multiple_relative_product" arity="2" since=""/>
<fsummary>Return the multiple relative product of a tuple of binary
relations and a relation.</fsummary>
<desc>
@@ -1242,7 +1242,7 @@ true</pre>
</func>
<func>
- <name name="no_elements" arity="1"/>
+ <name name="no_elements" arity="1" since=""/>
<fsummary>Return the number of elements of a set.</fsummary>
<desc>
<p>Returns the number of elements of the ordered or unordered
@@ -1251,7 +1251,7 @@ true</pre>
</func>
<func>
- <name name="partition" arity="1"/>
+ <name name="partition" arity="1" since=""/>
<fsummary>Return the coarsest partition given a set of sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#partition">partition</seealso> of
@@ -1268,7 +1268,7 @@ true</pre>
</func>
<func>
- <name name="partition" arity="2"/>
+ <name name="partition" arity="2" since=""/>
<fsummary>Return a partition of a set.</fsummary>
<desc>
<p>Returns the <seealso marker="#partition">partition</seealso> of
@@ -1284,7 +1284,7 @@ true</pre>
</func>
<func>
- <name name="partition" arity="3"/>
+ <name name="partition" arity="3" since=""/>
<fsummary>Return a partition of a set.</fsummary>
<desc>
<p>Returns a pair of sets that, regarded as constituting a
@@ -1307,7 +1307,7 @@ true</pre>
</func>
<func>
- <name name="partition_family" arity="2"/>
+ <name name="partition_family" arity="2" since=""/>
<fsummary>Return a family indexing a partition.</fsummary>
<desc>
<p>Returns <seealso marker="#family">family</seealso>
@@ -1328,7 +1328,7 @@ true</pre>
</func>
<func>
- <name name="product" arity="1"/>
+ <name name="product" arity="1" since=""/>
<fsummary>Return the Cartesian product of a tuple of sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#Cartesian_product_tuple">Cartesian
@@ -1347,7 +1347,7 @@ true</pre>
</func>
<func>
- <name name="product" arity="2"/>
+ <name name="product" arity="2" since=""/>
<fsummary>Return the Cartesian product of two sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#Cartesian_product">Cartesian
@@ -1365,7 +1365,7 @@ true</pre>
</func>
<func>
- <name name="projection" arity="2"/>
+ <name name="projection" arity="2" since=""/>
<fsummary>Return a set of substituted elements.</fsummary>
<desc>
<p>Returns the set created by substituting each element of
@@ -1384,7 +1384,7 @@ true</pre>
</func>
<func>
- <name name="range" arity="1"/>
+ <name name="range" arity="1" since=""/>
<fsummary>Return the range of a binary relation.</fsummary>
<desc>
<p>Returns the <seealso marker="#range">range</seealso> of the
@@ -1398,8 +1398,8 @@ true</pre>
</func>
<func>
- <name name="relation" arity="1"/>
- <name name="relation" arity="2"/>
+ <name name="relation" arity="1" since=""/>
+ <name name="relation" arity="2" since=""/>
<fsummary>Create a relation.</fsummary>
<desc>
<p>Creates a <seealso marker="#relation">relation</seealso>.
@@ -1417,7 +1417,7 @@ true</pre>
</func>
<func>
- <name name="relation_to_family" arity="1"/>
+ <name name="relation_to_family" arity="1" since=""/>
<fsummary>Create a family from a binary relation.</fsummary>
<desc>
<p>Returns <seealso marker="#family">family</seealso>
@@ -1435,8 +1435,8 @@ true</pre>
</func>
<func>
- <name name="relative_product" arity="1"/>
- <name name="relative_product" arity="2" clause_i="1"/>
+ <name name="relative_product" arity="1" since=""/>
+ <name name="relative_product" arity="2" clause_i="1" since=""/>
<fsummary>Return the relative product of a list of binary relations
and a binary relation.</fsummary>
<desc>
@@ -1466,7 +1466,7 @@ true</pre>
</func>
<func>
- <name name="relative_product" arity="2" clause_i="2"/>
+ <name name="relative_product" arity="2" clause_i="2" since=""/>
<fsummary>Return the relative product of
two binary relations.</fsummary>
<desc>
@@ -1477,7 +1477,7 @@ true</pre>
</func>
<func>
- <name name="relative_product1" arity="2"/>
+ <name name="relative_product1" arity="2" since=""/>
<fsummary>Return the relative_product of
two binary relations.</fsummary>
<desc>
@@ -1498,7 +1498,7 @@ true</pre>
</func>
<func>
- <name name="restriction" arity="2"/>
+ <name name="restriction" arity="2" since=""/>
<fsummary>Return a restriction of a binary relation.</fsummary>
<desc>
<p>Returns the <seealso marker="#restriction">restriction</seealso> of
@@ -1514,7 +1514,7 @@ true</pre>
</func>
<func>
- <name name="restriction" arity="3"/>
+ <name name="restriction" arity="3" since=""/>
<fsummary>Return a restriction of a set.</fsummary>
<desc>
<p>Returns a subset of <c><anno>Set1</anno></c> containing those
@@ -1530,8 +1530,8 @@ true</pre>
</func>
<func>
- <name name="set" arity="1"/>
- <name name="set" arity="2"/>
+ <name name="set" arity="1" since=""/>
+ <name name="set" arity="2" since=""/>
<fsummary>Create a set of atoms or any type of sets.</fsummary>
<desc>
<p>Creates an <seealso marker="#sets_definition">unordered
@@ -1543,7 +1543,7 @@ true</pre>
</func>
<func>
- <name name="specification" arity="2"/>
+ <name name="specification" arity="2" since=""/>
<fsummary>Select a subset using a predicate.</fsummary>
<desc>
<p>Returns the set containing every element
@@ -1564,7 +1564,7 @@ true</pre>
</func>
<func>
- <name name="strict_relation" arity="1"/>
+ <name name="strict_relation" arity="1" since=""/>
<fsummary>Return the strict relation corresponding to
a given relation.</fsummary>
<desc>
@@ -1580,7 +1580,7 @@ true</pre>
</func>
<func>
- <name name="substitution" arity="2"/>
+ <name name="substitution" arity="2" since=""/>
<fsummary>Return a function with a given set as domain.</fsummary>
<desc>
<p>Returns a function, the domain of which
@@ -1629,7 +1629,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="symdiff" arity="2"/>
+ <name name="symdiff" arity="2" since=""/>
<fsummary>Return the symmetric difference of two sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#symmetric_difference">symmetric
@@ -1645,7 +1645,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="symmetric_partition" arity="2"/>
+ <name name="symmetric_partition" arity="2" since=""/>
<fsummary>Return a partition of two sets.</fsummary>
<desc>
<p>Returns a triple of sets:</p>
@@ -1666,7 +1666,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="to_external" arity="1"/>
+ <name name="to_external" arity="1" since=""/>
<fsummary>Return the elements of a set.</fsummary>
<desc>
<p>Returns the <seealso marker="#external_set">external
@@ -1675,7 +1675,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="to_sets" arity="1"/>
+ <name name="to_sets" arity="1" since=""/>
<fsummary>Return a list or a tuple of the elements of a set.</fsummary>
<desc>
<p>Returns the elements of the ordered set <c><anno>ASet</anno></c>
@@ -1686,7 +1686,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="type" arity="1"/>
+ <name name="type" arity="1" since=""/>
<fsummary>Return the type of a set.</fsummary>
<desc>
<p>Returns the <seealso marker="#type">type</seealso> of an
@@ -1695,7 +1695,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="union" arity="1"/>
+ <name name="union" arity="1" since=""/>
<fsummary>Return the union of a set of sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#union_n">union</seealso> of the
@@ -1704,7 +1704,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="union" arity="2"/>
+ <name name="union" arity="2" since=""/>
<fsummary>Return the union of two sets.</fsummary>
<desc>
<p>Returns the <seealso marker="#union">union</seealso> of
@@ -1713,7 +1713,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="union_of_family" arity="1"/>
+ <name name="union_of_family" arity="1" since=""/>
<fsummary>Return the union of a family.</fsummary>
<desc>
<p>Returns the union of <seealso marker="#family">family</seealso>
@@ -1727,7 +1727,7 @@ images2(SetOfSets, BinRel) ->
</func>
<func>
- <name name="weak_relation" arity="1"/>
+ <name name="weak_relation" arity="1" since=""/>
<fsummary>Return the weak relation corresponding to
a given relation.</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/string.xml b/lib/stdlib/doc/src/string.xml
index 3348464eba..d102191a57 100644
--- a/lib/stdlib/doc/src/string.xml
+++ b/lib/stdlib/doc/src/string.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>string.xml</file>
</header>
- <module>string</module>
+ <module since="">string</module>
<modulesummary>String processing functions.</modulesummary>
<description>
<p>This module provides functions for string processing.</p>
@@ -130,7 +130,7 @@
<funcs>
<func>
- <name name="casefold" arity="1"/>
+ <name name="casefold" arity="1" since="OTP 20.0"/>
<fsummary>Convert a string to a comparable string.</fsummary>
<desc>
<p>
@@ -147,7 +147,7 @@
</func>
<func>
- <name name="chomp" arity="1"/>
+ <name name="chomp" arity="1" since="OTP 20.0"/>
<fsummary>Remove trailing end of line control characters.</fsummary>
<desc>
<p>
@@ -164,9 +164,9 @@
</func>
<func>
- <name name="equal" arity="2"/>
- <name name="equal" arity="3"/>
- <name name="equal" arity="4"/>
+ <name name="equal" arity="2" since=""/>
+ <name name="equal" arity="3" since="OTP 20.0"/>
+ <name name="equal" arity="4" since="OTP 20.0"/>
<fsummary>Test string equality.</fsummary>
<desc>
<p>
@@ -201,8 +201,8 @@ true</pre>
</func>
<func>
- <name name="find" arity="2"/>
- <name name="find" arity="3"/>
+ <name name="find" arity="2" since="OTP 20.0"/>
+ <name name="find" arity="3" since="OTP 20.0"/>
<fsummary>Find start of substring.</fsummary>
<desc>
<p>
@@ -230,7 +230,7 @@ nomatch</pre>
</func>
<func>
- <name name="is_empty" arity="1"/>
+ <name name="is_empty" arity="1" since="OTP 20.0"/>
<fsummary>Check if the string is empty.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>String</anno></c> is the
@@ -245,7 +245,7 @@ true</pre>
</func>
<func>
- <name name="length" arity="1"/>
+ <name name="length" arity="1" since="OTP 20.0"/>
<fsummary>Calculate length of the string.</fsummary>
<desc>
<p>
@@ -261,7 +261,7 @@ true</pre>
</func>
<func>
- <name name="lexemes" arity="2"/>
+ <name name="lexemes" arity="2" since="OTP 20.0"/>
<fsummary>Split string into lexemes.</fsummary>
<desc>
<p>
@@ -287,7 +287,7 @@ true</pre>
</func>
<func>
- <name name="lowercase" arity="1"/>
+ <name name="lowercase" arity="1" since="OTP 20.0"/>
<fsummary>Convert a string to lowercase</fsummary>
<desc>
<p>
@@ -306,7 +306,7 @@ true</pre>
</func>
<func>
- <name name="next_codepoint" arity="1"/>
+ <name name="next_codepoint" arity="1" since="OTP 20.0"/>
<fsummary>Pick the first codepoint.</fsummary>
<desc>
<p>
@@ -323,7 +323,7 @@ true</pre>
</func>
<func>
- <name name="next_grapheme" arity="1"/>
+ <name name="next_grapheme" arity="1" since="OTP 20.0"/>
<fsummary>Pick the first grapheme cluster.</fsummary>
<desc>
<p>
@@ -340,7 +340,7 @@ true</pre>
</func>
<func>
- <name name="nth_lexeme" arity="3"/>
+ <name name="nth_lexeme" arity="3" since="OTP 20.0"/>
<fsummary>Pick the nth lexeme.</fsummary>
<desc>
<p>Returns lexeme number <c><anno>N</anno></c> in
@@ -355,9 +355,9 @@ true</pre>
</func>
<func>
- <name name="pad" arity="2"/>
- <name name="pad" arity="3"/>
- <name name="pad" arity="4"/>
+ <name name="pad" arity="2" since="OTP 20.0"/>
+ <name name="pad" arity="3" since="OTP 20.0"/>
+ <name name="pad" arity="4" since="OTP 20.0"/>
<fsummary>Pad a string to given length.</fsummary>
<desc>
<p>
@@ -381,7 +381,7 @@ true</pre>
</func>
<func>
- <name name="prefix" arity="2"/>
+ <name name="prefix" arity="2" since="OTP 20.0"/>
<fsummary>Remove prefix from string.</fsummary>
<desc>
<p>
@@ -400,8 +400,8 @@ nomatch</pre>
</func>
<func>
- <name name="replace" arity="3"/>
- <name name="replace" arity="4"/>
+ <name name="replace" arity="3" since="OTP 20.0"/>
+ <name name="replace" arity="4" since="OTP 20.0"/>
<fsummary>Replace a pattern in string.</fsummary>
<desc>
<p>
@@ -423,7 +423,7 @@ nomatch</pre>
</func>
<func>
- <name name="reverse" arity="1"/>
+ <name name="reverse" arity="1" since="OTP 20.0"/>
<fsummary>Reverses a string</fsummary>
<desc>
<p>
@@ -439,8 +439,8 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="slice" arity="2"/>
- <name name="slice" arity="3"/>
+ <name name="slice" arity="2" since="OTP 20.0"/>
+ <name name="slice" arity="3" since="OTP 20.0"/>
<fsummary>Extract a part of string</fsummary>
<desc>
<p>Returns a substring of <c><anno>String</anno></c> of
@@ -459,8 +459,8 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="split" arity="2"/>
- <name name="split" arity="3"/>
+ <name name="split" arity="2" since="OTP 20.0"/>
+ <name name="split" arity="3" since="OTP 20.0"/>
<fsummary>Split a string into substrings.</fsummary>
<desc>
<p>
@@ -482,9 +482,9 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="take" arity="2"/>
- <name name="take" arity="3"/>
- <name name="take" arity="4"/>
+ <name name="take" arity="2" since="OTP 20.0"/>
+ <name name="take" arity="3" since="OTP 20.0"/>
+ <name name="take" arity="4" since="OTP 20.0"/>
<fsummary>Take leading or trailing parts.</fsummary>
<desc>
<p>Takes characters from <c><anno>String</anno></c> as long as
@@ -508,7 +508,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="titlecase" arity="1"/>
+ <name name="titlecase" arity="1" since="OTP 20.0"/>
<fsummary>Convert a string to titlecase.</fsummary>
<desc>
<p>
@@ -522,7 +522,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="to_float" arity="1"/>
+ <name name="to_float" arity="1" since=""/>
<fsummary>Return a float whose text representation is the integers
(ASCII values) of a string.</fsummary>
<desc>
@@ -544,7 +544,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="to_integer" arity="1"/>
+ <name name="to_integer" arity="1" since=""/>
<fsummary>Return an integer whose text representation is the integers
(ASCII values) of a string.</fsummary>
<desc>
@@ -566,7 +566,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="to_graphemes" arity="1"/>
+ <name name="to_graphemes" arity="1" since="OTP 20.0"/>
<fsummary>Convert a string to a list of grapheme clusters.</fsummary>
<desc>
<p>
@@ -582,9 +582,9 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="trim" arity="1"/>
- <name name="trim" arity="2"/>
- <name name="trim" arity="3"/>
+ <name name="trim" arity="1" since="OTP 20.0"/>
+ <name name="trim" arity="2" since="OTP 20.0"/>
+ <name name="trim" arity="3" since="OTP 20.0"/>
<fsummary>Trim leading or trailing, or both, characters.</fsummary>
<desc>
<p>
@@ -616,7 +616,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="uppercase" arity="1"/>
+ <name name="uppercase" arity="1" since="OTP 20.0"/>
<fsummary>Convert a string to uppercase.</fsummary>
<desc>
<p>
@@ -649,8 +649,8 @@ ÖÄÅ</pre>
<funcs>
<func>
- <name name="centre" arity="2"/>
- <name name="centre" arity="3"/>
+ <name name="centre" arity="2" since=""/>
+ <name name="centre" arity="3" since=""/>
<fsummary>Center a string.</fsummary>
<desc>
<p>Returns a string, where <c><anno>String</anno></c> is centered in the
@@ -664,8 +664,8 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="chars" arity="2"/>
- <name name="chars" arity="3"/>
+ <name name="chars" arity="2" since=""/>
+ <name name="chars" arity="3" since=""/>
<fsummary>Return a string consisting of numbers of characters.</fsummary>
<desc>
<p>Returns a string consisting of <c><anno>Number</anno></c> characters
@@ -678,7 +678,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="chr" arity="2"/>
+ <name name="chr" arity="2" since=""/>
<fsummary>Return the index of the first occurrence of
a character in a string.</fsummary>
<desc>
@@ -692,7 +692,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="concat" arity="2"/>
+ <name name="concat" arity="2" since=""/>
<fsummary>Concatenate two strings.</fsummary>
<desc>
<p>Concatenates <c><anno>String1</anno></c> and
@@ -712,7 +712,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="copies" arity="2"/>
+ <name name="copies" arity="2" since=""/>
<fsummary>Copy a string.</fsummary>
<desc>
<p>Returns a string containing <c><anno>String</anno></c> repeated
@@ -724,7 +724,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="cspan" arity="2"/>
+ <name name="cspan" arity="2" since=""/>
<fsummary>Span characters at start of a string.</fsummary>
<desc>
<p>Returns the length of the maximum initial segment of
@@ -741,7 +741,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="join" arity="2"/>
+ <name name="join" arity="2" since=""/>
<fsummary>Join a list of strings with separator.</fsummary>
<desc>
<p>Returns a string with the elements of <c><anno>StringList</anno></c>
@@ -757,8 +757,8 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="left" arity="2"/>
- <name name="left" arity="3"/>
+ <name name="left" arity="2" since=""/>
+ <name name="left" arity="3" since=""/>
<fsummary>Adjust left end of a string.</fsummary>
<desc>
<p>Returns <c><anno>String</anno></c> with the length adjusted in
@@ -778,7 +778,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="len" arity="1"/>
+ <name name="len" arity="1" since=""/>
<fsummary>Return the length of a string.</fsummary>
<desc>
<p>Returns the number of characters in <c><anno>String</anno></c>.</p>
@@ -789,7 +789,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="rchr" arity="2"/>
+ <name name="rchr" arity="2" since=""/>
<fsummary>Return the index of the last occurrence of
a character in a string.</fsummary>
<desc>
@@ -803,8 +803,8 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="right" arity="2"/>
- <name name="right" arity="3"/>
+ <name name="right" arity="2" since=""/>
+ <name name="right" arity="3" since=""/>
<fsummary>Adjust right end of a string.</fsummary>
<desc>
<p>Returns <c><anno>String</anno></c> with the length adjusted in
@@ -823,7 +823,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="rstr" arity="2"/>
+ <name name="rstr" arity="2" since=""/>
<fsummary>Find the index of a substring.</fsummary>
<desc>
<p>Returns the position where the last occurrence of
@@ -841,7 +841,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="span" arity="2"/>
+ <name name="span" arity="2" since=""/>
<fsummary>Span characters at start of a string.</fsummary>
<desc>
<p>Returns the length of the maximum initial segment of
@@ -858,7 +858,7 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="str" arity="2"/>
+ <name name="str" arity="2" since=""/>
<fsummary>Find the index of a substring.</fsummary>
<desc>
<p>Returns the position where the first occurrence of
@@ -876,9 +876,9 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="strip" arity="1"/>
- <name name="strip" arity="2"/>
- <name name="strip" arity="3"/>
+ <name name="strip" arity="1" since=""/>
+ <name name="strip" arity="2" since=""/>
+ <name name="strip" arity="3" since=""/>
<fsummary>Strip leading or trailing characters.</fsummary>
<desc>
<p>Returns a string, where leading or trailing, or both, blanks or a
@@ -898,8 +898,8 @@ ÖÄÅ</pre>
</func>
<func>
- <name name="sub_string" arity="2"/>
- <name name="sub_string" arity="3"/>
+ <name name="sub_string" arity="2" since=""/>
+ <name name="sub_string" arity="3" since=""/>
<fsummary>Extract a substring.</fsummary>
<desc>
<p>Returns a substring of <c><anno>String</anno></c>, starting at
@@ -916,8 +916,8 @@ sub_string("Hello World", 4, 8).
</func>
<func>
- <name name="substr" arity="2"/>
- <name name="substr" arity="3"/>
+ <name name="substr" arity="2" since=""/>
+ <name name="substr" arity="3" since=""/>
<fsummary>Return a substring of a string.</fsummary>
<desc>
<p>Returns a substring of <c><anno>String</anno></c>, starting at
@@ -934,8 +934,8 @@ sub_string("Hello World", 4, 8).
</func>
<func>
- <name name="sub_word" arity="2"/>
- <name name="sub_word" arity="3"/>
+ <name name="sub_word" arity="2" since=""/>
+ <name name="sub_word" arity="3" since=""/>
<fsummary>Extract subword.</fsummary>
<desc>
<p>Returns the word in position <c><anno>Number</anno></c> of
@@ -952,10 +952,10 @@ sub_string("Hello World", 4, 8).
</func>
<func>
- <name name="to_lower" arity="1" clause_i="1"/>
- <name name="to_lower" arity="1" clause_i="2"/>
- <name name="to_upper" arity="1" clause_i="1"/>
- <name name="to_upper" arity="1" clause_i="2"/>
+ <name name="to_lower" arity="1" clause_i="1" since=""/>
+ <name name="to_lower" arity="1" clause_i="2" since=""/>
+ <name name="to_upper" arity="1" clause_i="1" since=""/>
+ <name name="to_upper" arity="1" clause_i="2" since=""/>
<fsummary>Convert case of string (ISO/IEC 8859-1).</fsummary>
<type variable="String" name_i="1"/>
<type variable="Result" name_i="1"/>
@@ -974,7 +974,7 @@ sub_string("Hello World", 4, 8).
</func>
<func>
- <name name="tokens" arity="2"/>
+ <name name="tokens" arity="2" since=""/>
<fsummary>Split string into tokens.</fsummary>
<desc>
<p>Returns a list of tokens in <c><anno>String</anno></c>, separated
@@ -994,8 +994,8 @@ sub_string("Hello World", 4, 8).
</func>
<func>
- <name name="words" arity="1"/>
- <name name="words" arity="2"/>
+ <name name="words" arity="1" since=""/>
+ <name name="words" arity="2" since=""/>
<fsummary>Count blank separated words.</fsummary>
<desc>
<p>Returns the number of words in <c><anno>String</anno></c>, separated
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index 6d5065ca02..f15b1a2dd3 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>supervisor</module>
+ <module since="">supervisor</module>
<modulesummary>Generic supervisor behavior.</modulesummary>
<description>
<p>This behavior module provides a supervisor, a process that
@@ -208,8 +208,16 @@ child_spec() = #{id => child_id(), % mandatory
the child process is unconditionally terminated using
<c>exit(Child,kill)</c>.</p>
<p>If the child process is another supervisor, the shutdown time
- is to be set to <c>infinity</c> to give the subtree ample
- time to shut down. It is also allowed to set it to <c>infinity</c>,
+ must be set to <c>infinity</c> to give the subtree ample
+ time to shut down.</p>
+ <warning>
+ <p>Setting the shutdown time to anything other
+ than <c>infinity</c> for a child of type <c>supervisor</c>
+ can cause a race condition where the child in question
+ unlinks its own children, but fails to terminate them
+ before it is killed.</p>
+ </warning>
+ <p>It is also allowed to set it to <c>infinity</c>,
if the child process is a worker.</p>
<warning>
<p>Be careful when setting the shutdown time to
@@ -310,7 +318,7 @@ child_spec() = #{id => child_id(), % mandatory
<funcs>
<func>
- <name name="check_childspecs" arity="1"/>
+ <name name="check_childspecs" arity="1" since=""/>
<fsummary>Check if children specifications are syntactically correct.
</fsummary>
<desc>
@@ -321,7 +329,7 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="count_children" arity="1"/>
+ <name name="count_children" arity="1" since="OTP R13B04"/>
<fsummary>Return counts for the number of child specifications,
active children, supervisors, and workers.</fsummary>
<desc>
@@ -358,7 +366,7 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="delete_child" arity="2"/>
+ <name name="delete_child" arity="2" since=""/>
<fsummary>Delete a child specification from a supervisor.</fsummary>
<desc>
<p>Tells supervisor <c><anno>SupRef</anno></c> to delete the child
@@ -379,7 +387,7 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="get_childspec" arity="2"/>
+ <name name="get_childspec" arity="2" since="OTP 18.0"/>
<fsummary>Return the child specification map for the specified
child.</fsummary>
<desc>
@@ -392,7 +400,7 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="restart_child" arity="2"/>
+ <name name="restart_child" arity="2" since=""/>
<fsummary>Restart a terminated child process belonging to a supervisor.
</fsummary>
<desc>
@@ -428,7 +436,7 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="start_child" arity="2"/>
+ <name name="start_child" arity="2" since=""/>
<fsummary>Dynamically add a child process to a supervisor.</fsummary>
<type name="startchild_ret"/>
<type name="startchild_err"/>
@@ -495,8 +503,8 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="start_link" arity="2"/>
- <name name="start_link" arity="3"/>
+ <name name="start_link" arity="2" since=""/>
+ <name name="start_link" arity="3" since=""/>
<fsummary>Create a supervisor process.</fsummary>
<type name="startlink_ret"/>
<type name="startlink_err"/>
@@ -576,7 +584,7 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="terminate_child" arity="2"/>
+ <name name="terminate_child" arity="2" since=""/>
<fsummary>Terminate a child process belonging to a supervisor.</fsummary>
<desc>
<p>Tells supervisor <c><anno>SupRef</anno></c> to terminate the
@@ -613,7 +621,7 @@ child_spec() = #{id => child_id(), % mandatory
</func>
<func>
- <name name="which_children" arity="1"/>
+ <name name="which_children" arity="1" since=""/>
<fsummary>Return information about all children specifications and
child processes belonging to a supervisor.</fsummary>
<desc>
@@ -658,7 +666,7 @@ child_spec() = #{id => child_id(), % mandatory
<funcs>
<func>
- <name>Module:init(Args) -> Result</name>
+ <name since="">Module:init(Args) -> Result</name>
<fsummary>Return a supervisor specification.</fsummary>
<type>
<v>Args = term()</v>
diff --git a/lib/stdlib/doc/src/supervisor_bridge.xml b/lib/stdlib/doc/src/supervisor_bridge.xml
index c4c1b37548..ee5d97fea1 100644
--- a/lib/stdlib/doc/src/supervisor_bridge.xml
+++ b/lib/stdlib/doc/src/supervisor_bridge.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>supervisor_bridge</module>
+ <module since="">supervisor_bridge</module>
<modulesummary>Generic supervisor bridge behavior.</modulesummary>
<description>
<p>This behavior module provides a supervisor bridge, a process
@@ -57,8 +57,8 @@
<funcs>
<func>
- <name name="start_link" arity="2"/>
- <name name="start_link" arity="3"/>
+ <name name="start_link" arity="2" since=""/>
+ <name name="start_link" arity="3" since=""/>
<fsummary>Create a supervisor bridge process.</fsummary>
<desc>
<p>Creates a supervisor bridge process, linked to the calling process,
@@ -133,7 +133,7 @@
<funcs>
<func>
- <name>Module:init(Args) -> Result</name>
+ <name since="">Module:init(Args) -> Result</name>
<fsummary>Initialize process and start subsystem.</fsummary>
<type>
<v>Args = term()</v>
@@ -164,7 +164,7 @@
</func>
<func>
- <name>Module:terminate(Reason, State)</name>
+ <name since="">Module:terminate(Reason, State)</name>
<fsummary>Clean up and stop subsystem.</fsummary>
<type>
<v>Reason = shutdown | term()</v>
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index 9fe816e33a..6fc508b853 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -32,7 +32,7 @@
<rev></rev>
<file>sys.xml</file>
</header>
- <module>sys</module>
+ <module since="">sys</module>
<modulesummary>A functional interface to system messages.</modulesummary>
<description>
<p>This module contains functions for sending system messages used by
@@ -129,8 +129,8 @@
<funcs>
<func>
- <name name="change_code" arity="4"/>
- <name name="change_code" arity="5"/>
+ <name name="change_code" arity="4" since=""/>
+ <name name="change_code" arity="5" since=""/>
<fsummary>Send the code change system message to the process.</fsummary>
<desc>
<p>Tells the process to change code. The process must be
@@ -143,8 +143,8 @@
</func>
<func>
- <name name="get_state" arity="1"/>
- <name name="get_state" arity="2"/>
+ <name name="get_state" arity="1" since="OTP R16B01"/>
+ <name name="get_state" arity="2" since="OTP R16B01"/>
<fsummary>Get the state of the process.</fsummary>
<desc>
<p>Gets the state of the process.</p>
@@ -227,8 +227,8 @@
</func>
<func>
- <name name="get_status" arity="1"/>
- <name name="get_status" arity="2"/>
+ <name name="get_status" arity="1" since=""/>
+ <name name="get_status" arity="2" since=""/>
<fsummary>Get the status of the process.</fsummary>
<desc>
<p>Gets the status of the process.</p>
@@ -265,8 +265,8 @@
</func>
<func>
- <name name="install" arity="2"/>
- <name name="install" arity="3"/>
+ <name name="install" arity="2" since=""/>
+ <name name="install" arity="3" since=""/>
<fsummary>Install a debug function in the process.</fsummary>
<desc>
<p>Enables installation of alternative debug functions. An example of
@@ -283,8 +283,8 @@
</func>
<func>
- <name name="log" arity="2"/>
- <name name="log" arity="3"/>
+ <name name="log" arity="2" since=""/>
+ <name name="log" arity="3" since=""/>
<fsummary>Log system events in memory.</fsummary>
<desc>
<p>Turns the logging of system events on or off. If on, a
@@ -302,8 +302,8 @@
</func>
<func>
- <name name="log_to_file" arity="2"/>
- <name name="log_to_file" arity="3"/>
+ <name name="log_to_file" arity="2" since=""/>
+ <name name="log_to_file" arity="3" since=""/>
<fsummary>Log system events to the specified file.</fsummary>
<desc>
<p>Enables or disables the logging of all system events in text
@@ -315,8 +315,8 @@
</func>
<func>
- <name name="no_debug" arity="1"/>
- <name name="no_debug" arity="2"/>
+ <name name="no_debug" arity="1" since=""/>
+ <name name="no_debug" arity="2" since=""/>
<fsummary>Turn off debugging.</fsummary>
<desc>
<p>Turns off all debugging for the process. This includes
@@ -327,8 +327,8 @@
</func>
<func>
- <name name="remove" arity="2"/>
- <name name="remove" arity="3"/>
+ <name name="remove" arity="2" since=""/>
+ <name name="remove" arity="3" since=""/>
<fsummary>Remove a debug function from the process.</fsummary>
<desc>
<p>Removes an installed debug function from the
@@ -338,8 +338,8 @@
</func>
<func>
- <name name="replace_state" arity="2"/>
- <name name="replace_state" arity="3"/>
+ <name name="replace_state" arity="2" since="OTP R16B01"/>
+ <name name="replace_state" arity="3" since="OTP R16B01"/>
<fsummary>Replace the state of the process.</fsummary>
<desc>
<p>Replaces the state of the process, and returns the new state.</p>
@@ -451,8 +451,8 @@
</func>
<func>
- <name name="resume" arity="1"/>
- <name name="resume" arity="2"/>
+ <name name="resume" arity="1" since=""/>
+ <name name="resume" arity="2" since=""/>
<fsummary>Resume a suspended process.</fsummary>
<desc>
<p>Resumes a suspended process.</p>
@@ -460,8 +460,8 @@
</func>
<func>
- <name name="statistics" arity="2"/>
- <name name="statistics" arity="3"/>
+ <name name="statistics" arity="2" since=""/>
+ <name name="statistics" arity="3" since=""/>
<fsummary>Enable or disable the collections of statistics.</fsummary>
<desc>
<p>Enables or disables the collection of statistics. If
@@ -471,8 +471,8 @@
</func>
<func>
- <name name="suspend" arity="1"/>
- <name name="suspend" arity="2"/>
+ <name name="suspend" arity="1" since=""/>
+ <name name="suspend" arity="2" since=""/>
<fsummary>Suspend the process.</fsummary>
<desc>
<p>Suspends the process. When the process is suspended, it
@@ -482,8 +482,8 @@
</func>
<func>
- <name name="terminate" arity="2"/>
- <name name="terminate" arity="3"/>
+ <name name="terminate" arity="2" since="OTP 18.0"/>
+ <name name="terminate" arity="3" since="OTP 18.0"/>
<fsummary>Terminate the process.</fsummary>
<desc>
<p>Orders the process to terminate with the
@@ -494,8 +494,8 @@
</func>
<func>
- <name name="trace" arity="2"/>
- <name name="trace" arity="3"/>
+ <name name="trace" arity="2" since=""/>
+ <name name="trace" arity="3" since=""/>
<fsummary>Print all system events on <c>standard_io</c>.</fsummary>
<desc>
<p>Prints all system events on <c>standard_io</c>. The events are
@@ -518,7 +518,7 @@
<funcs>
<func>
- <name name="debug_options" arity="1"/>
+ <name name="debug_options" arity="1" since=""/>
<fsummary>Convert a list of options to a debug structure.</fsummary>
<desc>
<p>Can be used by a process that initiates a debug
@@ -529,7 +529,7 @@
</func>
<func>
- <name name="get_debug" arity="3"/>
+ <name name="get_debug" arity="3" since=""/>
<fsummary>Get the data associated with a debug option.</fsummary>
<desc>
<p>Gets the data associated with a debug option.
@@ -541,7 +541,7 @@
</func>
<func>
- <name name="handle_debug" arity="4"/>
+ <name name="handle_debug" arity="4" since=""/>
<fsummary>Generate a system event.</fsummary>
<desc>
<p>This function is called by a process when it generates a
@@ -556,7 +556,7 @@
</func>
<func>
- <name name="handle_system_msg" arity="6"/>
+ <name name="handle_system_msg" arity="6" since=""/>
<fsummary>Take care of system messages.</fsummary>
<desc>
<p>This function is used by a process module to take care of system
@@ -594,7 +594,7 @@
</func>
<func>
- <name name="print_log" arity="1"/>
+ <name name="print_log" arity="1" since=""/>
<fsummary>Print the logged events in the debug structure.</fsummary>
<desc>
<p>Prints the logged system events in the debug structure,
@@ -605,7 +605,7 @@
</func>
<func>
- <name>Module:system_code_change(Misc, Module, OldVsn, Extra) ->
+ <name since="">Module:system_code_change(Misc, Module, OldVsn, Extra) ->
{ok, NMisc}</name>
<fsummary>Called when the process is to perform a code change.</fsummary>
<type>
@@ -628,7 +628,7 @@
</func>
<func>
- <name>Module:system_continue(Parent, Debug, Misc) -> none()</name>
+ <name since="">Module:system_continue(Parent, Debug, Misc) -> none()</name>
<fsummary>Called when the process is to continue its execution.</fsummary>
<type>
<v>Parent = pid()</v>
@@ -644,7 +644,7 @@
</func>
<func>
- <name>Module:system_get_state(Misc) -> {ok, State}</name>
+ <name since="OTP 17.0">Module:system_get_state(Misc) -> {ok, State}</name>
<fsummary>Called when the process is to return its current state.
</fsummary>
<type>
@@ -661,7 +661,7 @@
</func>
<func>
- <name>Module:system_replace_state(StateFun, Misc) ->
+ <name since="OTP 17.0">Module:system_replace_state(StateFun, Misc) ->
{ok, NState, NMisc}</name>
<fsummary>Called when the process is to replace its current state.
</fsummary>
@@ -681,7 +681,7 @@
</func>
<func>
- <name>Module:system_terminate(Reason, Parent, Debug, Misc) -> none()</name>
+ <name since="">Module:system_terminate(Reason, Parent, Debug, Misc) -> none()</name>
<fsummary>Called when the process is to terminate.</fsummary>
<type>
<v>Reason = term()</v>
diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index e913e33589..165eecfbb0 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -32,7 +32,7 @@
<rev>D</rev>
<file>timer.xml</file>
</header>
- <module>timer</module>
+ <module since="">timer</module>
<modulesummary>Timer functions.</modulesummary>
<description>
<p>This module provides useful functions related to time. Unless otherwise
@@ -62,7 +62,7 @@
<funcs>
<func>
- <name name="apply_after" arity="4"/>
+ <name name="apply_after" arity="4" since=""/>
<fsummary>Apply <c>Module:Function(Arguments)</c> after a specified
<c>Time</c>.</fsummary>
<desc>
@@ -75,7 +75,7 @@
</func>
<func>
- <name name="apply_interval" arity="4"/>
+ <name name="apply_interval" arity="4" since=""/>
<fsummary>Evaluate <c>Module:Function(Arguments)</c> repeatedly at
intervals of <c>Time</c>.</fsummary>
<desc>
@@ -88,7 +88,7 @@
</func>
<func>
- <name name="cancel" arity="1"/>
+ <name name="cancel" arity="1" since=""/>
<fsummary>Cancel a previously requested time-out identified by
<c>TRef</c>.</fsummary>
<desc>
@@ -101,8 +101,8 @@
</func>
<func>
- <name name="exit_after" arity="2"/>
- <name name="exit_after" arity="3"/>
+ <name name="exit_after" arity="2" since=""/>
+ <name name="exit_after" arity="3" since=""/>
<fsummary>Send an exit signal with <c>Reason</c> after a specified
<c>Time</c>.</fsummary>
<desc>
@@ -117,7 +117,7 @@
</func>
<func>
- <name name="hms" arity="3"/>
+ <name name="hms" arity="3" since=""/>
<fsummary>Convert <c>Hours</c>+<c>Minutes</c>+<c>Seconds</c> to
<c>Milliseconds</c>.</fsummary>
<desc>
@@ -127,7 +127,7 @@
</func>
<func>
- <name name="hours" arity="1"/>
+ <name name="hours" arity="1" since=""/>
<fsummary>Convert <c>Hours</c> to <c>Milliseconds</c>.</fsummary>
<desc>
<p>Returns the number of milliseconds in <c><anno>Hours</anno></c>.</p>
@@ -135,8 +135,8 @@
</func>
<func>
- <name name="kill_after" arity="1"/>
- <name name="kill_after" arity="2"/>
+ <name name="kill_after" arity="1" since=""/>
+ <name name="kill_after" arity="2" since=""/>
<fsummary>Send an exit signal with <c>Reason</c> after a specified
<c>Time</c>.</fsummary>
<desc>
@@ -148,7 +148,7 @@
</func>
<func>
- <name name="minutes" arity="1"/>
+ <name name="minutes" arity="1" since=""/>
<fsummary>Converts <c>Minutes</c> to <c>Milliseconds</c>.</fsummary>
<desc>
<p>Returns the number of milliseconds in
@@ -157,7 +157,7 @@
</func>
<func>
- <name name="now_diff" arity="2"/>
+ <name name="now_diff" arity="2" since=""/>
<fsummary>Calculate time difference between time stamps.</fsummary>
<type_desc variable="Tdiff">In microseconds</type_desc>
<desc>
@@ -173,7 +173,7 @@
</func>
<func>
- <name name="seconds" arity="1"/>
+ <name name="seconds" arity="1" since=""/>
<fsummary>Convert <c>Seconds</c> to <c>Milliseconds</c>.</fsummary>
<desc>
<p>Returns the number of milliseconds in
@@ -182,8 +182,8 @@
</func>
<func>
- <name name="send_after" arity="2"/>
- <name name="send_after" arity="3"/>
+ <name name="send_after" arity="2" since=""/>
+ <name name="send_after" arity="3" since=""/>
<fsummary>Send <c>Message</c> to <c>Pid</c> after a specified
<c>Time</c>.</fsummary>
<desc>
@@ -206,8 +206,8 @@
</func>
<func>
- <name name="send_interval" arity="2"/>
- <name name="send_interval" arity="3"/>
+ <name name="send_interval" arity="2" since=""/>
+ <name name="send_interval" arity="3" since=""/>
<fsummary>Send <c>Message</c> repeatedly at intervals of <c>Time</c>.
</fsummary>
<desc>
@@ -231,7 +231,7 @@
</func>
<func>
- <name name="sleep" arity="1"/>
+ <name name="sleep" arity="1" since=""/>
<fsummary>Suspend the calling process for <c>Time</c> milliseconds.
</fsummary>
<desc>
@@ -244,7 +244,7 @@
</func>
<func>
- <name name="start" arity="0"/>
+ <name name="start" arity="0" since=""/>
<fsummary>Start a global timer server (named <c>timer_server</c>).
</fsummary>
<desc>
@@ -258,9 +258,9 @@
</func>
<func>
- <name name="tc" arity="1"/>
- <name name="tc" arity="2"/>
- <name name="tc" arity="3"/>
+ <name name="tc" arity="1" since="OTP R14B03"/>
+ <name name="tc" arity="2" since="OTP R14B"/>
+ <name name="tc" arity="3" since=""/>
<fsummary>Measure the real time it takes to evaluate <c>apply(Module,
Function, Arguments)</c> or <c>apply(Fun, Arguments)</c>.</fsummary>
<type_desc variable="Time">In microseconds</type_desc>
diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml
index d822aca89c..b7696a4b7e 100644
--- a/lib/stdlib/doc/src/unicode.xml
+++ b/lib/stdlib/doc/src/unicode.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>unicode</module>
+ <module since="">unicode</module>
<modulesummary>Functions for converting Unicode characters.</modulesummary>
<description>
<p>This module contains functions for converting between different character
@@ -139,7 +139,7 @@
<funcs>
<func>
- <name name="bom_to_encoding" arity="1"/>
+ <name name="bom_to_encoding" arity="1" since=""/>
<fsummary>Identify UTF byte order marks in a binary.</fsummary>
<type name="endian"/>
<type_desc variable="Bin">
@@ -156,7 +156,7 @@
</func>
<func>
- <name name="characters_to_binary" arity="1"/>
+ <name name="characters_to_binary" arity="1" since=""/>
<fsummary>Convert a collection of characters to a UTF-8 binary.</fsummary>
<desc>
<p>Same as <c>characters_to_binary(<anno>Data</anno>, unicode,
@@ -165,7 +165,7 @@
</func>
<func>
- <name name="characters_to_binary" arity="2"/>
+ <name name="characters_to_binary" arity="2" since=""/>
<fsummary>Convert a collection of characters to a UTF-8 binary.</fsummary>
<desc>
<p>Same as <c>characters_to_binary(<anno>Data</anno>,
@@ -174,7 +174,7 @@
</func>
<func>
- <name name="characters_to_binary" arity="3"/>
+ <name name="characters_to_binary" arity="3" since=""/>
<fsummary>Convert a collection of characters to a UTF-8 binary.</fsummary>
<desc>
<p>Behaves as <seealso marker="#characters_to_list/2">
@@ -211,7 +211,7 @@
</func>
<func>
- <name name="characters_to_list" arity="1"/>
+ <name name="characters_to_list" arity="1" since=""/>
<fsummary>Convert a collection of characters to a list of Unicode
characters.</fsummary>
<desc>
@@ -220,7 +220,7 @@
</func>
<func>
- <name name="characters_to_list" arity="2"/>
+ <name name="characters_to_list" arity="2" since=""/>
<fsummary>Convert a collection of characters to a list of Unicode
characters.</fsummary>
<desc>
@@ -367,7 +367,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfc_list" arity="1"/>
+ <name name="characters_to_nfc_list" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a list of canonical equivalent
composed Unicode characters.</fsummary>
<desc>
@@ -386,7 +386,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfc_binary" arity="1"/>
+ <name name="characters_to_nfc_binary" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a utf8 binary of canonical equivalent
composed Unicode characters.</fsummary>
<desc>
@@ -404,7 +404,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfd_list" arity="1"/>
+ <name name="characters_to_nfd_list" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a list of canonical equivalent
decomposed Unicode characters.</fsummary>
<desc>
@@ -423,7 +423,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfd_binary" arity="1"/>
+ <name name="characters_to_nfd_binary" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a utf8 binary of canonical equivalent
decomposed Unicode characters.</fsummary>
<desc>
@@ -441,7 +441,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfkc_list" arity="1"/>
+ <name name="characters_to_nfkc_list" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a list of canonical equivalent
composed Unicode characters.</fsummary>
<desc>
@@ -460,7 +460,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfkc_binary" arity="1"/>
+ <name name="characters_to_nfkc_binary" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a utf8 binary of compatibly equivalent
composed Unicode characters.</fsummary>
<desc>
@@ -478,7 +478,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfkd_list" arity="1"/>
+ <name name="characters_to_nfkd_list" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a list of compatibly equivalent
decomposed Unicode characters.</fsummary>
<desc>
@@ -497,7 +497,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="characters_to_nfkd_binary" arity="1"/>
+ <name name="characters_to_nfkd_binary" arity="1" since="OTP 20.0"/>
<fsummary>Normalize characters to a utf8 binary of compatibly equivalent
decomposed Unicode characters.</fsummary>
<desc>
@@ -515,7 +515,7 @@ decode_data(Data) ->
</func>
<func>
- <name name="encoding_to_bom" arity="1"/>
+ <name name="encoding_to_bom" arity="1" since=""/>
<fsummary>Create a binary UTF byte order mark from encoding.</fsummary>
<type_desc variable="Bin">
A <c>binary()</c> such that <c>byte_size(<anno>Bin</anno>) >= 4</c>.
diff --git a/lib/stdlib/doc/src/uri_string.xml b/lib/stdlib/doc/src/uri_string.xml
index 88d4600611..ad443486c5 100644
--- a/lib/stdlib/doc/src/uri_string.xml
+++ b/lib/stdlib/doc/src/uri_string.xml
@@ -27,7 +27,7 @@
<date>2018-02-07</date>
<rev>A</rev>
</header>
- <module>uri_string</module>
+ <module since="OTP 21.0">uri_string</module>
<modulesummary>URI processing functions.</modulesummary>
<description>
<p>This module contains functions for parsing and handling URIs
@@ -150,7 +150,7 @@
<funcs>
<func>
- <name name="compose_query" arity="1"/>
+ <name name="compose_query" arity="1" since="OTP 21.0"/>
<fsummary>Compose urlencoded query string.</fsummary>
<desc>
<p>Composes a form-urlencoded <c><anno>QueryString</anno></c> based on a
@@ -176,7 +176,7 @@
</func>
<func>
- <name name="compose_query" arity="2"/>
+ <name name="compose_query" arity="2" since="OTP 21.0"/>
<fsummary>Compose urlencoded query string.</fsummary>
<desc>
<p>Same as <c>compose_query/1</c> but with an additional
@@ -210,7 +210,7 @@
</func>
<func>
- <name name="dissect_query" arity="1"/>
+ <name name="dissect_query" arity="1" since="OTP 21.0"/>
<fsummary>Dissect query string.</fsummary>
<desc>
<p>Dissects an urlencoded <c><anno>QueryString</anno></c> and returns a
@@ -236,7 +236,7 @@
</func>
<func>
- <name name="normalize" arity="1"/>
+ <name name="normalize" arity="1" since="OTP 21.0"/>
<fsummary>Syntax-based normalization.</fsummary>
<desc>
<p>Transforms an <c><anno>URI</anno></c> into a normalized form
@@ -261,7 +261,7 @@
</func>
<func>
- <name name="normalize" arity="2"/>
+ <name name="normalize" arity="2" since="OTP 21.0"/>
<fsummary>Syntax-based normalization.</fsummary>
<desc>
<p>Same as <c>normalize/1</c> but with an additional
@@ -285,7 +285,7 @@
</func>
<func>
- <name name="parse" arity="1"/>
+ <name name="parse" arity="1" since="OTP 21.0"/>
<fsummary>Parse URI into a map.</fsummary>
<desc>
<p>Parses an <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>
@@ -309,7 +309,7 @@
</func>
<func>
- <name name="recompose" arity="1"/>
+ <name name="recompose" arity="1" since="OTP 21.0"/>
<fsummary>Recompose URI.</fsummary>
<desc>
<p>Creates an <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url> compliant
@@ -332,7 +332,7 @@
</func>
<func>
- <name name="transcode" arity="2"/>
+ <name name="transcode" arity="2" since="OTP 21.0"/>
<fsummary>Transcode URI.</fsummary>
<desc>
<p>Transcodes an <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>
diff --git a/lib/stdlib/doc/src/win32reg.xml b/lib/stdlib/doc/src/win32reg.xml
index f4a4fa1626..5e2aed6062 100644
--- a/lib/stdlib/doc/src/win32reg.xml
+++ b/lib/stdlib/doc/src/win32reg.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>win32reg.xml</file>
</header>
- <module>win32reg</module>
+ <module since="">win32reg</module>
<modulesummary>Provides access to the registry on Windows.</modulesummary>
<description>
<p>This module provides read and write access to the
@@ -112,7 +112,7 @@ hkdd HKEY_DYN_DATA</pre>
<funcs>
<func>
- <name name="change_key" arity="2"/>
+ <name name="change_key" arity="2" since=""/>
<fsummary>Move to a key in the registry.</fsummary>
<desc>
<p>Changes the current key to another key. Works like <c>cd</c>.
@@ -122,7 +122,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="change_key_create" arity="2"/>
+ <name name="change_key_create" arity="2" since=""/>
<fsummary>Move to a key, create it if it is not there.</fsummary>
<desc>
<p>Creates a key, or just changes to it, if it is already there. Works
@@ -133,7 +133,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="close" arity="1"/>
+ <name name="close" arity="1" since=""/>
<fsummary>Close the registry.</fsummary>
<desc>
<p>Closes the registry. After that, the <c><anno>RegHandle</anno></c>
@@ -142,7 +142,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="current_key" arity="1"/>
+ <name name="current_key" arity="1" since=""/>
<fsummary>Return the path to the current key.</fsummary>
<desc>
<p>Returns the path to the current key. This is the equivalent of
@@ -153,7 +153,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="delete_key" arity="1"/>
+ <name name="delete_key" arity="1" since=""/>
<fsummary>Delete the current key.</fsummary>
<desc>
<p>Deletes the current key, if it is valid. Calls the Win32 API
@@ -166,7 +166,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="delete_value" arity="2"/>
+ <name name="delete_value" arity="2" since=""/>
<fsummary>Delete the named value on the current key.</fsummary>
<desc>
<p>Deletes a named value on the current key. The atom <c>default</c> is
@@ -176,7 +176,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="expand" arity="1"/>
+ <name name="expand" arity="1" since=""/>
<fsummary>Expand a string with environment variables.</fsummary>
<desc>
<p>Expands a string containing environment variables between percent
@@ -189,7 +189,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="format_error" arity="1"/>
+ <name name="format_error" arity="1" since=""/>
<fsummary>Convert a POSIX error code to a string.</fsummary>
<desc>
<p>Converts a POSIX error code to a string
@@ -198,7 +198,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="open" arity="1"/>
+ <name name="open" arity="1" since=""/>
<fsummary>Open the registry for reading or writing.</fsummary>
<desc>
<p>Opens the registry for reading or writing. The current key is the
@@ -211,7 +211,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="set_value" arity="3"/>
+ <name name="set_value" arity="3" since=""/>
<fsummary>Set value at the current registry key with specified name.
</fsummary>
<desc>
@@ -230,7 +230,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="sub_keys" arity="1"/>
+ <name name="sub_keys" arity="1" since=""/>
<fsummary>Get subkeys to the current key.</fsummary>
<desc>
<p>Returns a list of subkeys to the current key. Calls the Win32
@@ -240,7 +240,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="value" arity="2"/>
+ <name name="value" arity="2" since=""/>
<fsummary>Get the named value on the current key.</fsummary>
<desc>
<p>Retrieves the named value (or default) on the current key.
@@ -251,7 +251,7 @@ hkdd HKEY_DYN_DATA</pre>
</func>
<func>
- <name name="values" arity="1"/>
+ <name name="values" arity="1" since=""/>
<fsummary>Get all values on the current key.</fsummary>
<desc>
<p>Retrieves a list of all values on the current key. The values
diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml
index 0b5eac1e16..bb2ed7727a 100644
--- a/lib/stdlib/doc/src/zip.xml
+++ b/lib/stdlib/doc/src/zip.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>zip.xml</file>
</header>
- <module>zip</module>
+ <module since="">zip</module>
<modulesummary>Utility for reading and creating 'zip' archives.
</modulesummary>
<description>
@@ -180,7 +180,7 @@
<funcs>
<func>
- <name name="foldl" arity="3"/>
+ <name name="foldl" arity="3" since="OTP R14B"/>
<fsummary>Fold a function over all files in a zip archive.</fsummary>
<desc>
<p>Calls <c><anno>Fun</anno>(<anno>FileInArchive</anno>, <anno>GetInfo
@@ -234,10 +234,10 @@
</func>
<func>
- <name name="list_dir" arity="1"/>
- <name name="list_dir" arity="2"/>
- <name name="table" arity="1" />
- <name name="table" arity="2"/>
+ <name name="list_dir" arity="1" since=""/>
+ <name name="list_dir" arity="2" since=""/>
+ <name name="table" arity="1" since=""/>
+ <name name="table" arity="2" since=""/>
<fsummary>Retrieve the name of all files in a zip archive.</fsummary>
<desc>
<p><c>list_dir/1</c> retrieves all filenames in the zip archive
@@ -263,7 +263,7 @@
</func>
<func>
- <name name="t" arity="1"/>
+ <name name="t" arity="1" since=""/>
<fsummary>Print the name of each file in a zip archive.</fsummary>
<desc>
<p>Prints all filenames in the zip archive <c><anno>Archive</anno></c>
@@ -272,7 +272,7 @@
</func>
<func>
- <name name="tt" arity="1"/>
+ <name name="tt" arity="1" since=""/>
<fsummary>Print name and information for each file in a zip archive.
</fsummary>
<desc>
@@ -283,10 +283,10 @@
</func>
<func>
- <name name="unzip" arity="1"/>
- <name name="unzip" arity="2"/>
- <name name="extract" arity="1"/>
- <name name="extract" arity="2"/>
+ <name name="unzip" arity="1" since=""/>
+ <name name="unzip" arity="2" since=""/>
+ <name name="extract" arity="1" since=""/>
+ <name name="extract" arity="2" since=""/>
<fsummary>Extract files from a zip archive.</fsummary>
<desc>
<p><c>unzip/1</c> extracts all files from a zip archive.</p>
@@ -353,10 +353,10 @@
</func>
<func>
- <name name="zip" arity="2"/>
- <name name="zip" arity="3"/>
- <name name="create" arity="2"/>
- <name name="create" arity="3"/>
+ <name name="zip" arity="2" since=""/>
+ <name name="zip" arity="3" since=""/>
+ <name name="create" arity="2" since=""/>
+ <name name="create" arity="3" since=""/>
<fsummary>Create a zip archive with options.</fsummary>
<desc>
<p>Creates a zip archive containing the files specified in
@@ -481,7 +481,7 @@
</func>
<func>
- <name name="zip_close" arity="1"/>
+ <name name="zip_close" arity="1" since=""/>
<fsummary>Close an open archive.</fsummary>
<desc>
<p>Closes a zip archive, previously opened with
@@ -492,8 +492,8 @@
</func>
<func>
- <name name="zip_get" arity="1"/>
- <name name="zip_get" arity="2"/>
+ <name name="zip_get" arity="1" since=""/>
+ <name name="zip_get" arity="2" since=""/>
<fsummary>Extract files from an open archive.</fsummary>
<desc>
<p>Extracts one or all files from an open archive.</p>
@@ -505,7 +505,7 @@
</func>
<func>
- <name name="zip_list_dir" arity="1"/>
+ <name name="zip_list_dir" arity="1" since=""/>
<fsummary>Return a table of files in open zip archive.</fsummary>
<desc>
<p>Returns the file list of an open zip archive. The first returned
@@ -514,8 +514,8 @@
</func>
<func>
- <name name="zip_open" arity="1"/>
- <name name="zip_open" arity="2"/>
+ <name name="zip_open" arity="1" since=""/>
+ <name name="zip_open" arity="2" since=""/>
<fsummary>Open an archive and return a handle to it.</fsummary>
<desc>
<p>Opens a zip archive, and reads and saves its directory. This
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index ef4c7d255c..3386cfcbe6 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -53,7 +53,7 @@
%%-------------------------------------------------------------------------
--type beam() :: module() | file:filename() | binary().
+-type beam() :: file:filename() | binary().
-type debug_info() :: {DbgiVersion :: atom(), Backend :: module(), Data :: term()} | 'no_debug_info'.
-type forms() :: [erl_parse:abstract_form() | erl_parse:form_info()].
@@ -690,30 +690,31 @@ chunk_to_data(debug_info=Id, Chunk, File, _Cs, AtomTable, Mod) ->
<<0:8,N:8,Mode0:N/binary,Rest/binary>> ->
Mode = binary_to_atom(Mode0, utf8),
Term = decrypt_chunk(Mode, Mod, File, Id, Rest),
- {AtomTable, {Id, Term}};
+ {AtomTable, {Id, anno_from_term(Term)}};
_ ->
case catch binary_to_term(Chunk) of
{'EXIT', _} ->
error({invalid_chunk, File, chunk_name_to_id(Id, File)});
Term ->
- {AtomTable, {Id, Term}}
+ {AtomTable, {Id, anno_from_term(Term)}}
end
end;
chunk_to_data(abstract_code=Id, Chunk, File, _Cs, AtomTable, Mod) ->
+ %% Before Erlang/OTP 20.0.
case Chunk of
<<>> ->
{AtomTable, {Id, no_abstract_code}};
<<0:8,N:8,Mode0:N/binary,Rest/binary>> ->
Mode = binary_to_atom(Mode0, utf8),
Term = decrypt_chunk(Mode, Mod, File, Id, Rest),
- {AtomTable, {Id, anno_from_term(Term)}};
+ {AtomTable, {Id, old_anno_from_term(Term)}};
_ ->
case catch binary_to_term(Chunk) of
{'EXIT', _} ->
error({invalid_chunk, File, chunk_name_to_id(Id, File)});
Term ->
try
- {AtomTable, {Id, anno_from_term(Term)}}
+ {AtomTable, {Id, old_anno_from_term(Term)}}
catch
_:_ ->
error({invalid_chunk, File,
@@ -947,14 +948,24 @@ decrypt_chunk(Type, Module, File, Id, Bin) ->
error({key_missing_or_invalid, File, Id})
end.
-anno_from_term({raw_abstract_v1, Forms}) ->
+old_anno_from_term({raw_abstract_v1, Forms}) ->
{raw_abstract_v1, anno_from_forms(Forms)};
-anno_from_term({Tag, Forms}) when Tag =:= abstract_v1; Tag =:= abstract_v2 ->
+old_anno_from_term({Tag, Forms}) when Tag =:= abstract_v1;
+ Tag =:= abstract_v2 ->
try {Tag, anno_from_forms(Forms)}
catch
_:_ ->
{Tag, Forms}
end;
+old_anno_from_term(T) ->
+ T.
+
+anno_from_term({debug_info_v1=Tag1, erl_abstract_code=Tag2, {Forms, Opts}}) ->
+ try {Tag1, Tag2, {anno_from_forms(Forms), Opts}}
+ catch
+ _:_ ->
+ {Tag1, Tag2, {Forms, Opts}}
+ end;
anno_from_term(T) ->
T.
diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl
index 9a600c1972..3a8fe2211b 100644
--- a/lib/stdlib/src/calendar.erl
+++ b/lib/stdlib/src/calendar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -357,13 +357,17 @@ rfc3339_to_system_time(DateTimeString) ->
rfc3339_to_system_time(DateTimeString, Options) ->
Unit = proplists:get_value(unit, Options, second),
%% _T is the character separating the date and the time:
- {DateStr, [_T|TimeStr]} = lists:split(10, DateTimeString),
- {TimeStr2, TimeStr3} = lists:split(8, TimeStr),
- {ok, [Hour, Min, Sec], []} = io_lib:fread("~d:~d:~d", TimeStr2),
- {ok, [Year, Month, Day], []} = io_lib:fread("~d-~d-~d", DateStr),
+ [Y1, Y2, Y3, Y4, $-, Mon1, Mon2, $-, D1, D2, _T,
+ H1, H2, $:, Min1, Min2, $:, S1, S2 | TimeStr] = DateTimeString,
+ Hour = list_to_integer([H1, H2]),
+ Min = list_to_integer([Min1, Min2]),
+ Sec = list_to_integer([S1, S2]),
+ Year = list_to_integer([Y1, Y2, Y3, Y4]),
+ Month = list_to_integer([Mon1, Mon2]),
+ Day = list_to_integer([D1, D2]),
DateTime = {{Year, Month, Day}, {Hour, Min, Sec}},
IsFractionChar = fun(C) -> C >= $0 andalso C =< $9 orelse C =:= $. end,
- {FractionStr, UtcOffset} = lists:splitwith(IsFractionChar, TimeStr3),
+ {FractionStr, UtcOffset} = lists:splitwith(IsFractionChar, TimeStr),
Time = datetime_to_system_time(DateTime),
Secs = Time - offset_adjustment(Time, second, UtcOffset),
check(DateTimeString, Options, Secs),
@@ -451,8 +455,9 @@ system_time_to_rfc3339(Time, Options) ->
DateTime = system_time_to_datetime(Secs),
{{Year, Month, Day}, {Hour, Min, Sec}} = DateTime,
FractionStr = fraction_str(Factor, AdjustedTime),
- flat_fwrite("~4.10.0B-~2.10.0B-~2.10.0B~c~2.10.0B:~2.10.0B:~2.10.0B~s~s",
- [Year, Month, Day, T, Hour, Min, Sec, FractionStr, Offset]).
+ L = [pad4(Year), "-", pad2(Month), "-", pad2(Day), [T],
+ pad2(Hour), ":", pad2(Min), ":", pad2(Sec), FractionStr, Offset],
+ lists:append(L).
%% time_difference(T1, T2) = Tdiff
%%
@@ -529,24 +534,41 @@ valid_date({Y, M, D}) ->
%% day_to_year(DayOfEpoch) = {Year, DayOfYear}
%%
-%% The idea here is to first guess a year, and then adjust. Although
-%% the implementation is recursive, at most 1 or 2 recursive steps
+%% The idea here is to first set the upper and lower bounds for a year,
+%% and then adjust a range by interpolation search. Although complexity
+%% of the algorithm is log(log(n)), at most 1 or 2 recursive steps
%% are taken.
-%% If DayOfEpoch is very large, we need far more than 1 or 2 iterations,
-%% since we just subtract a yearful of days at a time until we're there.
%%
-spec day_to_year(non_neg_integer()) -> {year(), day_of_year()}.
day_to_year(DayOfEpoch) when DayOfEpoch >= 0 ->
- Y0 = DayOfEpoch div ?DAYS_PER_YEAR,
- {Y1, D1} = dty(Y0, DayOfEpoch, dy(Y0)),
+ YMax = DayOfEpoch div ?DAYS_PER_YEAR,
+ YMin = DayOfEpoch div ?DAYS_PER_LEAP_YEAR,
+ {Y1, D1} = dty(YMin, YMax, DayOfEpoch, dy(YMin), dy(YMax)),
{Y1, DayOfEpoch - D1}.
--spec dty(year(), non_neg_integer(), non_neg_integer()) ->
+-spec dty(year(), year(), non_neg_integer(), non_neg_integer(),
+ non_neg_integer()) ->
{year(), non_neg_integer()}.
-dty(Y, D1, D2) when D1 < D2 ->
- dty(Y-1, D1, dy(Y-1));
-dty(Y, _D1, D2) ->
- {Y, D2}.
+dty(Min, Max, _D1, DMin, _DMax) when Min == Max ->
+ {Min, DMin};
+dty(Min, Max, D1, DMin, DMax) ->
+ Diff = Max - Min,
+ Mid = Min + (Diff * (D1 - DMin)) div (DMax - DMin),
+ MidLength =
+ case is_leap_year(Mid) of
+ true -> ?DAYS_PER_LEAP_YEAR;
+ false -> ?DAYS_PER_YEAR
+ end,
+ case dy(Mid) of
+ D2 when D1 < D2 ->
+ NewMax = Mid - 1,
+ dty(Min, NewMax, D1, DMin, dy(NewMax));
+ D2 when D1 - D2 >= MidLength ->
+ NewMin = Mid + 1,
+ dty(NewMin, Max, D1, dy(NewMin), DMax);
+ D2 ->
+ {Mid, D2}
+ end.
%%
%% The Gregorian days of the iso week 01 day 1 for a given year.
@@ -663,7 +685,7 @@ offset(OffsetOption, Secs0) when OffsetOption =:= "";
Secs = abs(Secs0),
Hour = Secs div 3600,
Min = (Secs rem 3600) div 60,
- io_lib:fwrite("~c~2.10.0B:~2.10.0B", [Sign, Hour, Min]);
+ [Sign | lists:append([pad2(Hour), ":", pad2(Min)])];
offset(OffsetOption, _Secs) ->
OffsetOption.
@@ -678,8 +700,10 @@ offset_string_adjustment(_Time, _Unit, "Z") ->
0;
offset_string_adjustment(_Time, _Unit, "z") ->
0;
-offset_string_adjustment(_Time, _Unit, [Sign|Tz]) ->
- {ok, [Hour, Min], []} = io_lib:fread("~d:~d", Tz),
+offset_string_adjustment(_Time, _Unit, Tz) ->
+ [Sign, H1, H2, $:, M1, M2] = Tz,
+ Hour = list_to_integer([H1, H2]),
+ Min = list_to_integer([M1, M2]),
Adjustment = 3600 * Hour + 60 * Min,
case Sign of
$- -> -Adjustment;
@@ -687,20 +711,19 @@ offset_string_adjustment(_Time, _Unit, [Sign|Tz]) ->
end.
local_offset(SystemTime, Unit) ->
- LocalTime = system_time_to_local_time(SystemTime, Unit),
+ %% Not optimized for special cases.
UniversalTime = system_time_to_universal_time(SystemTime, Unit),
+ LocalTime = erlang:universaltime_to_localtime(UniversalTime),
LocalSecs = datetime_to_gregorian_seconds(LocalTime),
UniversalSecs = datetime_to_gregorian_seconds(UniversalTime),
LocalSecs - UniversalSecs.
+fraction_str(1, _Time) ->
+ "";
fraction_str(Factor, Time) ->
- case Time rem Factor of
- 0 ->
- "";
- Fraction ->
- FS = io_lib:fwrite(".~*..0B", [log10(Factor), abs(Fraction)]),
- string:trim(FS, trailing, "0")
- end.
+ Fraction = Time rem Factor,
+ S = integer_to_list(abs(Fraction)),
+ [$. | pad(log10(Factor) - length(S), S)].
fraction(second, _) ->
0;
@@ -721,5 +744,21 @@ log10(1000) -> 3;
log10(1000000) -> 6;
log10(1000000000) -> 9.
-flat_fwrite(F, S) ->
- lists:flatten(io_lib:fwrite(F, S)).
+pad(0, S) ->
+ S;
+pad(I, S) ->
+ [$0 | pad(I - 1, S)].
+
+pad2(N) when N < 10 ->
+ [$0 | integer_to_list(N)];
+pad2(N) ->
+ integer_to_list(N).
+
+pad4(N) when N < 10 ->
+ [$0, $0, $0 | integer_to_list(N)];
+pad4(N) when N < 100 ->
+ [$0, $0 | integer_to_list(N)];
+pad4(N) when N < 1000 ->
+ [$0 | integer_to_list(N)];
+pad4(N) ->
+ integer_to_list(N).
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index e016d5a80e..0488c2bef2 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -616,12 +616,18 @@ next(Tab, Key) ->
%% Assuming that a file already exists, open it with the
%% parameters as already specified in the file itself.
%% Return a ref leading to the file.
-open_file(File) ->
- case dets_server:open_file(to_list(File)) of
- badarg -> % Should not happen.
- erlang:error(dets_process_died, [File]);
- Reply ->
- einval(Reply, [File])
+open_file(File0) ->
+ File = to_list(File0),
+ case is_list(File) of
+ true ->
+ case dets_server:open_file(File) of
+ badarg -> % Should not happen.
+ erlang:error(dets_process_died, [File]);
+ Reply ->
+ einval(Reply, [File])
+ end;
+ false ->
+ erlang:error(badarg, [File0])
end.
-spec open_file(Name, Args) -> {'ok', Name} | {'error', Reason} when
@@ -1088,6 +1094,7 @@ defaults(Tab, Args) ->
debug = false},
Fun = fun repl/2,
Defaults = lists:foldl(Fun, Defaults0, Args),
+ true = is_list(Defaults#open_args.file),
is_comp_min_max(Defaults).
to_list(T) when is_atom(T) -> atom_to_list(T);
@@ -1112,9 +1119,7 @@ repl({delayed_write, {Delay,Size} = C}, Defs)
Defs#open_args{delayed_write = C};
repl({estimated_no_objects, I}, Defs) ->
repl({min_no_slots, I}, Defs);
-repl({file, File}, Defs) when is_list(File) ->
- Defs#open_args{file = File};
-repl({file, File}, Defs) when is_atom(File) ->
+repl({file, File}, Defs) ->
Defs#open_args{file = to_list(File)};
repl({keypos, P}, Defs) when is_integer(P), P > 0 ->
Defs#open_args{keypos =P};
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index cc34d4bdd3..181a524db6 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -117,6 +117,7 @@ open(Name, File, StartLocation, Path, Pdm) ->
{'ok', Epp} | {'ok', Epp, Extra} | {'error', ErrorDescriptor} when
Options :: [{'default_encoding', DefEncoding :: source_encoding()} |
{'includes', IncludePath :: [DirectoryName :: file:name()]} |
+ {'source_name', SourceName :: file:name()} |
{'macros', PredefMacros :: macros()} |
{'name',FileName :: file:name()} |
'extra'],
@@ -248,6 +249,7 @@ parse_file(Ifile, Path, Predefs) ->
{'ok', [Form]} | {'ok', [Form], Extra} | {error, OpenError} when
FileName :: file:name(),
Options :: [{'includes', IncludePath :: [DirectoryName :: file:name()]} |
+ {'source_name', SourceName :: file:name()} |
{'macros', PredefMacros :: macros()} |
{'default_encoding', DefEncoding :: source_encoding()} |
'extra'],
@@ -540,9 +542,10 @@ server(Pid, Name, Options, #epp{pre_opened=PreOpened}=St) ->
init_server(Pid, Name, Options, St)
end.
-init_server(Pid, Name, Options, St0) ->
+init_server(Pid, FileName, Options, St0) ->
+ SourceName = proplists:get_value(source_name, Options, FileName),
Pdm = proplists:get_value(macros, Options, []),
- Ms0 = predef_macros(Name),
+ Ms0 = predef_macros(FileName),
case user_predef(Pdm, Ms0) of
{ok,Ms1} ->
#epp{file = File, location = AtLocation} = St0,
@@ -552,14 +555,14 @@ init_server(Pid, Name, Options, St0) ->
epp_reply(Pid, {ok,self(),Encoding}),
%% ensure directory of current source file is
%% first in path
- Path = [filename:dirname(Name) |
+ Path = [filename:dirname(FileName) |
proplists:get_value(includes, Options, [])],
- St = St0#epp{delta=0, name=Name, name2=Name,
+ St = St0#epp{delta=0, name=SourceName, name2=SourceName,
path=Path, macs=Ms1,
default_encoding=DefEncoding},
From = wait_request(St),
Anno = erl_anno:new(AtLocation),
- enter_file_reply(From, file_name(Name), Anno,
+ enter_file_reply(From, file_name(SourceName), Anno,
AtLocation, code),
wait_req_scan(St);
{error,E} ->
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 31c0e60fe1..2066b2f60f 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -329,7 +329,8 @@ expr({'fun',Line,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs) ->
20 -> fun (A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) ->
eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T], Info) end;
_Other ->
- erlang:raise(error, {'argument_limit',{'fun',Line,Cs}},
+ L = erl_anno:location(Line),
+ erlang:raise(error, {'argument_limit',{'fun',L,to_terms(Cs)}},
?STACKTRACE)
end,
ret_expr(F, Bs, RBs);
@@ -381,7 +382,9 @@ expr({named_fun,Line,Name,Cs} = Ex, Bs, Lf, Ef, RBs) ->
eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T],
RF, Info) end;
_Other ->
- erlang:raise(error, {'argument_limit',{named_fun,Line,Name,Cs}},
+ L = erl_anno:location(Line),
+ erlang:raise(error, {'argument_limit',
+ {named_fun,L,Name,to_terms(Cs)}},
?STACKTRACE)
end,
ret_expr(F, Bs, RBs);
@@ -1092,7 +1095,7 @@ match(Pat, Term, Bs) ->
match(Pat, Term, Bs, BBs) ->
case catch match1(Pat, Term, Bs, BBs) of
invalid ->
- erlang:raise(error, {illegal_pattern,Pat}, ?STACKTRACE);
+ erlang:raise(error, {illegal_pattern,to_term(Pat)}, ?STACKTRACE);
Other ->
Other
end.
@@ -1288,6 +1291,12 @@ merge_bindings(Bs1, Bs2) ->
%% end
%% end, Bs2, Bs1).
+to_terms(Abstrs) ->
+ [to_term(Abstr) || Abstr <- Abstrs].
+
+to_term(Abstr) ->
+ erl_parse:anno_to_term(Abstr).
+
%% Substitute {value, A, Item} for {var, A, Var}, preserving A.
%% {value, A, Item} is a shell/erl_eval convention, and for example
%% the linter cannot handle it.
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index b311a843c2..939abaff00 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -74,6 +74,7 @@ guard_bif(element, 2) -> true;
guard_bif(float, 1) -> true;
guard_bif(floor, 1) -> true;
guard_bif(hd, 1) -> true;
+guard_bif(is_map_key, 2) -> true;
guard_bif(length, 1) -> true;
guard_bif(map_size, 1) -> true;
guard_bif(map_get, 2) -> true;
@@ -109,7 +110,6 @@ new_type_test(is_function, 2) -> true;
new_type_test(is_integer, 1) -> true;
new_type_test(is_list, 1) -> true;
new_type_test(is_map, 1) -> true;
-new_type_test(is_map_key, 2) -> true;
new_type_test(is_number, 1) -> true;
new_type_test(is_pid, 1) -> true;
new_type_test(is_port, 1) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index e9ac2fcdff..e0cd68617b 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2262,8 +2262,7 @@ expr({'fun',Line,Body}, Vt, St) ->
{[],St};
{function,M,F,A} ->
%% New in R15.
- {Bvt, St1} = expr_list([M,F,A], Vt, St),
- {vtupdate(Bvt, Vt),St1}
+ expr_list([M,F,A], Vt, St)
end;
expr({named_fun,_,'_',Cs}, Vt, St) ->
fun_clauses(Cs, Vt, St);
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 3390cee8ae..5fa9c4f75c 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -872,7 +872,7 @@ Erlang code.
-type af_fun_type() :: {'type', anno(), 'fun', []}
| {'type', anno(), 'fun', [{'type', anno(), 'any'} |
abstract_type()]}
- | {'type', anno(), 'fun', af_function_type()}.
+ | af_function_type().
-type af_integer_range_type() ::
{'type', anno(), 'range', [af_singleton_integer_type()]}.
@@ -924,10 +924,11 @@ Erlang code.
-type af_function_constraint() :: [af_constraint()].
-type af_constraint() :: {'type', anno(), 'constraint',
- af_lit_atom('is_subtype'),
- [af_type_variable() | abstract_type()]}. % [V, T]
+ [af_lit_atom('is_subtype') |
+ [af_type_variable() | abstract_type()]]}. % [IsSubtype, [V, T]]
-type af_singleton_integer_type() :: af_integer()
+ | af_character()
| af_unary_op(af_singleton_integer_type())
| af_binary_op(af_singleton_integer_type()).
@@ -980,7 +981,7 @@ Erlang code.
-type af_unary_op(T) :: {'op', anno(), unary_op(), T}.
--type unary_op() :: '+' | '*' | 'bnot' | 'not'.
+-type unary_op() :: '+' | '-' | 'bnot' | 'not'.
%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}.
-type type_specifier_list() :: 'default' | [type_specifier(), ...].
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 367dbefb82..ada3ff5de3 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
_ -> ?TEST(T)
end).
-define(EXPRS_TEST(L),
- [?TEST(E) || E <- L]).
+ _ = [?TEST(E) || E <- L]).
-define(TEST(T),
%% Assumes that erl_anno has been compiled with DEBUG=true.
%% erl_pp does not use the annoations, but test it anyway.
@@ -697,6 +697,8 @@ fun_info(Extra) ->
%% BITS:
+bit_grp([], _Opts) ->
+ leaf("<<>>");
bit_grp(Fs, Opts) ->
append([['<<'], [bit_elems(Fs, Opts)], ['>>']]).
diff --git a/lib/stdlib/src/erl_tar.erl b/lib/stdlib/src/erl_tar.erl
index d8b8f466b1..7064fcacfa 100644
--- a/lib/stdlib/src/erl_tar.erl
+++ b/lib/stdlib/src/erl_tar.erl
@@ -324,7 +324,7 @@ do_open(Name, Mode) when is_list(Mode) ->
open1({binary,Bin}, read, _Raw, Opts) when is_binary(Bin) ->
case file:open(Bin, [ram,binary,read]) of
{ok,File} ->
- _ = [ram_file:uncompress(File) || Opts =:= [compressed]],
+ _ = [ram_file:uncompress(File) || lists:member(compressed, Opts)],
{ok, #reader{handle=File,access=read,func=fun file_op/2}};
Error ->
Error
@@ -357,7 +357,7 @@ open_mode([read|Rest], false, Raw, Opts) ->
open_mode([write|Rest], false, Raw, Opts) ->
open_mode(Rest, write, Raw, Opts);
open_mode([compressed|Rest], Access, Raw, Opts) ->
- open_mode(Rest, Access, Raw, [compressed|Opts]);
+ open_mode(Rest, Access, Raw, [compressed,read_ahead|Opts]);
open_mode([cooked|Rest], Access, _Raw, Opts) ->
open_mode(Rest, Access, [], Opts);
open_mode([], Access, Raw, Opts) ->
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index a322bd002d..b7b7b562ab 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1012,24 +1012,33 @@ filename_string_to_binary(List) ->
%% basedir
%% http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
--type basedir_type() :: 'user_cache' | 'user_config' | 'user_data'
- | 'user_log'
- | 'site_config' | 'site_data'.
+-type basedir_path_type() :: 'user_cache' | 'user_config' | 'user_data'
+ | 'user_log'.
+-type basedir_paths_type() :: 'site_config' | 'site_data'.
--spec basedir(Type,Application) -> file:filename_all() when
- Type :: basedir_type(),
+-type basedir_opts() :: #{author => string() | binary(),
+ os => 'windows' | 'darwin' | 'linux',
+ version => string() | binary()}.
+
+-spec basedir(PathType,Application) -> file:filename_all() when
+ PathType :: basedir_path_type(),
+ Application :: string() | binary();
+ (PathsType,Application) -> [file:filename_all()] when
+ PathsType :: basedir_paths_type(),
Application :: string() | binary().
basedir(Type,Application) when is_atom(Type), is_list(Application) orelse
is_binary(Application) ->
basedir(Type, Application, #{}).
--spec basedir(Type,Application,Opts) -> file:filename_all() when
- Type :: basedir_type(),
+-spec basedir(PathType,Application,Opts) -> file:filename_all() when
+ PathType :: basedir_path_type(),
+ Application :: string() | binary(),
+ Opts :: basedir_opts();
+ (PathsType,Application,Opts) -> [file:filename_all()] when
+ PathsType :: basedir_paths_type(),
Application :: string() | binary(),
- Opts :: #{author => string() | binary(),
- os => 'windows' | 'darwin' | 'linux',
- version => string() | binary()}.
+ Opts :: basedir_opts().
basedir(Type,Application,Opts) when is_atom(Type), is_map(Opts),
is_list(Application) orelse
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index faa43fbc1e..8965af253b 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -398,17 +398,11 @@ timeout_event_type(Type) ->
data :: term(),
postponed = [] :: [{event_type(),term()}],
%%
- timer_refs = #{} :: % timer ref => the timer's event type
- #{reference() => timeout_event_type()},
- timer_types = #{} :: % timer's event type => timer ref
- #{timeout_event_type() => reference()},
- cancel_timers = 0 :: non_neg_integer(),
- %% We add a timer to both timer_refs and timer_types
- %% when we start it. When we request an asynchronous
- %% timer cancel we remove it from timer_types. When
- %% the timer cancel message arrives we remove it from
- %% timer_refs.
- %%
+ timers = {#{},#{}} ::
+ {%% timer ref => the timer's event type
+ TimerRefs :: #{reference() => timeout_event_type()},
+ %% timer's event type => timer ref
+ TimerTypes :: #{timeout_event_type() => reference()}},
hibernate = false :: boolean(),
hibernate_after = infinity :: timeout()}).
@@ -857,7 +851,7 @@ wakeup_from_hibernate(Parent, Debug, S) ->
%% and detours through sys:handle_system_message/7 and proc_lib:hibernate/3
%% Entry point for system_continue/3
-loop(Parent, Debug, #state{hibernate = true, cancel_timers = 0} = S) ->
+loop(Parent, Debug, #state{hibernate = true} = S) ->
loop_hibernate(Parent, Debug, S);
loop(Parent, Debug, S) ->
loop_receive(Parent, Debug, S).
@@ -893,70 +887,20 @@ loop_receive(
Q = [EXIT],
terminate(exit, Reason, ?STACKTRACE(), Debug, S, Q);
{timeout,TimerRef,TimerMsg} ->
- #state{
- timer_refs = TimerRefs,
- timer_types = TimerTypes} = S,
- case TimerRefs of
- #{TimerRef := TimerType} ->
- %% We know of this timer; is it a running
- %% timer or a timer being cancelled that
- %% managed to send a late timeout message?
- case TimerTypes of
- #{TimerType := TimerRef} ->
- %% The timer type maps back to this
- %% timer ref, so it was a running timer
- %% Unregister the triggered timeout
- NewTimerRefs =
- maps:remove(TimerRef, TimerRefs),
- NewTimerTypes =
- maps:remove(TimerType, TimerTypes),
- loop_receive_result(
- Parent, Debug,
- S#state{
- timer_refs = NewTimerRefs,
- timer_types = NewTimerTypes},
- TimerType, TimerMsg);
- _ ->
- %% This was a late timeout message
- %% from timer being cancelled, so
- %% ignore it and expect a cancel_timer
- %% msg shortly
- loop_receive(Parent, Debug, S)
- end;
- _ ->
+ case S#state.timers of
+ {#{TimerRef := TimerType} = TimerRefs,TimerTypes} ->
+ %% Our timer
+ NewTimers =
+ {maps:remove(TimerRef, TimerRefs),
+ maps:remove(TimerType, TimerTypes)},
+ loop_receive_result(
+ Parent, Debug,
+ S#state{timers = NewTimers},
+ TimerType, TimerMsg);
+ {#{},_} ->
%% Not our timer; present it as an event
loop_receive_result(Parent, Debug, S, info, Msg)
end;
- {cancel_timer,TimerRef,_} ->
- #state{
- timer_refs = TimerRefs,
- cancel_timers = CancelTimers,
- hibernate = Hibernate} = S,
- case TimerRefs of
- #{TimerRef := _} ->
- %% We must have requested a cancel
- %% of this timer so it is already
- %% removed from TimerTypes
- NewTimerRefs =
- maps:remove(TimerRef, TimerRefs),
- NewCancelTimers = CancelTimers - 1,
- NewS =
- S#state{
- timer_refs = NewTimerRefs,
- cancel_timers = NewCancelTimers},
- if
- Hibernate =:= true, NewCancelTimers =:= 0 ->
- %% No more cancel_timer msgs to expect;
- %% we can hibernate
- loop_hibernate(Parent, Debug, NewS);
- NewCancelTimers >= 0 -> % Assert
- loop_receive(Parent, Debug, NewS)
- end;
- _ ->
- %% Not our cancel_timer msg;
- %% present it as an event
- loop_receive_result(Parent, Debug, S, info, Msg)
- end;
_ ->
%% External msg
case Msg of
@@ -1429,9 +1373,7 @@ loop_event_done(
loop_event_done(
Parent, Debug_0,
#state{
- state = State, postponed = P_0,
- timer_refs = TimerRefs_0, timer_types = TimerTypes_0,
- cancel_timers = CancelTimers_0} = S,
+ state = State, postponed = P_0, timers = Timers_0} = S,
Events_0, Event_0, NextState, NewData,
#trans_opts{
hibernate = Hibernate, timeouts_r = TimeoutsR,
@@ -1463,22 +1405,17 @@ loop_event_done(
if
NextState =:= State ->
{Events_0,P_1,
- cancel_timer_by_type(
- timeout, {TimerTypes_0,CancelTimers_0})};
+ cancel_timer_by_type(timeout, Timers_0)};
true ->
{lists:reverse(P_1, Events_0),
[],
cancel_timer_by_type(
state_timeout,
- cancel_timer_by_type(
- timeout, {TimerTypes_0,CancelTimers_0}))}
- %% The state timer is removed from TimerTypes
- %% but remains in TimerRefs until we get
- %% the cancel_timer msg
+ cancel_timer_by_type(timeout, Timers_0))}
end,
- {TimerRefs_3,{TimerTypes_3,CancelTimers_3},TimeoutEvents} =
+ {Timers_3,TimeoutEvents} =
%% Stop and start timers
- parse_timers(TimerRefs_0, Timers_2, TimeoutsR),
+ parse_timers(Timers_2, TimeoutsR),
%% Place next events last in reversed queue
Events_3R = lists:reverse(Events_2, NextEventsR),
%% Enqueue immediate timeout events
@@ -1489,9 +1426,7 @@ loop_event_done(
state = NextState,
data = NewData,
postponed = P_2,
- timer_refs = TimerRefs_3,
- timer_types = TimerTypes_3,
- cancel_timers = CancelTimers_3,
+ timers = Timers_3,
hibernate = Hibernate},
lists:reverse(Events_4R)).
@@ -1501,8 +1436,7 @@ loop_event_done_fast(
Parent, Hibernate,
#state{
state = NextState,
- timer_types = #{timeout := _} = TimerTypes,
- cancel_timers = CancelTimers} = S,
+ timers = {_,#{timeout := _}} = Timers} = S,
Events, P, NextState, NewData) ->
%%
%% Same state, event timeout active
@@ -1510,8 +1444,7 @@ loop_event_done_fast(
loop_event_done_fast(
Parent, Hibernate, S,
Events, P, NextState, NewData,
- cancel_timer_by_type(
- timeout, {TimerTypes,CancelTimers}));
+ cancel_timer_by_type(timeout, Timers));
loop_event_done_fast(
Parent, Hibernate,
#state{state = NextState} = S,
@@ -1529,8 +1462,7 @@ loop_event_done_fast(
loop_event_done_fast(
Parent, Hibernate,
#state{
- timer_types = #{timeout := _} = TimerTypes,
- cancel_timers = CancelTimers} = S,
+ timers = {_,#{timeout := _}} = Timers} = S,
Events, P, NextState, NewData) ->
%%
%% State change, event timeout active
@@ -1540,13 +1472,11 @@ loop_event_done_fast(
lists:reverse(P, Events), [], NextState, NewData,
cancel_timer_by_type(
state_timeout,
- cancel_timer_by_type(
- timeout, {TimerTypes,CancelTimers})));
+ cancel_timer_by_type(timeout, Timers)));
loop_event_done_fast(
Parent, Hibernate,
#state{
- timer_types = #{state_timeout := _} = TimerTypes,
- cancel_timers = CancelTimers} = S,
+ timers = {_,#{state_timeout := _}} = Timers} = S,
Events, P, NextState, NewData) ->
%%
%% State change, state timeout active
@@ -1556,8 +1486,7 @@ loop_event_done_fast(
lists:reverse(P, Events), [], NextState, NewData,
cancel_timer_by_type(
state_timeout,
- cancel_timer_by_type(
- timeout, {TimerTypes,CancelTimers})));
+ cancel_timer_by_type(timeout, Timers)));
loop_event_done_fast(
Parent, Hibernate,
#state{} = S,
@@ -1577,9 +1506,7 @@ loop_event_done_fast(
%% Fast path
%%
loop_event_done_fast(
- Parent, Hibernate, S,
- Events, P, NextState, NewData,
- {TimerTypes,CancelTimers}) ->
+ Parent, Hibernate, S, Events, P, NextState, NewData, Timers) ->
%%
loop_event_done(
Parent, ?not_sys_debug,
@@ -1587,8 +1514,7 @@ loop_event_done_fast(
state = NextState,
data = NewData,
postponed = P,
- timer_types = TimerTypes,
- cancel_timers = CancelTimers,
+ timers = Timers,
hibernate = Hibernate},
Events).
@@ -1703,41 +1629,40 @@ classify_time(_, _, Opts) when is_list(Opts) ->
%% and pending event timer
%%
%% Stop and start timers non-event timers
-parse_timers(TimerRefs, Timers, TimeoutsR) ->
- parse_timers(TimerRefs, Timers, TimeoutsR, #{}, []).
+parse_timers(Timers, TimeoutsR) ->
+ parse_timers(Timers, TimeoutsR, #{}, []).
%%
-parse_timers(
- TimerRefs, Timers, [], _Seen, TimeoutEvents) ->
+parse_timers(Timers, [], _Seen, TimeoutEvents) ->
%%
- {TimerRefs,Timers,TimeoutEvents};
+ {Timers,TimeoutEvents};
parse_timers(
- TimerRefs, Timers, [Timeout|TimeoutsR], Seen, TimeoutEvents) ->
+ Timers, [Timeout|TimeoutsR], Seen, TimeoutEvents) ->
%%
case Timeout of
{TimerType,Time,TimerMsg,TimerOpts} ->
%% Absolute timer
parse_timers(
- TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
+ Timers, TimeoutsR, Seen, TimeoutEvents,
TimerType, Time, TimerMsg, listify(TimerOpts));
%% Relative timers below
{TimerType,0,TimerMsg} ->
parse_timers(
- TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
+ Timers, TimeoutsR, Seen, TimeoutEvents,
TimerType, zero, TimerMsg, []);
{TimerType,Time,TimerMsg} ->
parse_timers(
- TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
+ Timers, TimeoutsR, Seen, TimeoutEvents,
TimerType, Time, TimerMsg, [])
end.
parse_timers(
- TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
+ Timers, TimeoutsR, Seen, TimeoutEvents,
TimerType, Time, TimerMsg, TimerOpts) ->
case Seen of
#{TimerType := _} ->
%% Type seen before - ignore
parse_timers(
- TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents);
+ Timers, TimeoutsR, Seen, TimeoutEvents);
#{} ->
%% Unseen type - handle
NewSeen = Seen#{TimerType => true},
@@ -1745,13 +1670,13 @@ parse_timers(
infinity ->
%% Cancel any running timer
parse_timers(
- TimerRefs, cancel_timer_by_type(TimerType, Timers),
+ cancel_timer_by_type(TimerType, Timers),
TimeoutsR, NewSeen, TimeoutEvents);
zero ->
%% Cancel any running timer
%% Handle zero time timeouts later
parse_timers(
- TimerRefs, cancel_timer_by_type(TimerType, Timers),
+ cancel_timer_by_type(TimerType, Timers),
TimeoutsR, NewSeen,
[{TimerType,TimerMsg}|TimeoutEvents]);
_ ->
@@ -1759,26 +1684,27 @@ parse_timers(
TimerRef =
erlang:start_timer(
Time, self(), TimerMsg, TimerOpts),
- case Timers of
- {#{TimerType := OldTimerRef} = TimerTypes,
- CancelTimers} ->
- %% Cancel the running timer
+ {TimerRefs,TimerTypes} = Timers,
+ case TimerTypes of
+ #{TimerType := OldTimerRef} ->
+ %% Cancel the running timer,
+ %% update the timeout type,
+ %% insert the new timer ref,
+ %% and remove the old timer ref
cancel_timer(OldTimerRef),
- NewCancelTimers = CancelTimers + 1,
%% Insert the new timer into
%% both TimerRefs and TimerTypes
parse_timers(
- TimerRefs#{TimerRef => TimerType},
- {TimerTypes#{TimerType => TimerRef},
- NewCancelTimers},
+ {maps:remove(
+ OldTimerRef,
+ TimerRefs#{TimerRef => TimerType}),
+ TimerTypes#{TimerType := TimerRef}},
TimeoutsR, NewSeen, TimeoutEvents);
- {#{} = TimerTypes,CancelTimers} ->
- %% Insert the new timer into
- %% both TimerRefs and TimerTypes
+ #{} ->
+ %% Insert the new timer type and ref
parse_timers(
- TimerRefs#{TimerRef => TimerType},
- {TimerTypes#{TimerType => TimerRef},
- CancelTimers},
+ {TimerRefs#{TimerRef => TimerType},
+ TimerTypes#{TimerType => TimerRef}},
TimeoutsR, NewSeen, TimeoutEvents)
end
end
@@ -2021,24 +1947,34 @@ listify(Item) when is_list(Item) ->
listify(Item) ->
[Item].
+
+-define(cancel_timer(TimerRef),
+ case erlang:cancel_timer(TimerRef) of
+ false ->
+ %% No timer found and we have not seen the timeout message
+ receive
+ {timeout,(TimerRef),_} ->
+ ok
+ end;
+ _ ->
+ %% Timer was running
+ ok
+ end).
+
+-compile({inline, [cancel_timer/1]}).
+cancel_timer(TimerRef) ->
+ ?cancel_timer(TimerRef).
+
%% Cancel timer if running, otherwise no op
%%
-%% This is an asynchronous cancel so the timer is not really cancelled
-%% until we get a cancel_timer msg i.e {cancel_timer,TimerRef,_}.
-%% In the mean time we might get a timeout message.
-%%
-%% Remove the timer from TimerTypes.
-%% When we get the cancel_timer msg we remove it from TimerRefs.
+%% Remove the timer from Timers.
-compile({inline, [cancel_timer_by_type/2]}).
-cancel_timer_by_type(TimerType, {TimerTypes,CancelTimers} = TT_CT) ->
+cancel_timer_by_type(TimerType, {TimerRefs,TimerTypes} = Timers) ->
case TimerTypes of
#{TimerType := TimerRef} ->
- ok = erlang:cancel_timer(TimerRef, [{async,true}]),
- {maps:remove(TimerType, TimerTypes),CancelTimers + 1};
+ ?cancel_timer(TimerRef),
+ {maps:remove(TimerRef, TimerRefs),
+ maps:remove(TimerType, TimerTypes)};
#{} ->
- TT_CT
+ Timers
end.
-
--compile({inline, [cancel_timer/1]}).
-cancel_timer(TimerRef) ->
- ok = erlang:cancel_timer(TimerRef, [{async,true}]).
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 3a5aba60b4..2b5a374cf2 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -87,6 +87,8 @@
-export([limit_term/2]).
+-export([chars_length/1]).
+
-export_type([chars/0, latin1_string/0, continuation/0,
fread_error/0, fread_item/0, format_spec/0, chars_limit/0]).
@@ -178,11 +180,11 @@ fread(Cont, Chars, Format) ->
Data :: [term()].
format(Format, Args) ->
- case catch io_lib_format:fwrite(Format, Args) of
- {'EXIT',_} ->
- erlang:error(badarg, [Format, Args]);
- Other ->
- Other
+ try io_lib_format:fwrite(Format, Args)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec format(Format, Data, Options) -> chars() when
@@ -193,11 +195,11 @@ format(Format, Args) ->
CharsLimit :: chars_limit().
format(Format, Args, Options) ->
- case catch io_lib_format:fwrite(Format, Args, Options) of
- {'EXIT',_} ->
- erlang:error(badarg, [Format, Args, Options]);
- Other ->
- Other
+ try io_lib_format:fwrite(Format, Args, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec scan_format(Format, Data) -> FormatList when
@@ -208,7 +210,9 @@ format(Format, Args, Options) ->
scan_format(Format, Args) ->
try io_lib_format:scan(Format, Args)
catch
- _:_ -> erlang:error(badarg, [Format, Args])
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec unscan_format(FormatList) -> {Format, Data} when
@@ -223,7 +227,12 @@ unscan_format(FormatList) ->
FormatList :: [char() | format_spec()].
build_text(FormatList) ->
- io_lib_format:build(FormatList).
+ try io_lib_format:build(FormatList)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList])
+ end.
-spec build_text(FormatList, Options) -> chars() when
FormatList :: [char() | format_spec()],
@@ -232,7 +241,23 @@ build_text(FormatList) ->
CharsLimit :: chars_limit().
build_text(FormatList, Options) ->
- io_lib_format:build(FormatList, Options).
+ try io_lib_format:build(FormatList, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList, Options])
+ end.
+
+%% Failure to load a module must not be labeled as badarg.
+%% C, R, and S are included so that the original error, which could be
+%% a bug in io_lib_format, can be found by tracing on
+%% test_modules_loaded/3.
+test_modules_loaded(_C, _R, _S) ->
+ Modules = [io_lib_format, io_lib_pretty, string, unicode],
+ case code:ensure_modules_loaded(Modules) of
+ ok -> ok;
+ Error -> erlang:error(Error)
+ end.
-spec print(Term) -> chars() when
Term :: term().
@@ -1108,3 +1133,17 @@ test_limit_map_assoc(K, V, D) ->
test_limit(V, D - 1).
test_limit_bitstring(_, _) -> ok.
+
+-spec chars_length(chars()) -> non_neg_integer().
+%% Optimized for deep lists S such that deep_latin1_char_list(S) is
+%% true. No binaries allowed! It is assumed that $\r is never followed
+%% by $\n if S is an iolist() (string:length() assigns such a
+%% sub-sequence length 1).
+chars_length(S) ->
+ try
+ %% true = deep_latin1_char_list(S),
+ iolist_size(S)
+ catch
+ _:_ ->
+ string:length(S)
+ end.
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index c814ab50d4..d1aa4cd157 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,18 +38,16 @@
%% and it also splits the handling of the control characters into two
%% parts.
--spec fwrite(Format, Data) -> FormatList when
+-spec fwrite(Format, Data) -> io_lib:chars() when
Format :: io:format(),
- Data :: [term()],
- FormatList :: [char() | io_lib:format_spec()].
+ Data :: [term()].
fwrite(Format, Args) ->
build(scan(Format, Args)).
--spec fwrite(Format, Data, Options) -> FormatList when
+-spec fwrite(Format, Data, Options) -> io_lib:chars() when
Format :: io:format(),
Data :: [term()],
- FormatList :: [char() | io_lib:format_spec()],
Options :: [Option],
Option :: {'chars_limit', CharsLimit},
CharsLimit :: io_lib:chars_limit().
@@ -248,8 +246,9 @@ count_small([#{control_char := $W}|Cs], #{w := W} = Cnts) ->
count_small(Cs, Cnts#{w := W + 1});
count_small([#{control_char := $s}|Cs], #{w := W} = Cnts) ->
count_small(Cs, Cnts#{w := W + 1});
-count_small([S|Cs], #{other := Other} = Cnts) when is_list(S) ->
- count_small(Cs, Cnts#{other := Other + string:length(S)});
+count_small([S|Cs], #{other := Other} = Cnts) when is_list(S);
+ is_binary(S) ->
+ count_small(Cs, Cnts#{other := Other + io_lib:chars_length(S)});
count_small([C|Cs], #{other := Other} = Cnts) when is_integer(C) ->
count_small(Cs, Cnts#{other := Other + 1});
count_small([], #{p := P, s := S, w := W, other := Other}) ->
@@ -281,10 +280,15 @@ build_limited([#{control_char := C, args := As, width := F, adjust := Ad,
true -> MaxLen0 div Count0
end,
S = control_limited(C, As, F, Ad, P, Pad, Enc, Str, MaxChars, I),
- Len = string:length(S),
NumOfPs = decr_pc(C, NumOfPs0),
Count = Count0 - 1,
- MaxLen = sub(MaxLen0, Len),
+ MaxLen = if
+ MaxLen0 < 0 -> % optimization
+ MaxLen0;
+ true ->
+ Len = io_lib:chars_length(S),
+ sub(MaxLen0, Len)
+ end,
if
NumOfPs > 0 -> [S|build_limited(Cs, NumOfPs, Count,
MaxLen, indentation(S, I))];
@@ -407,7 +411,7 @@ base(B) when is_integer(B) ->
term(T, none, _Adj, none, _Pad) -> T;
term(T, none, Adj, P, Pad) -> term(T, P, Adj, P, Pad);
term(T, F, Adj, P0, Pad) ->
- L = string:length(T),
+ L = io_lib:chars_length(T),
P = erlang:min(L, case P0 of none -> F; _ -> min(P0, F) end),
if
L > P ->
@@ -714,7 +718,7 @@ fwrite_g(Fl, F, Adj, P, Pad) when P >= 1 ->
end.
-%% iolist_to_chars(iolist()) -> deep_char_list()
+%% iolist_to_chars(iolist()) -> io_lib:chars()
iolist_to_chars([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 ->
[C | iolist_to_chars(Cs)];
@@ -730,7 +734,7 @@ iolist_to_chars(B) when is_binary(B) ->
%% cbinary() | nil())
%% cbinary() :: unicode:unicode_binary() | unicode:latin1_binary()
-%% cdata_to_chars(cdata()) -> io_lib:deep_char_list()
+%% cdata_to_chars(cdata()) -> io_lib:chars()
cdata_to_chars([C|Cs]) when is_integer(C), C >= $\000 ->
[C | cdata_to_chars(Cs)];
@@ -746,7 +750,7 @@ cdata_to_chars(B) when is_binary(B) ->
limit_string(S, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> S;
limit_string(S, _F, CharsLimit) ->
- case string:length(S) =< CharsLimit of
+ case io_lib:chars_length(S) =< CharsLimit of
true -> S;
false -> [string:slice(S, 0, sub(CharsLimit, 3)), "..."]
end.
@@ -760,11 +764,11 @@ limit_field(F, CharsLimit) ->
string(S, none, _Adj, none, _Pad) -> S;
string(S, F, Adj, none, Pad) ->
- string_field(S, F, Adj, string:length(S), Pad);
+ string_field(S, F, Adj, io_lib:chars_length(S), Pad);
string(S, none, _Adj, P, Pad) ->
- string_field(S, P, left, string:length(S), Pad);
+ string_field(S, P, left, io_lib:chars_length(S), Pad);
string(S, F, Adj, P, Pad) when F >= P ->
- N = string:length(S),
+ N = io_lib:chars_length(S),
if F > P ->
if N > P ->
adjust(flat_trunc(S, P), chars(Pad, F-P), Adj);
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl
index dca1b37ef3..ffc02febdc 100644
--- a/lib/stdlib/src/io_lib_pretty.erl
+++ b/lib/stdlib/src/io_lib_pretty.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -507,20 +507,20 @@ print_length(#{}=M, _D, _T, _RF, _Enc, _Str) when map_size(M) =:= 0 ->
{"#{}", 3, 0, no_more};
print_length(Atom, _D, _T, _RF, Enc, _Str) when is_atom(Atom) ->
S = write_atom(Atom, Enc),
- {S, string:length(S), 0, no_more};
+ {S, io_lib:chars_length(S), 0, no_more};
print_length(List, D, T, RF, Enc, Str) when is_list(List) ->
%% only flat lists are "printable"
case Str andalso printable_list(List, D, T, Enc) of
true ->
%% print as string, escaping double-quotes in the list
S = write_string(List, Enc),
- {S, string:length(S), 0, no_more};
+ {S, io_lib:chars_length(S), 0, no_more};
{true, Prefix} ->
%% Truncated lists when T < 0 could break some existing code.
S = write_string(Prefix, Enc),
%% NumOfDots = 0 to avoid looping--increasing the depth
%% does not make Prefix longer.
- {[S | "..."], 3 + string:length(S), 0, no_more};
+ {[S | "..."], 3 + io_lib:chars_length(S), 0, no_more};
false ->
case print_length_list(List, D, T, RF, Enc, Str) of
{What, Len, Dots, _More} when Dots > 0 ->
@@ -564,7 +564,7 @@ print_length(<<_/bitstring>> = Bin, D, T, RF, Enc, Str) ->
{[$<,$<,S,$>,$>], 4 + length(S), 0, no_more};
{false, List} when is_list(List) ->
S = io_lib:write_string(List, $"), %"
- {[$<,$<,S,"/utf8>>"], 9 + string:length(S), 0, no_more};
+ {[$<,$<,S,"/utf8>>"], 9 + io_lib:chars_length(S), 0, no_more};
{true, true, Prefix} ->
S = io_lib:write_string(Prefix, $"), %"
More = fun(T1, Dd) ->
@@ -576,7 +576,7 @@ print_length(<<_/bitstring>> = Bin, D, T, RF, Enc, Str) ->
More = fun(T1, Dd) ->
?FUNCTION_NAME(Bin, D+Dd, T1, RF, Enc, Str)
end,
- {[$<,$<,S|"/utf8...>>"], 12 + string:length(S), 3, More};
+ {[$<,$<,S|"/utf8...>>"], 12 + io_lib:chars_length(S), 3, More};
false ->
case io_lib:write_binary(Bin, D, T) of
{S, <<>>} ->
@@ -591,7 +591,7 @@ print_length(<<_/bitstring>> = Bin, D, T, RF, Enc, Str) ->
print_length(Term, _D, _T, _RF, _Enc, _Str) ->
S = io_lib:write(Term),
%% S can contain unicode, so iolist_size(S) cannot be used here
- {S, string:length(S), 0, no_more}.
+ {S, io_lib:chars_length(S), 0, no_more}.
print_length_map(Map, 1, _T, RF, Enc, Str) ->
More = fun(T1, Dd) -> ?FUNCTION_NAME(Map, 1+Dd, T1, RF, Enc, Str) end,
@@ -651,7 +651,7 @@ print_length_record(Tuple, 1, _T, RF, RDefs, Enc, Str) ->
{"{...}", 5, 3, More};
print_length_record(Tuple, D, T, RF, RDefs, Enc, Str) ->
Name = [$# | write_atom(element(1, Tuple), Enc)],
- NameL = string:length(Name),
+ NameL = io_lib:chars_length(Name),
T1 = tsub(T, NameL+2),
L = print_length_fields(RDefs, D - 1, T1, Tuple, 2, RF, Enc, Str),
{Len, Dots} = list_length(L, NameL + 2, 0),
@@ -677,7 +677,7 @@ print_length_fields([Def | Defs], D, T, Tuple, I, RF, Enc, Str) ->
print_length_field(Def, D, T, E, RF, Enc, Str) ->
Name = write_atom(Def, Enc),
- NameL = string:length(Name) + 3,
+ NameL = io_lib:chars_length(Name) + 3,
{_, Len, Dots, _} =
Field = print_length(E, D, tsub(T, NameL), RF, Enc, Str),
{{field, Name, NameL, Field}, NameL + Len, Dots, no_more}.
@@ -721,8 +721,8 @@ printable_list(_L, 1, _T, _Enc) ->
printable_list(L, _D, T, latin1) when T < 0 ->
io_lib:printable_latin1_list(L);
printable_list(L, _D, T, Enc) when T >= 0 ->
- case slice(L, tsub(T, 2)) of
- {prefix, ""} ->
+ case slice(L, tsub(T, 2), Enc) of
+ false ->
false;
{prefix, Prefix} when Enc =:= latin1 ->
io_lib:printable_latin1_list(Prefix) andalso {true, Prefix};
@@ -737,14 +737,46 @@ printable_list(L, _D, T, Enc) when T >= 0 ->
printable_list(L, _D, T, _Uni) when T < 0->
io_lib:printable_list(L).
-slice(L, N) ->
- case string:length(L) =< N of
- true ->
+slice(L, N, latin1) ->
+ try lists:split(N, L) of
+ {_, []} ->
all;
- false ->
- {prefix, string:slice(L, 0, N)}
+ {[], _} ->
+ false;
+ {L1, _} ->
+ {prefix, L1}
+ catch
+ _:_ ->
+ all
+ end;
+slice(L, N, _Uni) ->
+ %% Be careful not to traverse more of L than necessary.
+ try string:slice(L, 0, N) of
+ "" ->
+ false;
+ Prefix ->
+ %% Assume no binaries are introduced by string:slice().
+ case is_flat(L, lists:flatlength(Prefix)) of
+ true ->
+ case string:equal(Prefix, L) of
+ true ->
+ all;
+ false ->
+ {prefix, Prefix}
+ end;
+ false ->
+ false
+ end
+ catch _:_ -> false
end.
+is_flat(_L, 0) ->
+ true;
+is_flat([C|Cs], N) when is_integer(C) ->
+ is_flat(Cs, N - 1);
+is_flat(_, _N) ->
+ false.
+
printable_bin0(Bin, D, T, Enc) ->
Len = case D >= 0 of
true ->
@@ -763,6 +795,8 @@ printable_bin0(Bin, D, T, Enc) ->
end,
printable_bin(Bin, Len, D, Enc).
+printable_bin(_Bin, 0, _D, _Enc) ->
+ false;
printable_bin(Bin, Len, D, latin1) ->
N = erlang:min(20, Len),
L = binary_to_list(Bin, 1, N),
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index d117481d2e..97ec785c62 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -224,10 +224,12 @@ transform_from_shell(Dialect, Clauses, BoundEnvironment) ->
%% Called when translating during compiling
%%
--spec parse_transform(Forms, Options) -> Forms2 when
+-spec parse_transform(Forms, Options) -> Forms2 | Errors | Warnings when
Forms :: [erl_parse:abstract_form() | erl_parse:form_info()],
Forms2 :: [erl_parse:abstract_form() | erl_parse:form_info()],
- Options :: term().
+ Options :: term(),
+ Errors :: {error, ErrInfo :: [tuple()], WarnInfo :: []},
+ Warnings :: {warning, Forms2, WarnInfo :: [tuple()]}.
parse_transform(Forms, _Options) ->
SaveFilename = setup_filename(),
@@ -554,8 +556,8 @@ tg({call, Line, {remote,_,{atom,_,erlang},{atom, Line2, FunName}},ParaList},
FunName,length(ParaList)}})
end;
tg({call, Line, {remote,_,{atom,_,ModuleName},
- {atom, _, FunName}},_ParaList},B) ->
- throw({error,Line,{?ERR_GENREMOTECALL+B#tgd.eb,ModuleName,FunName}});
+ {atom, _, FunName}},ParaList},B) ->
+ throw({error,Line,{?ERR_GENREMOTECALL+B#tgd.eb,ModuleName,FunName,length(ParaList)}});
tg({cons,Line, H, T},B) ->
{cons, Line, tg(H,B), tg(T,B)};
tg({nil, Line},_B) ->
@@ -944,6 +946,7 @@ real_guard_function(node,0) -> true;
real_guard_function(node,1) -> true;
real_guard_function(round,1) -> true;
real_guard_function(size,1) -> true;
+real_guard_function(bit_size,1) -> true;
real_guard_function(map_size,1) -> true;
real_guard_function(map_get,2) -> true;
real_guard_function(tl,1) -> true;
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index 89a840be2d..cfbaf8b242 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -30,7 +30,7 @@
start/3, start/4, start/5, start_link/3, start_link/4, start_link/5,
hibernate/3,
init_ack/1, init_ack/2,
- init_p/3,init_p/5,format/1,format/2,format/3,report_cb/1,
+ init_p/3,init_p/5,format/1,format/2,format/3,report_cb/2,
initial_call/1,
translate_initial_call/1,
stop/1, stop/3]).
@@ -509,7 +509,7 @@ crash_report(Class, Reason, StartF, Stacktrace) ->
report=>[my_info(Class, Reason, StartF, Stacktrace),
linked_info(self())]},
#{domain=>[otp,sasl],
- report_cb=>fun proc_lib:report_cb/1,
+ report_cb=>fun proc_lib:report_cb/2,
logger_formatter=>#{title=>"CRASH REPORT"},
error_logger=>#{tag=>error_report,type=>crash_report}}).
@@ -750,14 +750,16 @@ check(Res) -> Res.
%%% Format a generated crash info structure.
%%% -----------------------------------------------------------
--spec report_cb(CrashReport) -> {Format,Args} when
- CrashReport :: #{label=>{proc_lib,crash},report=>[term()]},
- Format :: io:format(),
- Args :: [term()].
-report_cb(#{label:={proc_lib,crash},
- report:=CrashReport}) ->
- Depth = error_logger:get_format_depth(),
- get_format_and_args(CrashReport, utf8, Depth).
+-spec report_cb(CrashReport,FormatOpts) -> unicode:chardata() when
+ CrashReport :: #{label => {proc_lib,crash},
+ report => [term()]},
+ FormatOpts :: logger:report_cb_config().
+report_cb(#{label:={proc_lib,crash}, report:=CrashReport}, Extra) ->
+ Default = #{chars_limit => unlimited,
+ depth => unlimited,
+ single_line => false,
+ encoding => utf8},
+ do_format(CrashReport, maps:merge(Default,Extra)).
-spec format(CrashReport) -> string() when
CrashReport :: [term()].
@@ -777,84 +779,121 @@ format(CrashReport, Encoding) ->
Depth :: unlimited | pos_integer().
format(CrashReport, Encoding, Depth) ->
- {F,A} = get_format_and_args(CrashReport, Encoding, Depth),
- lists:flatten(io_lib:format(F,A)).
-
-get_format_and_args([OwnReport,LinkReport], Encoding, Depth) ->
- Extra = {Encoding,Depth},
- MyIndent = " ",
- {OwnFormat,OwnArgs} = format_report(OwnReport, MyIndent, Extra, [], []),
- {LinkFormat,LinkArgs} = format_link_report(LinkReport, MyIndent, Extra, [], []),
- {" crasher:~n"++OwnFormat++" neighbours:~n"++LinkFormat,OwnArgs++LinkArgs}.
-
-format_link_report([], _Indent, _Extra, Format, Args) ->
- {lists:flatten(lists:reverse(Format)),lists:append(lists:reverse(Args))};
-format_link_report([Link|Reps], Indent, Extra, Format, Args) ->
+ do_format(CrashReport, #{chars_limit => unlimited,
+ depth => Depth,
+ encoding => Encoding,
+ single_line => false}).
+
+do_format([OwnReport,LinkReport], #{single_line:=Single}=Extra) ->
+ Indent = if Single -> "";
+ true -> " "
+ end,
+ MyIndent = Indent ++ Indent,
+ Sep = nl(Single,"; "),
+ OwnFormat = format_report(OwnReport, MyIndent, Extra),
+ LinkFormat = lists:join(Sep,format_link_report(LinkReport, MyIndent, Extra)),
+ Nl = nl(Single," "),
+ Str = io_lib:format("~scrasher:"++Nl++"~ts"++Sep++"~sneighbours:"++Nl++"~ts",
+ [Indent,OwnFormat,Indent,LinkFormat]),
+ lists:flatten(Str).
+
+format_link_report([Link|Reps], Indent0, #{single_line:=Single}=Extra) ->
Rep = case Link of
{neighbour,Rep0} -> Rep0;
_ -> Link
end,
+ Indent = if Single -> "";
+ true -> Indent0
+ end,
LinkIndent = [" ",Indent],
- {LinkFormat,LinkArgs} = format_report(Rep, LinkIndent, Extra, [], []),
- F = "~sneighbour:\n"++LinkFormat,
- A = [Indent|LinkArgs],
- format_link_report(Reps, Indent, Extra, [F|Format], [A|Args]);
-format_link_report(Rep, Indent, Extra, Format, Args) ->
- {F,A} = format_report(Rep, Indent, Extra, [], []),
- format_link_report([], Indent, Extra, [F|Format],[A|Args]).
-
-format_report([], _Indent, _Extra, Format, Args) ->
- {lists:flatten(lists:reverse(Format)),lists:append(lists:reverse(Args))};
-format_report([Rep|Reps], Indent, Extra, Format, Args) ->
- {F,A} = format_rep(Rep, Indent, Extra),
- format_report(Reps, Indent, Extra, [F|Format], [A|Args]);
-format_report(Rep, Indent, {Enc,unlimited}=Extra, Format, Args) ->
- {F,A} = {"~s~"++modifier(Enc)++"p~n", [Indent, Rep]},
- format_report([], Indent, Extra, [F|Format], [A|Args]);
-format_report(Rep, Indent, {Enc,Depth}=Extra, Format, Args) ->
- {F,A} = {"~s~"++modifier(Enc)++"P~n", [Indent, Rep, Depth]},
- format_report([], Indent, Extra, [F|Format], [A|Args]).
-
-format_rep({initial_call,InitialCall}, Indent, Extra) ->
- format_mfa(Indent, InitialCall, Extra);
-format_rep({error_info,{Class,Reason,StackTrace}}, _Indent, Extra) ->
- {lists:flatten(format_exception(Class, Reason, StackTrace, Extra)),[]};
-format_rep({Tag,Data}, Indent, Extra) ->
- format_tag(Indent, Tag, Data, Extra).
-
-format_mfa(Indent, {M,F,Args}=StartF, {Enc,_}=Extra) ->
+ [[Indent,"neighbour:",nl(Single," "),format_report(Rep, LinkIndent, Extra)]|
+ format_link_report(Reps, Indent, Extra)];
+format_link_report(Rep, Indent, Extra) ->
+ format_report(Rep, Indent, Extra).
+
+format_report(Rep, Indent, #{single_line:=Single}=Extra) when is_list(Rep) ->
+ lists:join(nl(Single,", "),format_rep(Rep, Indent, Extra));
+format_report(Rep, Indent0, #{encoding:=Enc,depth:=Depth,
+ chars_limit:=Limit,single_line:=Single}) ->
+ {P,Tl} = p(Enc,Depth),
+ {Indent,Width} = if Single -> {"","0"};
+ true -> {Indent0,""}
+ end,
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ io_lib:format("~s~"++Width++P, [Indent, Rep | Tl], Opts).
+
+format_rep([{initial_call,InitialCall}|Rep], Indent, Extra) ->
+ [format_mfa(Indent, InitialCall, Extra)|format_rep(Rep, Indent, Extra)];
+format_rep([{error_info,{Class,Reason,StackTrace}}|Rep], Indent, Extra) ->
+ [format_exception(Class, Reason, StackTrace, Extra)|
+ format_rep(Rep, Indent, Extra)];
+format_rep([{Tag,Data}|Rep], Indent, Extra) ->
+ [format_tag(Indent, Tag, Data, Extra)|format_rep(Rep, Indent, Extra)];
+format_rep(_, _, _Extra) ->
+ [].
+
+format_exception(Class, Reason, StackTrace,
+ #{encoding:=Enc,depth:=Depth,chars_limit:=Limit,
+ single_line:=Single}=Extra) ->
+ PF = pp_fun(Extra),
+ StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
+ if Single ->
+ {P,Tl} = p(Enc,Depth),
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ [atom_to_list(Class), ": ",
+ io_lib:format("~0"++P,[{Reason,StackTrace}|Tl],Opts)];
+ true ->
+ EI = " ",
+ [EI, erl_error:format_exception(1+length(EI), Class, Reason,
+ StackTrace, StackFun, PF, Enc)]
+ end.
+
+format_mfa(Indent0, {M,F,Args}=StartF, #{encoding:=Enc,single_line:=Single}=Extra) ->
+ Indent = if Single -> "";
+ true -> Indent0
+ end,
try
A = length(Args),
- {lists:flatten([Indent,"initial call: ",atom_to_list(M),
- $:,to_string(F, Enc),$/,integer_to_list(A),"\n"]),[]}
+ [Indent,"initial call: ",atom_to_list(M),$:,to_string(F, Enc),$/,
+ integer_to_list(A)]
catch
error:_ ->
format_tag(Indent, initial_call, StartF, Extra)
end.
-format_tag(Indent, Tag, Data, {Enc,Depth}) ->
- {P,Tl} = p(Enc, Depth),
- {"~s~p: ~80.18" ++ P ++ "\n", [Indent, Tag, Data|Tl]}.
-
-format_exception(Class, Reason, StackTrace, {Enc,_}=Extra) ->
- PF = pp_fun(Extra),
- StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
- %% EI = " exception: ",
- EI = " ",
- [EI, erl_error:format_exception(1+length(EI), Class, Reason,
- StackTrace, StackFun, PF, Enc), "\n"].
-
to_string(A, latin1) ->
io_lib:write_atom_as_latin1(A);
to_string(A, _) ->
io_lib:write_atom(A).
-pp_fun({Enc,Depth}) ->
+pp_fun(#{encoding:=Enc,depth:=Depth,chars_limit:=Limit,single_line:=Single}) ->
{P,Tl} = p(Enc, Depth),
+ Width = if Single -> "0";
+ true -> ""
+ end,
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
fun(Term, I) ->
- io_lib:format("~." ++ integer_to_list(I) ++ P, [Term|Tl])
+ io_lib:format("~" ++ Width ++ "." ++ integer_to_list(I) ++ P,
+ [Term|Tl], Opts)
end.
+format_tag(Indent0, Tag, Data, #{encoding:=Enc,depth:=Depth,chars_limit:=Limit,single_line:=Single}) ->
+ {P,Tl} = p(Enc, Depth),
+ {Indent,Width} = if Single -> {"","0"};
+ true -> {Indent0,""}
+ end,
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ io_lib:format("~s~" ++ Width ++ "p: ~" ++ Width ++ ".18" ++ P,
+ [Indent, Tag, Data|Tl], Opts).
+
p(Encoding, Depth) ->
{Letter, Tl} = case Depth of
unlimited -> {"p", []};
@@ -866,6 +905,8 @@ p(Encoding, Depth) ->
modifier(latin1) -> "";
modifier(_) -> "t".
+nl(true,Else) -> Else;
+nl(false,_) -> "\n".
%%% -----------------------------------------------------------
%%% Stop a process and wait for it to terminate
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 8d1cc09a8b..9a1b92a87c 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -16,11 +16,50 @@
%% limitations under the License.
%%
%% %CopyrightEnd%
+%%
+%% We allow upgrade from, and downgrade to all previous
+%% versions from the following OTP releases:
+%% - OTP 20
+%% - OTP 21
+%%
+%% We also allow upgrade from, and downgrade to all
+%% versions that have branched off from the above
+%% stated previous versions.
+%%
{"%VSN%",
- %% Up from - max one major revision back
- [{<<"3\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.*
- {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}],% OTP-21.*
- %% Down to - max one major revision back
- [{<<"3\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.*
- {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-20.*
-}.
+ [{<<"^3\\.4$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.5$">>,[restart_new_emulator]},
+ {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.6$">>,[restart_new_emulator]},
+ {<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.7$">>,[restart_new_emulator]},
+ {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.8$">>,[restart_new_emulator]},
+ {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
+ [{<<"^3\\.4$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.5$">>,[restart_new_emulator]},
+ {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.6$">>,[restart_new_emulator]},
+ {<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.7$">>,[restart_new_emulator]},
+ {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.8$">>,[restart_new_emulator]},
+ {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 73219f8fd8..6418dc7eb6 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@ normal(Conf) when is_list(Conf) ->
BeamFile = Simple ++ ".beam",
simple_file(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
do_normal(Source, PrivDir, BeamFile, []),
@@ -95,7 +95,7 @@ normal(Conf) when is_list(Conf) ->
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
@@ -173,7 +173,7 @@ error(Conf) when is_list(Conf) ->
WrongFile = Simple ++ "foo.beam",
simple_file(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
{ok,_} = compile:file(Source, [{outdir,PrivDir},debug_info]),
ACopy = filename:join(PrivDir, "a_copy.beam"),
@@ -213,7 +213,7 @@ error(Conf) when is_list(Conf) ->
%% we have eliminated them.
ok = file:write_file(BeamFile, <<"FOR1",5:32,"BEAMfel">>),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
file:delete(Source),
file:delete(WrongFile),
@@ -273,7 +273,7 @@ cmp(Conf) when is_list(Conf) ->
{Source2D1, BeamFile2D1} = make_beam(Dir1, simple2, concat),
{SourceD2, BeamFileD2} = make_beam(Dir2, simple, concat),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% cmp
@@ -300,7 +300,7 @@ cmp(Conf) when is_list(Conf) ->
ver(not_a_directory, beam_lib:diff_dirs(foo, bar)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, Source2D1,
BeamFile2D1, SourceD2, BeamFileD2]),
@@ -321,7 +321,7 @@ cmp_literals(Conf) when is_list(Conf) ->
{SourceD1, BeamFileD1} = make_beam(Dir1, simple, constant),
{SourceD2, BeamFileD2} = make_beam(Dir2, simple, constant2),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% cmp
@@ -334,7 +334,7 @@ cmp_literals(Conf) when is_list(Conf) ->
ver(chunks_different, beam_lib:cmp(B1, B2)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, SourceD2, BeamFileD2]),
@@ -351,7 +351,7 @@ strip(Conf) when is_list(Conf) ->
{Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant),
{Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% strip binary
@@ -392,7 +392,7 @@ strip(Conf) when is_list(Conf) ->
(catch lines:t(atom)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1,
Source2D1, BeamFile2D1,
@@ -457,7 +457,7 @@ building(Conf) when is_list(Conf) ->
{SourceD1, BeamFileD1} = make_beam(Dir1, building, member),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% read all chunks
@@ -487,7 +487,7 @@ building(Conf) when is_list(Conf) ->
end, ChunkIds),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, BeamFileD2]),
file:del_dir(Dir1),
@@ -535,7 +535,7 @@ encrypted_abstr_1(Conf) ->
%% Avoid getting an extra port when crypto starts erl_ddll.
erl_ddll:start(),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
Key = "#a_crypto_key",
@@ -549,7 +549,7 @@ encrypted_abstr_1(Conf) ->
ok = crypto:stop(), %To get rid of extra ets tables.
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
@@ -658,7 +658,7 @@ encrypted_abstr_file_1(Conf) ->
%% Avoid getting an extra port when crypto starts erl_ddll.
erl_ddll:start(),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
Key = "Long And niCe 99Krypto Key",
@@ -676,7 +676,7 @@ encrypted_abstr_file_1(Conf) ->
file:delete(filename:join(PrivDir, ".erlang.crypt")),
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index c5cfea5e9e..e0811f19cf 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -22,7 +22,8 @@
-export([all/0, suite/0,
interesting/1,scope_return/1,random_ref_comp/1,random_ref_sr_comp/1,
random_ref_fla_comp/1,parts/1, bin_to_list/1, list_to_bin/1,
- copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1]).
+ copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1,
+ check_no_invalid_read_bug/1]).
-export([random_number/1, make_unaligned/1]).
@@ -36,7 +37,7 @@ all() ->
[scope_return,interesting, random_ref_fla_comp, random_ref_sr_comp,
random_ref_comp, parts, bin_to_list, list_to_bin, copy,
referenced, guard, encode_decode, badargs,
- longest_common_trap].
+ longest_common_trap, check_no_invalid_read_bug].
-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
@@ -1361,3 +1362,13 @@ make_unaligned2(Bin0) when is_binary(Bin0) ->
Bin.
id(I) -> I.
+
+check_no_invalid_read_bug(Config) when is_list(Config) ->
+ check_no_invalid_read_bug(24);
+check_no_invalid_read_bug(60) ->
+ ok;
+check_no_invalid_read_bug(I) ->
+ N = 1 bsl I,
+ binary:encode_unsigned(N+N),
+ binary:encode_unsigned(N+N, little),
+ check_no_invalid_read_bug(I+1).
diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl
index 55118e251c..224c0d5625 100644
--- a/lib/stdlib/test/calendar_SUITE.erl
+++ b/lib/stdlib/test/calendar_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
gregorian_days/1,
+ big_gregorian_days/1,
gregorian_seconds/1,
day_of_the_week/1,
day_of_the_week_calibrate/1,
@@ -36,13 +37,16 @@
-define(START_YEAR, 1947).
-define(END_YEAR, 2012).
+-define(BIG_START_YEAR, 20000000).
+-define(BIG_END_YEAR, 20000020).
+
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[gregorian_days, gregorian_seconds, day_of_the_week,
day_of_the_week_calibrate, leap_years,
last_day_of_the_month, local_time_to_universal_time_dst,
- iso_week_number, system_time, rfc3339].
+ iso_week_number, system_time, rfc3339, big_gregorian_days].
groups() ->
[].
@@ -67,6 +71,14 @@ gregorian_days(Config) when is_list(Config) ->
MaxDays = calendar:date_to_gregorian_days({?END_YEAR, 1, 1}),
check_gregorian_days(Days, MaxDays).
+%% Tests that date_to_gregorian_days and gregorian_days_to_date
+%% are each others inverses from ?BIG_START_YEAR-01-01 up to ?BIG_END_YEAR-01-01.
+%% At the same time valid_date is tested.
+big_gregorian_days(Config) when is_list(Config) ->
+ Days = calendar:date_to_gregorian_days({?BIG_START_YEAR, 1, 1}),
+ MaxDays = calendar:date_to_gregorian_days({?BIG_END_YEAR, 1, 1}),
+ check_gregorian_days(Days, MaxDays).
+
%% Tests that datetime_to_gregorian_seconds and
%% gregorian_seconds_to_date are each others inverses for a sampled
%% number of seconds from ?START_YEAR-01-01 up to ?END_YEAR-01-01: We check
@@ -183,14 +195,15 @@ rfc3339(Config) when is_list(Config) ->
D = [{time_designator, $\s}],
Z = [{offset, "Z"}],
- "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
- "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12t23:20:50.52z", Ms),
- "1985-04-12T21:20:50.52Z" =
+ "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
+ "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12t23:20:50.52z", Ms),
+ "1985-04-12T21:20:50.520Z" =
test_parse("1985-04-12T23:20:50.52+02:00", Ms),
"1985-04-12T23:20:50Z" = test_parse("1985-04-12T23:20:50.52Z", S),
- "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
- "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12t23:20:50.52z", Mys),
- "1985-04-12 21:20:50.52Z" =
+ "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
+ "1985-04-12T23:20:50.520000Z" =
+ test_parse("1985-04-12t23:20:50.52z", Mys),
+ "1985-04-12 21:20:50.520000000Z" =
test_parse("1985-04-12 23:20:50.52+02:00", Ns++D),
"1985-04-12T23:20:50Z" = test_parse("1985-04-12T23:20:50.52Z"),
"1996-12-20T00:39:57Z" = test_parse("1996-12-19T16:39:57-08:00"),
@@ -221,17 +234,20 @@ rfc3339(Config) when is_list(Config) ->
"1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60Z"),
"1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.5Z"),
"1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.55Z"),
- "1970-01-02T00:00:00.55Z" = test_parse("1970-01-01T23:59:60.55Z", Ms),
- "1970-01-02T00:00:00.55Z" = test_parse("1970-01-01T23:59:60.55Z", Mys),
- "1970-01-02T00:00:00.55Z" = test_parse("1970-01-01T23:59:60.55Z", Ns),
+ "1970-01-02T00:00:00.550Z" = test_parse("1970-01-01T23:59:60.55Z", Ms),
+ "1970-01-02T00:00:00.550000Z" =
+ test_parse("1970-01-01T23:59:60.55Z", Mys),
+ "1970-01-02T00:00:00.550000000Z" =
+ test_parse("1970-01-01T23:59:60.55Z", Ns),
"1970-01-02T00:00:00.999999Z" =
test_parse("1970-01-01T23:59:60.999999Z", Mys),
- "1970-01-02T00:00:01Z" =
+ "1970-01-02T00:00:01.000Z" =
test_parse("1970-01-01T23:59:60.999999Z", Ms),
"1970-01-01T00:00:00Z" = test_parse("1970-01-01T00:00:00+00:00"),
"1970-01-01T00:00:00Z" = test_parse("1970-01-01T00:00:00-00:00"),
"1969-12-31T00:01:00Z" = test_parse("1970-01-01T00:00:00+23:59"),
- "1918-11-11T09:00:00Z" = test_parse("1918-11-11T11:00:00+02:00", Mys),
+ "1918-11-11T09:00:00.000000Z" =
+ test_parse("1918-11-11T11:00:00+02:00", Mys),
"1970-01-01T00:00:00.000001Z" =
test_parse("1970-01-01T00:00:00.000001Z", Mys),
@@ -242,26 +258,26 @@ rfc3339(Config) when is_list(Config) ->
test_time(erlang:system_time(millisecond), Ms),
test_time(erlang:system_time(microsecond), Mys++[{offset, "-02:20"}]),
- T = erlang:system_time(second),
- TS = do_format(T, []),
- TS = do_format(T * 1000, Ms),
- TS = do_format(T * 1000 * 1000, Mys),
- TS = do_format(T * 1000 * 1000 * 1000, Ns),
-
946720800 = TO = do_parse("2000-01-01 10:00:00Z", []),
Str = "2000-01-01T10:02:00+00:02",
Str = do_format(TO, [{offset, 120}]),
- Str = do_format(TO * 1000, [{offset, 120 * 1000}]++Ms),
- Str = do_format(TO * 1000 * 1000, [{offset, 120 * 1000 * 1000}]++Mys),
- Str = do_format(TO * 1000 * 1000 * 1000,
- [{offset, 120 * 1000 * 1000 * 1000}]++Ns),
+ "2000-01-01T10:02:00.000+00:02" =
+ do_format(TO * 1000, [{offset, 120 * 1000}]++Ms),
+ "2000-01-01T10:02:00.000000+00:02" =
+ do_format(TO * 1000 * 1000, [{offset, 120 * 1000 * 1000}]++Mys),
+ "2000-01-01T10:02:00.000000000+00:02" =
+ do_format(TO * 1000 * 1000 * 1000,
+ [{offset, 120 * 1000 * 1000 * 1000}]++Ns),
NStr = "2000-01-01T09:58:00-00:02",
NStr = do_format(TO, [{offset, -120}]),
- NStr = do_format(TO * 1000, [{offset, -120 * 1000}]++Ms),
- NStr = do_format(TO * 1000 * 1000, [{offset, -120 * 1000 * 1000}]++Mys),
- NStr = do_format(TO * 1000 * 1000 * 1000,
- [{offset, -120 * 1000 * 1000 * 1000}]++Ns),
+ "2000-01-01T09:58:00.000-00:02" =
+ do_format(TO * 1000, [{offset, -120 * 1000}]++Ms),
+ "2000-01-01T09:58:00.000000-00:02" =
+ do_format(TO * 1000 * 1000, [{offset, -120 * 1000 * 1000}]++Mys),
+ "2000-01-01T09:58:00.000000000-00:02" =
+ do_format(TO * 1000 * 1000 * 1000,
+ [{offset, -120 * 1000 * 1000 * 1000}]++Ns),
543210000 = do_parse("1970-01-01T00:00:00.54321Z", Ns),
54321000 = do_parse("1970-01-01T00:00:00.054321Z", Ns),
@@ -278,18 +294,18 @@ rfc3339(Config) when is_list(Config) ->
-1613833200000000 = do_parse("1918-11-11T11:00:00+02:00", Mys),
-1613833200000000 = do_parse("1918-11-11T09:00:00Z", Mys),
- "1970-01-01T00:00:00Z" = do_format_z(0, Mys),
+ "1970-01-01T00:00:00.000000Z" = do_format_z(0, Mys),
"1970-01-01T00:00:01Z" = do_format_z(1, S),
"1970-01-01T00:00:00.001Z" = do_format_z(1, Ms),
"1970-01-01T00:00:00.000001Z" = do_format_z(1, Mys),
"1970-01-01T00:00:00.000000001Z" = do_format_z(1, Ns),
- "1970-01-01T00:00:01Z" = do_format_z(1000000, Mys),
- "1970-01-01T00:00:00.54321Z" = do_format_z(543210, Mys),
+ "1970-01-01T00:00:01.000000Z" = do_format_z(1000000, Mys),
+ "1970-01-01T00:00:00.543210Z" = do_format_z(543210, Mys),
"1970-01-01T00:00:00.543Z" = do_format_z(543, Ms),
- "1970-01-01T00:00:00.54321Z" = do_format_z(543210000, Ns),
- "1970-01-01T00:00:06.54321Z" = do_format_z(6543210, Mys),
- "1979-06-21T12:12:12Z" = do_format_z(298815132000000, Mys),
- "1918-11-11T13:00:00Z" = do_format_z(-1613818800000000, Mys),
+ "1970-01-01T00:00:00.543210000Z" = do_format_z(543210000, Ns),
+ "1970-01-01T00:00:06.543210Z" = do_format_z(6543210, Mys),
+ "1979-06-21T12:12:12.000000Z" = do_format_z(298815132000000, Mys),
+ "1918-11-11T13:00:00.000000Z" = do_format_z(-1613818800000000, Mys),
ok.
%%
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index fe324391af..65977a764a 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -3417,6 +3417,7 @@ otp_11709(Config) when is_list(Config) ->
ok.
%% OTP-13229. open_file() exits with badarg when given binary file name.
+%% Also OTP-15253.
otp_13229(_Config) ->
F = <<"binfile.tab">>,
try dets:open_file(name, [{file, F}]) of
@@ -3425,6 +3426,20 @@ otp_13229(_Config) ->
catch
error:badarg ->
ok
+ end,
+ try dets:open_file(F, []) of % OTP-15253
+ R2 ->
+ exit({open_succeeded, R2})
+ catch
+ error:badarg ->
+ ok
+ end,
+ try dets:open_file(F) of
+ R3 ->
+ exit({open_succeeded, R3})
+ catch
+ error:badarg ->
+ ok
end.
%% OTP-13260. Race when opening a table.
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index a3e294ffea..0ac99ad03a 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -29,7 +29,7 @@
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
otp_11728/1, encoding/1, extends/1, function_macro/1,
test_error/1, test_warning/1, otp_14285/1,
- test_if/1]).
+ test_if/1,source_name/1]).
-export([epp_parse_erl_form/2]).
@@ -70,7 +70,7 @@ all() ->
overload_mac, otp_8388, otp_8470, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
encoding, extends, function_macro, test_error, test_warning,
- otp_14285, test_if].
+ otp_14285, test_if, source_name].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -1702,6 +1702,18 @@ function_macro(Config) ->
ok.
+source_name(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "source_name.erl"),
+
+ source_name_1(File, "/test/gurka.erl"),
+ source_name_1(File, "gaffel.erl"),
+
+ ok.
+
+source_name_1(File, Expected) ->
+ Res = epp:parse_file(File, [{source_name, Expected}]),
+ {ok, [{attribute,_,file,{Expected,_}} | _Forms]} = Res.
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
diff --git a/lib/stdlib/test/epp_SUITE_data/source_name.erl b/lib/stdlib/test/epp_SUITE_data/source_name.erl
new file mode 100644
index 0000000000..71ad2dddb9
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/source_name.erl
@@ -0,0 +1,27 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(source_name).
+-export([ok/0]).
+
+%% Changing source name should not affect headers
+-include("bar.hrl").
+
+ok() -> ok.
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index f9ab83a120..d18c7c255c 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -67,7 +67,8 @@
record_errors/1, otp_11879_cont/1,
non_latin1_module/1, otp_14323/1,
stacktrace_syntax/1,
- otp_14285/1, otp_14378/1]).
+ otp_14285/1, otp_14378/1,
+ external_funs/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -88,7 +89,7 @@ all() ->
maps, maps_type, maps_parallel_match,
otp_11851, otp_11879, otp_13230,
record_errors, otp_11879_cont, non_latin1_module, otp_14323,
- stacktrace_syntax, otp_14285, otp_14378].
+ stacktrace_syntax, otp_14285, otp_14378, external_funs].
groups() ->
[{unused_vars_warn, [],
@@ -4134,6 +4135,21 @@ otp_14285(Config) ->
run(Config, Ts),
ok.
+external_funs(Config) when is_list(Config) ->
+ Ts = [{external_funs_1,
+ %% ERL-762: Unused variable warning not being emitted.
+ <<"f() ->
+ BugVar = process_info(self()),
+ if true -> fun m:f/1 end.
+ f(M, F) ->
+ BugVar = process_info(self()),
+ if true -> fun M:F/1 end.">>,
+ [],
+ {warnings,[{2,erl_lint,{unused_var,'BugVar'}},
+ {5,erl_lint,{unused_var,'BugVar'}}]}}],
+ run(Config, Ts),
+ ok.
+
format_error(E) ->
lists:flatten(erl_lint:format_error(E)).
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index dda8d0a12e..f5d80e7e68 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@
otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1,
otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
otp_10302/1, otp_10820/1, otp_11100/1, otp_11861/1, pr_1014/1,
- otp_13662/1, otp_14285/1]).
+ otp_13662/1, otp_14285/1, otp_15592/1]).
%% Internal export.
-export([ehook/6]).
@@ -81,7 +81,7 @@ groups() ->
[otp_6321, otp_6911, otp_6914, otp_8150, otp_8238,
otp_8473, otp_8522, otp_8567, otp_8664, otp_9147,
otp_10302, otp_10820, otp_11100, otp_11861, pr_1014, otp_13662,
- otp_14285]}].
+ otp_14285, otp_15592]}].
init_per_suite(Config) ->
Config.
@@ -1167,6 +1167,11 @@ otp_14285(_Config) ->
[{encoding,latin1}])),
ok.
+otp_15592(_Config) ->
+ ok = pp_expr(<<"long12345678901234567890123456789012345678901234"
+ "56789012345678901234:f(<<>>)">>),
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
compile(Config, Tests) ->
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 7a48d1d55e..433b812fd5 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -41,7 +41,7 @@
-export([t_delete_object/1, t_init_table/1, t_whitebox/1,
select_bound_chunk/1,
t_delete_all_objects/1, t_insert_list/1, t_test_ms/1,
- t_select_delete/1,t_select_replace/1,t_ets_dets/1]).
+ t_select_delete/1,t_select_replace/1,t_select_replace_next_bug/1,t_ets_dets/1]).
-export([ordered/1, ordered_match/1, interface_equality/1,
fixtable_next/1, fixtable_insert/1, rename/1, rename_unnamed/1, evil_rename/1,
@@ -59,6 +59,7 @@
-export([otp_5340/1]).
-export([otp_6338/1]).
-export([otp_6842_select_1000/1]).
+-export([select_mbuf_trapping/1]).
-export([otp_7665/1]).
-export([meta_wb/1]).
-export([grow_shrink/1, grow_pseudo_deleted/1, shrink_pseudo_deleted/1]).
@@ -66,7 +67,7 @@
meta_lookup_named_read/1, meta_lookup_named_write/1,
meta_newdel_unnamed/1, meta_newdel_named/1]).
-export([smp_insert/1, smp_fixed_delete/1, smp_unfix_fix/1, smp_select_delete/1,
- smp_select_replace/1, otp_8166/1, otp_8732/1]).
+ smp_select_replace/1, otp_8166/1, otp_8732/1, delete_unfix_race/1]).
-export([exit_large_table_owner/1,
exit_many_large_table_owner/1,
exit_many_tables_owner/1,
@@ -125,10 +126,12 @@ all() ->
select_bound_chunk,
t_init_table, t_whitebox, t_delete_all_objects,
t_insert_list, t_test_ms, t_select_delete, t_select_replace,
+ t_select_replace_next_bug,
t_ets_dets, memory, t_select_reverse, t_bucket_disappears,
t_named_select,
select_fail, t_insert_new, t_repair_continuation,
otp_5340, otp_6338, otp_6842_select_1000, otp_7665,
+ select_mbuf_trapping,
otp_8732, meta_wb, grow_shrink, grow_pseudo_deleted,
shrink_pseudo_deleted, {group, meta_smp}, smp_insert,
smp_fixed_delete, smp_unfix_fix, smp_select_replace,
@@ -142,7 +145,8 @@ all() ->
ets_all,
massive_ets_all,
take,
- whereis_table].
+ whereis_table,
+ delete_unfix_race].
groups() ->
[{new, [],
@@ -1465,6 +1469,25 @@ t_select_replace(Config) when is_list(Config) ->
verify_etsmem(EtsMem).
+%% OTP-15346: Bug caused select_replace of bound key to corrupt static stack
+%% used by ets:next and ets:prev.
+t_select_replace_next_bug(Config) when is_list(Config) ->
+ T = ets:new(k, [ordered_set]),
+ [ets:insert(T, {I, value}) || I <- lists:seq(1,10)],
+ 1 = ets:first(T),
+
+ %% Make sure select_replace does not leave pointer
+ %% to deallocated {2,value} in static stack.
+ MS = [{{2,value}, [], [{{2,"new_value"}}]}],
+ 1 = ets:select_replace(T, MS),
+
+ %% This would crash or give wrong result at least on DEBUG emulator
+ %% where deallocated memory is overwritten.
+ 2 = ets:next(T, 1),
+
+ ets:delete(T).
+
+
%% Test that partly bound keys gives faster matches.
partly_bound(Config) when is_list(Config) ->
case os:type() of
@@ -5110,6 +5133,61 @@ otp_6338(Config) when is_list(Config) ->
[[4839,recv]] = ets:match(T,{[{sbm,ppb2_bs12@blade_0_8},'$1'],'$2'}),
ets:delete(T).
+%% OTP-15660: Verify select not doing excessive trapping
+%% when process have mbuf heap fragments.
+select_mbuf_trapping(Config) when is_list(Config) ->
+ select_mbuf_trapping_do(set),
+ select_mbuf_trapping_do(ordered_set).
+
+select_mbuf_trapping_do(Type) ->
+ T = ets:new(xxx, [Type]),
+ NKeys = 50,
+ [ets:insert(T, {K, value}) || K <- lists:seq(1,NKeys)],
+
+ {priority, Prio} = process_info(self(), priority),
+ Tracee = self(),
+ [SchedTracer]
+ = start_loopers(1, Prio,
+ fun (SC) ->
+ receive
+ {trace, Tracee, out, _} ->
+ SC+1;
+ done ->
+ Tracee ! {schedule_count, SC},
+ exit(normal)
+ end
+ end,
+ 0),
+
+ erlang:garbage_collect(),
+ 1 = erlang:trace(self(), true, [running,{tracer,SchedTracer}]),
+
+ %% Artificially create an mbuf heap fragment
+ MbufTerm = "Frag me up",
+ MbufTerm = erts_debug:set_internal_state(mbuf, MbufTerm),
+
+ Keys = ets:select(T, [{{'$1', value}, [], ['$1']}]),
+ NKeys = length(Keys),
+
+ 1 = erlang:trace(self(), false, [running]),
+ Ref = erlang:trace_delivered(Tracee),
+ receive
+ {trace_delivered, Tracee, Ref} ->
+ SchedTracer ! done
+ end,
+ receive
+ {schedule_count, N} ->
+ io:format("~p context switches: ~p", [Type,N]),
+ if
+ N < 3 -> ok;
+ true -> ct:fail(failed)
+ end
+ end,
+ true = ets:delete(T),
+ ok.
+
+
+
%% Elements could come in the wrong order in a bag if a rehash occurred.
otp_5340(Config) when is_list(Config) ->
repeat_for_opts(fun otp_5340_do/1).
@@ -5489,6 +5567,46 @@ smp_fixed_delete_do() ->
%%verify_table_load(T),
ets:delete(T).
+%% ERL-720
+%% Provoke race between ets:delete and table unfix (by select_count)
+%% that caused ets_misc memory counter to indicate false leak.
+delete_unfix_race(Config) when is_list(Config) ->
+ EtsMem = etsmem(),
+ Table = ets:new(t,[set,public,{write_concurrency,true}]),
+ InsertOp =
+ fun() ->
+ receive stop ->
+ false
+ after 0 ->
+ ets:insert(Table, {rand:uniform(10)}),
+ true
+ end
+ end,
+ DeleteOp =
+ fun() ->
+ receive stop ->
+ false
+ after 0 ->
+ ets:delete(Table, rand:uniform(10)),
+ true
+ end
+ end,
+ SelectOp =
+ fun() ->
+ ets:select_count(Table, ets:fun2ms(fun(X) -> true end))
+ end,
+ Main = self(),
+ Ins = spawn(fun()-> repeat_while(InsertOp), Main ! self() end),
+ Del = spawn(fun()-> repeat_while(DeleteOp), Main ! self() end),
+ spawn(fun()->
+ repeat(SelectOp, 10000),
+ Del ! stop,
+ Ins ! stop
+ end),
+ [receive Pid -> ok end || Pid <- [Ins,Del]],
+ ets:delete(Table),
+ verify_etsmem(EtsMem).
+
num_of_buckets(T) ->
element(1,ets:info(T,stats)).
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index 41ee3246f5..a8264e5a84 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -124,8 +124,10 @@ start2(Config) when is_list(Config) ->
{ok, Pid0} = gen_fsm:start(gen_fsm_SUITE, [], []),
ok = do_func_test(Pid0),
ok = do_sync_func_test(Pid0),
+ MRef = monitor(process,Pid0),
shutdown_stopped =
gen_fsm:sync_send_all_state_event(Pid0, stop_shutdown),
+ receive {'DOWN',MRef,_,_,shutdown} -> ok end,
{'EXIT', {noproc,_}} =
(catch gen_fsm:sync_send_event(Pid0, hej)),
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 91fe1133f6..7796da66b8 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,8 @@
otp_10836/1, io_lib_width_too_small/1,
io_with_huge_message_queue/1, format_string/1,
maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1,
- otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1]).
+ otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1,
+ otp_15159/1, otp_15639/1, otp_15847/1]).
-export([pretty/2, trf/3]).
@@ -63,7 +64,8 @@ all() ->
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836,
io_lib_width_too_small, io_with_huge_message_queue,
format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175,
- otp_14285, limit_term, otp_14983, otp_15103].
+ otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159,
+ otp_15639, otp_15847].
%% Error cases for output.
error_1(Config) when is_list(Config) ->
@@ -2633,3 +2635,54 @@ otp_15103(_Config) ->
"[{a,\n b,\n c},\n {a,\n b,...},\n {a,...},\n {...}|...]" =
lists:flatten(S5),
ok.
+
+otp_15159(_Config) ->
+ "[atom]" =
+ lists:flatten(io_lib:format("~p", [[atom]], [{chars_limit,5}])),
+ ok.
+
+otp_15076(_Config) ->
+ {'EXIT', {badarg, _}} = (catch io_lib:format("~c", [a])),
+ L = io_lib:scan_format("~c", [a]),
+ {"~c", [a]} = io_lib:unscan_format(L),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L)),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L, [])),
+ ok.
+
+otp_15639(_Config) ->
+ L = lists:duplicate(10, "a"),
+ LOpts = [{encoding, latin1}, {chars_limit, 10}],
+ UOpts = [{encoding, unicode}, {chars_limit, 10}],
+ "[[...]|...]" = pretty(L, LOpts),
+ "[[...]|...]" = pretty(L, UOpts),
+ "[\"a\",[...]|...]" =
+ pretty(L, [{chars_limit, 12}, {encoding, latin1}]),
+ "[\"a\",[...]|...]" =
+ pretty(L, [{chars_limit, 12}, {encoding, unicode}]),
+
+ %% Latin-1
+ "\"12345678\"" = pretty("12345678", LOpts),
+ "\"12345678\"..." = pretty("123456789", LOpts),
+ "\"\\r\\n123456\"..." = pretty("\r\n1234567", LOpts),
+ "\"\\r1234567\"..." = pretty("\r12345678", LOpts),
+ "\"\\r\\n123456\"..." = pretty("\r\n12345678", LOpts),
+ "\"12345678\"..." = pretty("12345678"++[x], LOpts),
+ "[49,50|...]" = pretty("1234567"++[x], LOpts),
+ "[49,x]" = pretty("1"++[x], LOpts),
+ "[[...]|...]" = pretty(["1","2","3","4","5","6","7","8"], LOpts),
+ %% Unicode
+ "\"12345678\"" = pretty("12345678", UOpts),
+ "\"12345678\"..." = pretty("123456789", UOpts),
+ "\"\\r\\n1234567\"" = pretty("\r\n1234567", UOpts),
+ "\"\\r1234567\"..." = pretty("\r12345678", UOpts),
+ "\"\\r\\n1234567\"..." = pretty("\r\n12345678", UOpts),
+ "[49,50|...]" = pretty("12345678"++[x], UOpts),
+ "\"12345678\"..." = pretty("123456789"++[x], UOpts),
+ "[[...]|...]" = pretty(["1","2","3","4","5","6","7","8"], UOpts),
+ ok.
+
+otp_15847(_Config) ->
+ T = {someRecord,<<"1234567890">>,some,more},
+ "{someRecord,<<...>>,...}" =
+ pretty(T, [{chars_limit,20}, {encoding,latin1}]),
+ ok.
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index 837ab4e97e..984b51e7ae 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -2597,6 +2597,20 @@ subtract(Config) when is_list(Config) ->
{'EXIT',_} = (catch sub([a|b], [])),
{'EXIT',_} = (catch sub([a|b], [a])),
+ %% Trapping, both crashing and otherwise.
+ [sub_trapping(N) || N <- lists:seq(0, 18)],
+
+ %% The current implementation chooses which algorithm to use based on
+ %% certain thresholds, and we need proper coverage for all corner cases.
+ [sub_thresholds(N) || N <- lists:seq(0, 32)],
+
+ %% Trapping, both crashing and otherwise.
+ [sub_trapping(N) || N <- lists:seq(0, 18)],
+
+ %% The current implementation chooses which algorithm to use based on
+ %% certain thresholds, and we need proper coverage for all corner cases.
+ [sub_thresholds(N) || N <- lists:seq(0, 32)],
+
ok.
sub_non_matching(A, B) ->
@@ -2606,6 +2620,41 @@ sub(A, B) ->
Res = A -- B,
Res = lists:subtract(A, B).
+sub_trapping(N) ->
+ List = lists:duplicate(N + (1 bsl N), gurka),
+ ImproperList = List ++ crash,
+
+ {'EXIT',_} = (catch sub_trapping_1(ImproperList, [])),
+ {'EXIT',_} = (catch sub_trapping_1(List, ImproperList)),
+
+ List = List -- lists:duplicate(N + (1 bsl N), gaffel),
+ ok = sub_trapping_1(List, []).
+
+sub_trapping_1([], _) -> ok;
+sub_trapping_1(L, R) -> sub_trapping_1(L -- R, [gurka | R]).
+
+sub_thresholds(N) ->
+ %% This needs to be long enough to cause trapping.
+ OtherLen = 1 bsl 18,
+ Other = lists:seq(0, OtherLen - 1),
+
+ Disjoint = lists:seq(-N, -1),
+ Subset = lists:seq(1, N),
+
+ %% LHS is disjoint from RHS, so all elements must be retained.
+ Disjoint = Disjoint -- Other,
+
+ %% LHS is covered by RHS, so all elements must be removed.
+ [] = Subset -- Other,
+
+ %% RHS is disjoint from LHS, so all elements must be retained.
+ Other = Other -- Disjoint,
+
+ %% RHS is covered by LHS, so N elements must be removed.
+ N = OtherLen - length(Other -- Subset),
+
+ ok.
+
%% Test lists:droplast/1
droplast(Config) when is_list(Config) ->
[] = lists:droplast([x]),
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index d753d929f5..b76c9f5341 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -475,10 +475,11 @@ stats_standard_normal_box_muller_2(Config) when is_list(Config) ->
stats_standard_normal(Config) when is_list(Config) ->
+ Retries = 7,
try math:erfc(1.0) of
_ ->
stats_standard_normal(
- fun rand:normal_s/1, rand:seed_s(exrop), 3)
+ fun rand:normal_s/1, rand:seed_s(exrop), Retries)
catch error:_ ->
{skip, "math:erfc/1 not supported"}
end.
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput2 b/lib/stdlib/test/re_SUITE_data/testoutput2
index 811bbefc84..61ed8d9d4e 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput2
+++ b/lib/stdlib/test/re_SUITE_data/testoutput2
@@ -14705,4 +14705,20 @@ No options
No first char
No need char
+"(?<=(a))\1?b"
+ ab
+ 0: b
+ 1: a
+ aaab
+ 0: ab
+ 1: a
+
+"(?=(a))\1?b"
+ ab
+ 0: ab
+ 1: a
+ aaab
+ 0: ab
+ 1: a
+
/-- End of testinput2 --/
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput5 b/lib/stdlib/test/re_SUITE_data/testoutput5
index bab989ca7e..090e1e1c85 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput5
+++ b/lib/stdlib/test/re_SUITE_data/testoutput5
@@ -1942,4 +1942,12 @@ Need char = 'z'
0: \x{17f}
0+
+/\C[^\v]+\x80/8
+ [AΏBŀC]
+No match
+
+/\C[^\d]+\x80/8
+ [AΏBŀC]
+No match
+
/-- End of testinput5 --/
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index ed7dd04171..9370067910 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -2339,6 +2339,13 @@ order_of_children(_Config) ->
%% Test that a non-simple supervisor scales well for starting and
%% stopping many children.
scale_start_stop_many_children(_Config) ->
+ case erlang:system_info(build_type) of
+ opt -> scale_start_stop_many_children();
+ Other -> {skip,"Run on build type 'opt' only (current: '" ++
+ atom_to_list(Other)++"')"}
+ end.
+
+scale_start_stop_many_children() ->
process_flag(trap_exit, true),
{ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
N1 = 1000,
diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl
index 3278eb0eb0..fcc4419569 100644
--- a/lib/stdlib/test/sys_SUITE.erl
+++ b/lib/stdlib/test/sys_SUITE.erl
@@ -219,7 +219,7 @@ spec_proc(Mod) ->
{Mod,system_get_state},{throw,fail}},_}} ->
ok
end,
- ok = sys:terminate(Mod, normal),
+ ok = sync_terminate(Mod),
{ok,_} = Mod:start_link(4),
ok = case catch sys:replace_state(Mod, fun(_) -> {} end) of
{} ->
@@ -228,7 +228,7 @@ spec_proc(Mod) ->
{Mod,system_replace_state},{throw,fail}},_}} ->
ok
end,
- ok = sys:terminate(Mod, normal),
+ ok = sync_terminate(Mod),
{ok,_} = Mod:start_link(4),
StateFun = fun(_) -> error(fail) end,
ok = case catch sys:replace_state(Mod, StateFun) of
@@ -240,7 +240,18 @@ spec_proc(Mod) ->
{'EXIT',{{callback_failed,StateFun,{error,fail}},_}} ->
ok
end,
- ok = sys:terminate(Mod, normal).
+ ok = sync_terminate(Mod).
+
+sync_terminate(Mod) ->
+ P = whereis(Mod),
+ MRef = erlang:monitor(process,P),
+ ok = sys:terminate(Mod, normal),
+ receive
+ {'DOWN',MRef,_,_,normal} ->
+ ok
+ end,
+ undefined = whereis(Mod),
+ ok.
%%%%%%%%%%%%%%%%%%%%
%% Dummy server
diff --git a/lib/stdlib/test/unicode_util_SUITE.erl b/lib/stdlib/test/unicode_util_SUITE.erl
index 962b307b07..044b4e5834 100644
--- a/lib/stdlib/test/unicode_util_SUITE.erl
+++ b/lib/stdlib/test/unicode_util_SUITE.erl
@@ -126,17 +126,30 @@ verify_gc(Line0, N, Acc) ->
%io:format("Line: ~s~n",[Line]),
[Data|_Comments] = string:tokens(Line, "#"),
- %io:format("Data: ~w~n",[string:tokens(Data, " \t")]),
+ %% io:format("Data: ~w~n",[string:tokens(Data, " \t")]),
{Str,Res} = gc_test_data(string:tokens(Data, " \t"), [], [[]]),
- try
- Res = fetch(Str, fun unicode_util:gc/1),
- Acc
- catch _Cl:{badmatch, Other} ->
+ %% io:format("InputStr: ~w ~w~n",[Str,unicode:characters_to_binary(Str)]),
+ case verify_gc(Str, Res, N, Line) andalso
+ verify_gc(unicode:characters_to_binary(Str), Res, N, Line0) of
+ true -> Acc;
+ false -> Acc+1
+ end.
+
+verify_gc({error,_,[CP|_]}=Err, _Res, N, Line) ->
+ IsSurrogate = 16#D800 =< CP andalso CP =< 16#DFFF,
+ %% Surrogat is not valid in utf8 encoding only utf16
+ IsSurrogate orelse
+ io:format("~w: ~ts~n Error in unicode:characters_to_binary ~w~n", [N, Line, Err]),
+ IsSurrogate;
+verify_gc(Str, Res, N, Line) ->
+ try fetch(Str, fun unicode_util:gc/1) of
+ Res -> true;
+ Other ->
io:format("Failed: ~p~nInput: ~ts~n\t=> ~w |~ts|~n",[N, Line, Str, Str]),
io:format("Expected: ~p~n", [Res]),
io:format("Got: ~w~n", [Other]),
- Acc+1;
- Cl:R:Stacktrace ->
+ false
+ catch Cl:R:Stacktrace ->
io:format("~p: ~ts => |~tp|~n",[N, Line, Str]),
io:format("Expected: ~p~n", [Res]),
erlang:raise(Cl,R,Stacktrace)
diff --git a/lib/stdlib/uc_spec/gen_unicode_mod.escript b/lib/stdlib/uc_spec/gen_unicode_mod.escript
index fe5a860d45..535f01a1c5 100755
--- a/lib/stdlib/uc_spec/gen_unicode_mod.escript
+++ b/lib/stdlib/uc_spec/gen_unicode_mod.escript
@@ -646,7 +646,7 @@ gen_gc(Fd, GBP) ->
io:put_chars(Fd, "is_emodifier(_) -> false.\n\n"),
io:put_chars(Fd, "gc_zwj(R0, Acc) ->\n case cp(R0) of\n"),
- GenZWJGlue = fun(Range) -> io:format(Fd, "~8c~s gc_extend(R1, R0, [CP|Acc]);\n",
+ GenZWJGlue = fun(Range) -> io:format(Fd, "~8c~s gc_extend(cp(R1), R0, [CP|Acc]);\n",
[$\s,gen_case_clause(Range)]) end,
[GenZWJGlue(CP) || CP <- merge_ranges(maps:get(glue_after_zwj,GBP))],
GenZWJEBG = fun(Range) -> io:format(Fd, "~8c~s gc_e_cont(R1, [CP|Acc]);\n",
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 0525b2de0b..80ec81b832 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 3.5
+STDLIB_VSN = 3.8.2
diff --git a/lib/syntax_tools/doc/src/Makefile b/lib/syntax_tools/doc/src/Makefile
index 797f9c265f..d953287bad 100644
--- a/lib/syntax_tools/doc/src/Makefile
+++ b/lib/syntax_tools/doc/src/Makefile
@@ -125,6 +125,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index 7ba90a6495..772f5e6e04 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -32,14 +32,40 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
-<section><title>Syntax_Tools 2.1.5</title>
+<section><title>Syntax_Tools 2.1.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
- <p> Fix a bug regarding reverting map types. </p>
+ <p> Fix pretty-printing of type funs. </p>
<p>
- Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ Own Id: OTP-15519 Aux Id: ERL-815 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Syntax_Tools 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the <c>TypeName</c> type in erl_syntax_lib.</p>
+ <p>
+ Own Id: OTP-15207 Aux Id: PR-1888 </p>
+ </item>
+ <item>
+ <p> Correct unfolding of the stacktrace variable. </p>
+ <p>
+ Own Id: OTP-15291 Aux Id: ERL-719 </p>
+ </item>
+ <item>
+ <p> Correct <c>erl_syntax:revert/1</c> bug regarding the
+ types <c>map()</c> and <c>tuple()</c>. </p>
+ <p>
+ Own Id: OTP-15294</p>
</item>
</list>
</section>
@@ -48,6 +74,20 @@
<section><title>Improvements and New Features</title>
<list>
<item>
+ <p> Support bitstrings as literals in module
+ <c>erl_syntax</c>. </p>
+ <p>
+ Own Id: OTP-15165 Aux Id: PR-1842 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Syntax_Tools 2.1.5</title>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
<p>
Update to use the new string api instead of the old.</p>
<p>
@@ -55,7 +95,18 @@
</item>
</list>
</section>
+</section>
+<section><title>Syntax_Tools 2.1.4.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding reverting map types. </p>
+ <p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ </item>
+ </list>
+ </section>
</section>
<section><title>Syntax_Tools 2.1.4</title>
@@ -109,6 +160,20 @@
</section>
+<section><title>Syntax_Tools 2.1.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding reverting map types. </p>
+ <p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index 6906ef1553..6ad9bec2e6 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -1101,8 +1101,9 @@ lay_2(Node, Ctxt) ->
Ctxt1 = reset_prec(Ctxt),
D1 = lay(erl_syntax:constrained_function_type_body(Node),
Ctxt1),
+ Ctxt2 = Ctxt1#ctxt{clause = undefined},
D2 = lay(erl_syntax:constrained_function_type_argument(Node),
- Ctxt1),
+ Ctxt2),
beside(D1,
beside(floating(text(" when ")), D2));
@@ -1113,7 +1114,7 @@ lay_2(Node, Ctxt) ->
_ ->
{"fun(", ")"}
end,
- Ctxt1 = reset_prec(Ctxt),
+ Ctxt1 = (reset_prec(Ctxt))#ctxt{clause = undefined},
D1 = case erl_syntax:function_type_arguments(Node) of
any_arity ->
text("(...)");
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 029f1e88ac..1be644c620 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -3897,7 +3897,7 @@ unfold_try_clauses(Cs) ->
unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw},
V,
- [{var, _, '_'}]]}],
+ {var, _, '_'}]}],
Guard, Body}) ->
{clause, Pos, [V], Guard, Body};
unfold_try_clause({clause, Pos, [{tuple, _, [C, V, Stacktrace]}],
@@ -5455,8 +5455,12 @@ map_type(Fields) ->
revert_map_type(Node) ->
Pos = get_pos(Node),
- {type, Pos, map, map_type_fields(Node)}.
-
+ case map_type_fields(Node) of
+ any_size ->
+ {type, Pos, map, any};
+ Fields ->
+ {type, Pos, map, Fields}
+ end.
%% =====================================================================
%% @doc Returns the list of field subtrees of a `map_type' node.
@@ -5714,7 +5718,12 @@ tuple_type(Elements) ->
revert_tuple_type(Node) ->
Pos = get_pos(Node),
- {type, Pos, tuple, tuple_type_elements(Node)}.
+ case tuple_type_elements(Node) of
+ any_size ->
+ {type, Pos, tuple, any};
+ TypeElements ->
+ {type, Pos, tuple, TypeElements}
+ end.
%% =====================================================================
@@ -7223,7 +7232,7 @@ macro_arguments(Node) ->
%% @doc Returns the syntax tree corresponding to an Erlang term.
%% `Term' must be a literal term, i.e., one that can be
%% represented as a source code literal. Thus, it may not contain a
-%% process identifier, port, reference, binary or function value as a
+%% process identifier, port, reference or function value as a
%% subterm. The function recognises printable strings, in order to get a
%% compact and readable representation. Evaluation fails with reason
%% `badarg' if `Term' is not a literal term.
@@ -7257,6 +7266,13 @@ abstract(T) when is_map(T) ->
|| {Key,Value} <- maps:to_list(T)]);
abstract(T) when is_binary(T) ->
binary([binary_field(integer(B)) || B <- binary_to_list(T)]);
+abstract(T) when is_bitstring(T) ->
+ S = bit_size(T),
+ ByteS = S div 8,
+ BitS = S rem 8,
+ <<Bin:ByteS/binary, I:BitS>> = T,
+ binary([binary_field(integer(B)) || B <- binary_to_list(Bin)]
+ ++ [binary_field(integer(I), integer(BitS), [])]);
abstract(T) ->
erlang:error({badarg, T}).
@@ -7332,15 +7348,20 @@ concrete(Node) ->
Node0 -> maps:merge(concrete(Node0),M0)
end;
binary ->
- Fs = [revert_binary_field(
- binary_field(binary_field_body(F),
- case binary_field_size(F) of
- none -> none;
- S ->
- revert(S)
- end,
- binary_field_types(F)))
- || F <- binary_fields(Node)],
+ Fs = [begin
+ B = binary_field_body(F),
+ {Body, Size} =
+ case type(B) of
+ size_qualifier ->
+ {size_qualifier_body(B),
+ size_qualifier_argument(B)};
+ _ ->
+ {B, none}
+ end,
+ revert_binary_field(
+ binary_field(Body, Size, binary_field_types(F)))
+ end
+ || F <- binary_fields(Node)],
{value, B, _} =
eval_bits:expr_grp(Fs, [],
fun(F, _) ->
@@ -7413,7 +7434,14 @@ is_literal(T) ->
is_literal_binary_field(F) ->
case binary_field_types(F) of
- [] -> is_literal(binary_field_body(F));
+ [] -> B = binary_field_body(F),
+ case type(B) of
+ size_qualifier ->
+ is_literal(size_qualifier_body(B)) andalso
+ is_literal(size_qualifier_argument(B));
+ _ ->
+ is_literal(B)
+ end;
_ -> false
end.
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index ced0dba3e2..352165893f 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -1981,7 +1981,7 @@ analyze_application(Node) ->
%%
%% @see analyze_type_name/1
--type typeName() :: atom() | {module(), atom(), arity()} | {atom(), arity()}.
+-type typeName() :: atom() | {module(), {atom(), arity()}} | {atom(), arity()}.
-spec analyze_type_application(erl_syntax:syntaxTree()) -> typeName().
diff --git a/lib/syntax_tools/test/merl_SUITE.erl b/lib/syntax_tools/test/merl_SUITE.erl
index 52bbd9b3b8..6389ad7738 100644
--- a/lib/syntax_tools/test/merl_SUITE.erl
+++ b/lib/syntax_tools/test/merl_SUITE.erl
@@ -30,13 +30,14 @@
%% Test cases
-export([merl_smoke_test/1,
- transform_parse_error_test/1]).
+ transform_parse_error_test/1, otp_15291/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[merl_smoke_test,
- transform_parse_error_test].
+ transform_parse_error_test,
+ otp_15291].
groups() ->
[].
@@ -101,6 +102,15 @@ transform_parse_error_test(_Config) ->
[?Q("merl:qquote(2, \"{\", [{var, V}])")], []))),
ok.
+otp_15291(_Config) ->
+ C0 = merl:quote("() -> ok"),
+ {clause,1,[],[],[{atom,1,ok}]} = C0,
+ C2 = merl:quote("(_,_) -> ok"),
+ {clause,1,[{var,1,'_'},{var,1,'_'}],[],[{atom,1,ok}]} = C2,
+ C1 = merl:quote("(_) -> ok"),
+ {clause,1,[{var,1,'_'}],[],[{atom,1,ok}]} = C1,
+ ok.
+
%% utilities
f(Ts) when is_list(Ts) ->
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index c8e6448d37..6b42f7a0a1 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -25,15 +25,15 @@
%% Test cases
-export([app_test/1,appup_test/1,smoke_test/1,revert/1,revert_map/1,
revert_map_type/1,
- t_abstract_type/1,t_erl_parse_type/1,t_epp_dodger/1,
- t_comment_scan/1,t_igor/1,t_erl_tidy/1]).
+ t_abstract_type/1,t_erl_parse_type/1,t_type/1, t_epp_dodger/1,
+ t_comment_scan/1,t_igor/1,t_erl_tidy/1,t_prettypr/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app_test,appup_test,smoke_test,revert,revert_map,revert_map_type,
- t_abstract_type,t_erl_parse_type,t_epp_dodger,
- t_comment_scan,t_igor,t_erl_tidy].
+ t_abstract_type,t_erl_parse_type,t_type,t_epp_dodger,
+ t_comment_scan,t_igor,t_erl_tidy,t_prettypr].
groups() ->
[].
@@ -145,6 +145,74 @@ revert_map_type(Config) when is_list(Config) ->
%% api tests
+t_type(Config) when is_list(Config) ->
+ F0 = fun validate_basic_type/1,
+ Appl0 = fun(Name) ->
+ Atom = erl_syntax:atom(Name),
+ erl_syntax:type_application(none, Atom, [])
+ end,
+ User0 = fun(Name) ->
+ Atom = erl_syntax:atom(Name),
+ erl_syntax:user_type_application(Atom, [])
+ end,
+ ok = validate(F0,[{"tuple()", erl_syntax:tuple_type()}
+ ,{"{}", erl_syntax:tuple_type([])}
+ ,{"integer()", Appl0(integer)}
+ ,{"foo()", User0(foo)}
+ ,{"map()", erl_syntax:map_type()}
+ ,{"#{}", erl_syntax:map_type([])}
+ ,{"1..2", erl_syntax:integer_range_type
+ (erl_syntax:integer(1), erl_syntax:integer(2))}
+ ,{"<<_:1,_:_*2>>", erl_syntax:bitstring_type
+ (erl_syntax:integer(1), erl_syntax:integer(2))}
+ ,{"fun()", erl_syntax:fun_type()}
+ ]),
+
+ F = fun validate_type/1,
+ ok = validate(F,[{"{}", tuple_type, false}
+ ,{"tuple()", tuple_type, true}
+ ,{"{atom()}", tuple_type, false}
+ ,{"{atom(),integer()}", tuple_type, false}
+ ,{"integer()", type_application, false}
+ ,{"foo()", user_type_application, false}
+ ,{"foo(integer())", user_type_application, false}
+ ,{"module:function()", type_application, false}
+ ,{"map()", map_type, true}
+ ,{"#{}", map_type, false}
+ ,{"#{atom() => integer()}", map_type, false}
+ ,{"#{atom() := integer()}", map_type, false}
+ ,{"#r{}", record_type, false}
+ ,{"#r{a :: integer()}", record_type, false}
+ ,{"[]", type_application, false}
+ ,{"nil()", type_application, false}
+ ,{"[atom()]", type_application, false}
+ ,{"1..2", integer_range_type, false}
+ ,{"<<_:1,_:_*2>>", bitstring_type, false}
+ ,{"fun()", fun_type, true}
+ ,{"integer() | atom()", type_union, false}
+ ,{"A :: fun()", annotated_type, false}
+ ,{"fun((...) -> atom())", function_type, false}
+ ,{"fun((integer()) -> atom())", function_type, false}
+ ,{"V", variable, true}
+ ]),
+ ok.
+
+validate_basic_type({String, Tree}) ->
+ ErlT = string_to_type(String),
+ ErlT = erl_syntax:revert(Tree),
+ ok.
+
+validate_type({String, Type, Leaf}) ->
+ ErlT = string_to_type(String),
+ Type = erl_syntax:type(ErlT),
+ Leaf = erl_syntax:is_leaf(ErlT),
+ Tree = erl_syntax_lib:map(fun(Node) -> Node end, ErlT),
+ Type = erl_syntax:type(Tree),
+ _ = erl_syntax:meta(Tree),
+ RevT = erl_syntax:revert(Tree),
+ Type = erl_syntax:type(RevT),
+ ok.
+
t_abstract_type(Config) when is_list(Config) ->
F = fun validate_abstract_type/1,
ok = validate(F,[{hi,atom},
@@ -157,6 +225,7 @@ t_abstract_type(Config) when is_list(Config) ->
{[$a,$b,$c],string},
{"hello world",string},
{<<1,2,3>>,binary},
+ {<<1,2,3:4>>,binary},
{#{a=>1,"b"=>2},map_expr},
{#{#{i=>1}=>1,"b"=>#{v=>2}},map_expr},
{{a,b,c},tuple}]),
@@ -231,6 +300,14 @@ t_comment_scan(Config) when is_list(Config) ->
ok = test_comment_scan(Filenames,DataDir),
ok.
+t_prettypr(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ Filenames = ["type_specs.erl",
+ "specs_and_funs.erl"],
+ ok = test_prettypr(Filenames,DataDir,PrivDir),
+ ok.
+
test_files(Config) ->
DataDir = ?config(data_dir, Config),
[ filename:join(DataDir,Filename) || Filename <- test_files() ].
@@ -238,7 +315,8 @@ test_files(Config) ->
test_files() ->
["syntax_tools_SUITE_test_module.erl",
"syntax_tools_test.erl",
- "type_specs.erl"].
+ "type_specs.erl",
+ "specs_and_funs.erl"].
t_igor(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
@@ -290,6 +368,27 @@ test_comment_scan([File|Files],DataDir) ->
test_comment_scan(Files,DataDir).
+test_prettypr([],_,_) -> ok;
+test_prettypr([File|Files],DataDir,PrivDir) ->
+ Filename = filename:join(DataDir,File),
+ io:format("Parsing ~p~n", [Filename]),
+ {ok, Fs0} = epp:parse_file(Filename, [], []),
+ Fs = erl_syntax:form_list(Fs0),
+ PP = erl_prettypr:format(Fs, [{paper, 120}, {ribbon, 110}]),
+ io:put_chars(PP),
+ OutFile = filename:join(PrivDir, File),
+ ok = file:write_file(OutFile,iolist_to_binary(PP)),
+ io:format("Parsing OutFile: ~s~n", [OutFile]),
+ {ok, Fs2} = epp:parse_file(OutFile, [], []),
+ case [Error || {error, _} = Error <- Fs2] of
+ [] ->
+ ok;
+ Errors ->
+ ?t:fail(Errors)
+ end,
+ test_prettypr(Files,DataDir,PrivDir).
+
+
test_epp_dodger([], _, _) -> ok;
test_epp_dodger([Filename|Files],DataDir,PrivDir) ->
io:format("Parsing ~p~n", [Filename]),
@@ -450,6 +549,13 @@ string_to_expr(String) ->
{ok,[Expr]} = erl_parse:parse_exprs(Ts),
Expr.
+string_to_type(String) ->
+ io:format("Str: ~p~n", [String]),
+ {ok,Ts,_} = erl_scan:string("-type foo() :: "++String++".", 0),
+ {ok,Form} = erl_parse:parse_form(Ts),
+ {attribute,_,type,{foo,Type,_NoParms=[]}} = Form,
+ Type.
+
p_run(Test, List) ->
N = erlang:system_info(schedulers),
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE_data/specs_and_funs.erl b/lib/syntax_tools/test/syntax_tools_SUITE_data/specs_and_funs.erl
new file mode 100644
index 0000000000..8dfeaf5a6b
--- /dev/null
+++ b/lib/syntax_tools/test/syntax_tools_SUITE_data/specs_and_funs.erl
@@ -0,0 +1,18 @@
+-module(specs_and_funs).
+
+-export([my_apply/3, two/1]).
+
+%% OTP-15519, ERL-815
+
+-spec my_apply(Fun, Arg, fun((A) -> A)) -> Result when
+ Fun :: fun((Arg) -> Result),
+ Arg :: any(),
+ Result :: any().
+
+my_apply(Fun, Arg, _) ->
+ Fun(Arg).
+
+-spec two(fun((A) -> A)) -> fun((B) -> B).
+
+two(F) ->
+ F(fun(X) -> X end).
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index 4d13267f16..538c71dc24 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 2.1.5
+SYNTAX_TOOLS_VSN = 2.1.7
diff --git a/lib/tftp/doc/src/Makefile b/lib/tftp/doc/src/Makefile
index a2fdcf6325..5d76799e41 100644
--- a/lib/tftp/doc/src/Makefile
+++ b/lib/tftp/doc/src/Makefile
@@ -103,6 +103,7 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
man: $(MAN3_FILES)
diff --git a/lib/tftp/doc/src/notes.xml b/lib/tftp/doc/src/notes.xml
index 3a4d97a008..ff6113a89d 100644
--- a/lib/tftp/doc/src/notes.xml
+++ b/lib/tftp/doc/src/notes.xml
@@ -33,7 +33,22 @@
<file>notes.xml</file>
</header>
- <section><title>TFTP 1.0</title>
+ <section><title>Tftp 1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>TFTP 1.0</title>
<section><title>First released version</title>
<list>
diff --git a/lib/tftp/doc/src/tftp.xml b/lib/tftp/doc/src/tftp.xml
index 481e5446ad..57d64b7379 100644
--- a/lib/tftp/doc/src/tftp.xml
+++ b/lib/tftp/doc/src/tftp.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>tftp</module>
+ <module since="">tftp</module>
<modulesummary>Trivial FTP.</modulesummary>
<description>
<p>Interface module for the <c>tftp</c> application.</p>
@@ -150,7 +150,7 @@
<tag><c>{logger, Module}</c></tag>
<item>
- <p><c>Module = module()()</c></p>
+ <p><c>Module = module()</c></p>
<p>Callback module for customized logging of errors, warnings, and
info messages. The callback module must implement the
@@ -172,7 +172,7 @@
<funcs>
<func>
- <name>change_config(daemons, Options) -> [{Pid, Result}]</name>
+ <name since="">change_config(daemons, Options) -> [{Pid, Result}]</name>
<fsummary>Changes configuration for all daemons.
</fsummary>
<type>
@@ -187,7 +187,7 @@
</func>
<func>
- <name>change_config(servers, Options) -> [{Pid, Result}]</name>
+ <name since="">change_config(servers, Options) -> [{Pid, Result}]</name>
<fsummary>Changes configuration for all servers.
</fsummary>
<type>
@@ -202,7 +202,7 @@
</func>
<func>
- <name>change_config(Pid, Options) -> Result</name>
+ <name since="">change_config(Pid, Options) -> Result</name>
<fsummary>Changes configuration for a TFTP daemon, server,
or client process.</fsummary>
<type>
@@ -217,10 +217,10 @@
</func>
<func>
- <name>info(daemons) -> [{Pid, Options}]</name>
+ <name since="">info(daemons) -> [{Pid, Options}]</name>
<fsummary>Returns information about all daemons.</fsummary>
<type>
- <v>Pid = [pid()()]</v>
+ <v>Pid = [pid()]</v>
<v>Options = [option()]</v>
<v>Reason = term()</v>
</type>
@@ -230,10 +230,10 @@
</func>
<func>
- <name>info(servers) -> [{Pid, Options}]</name>
+ <name since="">info(servers) -> [{Pid, Options}]</name>
<fsummary>Returns information about all servers.</fsummary>
<type>
- <v>Pid = [pid()()]</v>
+ <v>Pid = [pid()]</v>
<v>Options = [option()]</v>
<v>Reason = term()</v>
</type>
@@ -243,7 +243,7 @@
</func>
<func>
- <name>info(Pid) -> {ok, Options} | {error, Reason}</name>
+ <name since="">info(Pid) -> {ok, Options} | {error, Reason}</name>
<fsummary>Returns information about a daemon, server, or client process.</fsummary>
<type>
<v>Options = [option()]</v>
@@ -255,7 +255,7 @@
</func>
<func>
- <name>read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
+ <name since="">read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
<fsummary>Reads a (virtual) file from a TFTP server.</fsummary>
<type>
<v>RemoteFilename = string()</v>
@@ -285,7 +285,7 @@
</func>
<func>
- <name>start(Options) -> {ok, Pid} | {error, Reason}</name>
+ <name since="">start(Options) -> {ok, Pid} | {error, Reason}</name>
<fsummary>Starts a daemon process.</fsummary>
<type>
<v>Options = [option()]</v>
@@ -301,7 +301,7 @@
</func>
<func>
- <name>write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
+ <name since="">write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
<fsummary>Writes a (virtual) file to a TFTP server.</fsummary>
<type>
<v>RemoteFilename = string()</v>
@@ -389,7 +389,7 @@
<funcs>
<func>
- <name>Module:abort(Code, Text, State) -> ok</name>
+ <name since="OTP 18.1">Module:abort(Code, Text, State) -> ok</name>
<fsummary>Aborts the file transfer.</fsummary>
<type>
<v>Code = undef | enoent | eacces | enospc</v>
@@ -413,7 +413,7 @@
</func>
<func>
- <name>Module:open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
+ <name since="OTP 18.1">Module:open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
<fsummary>Opens a file for read or write access.</fsummary>
<type>
<v>Peer = {PeerType, PeerHost, PeerPort}</v>
@@ -448,7 +448,7 @@
</func>
<func>
- <name>Module:prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
+ <name since="OTP 18.1">Module:prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
<fsummary>Prepares to open a file on the client side.</fsummary>
<type>
<v>Peer = {PeerType, PeerHost, PeerPort}</v>
@@ -483,7 +483,7 @@
</func>
<func>
- <name>Module:read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name>
+ <name since="OTP 18.1">Module:read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name>
<fsummary>Reads a chunk from the file.</fsummary>
<type>
<v>State = NewState = term()</v>
@@ -510,7 +510,7 @@
</func>
<func>
- <name>Module:write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name>
+ <name since="OTP 18.1">Module:write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name>
<fsummary>Writes a chunk to the file.</fsummary>
<type>
<v>Bin = binary()</v>
@@ -549,7 +549,7 @@
<funcs>
<func>
- <name>Logger:error_msg(Format, Data) -> ok | exit(Reason)</name>
+ <name since="OTP 18.1">Logger:error_msg(Format, Data) -> ok | exit(Reason)</name>
<fsummary>Logs an error message.</fsummary>
<type>
<v>Format = string()</v>
@@ -565,7 +565,7 @@
</func>
<func>
- <name>Logger:info_msg(Format, Data) -> ok | exit(Reason)</name>
+ <name since="OTP 18.1">Logger:info_msg(Format, Data) -> ok | exit(Reason)</name>
<fsummary>Logs an info message.</fsummary>
<type>
<v>Format = string()</v>
@@ -579,7 +579,7 @@
</func>
<func>
- <name>Logger:warning_msg(Format, Data) -> ok | exit(Reason)</name>
+ <name since="OTP 18.1">Logger:warning_msg(Format, Data) -> ok | exit(Reason)</name>
<fsummary>Logs a warning message.</fsummary>
<type>
<v>Format = string()</v>
diff --git a/lib/tftp/src/tftp.app.src b/lib/tftp/src/tftp.app.src
index 2a87d39ada..9e79fe32bf 100644
--- a/lib/tftp/src/tftp.app.src
+++ b/lib/tftp/src/tftp.app.src
@@ -1,6 +1,6 @@
{application, tftp,
[{description, "TFTP application"},
- {vsn, "1.0"},
+ {vsn, "%VSN%"},
{registered, []},
{mod, { tftp_app, []}},
{applications,
diff --git a/lib/tftp/vsn.mk b/lib/tftp/vsn.mk
index f1b0851a8f..1a547fbe9b 100644
--- a/lib/tftp/vsn.mk
+++ b/lib/tftp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = tftp
-TFTP_VSN = 1.0
+TFTP_VSN = 1.0.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(TFTP_VSN)$(PRE_VSN)"
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index cfe91917f8..289322b6fa 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -29,7 +29,6 @@ CC=@CC@
LD=@LD@
AR=@AR@
RANLIB=@RANLIB@
-RM=@RM@
MKDIR=@MKDIR@
INSTALL=@INSTALL@
INSTALL_DIR=@INSTALL_DIR@
@@ -158,9 +157,9 @@ $(ERTS_LIB):
docs:
clean:
- $(RM) -rf ../obj/*
- $(RM) -rf ../bin/*
- $(RM) -f ./*~
+ $(RM) -r ../obj/*
+ $(RM) -r ../bin/*
+ $(RM) ./*~
.PHONY: all erts_lib docs clean
diff --git a/lib/tools/doc/src/Makefile b/lib/tools/doc/src/Makefile
index 001c31a443..5ff4fe3113 100644
--- a/lib/tools/doc/src/Makefile
+++ b/lib/tools/doc/src/Makefile
@@ -120,6 +120,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
diff --git a/lib/tools/doc/src/cover.xml b/lib/tools/doc/src/cover.xml
index 15cd784253..64c24cea2a 100644
--- a/lib/tools/doc/src/cover.xml
+++ b/lib/tools/doc/src/cover.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>cover</module>
+ <module since="">cover</module>
<modulesummary>A Coverage Analysis Tool for Erlang</modulesummary>
<description>
<p>The module <c>cover</c> provides a set of functions for coverage
@@ -115,7 +115,7 @@
</description>
<funcs>
<func>
- <name>start() -> {ok,Pid} | {error,Reason}</name>
+ <name since="">start() -> {ok,Pid} | {error,Reason}</name>
<fsummary>Start Cover.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -128,7 +128,7 @@
</desc>
</func>
<func>
- <name>start(Nodes) -> {ok,StartedNodes} | {error,not_main_node}</name>
+ <name since="">start(Nodes) -> {ok,StartedNodes} | {error,not_main_node}</name>
<fsummary>Start Cover on remote nodes.</fsummary>
<type>
<v>Nodes = StartedNodes = [atom()]</v>
@@ -139,10 +139,10 @@
</desc>
</func>
<func>
- <name>compile(ModFiles) -> Result | [Result]</name>
- <name>compile(ModFiles, Options) -> Result | [Result]</name>
- <name>compile_module(ModFiles) -> Result | [Result]</name>
- <name>compile_module(ModFiles, Options) -> Result | [Result]</name>
+ <name since="">compile(ModFiles) -> Result | [Result]</name>
+ <name since="">compile(ModFiles, Options) -> Result | [Result]</name>
+ <name since="">compile_module(ModFiles) -> Result | [Result]</name>
+ <name since="">compile_module(ModFiles, Options) -> Result | [Result]</name>
<fsummary>Compile one or more modules for Cover analysis.</fsummary>
<type>
<v>ModFiles = ModFile | [ModFile]</v>
@@ -176,9 +176,9 @@
</desc>
</func>
<func>
- <name>compile_directory() -> [Result] | {error,Reason}</name>
- <name>compile_directory(Dir) -> [Result] | {error,Reason}</name>
- <name>compile_directory(Dir, Options) -> [Result] | {error,Reason}</name>
+ <name since="">compile_directory() -> [Result] | {error,Reason}</name>
+ <name since="">compile_directory(Dir) -> [Result] | {error,Reason}</name>
+ <name since="">compile_directory(Dir, Options) -> [Result] | {error,Reason}</name>
<fsummary>Compile all modules in a directory for Cover analysis.</fsummary>
<type>
<v>Dir = string()</v>
@@ -199,7 +199,7 @@
</desc>
</func>
<func>
- <name>compile_beam(ModFiles) -> Result | [Result]</name>
+ <name since="">compile_beam(ModFiles) -> Result | [Result]</name>
<fsummary>Compile one or more modules for Cover analysis, using existing beam(s).</fsummary>
<type>
<v>ModFiles = ModFile | [ModFile]</v>
@@ -241,8 +241,8 @@
</desc>
</func>
<func>
- <name>compile_beam_directory() -> [Result] | {error,Reason}</name>
- <name>compile_beam_directory(Dir) -> [Result] | {error,Reason}</name>
+ <name since="">compile_beam_directory() -> [Result] | {error,Reason}</name>
+ <name since="">compile_beam_directory(Dir) -> [Result] | {error,Reason}</name>
<fsummary>Compile all .beam files in a directory for Cover analysis.</fsummary>
<type>
<v>Dir = string()</v>
@@ -260,14 +260,14 @@
</desc>
</func>
<func>
- <name>analyse() -> {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse(Modules) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse(Analysis) -> {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse(Level) -> {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse(Modules, Analysis) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse(Modules, Level) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse(Analysis, Level) -> {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse(Modules, Analysis, Level) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="OTP 18.0">analyse() -> {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse(Modules) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse(Analysis) -> {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse(Level) -> {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse(Modules, Analysis) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse(Modules, Level) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse(Analysis, Level) -> {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse(Modules, Analysis, Level) -> OneResult | {result,Ok,Fail} | {error,not_main_node}</name>
<fsummary>Analyse one or more Cover compiled modules.</fsummary>
<type>
<v>Modules = Module | [Module]</v>
@@ -305,10 +305,10 @@
</desc>
</func>
<func>
- <name>analyse_to_file() -> {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse_to_file(Modules) -> Answer | {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse_to_file(Options) -> {result,Ok,Fail} | {error,not_main_node}</name>
- <name>analyse_to_file(Modules,Options) -> Answer | {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="OTP 18.0">analyse_to_file() -> {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse_to_file(Modules) -> Answer | {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse_to_file(Options) -> {result,Ok,Fail} | {error,not_main_node}</name>
+ <name since="">analyse_to_file(Modules,Options) -> Answer | {result,Ok,Fail} | {error,not_main_node}</name>
<fsummary>Detailed coverage analysis of one or more Cover compiled modules.</fsummary>
<type>
<v>Modules = Module | [Module]</v>
@@ -359,10 +359,10 @@
</desc>
</func>
<func>
- <name>async_analyse_to_file(Module) -> </name>
- <name>async_analyse_to_file(Module,Options) -> </name>
- <name>async_analyse_to_file(Module, OutFile) -> </name>
- <name>async_analyse_to_file(Module, OutFile, Options) -> pid()</name>
+ <name since="OTP R14B02">async_analyse_to_file(Module) -> </name>
+ <name since="OTP R14B02">async_analyse_to_file(Module,Options) -> </name>
+ <name since="OTP R14B02">async_analyse_to_file(Module, OutFile) -> </name>
+ <name since="OTP R14B02">async_analyse_to_file(Module, OutFile, Options) -> pid()</name>
<fsummary>Asynchronous call to analyse_to_file.</fsummary>
<type>
<v>Module = atom()</v>
@@ -384,7 +384,7 @@
</desc>
</func>
<func>
- <name>modules() -> [Module] | {error,not_main_node}</name>
+ <name since="">modules() -> [Module] | {error,not_main_node}</name>
<fsummary>Return all Cover compiled modules.</fsummary>
<type>
<v>Module = atom()</v>
@@ -395,7 +395,7 @@
</desc>
</func>
<func>
- <name>imported_modules() -> [Module] | {error,not_main_node}</name>
+ <name since="">imported_modules() -> [Module] | {error,not_main_node}</name>
<fsummary>Return all modules for which there are imported data.</fsummary>
<type>
<v>Module = atom()</v>
@@ -406,7 +406,7 @@
</desc>
</func>
<func>
- <name>imported() -> [File] | {error,not_main_node}</name>
+ <name since="">imported() -> [File] | {error,not_main_node}</name>
<fsummary>Return all imported files.</fsummary>
<type>
<v>File = string()</v>
@@ -416,7 +416,7 @@
</desc>
</func>
<func>
- <name>which_nodes() -> [Node] | {error,not_main_node}</name>
+ <name since="">which_nodes() -> [Node] | {error,not_main_node}</name>
<fsummary>Return all nodes that are part of the coverage analysis.</fsummary>
<type>
<v>Node = atom()</v>
@@ -428,7 +428,7 @@
</desc>
</func>
<func>
- <name>is_compiled(Module) -> {file,File} | false | {error,not_main_node}</name>
+ <name since="">is_compiled(Module) -> {file,File} | false | {error,not_main_node}</name>
<fsummary>Check if a module is Cover compiled.</fsummary>
<type>
<v>Module = atom()</v>
@@ -442,8 +442,8 @@
</desc>
</func>
<func>
- <name>reset(Module) -></name>
- <name>reset() -> ok | {error,not_main_node}</name>
+ <name since="">reset(Module) -></name>
+ <name since="">reset() -> ok | {error,not_main_node}</name>
<fsummary>Reset coverage data for Cover compiled modules.</fsummary>
<type>
<v>Module = atom()</v>
@@ -458,8 +458,8 @@
</desc>
</func>
<func>
- <name>export(ExportFile)</name>
- <name>export(ExportFile,Module) -> ok | {error,Reason}</name>
+ <name since="">export(ExportFile)</name>
+ <name since="">export(ExportFile,Module) -> ok | {error,Reason}</name>
<fsummary>Reset coverage data for Cover compiled modules.</fsummary>
<type>
<v>ExportFile = string()</v>
@@ -480,7 +480,7 @@
</desc>
</func>
<func>
- <name>import(ExportFile) -> ok | {error,Reason}</name>
+ <name since="">import(ExportFile) -> ok | {error,Reason}</name>
<fsummary>Reset coverage data for Cover compiled modules.</fsummary>
<type>
<v>ExportFile = string()</v>
@@ -504,14 +504,14 @@
</desc>
</func>
<func>
- <name>stop() -> ok | {error,not_main_node}</name>
+ <name since="">stop() -> ok | {error,not_main_node}</name>
<fsummary>Stop Cover.</fsummary>
<desc>
<p>Stops the Cover server and unloads all Cover compiled code.</p>
</desc>
</func>
<func>
- <name>stop(Nodes) -> ok | {error,not_main_node}</name>
+ <name since="">stop(Nodes) -> ok | {error,not_main_node}</name>
<fsummary>Stop Cover on remote nodes.</fsummary>
<type>
<v>Nodes = [atom()]</v>
@@ -523,7 +523,7 @@
</desc>
</func>
<func>
- <name>flush(Nodes) -> ok | {error,not_main_node}</name>
+ <name since="OTP R16B">flush(Nodes) -> ok | {error,not_main_node}</name>
<fsummary>Collect cover data from remote nodes.</fsummary>
<type>
<v>Nodes = [atom()]</v>
diff --git a/lib/tools/doc/src/cprof.xml b/lib/tools/doc/src/cprof.xml
index df0acbe617..b6af8b6d28 100644
--- a/lib/tools/doc/src/cprof.xml
+++ b/lib/tools/doc/src/cprof.xml
@@ -34,7 +34,7 @@
<rev>PA1</rev>
<file>cprof.sgml</file>
</header>
- <module>cprof</module>
+ <module since="">cprof</module>
<modulesummary>A simple Call Count Profiling Tool using breakpoints for minimal runtime performance impact.</modulesummary>
<description>
<p>The <c>cprof</c> module is used to profile a program
@@ -65,10 +65,10 @@
</description>
<funcs>
<func>
- <name>analyse() -> {AllCallCount, ModAnalysisList}</name>
- <name>analyse(Limit) -> {AllCallCount, ModAnalysisList}</name>
- <name>analyse(Mod) -> ModAnalysis</name>
- <name>analyse(Mod, Limit) -> ModAnalysis</name>
+ <name since="">analyse() -> {AllCallCount, ModAnalysisList}</name>
+ <name since="">analyse(Limit) -> {AllCallCount, ModAnalysisList}</name>
+ <name since="">analyse(Mod) -> ModAnalysis</name>
+ <name since="">analyse(Mod, Limit) -> ModAnalysis</name>
<fsummary>Collect and analyse call counters.</fsummary>
<type>
<v>Limit = integer()</v>
@@ -122,7 +122,7 @@
</desc>
</func>
<func>
- <name>pause() -> integer()</name>
+ <name since="">pause() -> integer()</name>
<fsummary>Pause running call count trace for all functions.</fsummary>
<desc>
<p>Pause call count tracing for all functions in all modules
@@ -137,9 +137,9 @@
</desc>
</func>
<func>
- <name>pause(FuncSpec) -> integer()</name>
- <name>pause(Mod, Func) -> integer()</name>
- <name>pause(Mod, Func, Arity) -> integer()</name>
+ <name since="">pause(FuncSpec) -> integer()</name>
+ <name since="">pause(Mod, Func) -> integer()</name>
+ <name since="">pause(Mod, Func, Arity) -> integer()</name>
<fsummary>Pause running call count trace for matching functions.</fsummary>
<type>
<v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v>
@@ -167,10 +167,10 @@
</desc>
</func>
<func>
- <name>restart() -> integer()</name>
- <name>restart(FuncSpec) -> integer()</name>
- <name>restart(Mod, Func) -> integer()</name>
- <name>restart(Mod, Func, Arity) -> integer()</name>
+ <name since="">restart() -> integer()</name>
+ <name since="">restart(FuncSpec) -> integer()</name>
+ <name since="">restart(Mod, Func) -> integer()</name>
+ <name since="">restart(Mod, Func, Arity) -> integer()</name>
<fsummary>Restart existing call counters for matching functions.</fsummary>
<type>
<v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v>
@@ -197,7 +197,7 @@
</desc>
</func>
<func>
- <name>start() -> integer()</name>
+ <name since="">start() -> integer()</name>
<fsummary>Start call count tracing for all functions.</fsummary>
<desc>
<p>Start call count tracing for all functions in all modules,
@@ -212,9 +212,9 @@
</desc>
</func>
<func>
- <name>start(FuncSpec) -> integer()</name>
- <name>start(Mod, Func) -> integer()</name>
- <name>start(Mod, Func, Arity) -> integer()</name>
+ <name since="">start(FuncSpec) -> integer()</name>
+ <name since="">start(Mod, Func) -> integer()</name>
+ <name since="">start(Mod, Func, Arity) -> integer()</name>
<fsummary>Start call count tracing for matching functions.</fsummary>
<type>
<v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v>
@@ -240,7 +240,7 @@
</desc>
</func>
<func>
- <name>stop() -> integer()</name>
+ <name since="">stop() -> integer()</name>
<fsummary>Stop call count tracing for all functions.</fsummary>
<desc>
<p>Stop call count tracing for all functions in all modules,
@@ -255,9 +255,9 @@
</desc>
</func>
<func>
- <name>stop(FuncSpec) -> integer()</name>
- <name>stop(Mod, Func) -> integer()</name>
- <name>stop(Mod, Func, Arity) -> integer()</name>
+ <name since="">stop(FuncSpec) -> integer()</name>
+ <name since="">stop(Mod, Func) -> integer()</name>
+ <name since="">stop(Mod, Func, Arity) -> integer()</name>
<fsummary>Stop call count tracing for matching functions.</fsummary>
<type>
<v>FuncSpec = Mod | {Mod,Func,Arity}, {FS}</v>
diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml
index f098b7d39e..c9e4edd991 100644
--- a/lib/tools/doc/src/eprof.xml
+++ b/lib/tools/doc/src/eprof.xml
@@ -28,7 +28,7 @@
<date></date>
<rev></rev>
</header>
- <module>eprof</module>
+ <module since="">eprof</module>
<modulesummary>A Time Profiling Tool for Erlang</modulesummary>
<description>
<p>The module <c>eprof</c> provides a set of functions for time
@@ -40,7 +40,7 @@
</description>
<funcs>
<func>
- <name>start() -> {ok,Pid} | {error,Reason}</name>
+ <name since="">start() -> {ok,Pid} | {error,Reason}</name>
<fsummary>Start Eprof.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -51,9 +51,9 @@
</desc>
</func>
<func>
- <name>start_profiling(Rootset) -> profiling | {error, Reason}</name>
- <name>start_profiling(Rootset,Pattern) -> profiling | {error, Reason}</name>
- <name>start_profiling(Rootset,Pattern,Options) -> profiling | {error, Reason}</name>
+ <name since="">start_profiling(Rootset) -> profiling | {error, Reason}</name>
+ <name since="OTP R14B">start_profiling(Rootset,Pattern) -> profiling | {error, Reason}</name>
+ <name since="OTP R16B01">start_profiling(Rootset,Pattern,Options) -> profiling | {error, Reason}</name>
<fsummary>Start profiling.</fsummary>
<type>
<v>Rootset = [atom() | pid()]</v>
@@ -79,7 +79,7 @@
</desc>
</func>
<func>
- <name>stop_profiling() -> profiling_stopped | profiling_already_stopped</name>
+ <name since="">stop_profiling() -> profiling_stopped | profiling_already_stopped</name>
<fsummary>Stop profiling.</fsummary>
<desc>
<p>Stops profiling started with <c>start_profiling/1</c> or
@@ -87,14 +87,14 @@
</desc>
</func>
<func>
- <name>profile(Fun) -> profiling | {error, Reason}</name>
- <name>profile(Fun, Options) -> profiling | {error, Reason}</name>
- <name>profile(Rootset) -> profiling | {error, Reason}</name>
- <name>profile(Rootset,Fun) -> {ok, Value} | {error,Reason}</name>
- <name>profile(Rootset,Fun,Pattern) -> {ok, Value} | {error, Reason}</name>
- <name>profile(Rootset,Module,Function,Args) -> {ok, Value} | {error, Reason}</name>
- <name>profile(Rootset,Module,Function,Args,Pattern) -> {ok, Value} | {error, Reason}</name>
- <name>profile(Rootset,Module,Function,Args,Pattern,Options) -> {ok, Value} | {error, Reason}</name>
+ <name since="">profile(Fun) -> profiling | {error, Reason}</name>
+ <name since="">profile(Fun, Options) -> profiling | {error, Reason}</name>
+ <name since="">profile(Rootset) -> profiling | {error, Reason}</name>
+ <name since="">profile(Rootset,Fun) -> {ok, Value} | {error,Reason}</name>
+ <name since="OTP R14B">profile(Rootset,Fun,Pattern) -> {ok, Value} | {error, Reason}</name>
+ <name since="">profile(Rootset,Module,Function,Args) -> {ok, Value} | {error, Reason}</name>
+ <name since="OTP R14B">profile(Rootset,Module,Function,Args,Pattern) -> {ok, Value} | {error, Reason}</name>
+ <name since="OTP R16B01">profile(Rootset,Module,Function,Args,Pattern,Options) -> {ok, Value} | {error, Reason}</name>
<fsummary>Start profiling.</fsummary>
<type>
<v>Rootset = [atom() | pid()]</v>
@@ -128,9 +128,9 @@
</desc>
</func>
<func>
- <name>analyze() -> ok</name>
- <name>analyze(Type) -> ok</name>
- <name>analyze(Type,Options) -> ok</name>
+ <name since="OTP R14B">analyze() -> ok</name>
+ <name since="OTP R14B">analyze(Type) -> ok</name>
+ <name since="OTP R14B">analyze(Type,Options) -> ok</name>
<fsummary>Display profiling results per process.</fsummary>
<type>
<v>Type = procs | total</v>
@@ -152,7 +152,7 @@
</desc>
</func>
<func>
- <name>log(File) -> ok</name>
+ <name since="">log(File) -> ok</name>
<fsummary>Activate logging of <c>eprof</c>printouts.</fsummary>
<type>
<v>File = atom() | string()</v>
@@ -164,7 +164,7 @@
</desc>
</func>
<func>
- <name>stop() -> stopped</name>
+ <name since="">stop() -> stopped</name>
<fsummary>Stop Eprof.</fsummary>
<desc>
<p>Stops the Eprof server.</p>
diff --git a/lib/tools/doc/src/fprof.xml b/lib/tools/doc/src/fprof.xml
index 1fd828d127..4bb8862016 100644
--- a/lib/tools/doc/src/fprof.xml
+++ b/lib/tools/doc/src/fprof.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>fprof.sgml</file>
</header>
- <module>fprof</module>
+ <module since="">fprof</module>
<modulesummary>A Time Profiling Tool using trace to file for minimal runtime performance impact.</modulesummary>
<description>
<p>This module is used to profile a program
@@ -101,7 +101,7 @@
</description>
<funcs>
<func>
- <name>start() -> {ok, Pid} | {error, {already_started, Pid}}</name>
+ <name since="">start() -> {ok, Pid} | {error, {already_started, Pid}}</name>
<fsummary>Starts the <c>fprof</c>&nbsp;server.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -117,14 +117,14 @@
</desc>
</func>
<func>
- <name>stop() -> ok</name>
+ <name since="">stop() -> ok</name>
<fsummary>Same as <c>stop(normal)</c>.</fsummary>
<desc>
<p>Same as <c>stop(normal)</c>.</p>
</desc>
</func>
<func>
- <name>stop(Reason) -> ok</name>
+ <name since="">stop(Reason) -> ok</name>
<fsummary>Stops the <c>fprof</c>&nbsp;server.</fsummary>
<type>
<v>Reason = term()</v>
@@ -149,7 +149,7 @@
</desc>
</func>
<func>
- <name>apply(Func, Args) -> term()</name>
+ <name since="">apply(Func, Args) -> term()</name>
<fsummary>Same as <c>apply(Func, Args, [])</c>.</fsummary>
<type>
<v>Func = function() | {Module, Function}</v>
@@ -162,7 +162,7 @@
</desc>
</func>
<func>
- <name>apply(Module, Function, Args) -> term()</name>
+ <name since="">apply(Module, Function, Args) -> term()</name>
<fsummary>Same as <c>apply({Module, Function}, Args, [])</c>.</fsummary>
<type>
<v>Args = [term()]</v>
@@ -174,7 +174,7 @@
</desc>
</func>
<func>
- <name>apply(Func, Args, OptionList) -> term()</name>
+ <name since="">apply(Func, Args, OptionList) -> term()</name>
<fsummary>Calls <c>erlang:apply(Func, Args)</c>surrounded by<c>trace([start | OptionList])</c>and<c>trace(stop)</c>.</fsummary>
<type>
<v>Func = function() | {Module, Function}</v>
@@ -210,7 +210,7 @@
</desc>
</func>
<func>
- <name>apply(Module, Function, Args, OptionList) -> term()</name>
+ <name since="">apply(Module, Function, Args, OptionList) -> term()</name>
<fsummary>Same as <c>apply({Module, Function}, Args, OptionList)</c>.</fsummary>
<type>
<v>Module = atom()</v>
@@ -228,7 +228,7 @@
</desc>
</func>
<func>
- <name>trace(start, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">trace(start, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>trace([start, {file, Filename}])</c>.</fsummary>
<type>
<v>Reason = term()</v>
@@ -238,7 +238,7 @@
</desc>
</func>
<func>
- <name>trace(verbose, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">trace(verbose, Filename) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>trace([start, verbose, {file, Filename}])</c>.</fsummary>
<type>
<v>Reason = term()</v>
@@ -249,7 +249,7 @@
</desc>
</func>
<func>
- <name>trace(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">trace(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>trace([{OptionName, OptionValue}])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -262,7 +262,7 @@
</desc>
</func>
<func>
- <name>trace(verbose) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">trace(verbose) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>trace([start, verbose])</c>.</fsummary>
<type>
<v>Reason = term()</v>
@@ -272,7 +272,7 @@
</desc>
</func>
<func>
- <name>trace(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">trace(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>trace([OptionName])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -283,7 +283,7 @@
</desc>
</func>
<func>
- <name>trace({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">trace({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>trace([{OptionName, OptionValue}])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -296,7 +296,7 @@
</desc>
</func>
<func>
- <name>trace([Option]) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">trace([Option]) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Starts or stops tracing.</fsummary>
<type>
<v>Option = start | stop | {procs, PidSpec} | {procs, [PidSpec]} | verbose | {verbose, bool()} | file | {file, Filename} | {tracer, Tracer}</v>
@@ -360,7 +360,7 @@
</desc>
</func>
<func>
- <name>profile() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">profile() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>profile([])</c>.</fsummary>
<type>
<v>Reason = term()</v>
@@ -370,7 +370,7 @@
</desc>
</func>
<func>
- <name>profile(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">profile(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>profile([{OptionName, OptionValue}])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -383,7 +383,7 @@
</desc>
</func>
<func>
- <name>profile(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">profile(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>profile([OptionName])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -394,7 +394,7 @@
</desc>
</func>
<func>
- <name>profile({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">profile({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>profile([{OptionName, OptionValue}])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -407,7 +407,7 @@
</desc>
</func>
<func>
- <name>profile([Option]) -> ok | {ok, Tracer} | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">profile([Option]) -> ok | {ok, Tracer} | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Compiles a trace into raw profile data held by the <c>fprof</c>&nbsp;server.</fsummary>
<type>
<v>Option = file | {file, Filename} | dump | {dump, Dump} | append | start | stop</v>
@@ -465,7 +465,7 @@
</desc>
</func>
<func>
- <name>analyse() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">analyse() -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>analyse([])</c>.</fsummary>
<type>
<v>Reason = term()</v>
@@ -475,7 +475,7 @@
</desc>
</func>
<func>
- <name>analyse(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">analyse(OptionName, OptionValue) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>analyse([{OptionName, OptionValue}])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -488,7 +488,7 @@
</desc>
</func>
<func>
- <name>analyse(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">analyse(OptionName) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>analyse([OptionName])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -499,7 +499,7 @@
</desc>
</func>
<func>
- <name>analyse({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">analyse({OptionName, OptionValue}) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Same as <c>analyse([{OptionName, OptionValue}])</c>.</fsummary>
<type>
<v>OptionName = atom()</v>
@@ -512,7 +512,7 @@
</desc>
</func>
<func>
- <name>analyse([Option]) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
+ <name since="">analyse([Option]) -> ok | {error, Reason} | {'EXIT', ServerPid, Reason}</name>
<fsummary>Analyses raw profile data in the <c>fprof</c>&nbsp;server.</fsummary>
<type>
<v>Option = dest | {dest, Dest} | append | {cols, Cols} | callers | {callers, bool()} | no_callers | {sort, SortSpec} | totals | {totals, bool()} | details | {details, bool()} | no_details</v>
diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml
index 9fd9332373..75be22de9b 100644
--- a/lib/tools/doc/src/instrument.xml
+++ b/lib/tools/doc/src/instrument.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>instrument.sgml</file>
</header>
- <module>instrument</module>
+ <module since="">instrument</module>
<modulesummary>Analysis and Utility Functions for Instrumentation</modulesummary>
<description>
<p>The module <c>instrument</c> contains support for studying the resource
@@ -92,7 +92,7 @@
<funcs>
<func>
- <name name="allocations" arity="0"/>
+ <name name="allocations" arity="0" since="OTP 21.0"/>
<fsummary>Return a summary of all allocations in the system.</fsummary>
<desc>
<p>Shorthand for
@@ -101,7 +101,7 @@
</func>
<func>
- <name name="allocations" arity="1"/>
+ <name name="allocations" arity="1" since="OTP 21.0"/>
<fsummary>Return a summary of all allocations filtered by allocator type
and scheduler id.</fsummary>
<desc>
@@ -170,7 +170,7 @@
</func>
<func>
- <name name="carriers" arity="0"/>
+ <name name="carriers" arity="0" since="OTP 21.0"/>
<fsummary>Return a list of all carriers in the system.</fsummary>
<desc>
<p>Shorthand for
@@ -179,7 +179,7 @@
</func>
<func>
- <name name="carriers" arity="1"/>
+ <name name="carriers" arity="1" since="OTP 21.0"/>
<fsummary>Return a list of all carriers filtered by allocator type and
scheduler id.</fsummary>
<desc>
diff --git a/lib/tools/doc/src/lcnt.xml b/lib/tools/doc/src/lcnt.xml
index d2595cdb60..1d434decfc 100644
--- a/lib/tools/doc/src/lcnt.xml
+++ b/lib/tools/doc/src/lcnt.xml
@@ -34,7 +34,7 @@
<rev>PA1</rev>
<file>lcnt.xml</file>
</header>
- <module>lcnt</module>
+ <module since="OTP R13B04">lcnt</module>
<modulesummary>A runtime system Lock Profiling tool.</modulesummary>
<description>
<p>The <c>lcnt</c> module is used to profile the internal ethread locks in the
@@ -71,7 +71,7 @@
<funcs>
<func>
- <name>start() -> {ok, Pid} | {error, {already_started, Pid}} </name>
+ <name since="OTP R13B04">start() -> {ok, Pid} | {error, {already_started, Pid}} </name>
<fsummary>Starts the lock profiler server.</fsummary>
<type>
<v>Pid = pid()</v>
@@ -84,7 +84,7 @@
</func>
<func>
- <name>stop() -> ok</name>
+ <name since="OTP R13B04">stop() -> ok</name>
<fsummary>Stops the lock profiler server.</fsummary>
<desc>
<p>Stops the lock profiler server.</p>
@@ -92,13 +92,13 @@
</func>
<func>
- <name>collect() -> ok</name>
+ <name since="OTP R13B04">collect() -> ok</name>
<fsummary>Same as <c>collect(node())</c>.</fsummary>
<desc><p>Same as <c>collect(node())</c>.</p></desc>
</func>
<func>
- <name>collect(Node) -> ok</name>
+ <name since="OTP R13B04">collect(Node) -> ok</name>
<fsummary>Collects lock statistics from the runtime system.</fsummary>
<type>
<v>Node = node()</v>
@@ -113,13 +113,13 @@
</func>
<func>
- <name>clear() -> ok</name>
+ <name since="OTP R13B04">clear() -> ok</name>
<fsummary>Same as <c>clear(node())</c>.</fsummary>
<desc><p>Same as <c>clear(node())</c>.</p></desc>
</func>
<func>
- <name>clear(Node) -> ok</name>
+ <name since="OTP R13B04">clear(Node) -> ok</name>
<fsummary>Clears the internal lock statistics from runtime system.</fsummary>
<type>
<v>Node = node()</v>
@@ -133,12 +133,12 @@
</desc>
</func>
<func>
- <name>conflicts() -> ok</name>
+ <name since="OTP R13B04">conflicts() -> ok</name>
<fsummary>Same as <c>conflicts([])</c>.</fsummary>
<desc><p>Same as <c>conflicts([])</c>.</p></desc>
</func>
<func>
- <name>conflicts([Option]) -> ok</name>
+ <name since="OTP R13B04">conflicts([Option]) -> ok</name>
<fsummary>Prints a list of internal lock counters.</fsummary>
<type>
<v>Option = {sort, Sort} | {reverse, bool()} | {thresholds, [Thresholds]} | {print, [Print | {Print, integer()}]} | {max_locks, MaxLocks} | {combine, bool()}</v>
@@ -154,14 +154,14 @@
</func>
<func>
- <name>locations() -> ok</name>
+ <name since="OTP R13B04">locations() -> ok</name>
<fsummary>Same as <c>locations([])</c>.</fsummary>
<desc>
<p>Same as <c>locations([])</c>.</p>
</desc>
</func>
<func>
- <name>locations([Option]) -> ok</name>
+ <name since="OTP R13B04">locations([Option]) -> ok</name>
<fsummary>Prints a list of internal lock counters by source code locations.</fsummary>
<type>
<v>Option = {sort, Sort} | {thresholds, [Thresholds]} | {print, [Print | {Print, integer()}]} | {max_locks, MaxLocks} | {combine, bool()}</v>
@@ -177,12 +177,12 @@
</func>
<func>
- <name>inspect(Lock) -> ok</name>
+ <name since="OTP R13B04">inspect(Lock) -> ok</name>
<fsummary>Same as <c>inspect(Lock, [])</c>.</fsummary>
<desc><p>Same as <c>inspect(Lock, [])</c>.</p></desc>
</func>
<func>
- <name>inspect(Lock, [Option]) -> ok</name>
+ <name since="OTP R13B04">inspect(Lock, [Option]) -> ok</name>
<fsummary>Prints a list of internal lock counters for a specific lock.</fsummary>
<type>
<v>Lock = Name | {Name, Id | [Id]}</v>
@@ -268,7 +268,7 @@
</func>
<func>
- <name>information() -> ok</name>
+ <name since="OTP R13B04">information() -> ok</name>
<fsummary>Prints lcnt server state and generic information about collected lock statistics.</fsummary>
<desc>
<p>Prints lcnt server state and generic information about collected lock statistics.</p>
@@ -276,7 +276,7 @@
</func>
<func>
- <name>swap_pid_keys() -> ok</name>
+ <name since="OTP R13B04">swap_pid_keys() -> ok</name>
<fsummary>Swaps places on <c>Name</c> and <c>Id</c> space for ports and processes.</fsummary>
<desc>
<p>Swaps places on <c>Name</c> and <c>Id</c> space for ports and processes.</p>
@@ -284,7 +284,7 @@
</func>
<func>
- <name>load(Filename) -> ok</name>
+ <name since="OTP R13B04">load(Filename) -> ok</name>
<fsummary>Restores previously saved data to the server.</fsummary>
<type>
<v>Filename = filename()</v>
@@ -295,7 +295,7 @@
</func>
<func>
- <name>save(Filename) -> ok</name>
+ <name since="OTP R13B04">save(Filename) -> ok</name>
<fsummary>Saves the collected data to file.</fsummary>
<type>
<v>Filename = filename()</v>
@@ -312,7 +312,7 @@
</section>
<funcs>
<func>
- <name>apply(Fun) -> term()</name>
+ <name since="OTP R13B04">apply(Fun) -> term()</name>
<fsummary>Same as <c>apply(Fun, [])</c>.</fsummary>
<type>
<v>Fun = fun()</v>
@@ -322,7 +322,7 @@
</desc>
</func>
<func>
- <name>apply(Fun, Args) -> term()</name>
+ <name since="OTP R13B04">apply(Fun, Args) -> term()</name>
<fsummary>Same as <c>apply(Module, Function, Args)</c>.</fsummary>
<type>
<v>Fun = fun()</v>
@@ -333,7 +333,7 @@
</desc>
</func>
<func>
- <name>apply(Module, Function, Args) -> term()</name>
+ <name since="OTP R13B04">apply(Module, Function, Args) -> term()</name>
<fsummary>Clears counters, applies function and collects the profiling results.</fsummary>
<type>
<v>Module = atom()</v>
@@ -358,12 +358,12 @@
</func>
<func>
- <name>pid(Id, Serial) -> pid()</name>
+ <name since="OTP R13B04">pid(Id, Serial) -> pid()</name>
<fsummary>Same as <c>pid(node(), Id, Serial)</c>.</fsummary>
<desc><p>Same as <c>pid(node(), Id, Serial)</c>.</p></desc>
</func>
<func>
- <name>pid(Node, Id, Serial) -> pid()</name>
+ <name since="OTP R13B04">pid(Node, Id, Serial) -> pid()</name>
<fsummary>Creates a process id with creation 0.</fsummary>
<type>
<v>Node = node()</v>
@@ -376,12 +376,12 @@
</func>
<func>
- <name>port(Id) -> port()</name>
+ <name since="OTP R13B04">port(Id) -> port()</name>
<fsummary>Same as <c>port(node(), Id)</c>.</fsummary>
<desc><p>Same as <c>port(node(), Id)</c>.</p></desc>
</func>
<func>
- <name>port(Node, Id) -> port()</name>
+ <name since="OTP R13B04">port(Node, Id) -> port()</name>
<fsummary>Creates a port id with creation 0.</fsummary>
<type>
<v>Node = node()</v>
@@ -399,12 +399,12 @@
<funcs>
<func>
- <name>rt_collect() -> [lock_counter_data()]</name>
+ <name since="OTP R13B04">rt_collect() -> [lock_counter_data()]</name>
<fsummary>Same as <c>rt_collect(node())</c>.</fsummary>
<desc> <p>Same as <c>rt_collect(node())</c>.</p> </desc>
</func>
<func>
- <name>rt_collect(Node) -> [lock_counter_data()]</name>
+ <name since="OTP R13B04">rt_collect(Node) -> [lock_counter_data()]</name>
<fsummary>Returns a list of raw lock counter data.</fsummary>
<type>
<v>Node = node()</v>
@@ -413,12 +413,12 @@
</func>
<func>
- <name>rt_clear() -> ok</name>
+ <name since="OTP R13B04">rt_clear() -> ok</name>
<fsummary>Same as <c>rt_clear(node())</c>.</fsummary>
<desc> <p>Same as <c>rt_clear(node())</c>.</p> </desc>
</func>
<func>
- <name>rt_clear(Node) -> ok</name>
+ <name since="OTP R13B04">rt_clear(Node) -> ok</name>
<fsummary>Clears the internal counters.</fsummary>
<type>
<v>Node = node()</v>
@@ -427,13 +427,13 @@
</func>
<func>
- <name>rt_mask() -> [category_atom()]</name>
+ <name since="OTP 20.1">rt_mask() -> [category_atom()]</name>
<fsummary>Same as <c>rt_mask(node())</c>.</fsummary>
<desc><p>Same as <c>rt_mask(node())</c>.</p></desc>
</func>
<func>
- <name>rt_mask(Node) -> [category_atom()]</name>
+ <name since="OTP 20.1">rt_mask(Node) -> [category_atom()]</name>
<fsummary>Returns the current lock category mask.</fsummary>
<type>
<v>Node = node()</v>
@@ -447,7 +447,7 @@
</func>
<func>
- <name>rt_mask(Categories) -> ok | {error, copy_save_enabled}</name>
+ <name since="OTP 20.1">rt_mask(Categories) -> ok | {error, copy_save_enabled}</name>
<fsummary>Same as <c>rt_mask(node(), Categories)</c>.</fsummary>
<type>
<v>Categories = [atom()]</v>
@@ -456,7 +456,7 @@
</func>
<func>
- <name>rt_mask(Node, Categories) -> ok | {error, copy_save_enabled}</name>
+ <name since="OTP 20.1">rt_mask(Node, Categories) -> ok | {error, copy_save_enabled}</name>
<fsummary>Changes the lock category mask.</fsummary>
<type>
<v>Node = node()</v>
@@ -489,12 +489,12 @@
</func>
<func>
- <name>rt_opt({Type, bool()}) -> bool()</name>
+ <name since="OTP R13B04">rt_opt({Type, bool()}) -> bool()</name>
<fsummary>Same as <c>rt_opt(node(), {Type, Opt})</c>.</fsummary>
<desc> <p>Same as <c>rt_opt(node(), {Type, Opt})</c>.</p> </desc>
</func>
<func>
- <name>rt_opt(Node, {Type, bool()}) -> bool()</name>
+ <name since="OTP R13B04">rt_opt(Node, {Type, bool()}) -> bool()</name>
<fsummary>Changes the lock counter behavior and returns the previous behaviour.</fsummary>
<type>
<v>Node = node()</v>
diff --git a/lib/tools/doc/src/make.xml b/lib/tools/doc/src/make.xml
index 123fcd4afc..af2404707f 100644
--- a/lib/tools/doc/src/make.xml
+++ b/lib/tools/doc/src/make.xml
@@ -30,7 +30,7 @@
<date></date>
<rev></rev>
</header>
- <module>make</module>
+ <module since="">make</module>
<modulesummary>A Make Utility for Erlang</modulesummary>
<description>
<p>The module <c>make</c> provides a set of functions similar to
@@ -38,8 +38,8 @@
</description>
<funcs>
<func>
- <name>all() -> up_to_date | error</name>
- <name>all(Options) -> up_to_date | error</name>
+ <name since="">all() -> up_to_date | error</name>
+ <name since="">all(Options) -> up_to_date | error</name>
<fsummary>Compile a set of modules.</fsummary>
<type>
<v>Options = [Option]</v>
@@ -87,8 +87,8 @@
</desc>
</func>
<func>
- <name>files(ModFiles) -> up_to_date | error</name>
- <name>files(ModFiles, Options) -> up_to_date | error</name>
+ <name since="">files(ModFiles) -> up_to_date | error</name>
+ <name since="">files(ModFiles, Options) -> up_to_date | error</name>
<fsummary>Compile a set of modules.</fsummary>
<type>
<v>ModFiles = [Module | File]</v>
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 8b0a2ca283..faae48f72d 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -31,6 +31,97 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 3.1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>cover</c> would fail to start if two processes
+ tried to start it at the exact same time.</p>
+ <p>
+ Own Id: OTP-15813 Aux Id: ERL-943 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Minor fixes for <c>make clean</c>.</p>
+ <p>
+ Own Id: OTP-15657</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ In the HTML file generated by
+ <c>cover:analyse_to_file/1,2</c>, a link is now added to
+ the line number. This makes it easier to share pointers
+ to specific lines.</p>
+ <p>
+ Own Id: OTP-15541</p>
+ </item>
+ <item>
+ <p>
+ Uncovered lines are now marked with a sad face,
+ <c>:-(</c>, in the HTML output from
+ <c>cover:analyse_to_file/1,2</c>. This is to make these
+ lines easier to find by search.</p>
+ <p>
+ Own Id: OTP-15542</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 3.0.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Remove emacs warnings and added more tests.</p>
+ <p>
+ Own Id: OTP-15476</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 3.0.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The HTML pages generated by cover:analyse_to_file/1 and
+ related functions is improved for readability.</p>
+ <p>
+ Own Id: OTP-15213 Aux Id: PR-1807 </p>
+ </item>
+ <item>
+ <p>
+ Add alignment functionality in emacs.</p>
+ <p>
+ Own Id: OTP-15239 Aux Id: PR-1728 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 3.0</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/tools/doc/src/tags.xml b/lib/tools/doc/src/tags.xml
index ea0ae5cc4d..90a8b28177 100644
--- a/lib/tools/doc/src/tags.xml
+++ b/lib/tools/doc/src/tags.xml
@@ -32,7 +32,7 @@
<rev>A</rev>
<file>tags.sgml</file>
</header>
- <module>tags</module>
+ <module since="">tags</module>
<modulesummary>Generate Emacs TAGS file from Erlang source files</modulesummary>
<description>
<p>A <c>TAGS</c> file is used by Emacs to find function and variable
@@ -42,14 +42,14 @@
</description>
<funcs>
<func>
- <name>file(File [, Options])</name>
+ <name since="">file(File [, Options])</name>
<fsummary>Create a <c>TAGS</c>file for the file <c>File</c>.</fsummary>
<desc>
<p>Create a <c>TAGS</c> file for the file <c>File</c>.</p>
</desc>
</func>
<func>
- <name>files(FileList [, Options])</name>
+ <name since="">files(FileList [, Options])</name>
<fsummary>Create a TAGS file for the files in the list<c>FileList</c>.</fsummary>
<desc>
<p>Create a TAGS file for the files in the list
@@ -57,7 +57,7 @@
</desc>
</func>
<func>
- <name>dir(Dir [, Options])</name>
+ <name since="">dir(Dir [, Options])</name>
<fsummary>Create a TAGS file for all files in directory<c>Dir</c>.</fsummary>
<desc>
<p>Create a TAGS file for all files in directory
@@ -65,7 +65,7 @@
</desc>
</func>
<func>
- <name>dirs(DirList [, Options])</name>
+ <name since="">dirs(DirList [, Options])</name>
<fsummary>Create a TAGS file for all files in any directory in<c>DirList</c>.</fsummary>
<desc>
<p>Create a TAGS file for all files in any directory in
@@ -73,7 +73,7 @@
</desc>
</func>
<func>
- <name>subdir(Dir [, Options])</name>
+ <name since="">subdir(Dir [, Options])</name>
<fsummary>Descend recursively down the directory <c>Dir</c>and create a <c>TAGS</c>file based on all files found.</fsummary>
<desc>
<p>Descend recursively down the directory <c>Dir</c> and
@@ -81,7 +81,7 @@
</desc>
</func>
<func>
- <name>subdirs(DirList [, Options])</name>
+ <name since="">subdirs(DirList [, Options])</name>
<fsummary>Descend recursively down all the directories in<c>DirList</c>and create a <c>TAGS</c>file based on all files found.</fsummary>
<desc>
<p>Descend recursively down all the directories in
@@ -90,7 +90,7 @@
</desc>
</func>
<func>
- <name>root([Options])</name>
+ <name since="">root([Options])</name>
<fsummary>Create a <c>TAGS</c>file covering all files in the Erlang distribution.</fsummary>
<desc>
<p>Create a <c>TAGS</c> file covering all files in
diff --git a/lib/tools/doc/src/xref.xml b/lib/tools/doc/src/xref.xml
index 6f833246ad..ab3641a52f 100644
--- a/lib/tools/doc/src/xref.xml
+++ b/lib/tools/doc/src/xref.xml
@@ -32,7 +32,7 @@
<rev>PA1</rev>
<file>xref.sgml</file>
</header>
- <module>xref</module>
+ <module since="">xref</module>
<modulesummary>A Cross Reference Tool for analyzing dependencies between functions, modules, applications and releases.</modulesummary>
<description>
<p>Xref is a cross reference tool that can be used for finding
@@ -729,7 +729,7 @@ xref() = atom() | pid() </pre>
</description>
<funcs>
<func>
- <name>add_application(Xref, Directory [, Options]) -> {ok, application()} | Error</name>
+ <name since="">add_application(Xref, Directory [, Options]) -> {ok, application()} | Error</name>
<fsummary>Add the modules of an application.</fsummary>
<type>
<v>Directory = directory()</v>
@@ -761,7 +761,7 @@ xref() = atom() | pid() </pre>
</desc>
</func>
<func>
- <name>add_directory(Xref, Directory [, Options]) -> {ok, Modules} | Error</name>
+ <name since="">add_directory(Xref, Directory [, Options]) -> {ok, Modules} | Error</name>
<fsummary>Add the modules in a directory.</fsummary>
<type>
<v>Directory = directory()</v>
@@ -791,7 +791,7 @@ xref() = atom() | pid() </pre>
</desc>
</func>
<func>
- <name>add_module(Xref, File [, Options]) -> {ok, module()} | Error</name>
+ <name since="">add_module(Xref, File [, Options]) -> {ok, module()} | Error</name>
<fsummary>Add a module.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -814,7 +814,7 @@ xref() = atom() | pid() </pre>
</desc>
</func>
<func>
- <name>add_release(Xref, Directory [, Options]) -> {ok, release()} | Error</name>
+ <name since="">add_release(Xref, Directory [, Options]) -> {ok, release()} | Error</name>
<fsummary>Add the modules of a release.</fsummary>
<type>
<v>Directory = directory()</v>
@@ -849,7 +849,7 @@ xref() = atom() | pid() </pre>
</desc>
</func>
<func>
- <name>analyze(Xref, Analysis [, Options]) -> {ok, Answer} | Error</name>
+ <name since="">analyze(Xref, Analysis [, Options]) -> {ok, Answer} | Error</name>
<fsummary>Evaluate a predefined analysis.</fsummary>
<type>
<v>Analysis = undefined_function_calls | undefined_functions | locals_not_used | exports_not_used | deprecated_function_calls | {deprecated_function_calls, DeprFlag} | deprecated_functions | {deprecated_functions, DeprFlag} | {call, FuncSpec} | {use, FuncSpec} | {module_call, ModSpec} | {module_use, ModSpec} | {application_call, AppSpec} | {application_use, AppSpec} | {release_call, RelSpec} | {release_use, RelSpec}</v>
@@ -939,7 +939,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>d(Directory) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name>
+ <name since="">d(Directory) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name>
<fsummary>Check the modules in a directory using the code path.</fsummary>
<type>
<v>Directory = directory()</v>
@@ -979,8 +979,8 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>forget(Xref) -> ok</name>
- <name>forget(Xref, Variables) -> ok | Error</name>
+ <name since="">forget(Xref) -> ok</name>
+ <name since="">forget(Xref, Variables) -> ok | Error</name>
<fsummary>Remove user variables and their values.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -994,7 +994,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>format_error(Error) -> Chars</name>
+ <name since="">format_error(Error) -> Chars</name>
<fsummary>Return an English description of an Xref error reply.</fsummary>
<type>
<v>Error = {error, module(), term()}</v>
@@ -1008,8 +1008,8 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>get_default(Xref) -> [{Option, Value}]</name>
- <name>get_default(Xref, Option) -> {ok, Value} | Error</name>
+ <name since="">get_default(Xref) -> [{Option, Value}]</name>
+ <name since="">get_default(Xref, Option) -> {ok, Value} | Error</name>
<fsummary>Return the default values of options.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -1023,7 +1023,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>get_library_path(Xref) -> {ok, LibraryPath}</name>
+ <name since="">get_library_path(Xref) -> {ok, LibraryPath}</name>
<fsummary>Return the library path.</fsummary>
<type>
<v>LibraryPath = library_path()</v>
@@ -1034,9 +1034,9 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>info(Xref) -> [Info]</name>
- <name>info(Xref, Category) -> [{Item, [Info]}]</name>
- <name>info(Xref, Category, Items) -> [{Item, [Info]}]</name>
+ <name since="">info(Xref) -> [Info]</name>
+ <name since="">info(Xref, Category) -> [{Item, [Info]}]</name>
+ <name since="">info(Xref, Category, Items) -> [{Item, [Info]}]</name>
<fsummary>Return information about an Xref server.</fsummary>
<type>
<v>Application = [] | [application()]</v>
@@ -1220,8 +1220,8 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>m(Module) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name>
- <name>m(File) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name>
+ <name since="">m(Module) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name>
+ <name since="">m(File) -> [DebugInfoResult] | [NoDebugInfoResult] | Error</name>
<fsummary>Check a module using the code path.</fsummary>
<type>
<v>DebugInfoResult = {deprecated, [funcall()]} | {undefined, [funcall()]} | {unused, [mfa()]}</v>
@@ -1263,7 +1263,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>q(Xref, Query [, Options]) -> {ok, Answer} | Error</name>
+ <name since="">q(Xref, Query [, Options]) -> {ok, Answer} | Error</name>
<fsummary>Evaluate a query.</fsummary>
<type>
<v>Answer = false | [constant()] | [Call] | [Component] | int() | [DefineAt] | [CallAt] | [AllLines]</v>
@@ -1322,7 +1322,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>remove_application(Xref, Applications) -> ok | Error</name>
+ <name since="">remove_application(Xref, Applications) -> ok | Error</name>
<fsummary>Remove applications and their modules.</fsummary>
<type>
<v>Applications = application() | [application()]</v>
@@ -1335,7 +1335,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>remove_module(Xref, Modules) -> ok | Error</name>
+ <name since="">remove_module(Xref, Modules) -> ok | Error</name>
<fsummary>Remove analyzed modules.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -1348,7 +1348,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>remove_release(Xref, Releases) -> ok | Error</name>
+ <name since="">remove_release(Xref, Releases) -> ok | Error</name>
<fsummary>Remove releases and their applications and modules.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -1363,7 +1363,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>replace_application(Xref, Application, Directory [, Options]) -> {ok, application()} | Error</name>
+ <name since="">replace_application(Xref, Application, Directory [, Options]) -> {ok, application()} | Error</name>
<fsummary>Replace an application's modules.</fsummary>
<type>
<v>Application = application()</v>
@@ -1384,7 +1384,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>replace_module(Xref, Module, File [, Options]) -> {ok, module()} | Error</name>
+ <name since="">replace_module(Xref, Module, File [, Options]) -> {ok, module()} | Error</name>
<fsummary>Replace an analyzed module.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -1409,8 +1409,8 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>set_default(Xref, Option, Value) -> {ok, OldValue} | Error</name>
- <name>set_default(Xref, OptionValues) -> ok | Error</name>
+ <name since="">set_default(Xref, Option, Value) -> {ok, OldValue} | Error</name>
+ <name since="">set_default(Xref, OptionValues) -> ok | Error</name>
<fsummary>Set the default values of options.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -1435,7 +1435,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>set_library_path(Xref, LibraryPath [, Options]) -> ok | Error</name>
+ <name since="">set_library_path(Xref, LibraryPath [, Options]) -> ok | Error</name>
<fsummary>Set the library path and finds the library modules.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -1469,7 +1469,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>start(NameOrOptions) -> Return</name>
+ <name since="">start(NameOrOptions) -> Return</name>
<fsummary>Create an Xref server.</fsummary>
<type>
<v>NameOrOptions = Name | Options</v>
@@ -1487,7 +1487,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>start(Name, Options) -> Return</name>
+ <name since="">start(Name, Options) -> Return</name>
<fsummary>Create an Xref server.</fsummary>
<type>
<v>Name = atom()</v>
@@ -1504,7 +1504,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>stop(Xref)</name>
+ <name since="">stop(Xref)</name>
<fsummary>Delete an Xref server.</fsummary>
<type>
<v>Xref = xref()</v>
@@ -1514,7 +1514,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>update(Xref [, Options]) -> {ok, Modules} | Error</name>
+ <name since="">update(Xref [, Options]) -> {ok, Modules} | Error</name>
<fsummary>Replace newly compiled analyzed modules.</fsummary>
<type>
<v>Error = {error, module(), Reason}</v>
@@ -1534,7 +1534,7 @@ Evaluates a predefined analysis.
</desc>
</func>
<func>
- <name>variables(Xref [, Options]) -> {ok, [VariableInfo]}</name>
+ <name since="">variables(Xref [, Options]) -> {ok, [VariableInfo]}</name>
<fsummary>Return the names of variables.</fsummary>
<type>
<v>Options = [Option] | Option</v>
diff --git a/lib/tools/emacs/Makefile b/lib/tools/emacs/Makefile
index ea4d6cb723..b7775d1c8c 100644
--- a/lib/tools/emacs/Makefile
+++ b/lib/tools/emacs/Makefile
@@ -46,6 +46,7 @@ EMACS_FILES= \
erlang-eunit \
erlang-edoc \
erlang-flymake \
+ erlang-test \
erlang
README_FILES= README
diff --git a/lib/tools/emacs/erlang-edoc.el b/lib/tools/emacs/erlang-edoc.el
index d0dcc81028..ea1e263faf 100644
--- a/lib/tools/emacs/erlang-edoc.el
+++ b/lib/tools/emacs/erlang-edoc.el
@@ -28,6 +28,7 @@
(defcustom erlang-edoc-indent-level 2
"Indentation level of xhtml in Erlang edoc."
+ :type '(integer)
:safe 'integerp
:group 'erlang)
diff --git a/lib/tools/emacs/erlang-eunit.el b/lib/tools/emacs/erlang-eunit.el
index 38c40927f4..53543d7b01 100644
--- a/lib/tools/emacs/erlang-eunit.el
+++ b/lib/tools/emacs/erlang-eunit.el
@@ -23,6 +23,7 @@
(eval-when-compile
(require 'cl))
+(require 'erlang)
(defvar erlang-eunit-src-candidate-dirs '("../src" ".")
"*Name of directories which to search for source files matching
@@ -331,8 +332,7 @@ With prefix arg, compiles for debug and runs tests with the verbose flag set."
t)
(apply test-fun test-args)
(if under-cover
- (save-excursion
- (set-buffer (find-file-noselect src-filename))
+ (with-current-buffer (find-file-noselect src-filename)
(erlang-eunit-analyze-coverage)))))))
(defun erlang-eunit-compile-and-run-module-tests-under-cover ()
@@ -348,8 +348,7 @@ With prefix arg, compiles for debug and runs tests with the verbose flag set."
(defun erlang-eunit-compile-file (file-path &optional under-cover)
(if (file-readable-p file-path)
- (save-excursion
- (set-buffer (find-file-noselect file-path))
+ (with-current-buffer (find-file-noselect file-path)
;; In order to run a code coverage analysis on a
;; module, we have two options:
;;
@@ -376,8 +375,7 @@ With prefix arg, compiles for debug and runs tests with the verbose flag set."
(error msg))))
(defun erlang-eunit-last-compilation-successful-p ()
- (save-excursion
- (set-buffer inferior-erlang-buffer)
+ (with-current-buffer inferior-erlang-buffer
(goto-char compilation-parsing-end)
(erlang-eunit-all-list-elems-fulfill-p
(lambda (re) (let ((continue t)
diff --git a/lib/tools/emacs/erlang-pkg.el b/lib/tools/emacs/erlang-pkg.el
index 02d6bebbf4..7e95e4050e 100644
--- a/lib/tools/emacs/erlang-pkg.el
+++ b/lib/tools/emacs/erlang-pkg.el
@@ -1,3 +1,6 @@
(define-package "erlang" "2.7.0"
"Erlang major mode"
'((emacs "24.1")))
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/lib/tools/emacs/erlang-skels.el b/lib/tools/emacs/erlang-skels.el
index 534f50ab33..3ebc6e8e1e 100644
--- a/lib/tools/emacs/erlang-skels.el
+++ b/lib/tools/emacs/erlang-skels.el
@@ -1985,7 +1985,7 @@ configured off."
The first character of DD is space if the value is less than 10."
(let ((date (current-time-string)))
(format "%2d %s %s"
- (string-to-int (substring date 8 10))
+ (string-to-number (substring date 8 10))
(substring date 4 7)
(substring date -4))))
diff --git a/lib/tools/emacs/erlang-test.el b/lib/tools/emacs/erlang-test.el
index efe3d515e9..2ee584d11a 100644
--- a/lib/tools/emacs/erlang-test.el
+++ b/lib/tools/emacs/erlang-test.el
@@ -29,7 +29,7 @@
;; This library require GNU Emacs 25 or later.
;;
-;; There are two ways to run emacs unit tests.
+;; There are three ways to run the erlang emacs unit tests.
;;
;; 1. Within a running emacs process. Load this file. Then to run
;; all defined test cases:
@@ -49,11 +49,15 @@
;;
;; The -L option adds a directory to the load-path. It should be the
;; directory containing erlang.el and erlang-test.el.
+;;
+;; 3. Call the script test-erlang-mode in this directory. This script
+;; use the second method.
;;; Code:
+(eval-when-compile
+ (require 'cl))
(require 'ert)
-(require 'cl-lib)
(require 'erlang)
(defvar erlang-test-code
@@ -63,7 +67,7 @@
("SYMBOL" . "-define(SYMBOL, value).")
("MACRO" . "-define(MACRO(X), X + X).")
("struct" . "-record(struct, {until,maps,are,everywhere}).")
- ("function". "function() -> #struct{}."))
+ ("function" . "function() -> #struct{}."))
"Alist of erlang test code.
Each entry have the format (TAGNAME . ERLANG_CODE). If TAGNAME
is nil there is no definitions in the ERLANG_CODE. The
@@ -116,8 +120,8 @@ concatenated to form an erlang file to test on.")
(defun erlang-test-create-erlang-file (erlang-file)
(with-temp-file erlang-file
- (cl-loop for (_ . code) in erlang-test-code
- do (insert code "\n"))))
+ (loop for (_ . code) in erlang-test-code
+ do (insert code "\n"))))
(defun erlang-test-compile-tags (erlang-file tags-file)
(should (zerop (call-process "etags" nil nil nil
@@ -132,19 +136,20 @@ concatenated to form an erlang file to test on.")
(sort (erlang-expected-completion-table) #'string-lessp))))
(defun erlang-expected-completion-table ()
- (append (cl-loop for (symbol . _) in erlang-test-code
- when (stringp symbol)
- append (list symbol (concat "erlang_test:" symbol)))
+ (append (loop for (symbol . _) in erlang-test-code
+ when (stringp symbol)
+ append (list symbol (concat "erlang_test:" symbol)))
(list "erlang_test:" "erlang_test:module_info")))
(defun erlang-test-xref-find-definitions (erlang-file erlang-buffer)
- (cl-loop for (tagname . code) in erlang-test-code
- for line = 1 then (1+ line)
- do (when tagname
- (switch-to-buffer erlang-buffer)
- (erlang-test-xref-jump tagname erlang-file line)
- (erlang-test-xref-jump (concat "erlang_test:" tagname)
- erlang-file line)))
+ (loop for (tagname . code) in erlang-test-code
+ for line = 1 then (1+ line)
+ do (when tagname
+ (switch-to-buffer erlang-buffer)
+ (erlang-test-xref-jump tagname erlang-file line)
+ (when (string-equal tagname "function")
+ (erlang-test-xref-jump (concat "erlang_test:" tagname)
+ erlang-file line))))
(erlang-test-xref-jump "erlang_test:" erlang-file 1))
(defun erlang-test-xref-jump (id expected-file expected-line)
@@ -213,27 +218,27 @@ concatenated to form an erlang file to test on.")
(ert-deftest erlang-test-parse-id ()
- (cl-loop for id-string in '("fun/10"
- "qualified-function module:fun/10"
- "record reko"
- "macro _SYMBOL"
- "macro MACRO/10"
- "module modula"
- "macro"
- nil)
- for id-list in '((nil nil "fun" 10)
- (qualified-function "module" "fun" 10)
- (record nil "reko" nil)
- (macro nil "_SYMBOL" nil)
- (macro nil "MACRO" 10)
- (module nil "modula" nil)
- (nil nil "macro" nil)
- nil)
- for id-list2 = (erlang-id-to-list id-string)
- do (should (equal id-list id-list2))
- for id-string2 = (erlang-id-to-string id-list)
- do (should (equal id-string id-string2))
- collect id-list2))
+ (loop for id-string in '("fun/10"
+ "qualified-function module:fun/10"
+ "record reko"
+ "macro _SYMBOL"
+ "macro MACRO/10"
+ "module modula"
+ "macro"
+ nil)
+ for id-list in '((nil nil "fun" 10)
+ (qualified-function "module" "fun" 10)
+ (record nil "reko" nil)
+ (macro nil "_SYMBOL" nil)
+ (macro nil "MACRO" 10)
+ (module nil "modula" nil)
+ (nil nil "macro" nil)
+ nil)
+ for id-list2 = (erlang-id-to-list id-string)
+ do (should (equal id-list id-list2))
+ for id-string2 = (erlang-id-to-string id-list)
+ do (should (equal id-string id-string2))
+ collect id-list2))
(provide 'erlang-test)
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 3211132254..3cbe9daa60 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -77,6 +77,9 @@
;;; Code:
(eval-when-compile (require 'cl))
+(require 'align)
+(require 'comint)
+(require 'tempo)
;; Variables:
@@ -333,6 +336,7 @@ when a new function header is generated. When nil, no blank line is
inserted between the current line and the new header. When bound to a
number it represents the number of blank lines which should be
inserted."
+ :type '(restricted-sexp :match-alternatives (integerp 'nil))
:group 'erlang)
(defvar erlang-electric-semicolon-criteria
@@ -1405,6 +1409,19 @@ Other commands:
(add-function :before-until (local 'eldoc-documentation-function)
#'erldoc-eldoc-function))
(run-hooks 'erlang-mode-hook)
+
+ ;; Align maps.
+ (add-to-list 'align-rules-list
+ '(erlang-maps
+ (regexp . "\\(\\s-*\\)\\(=>\\)\\s-*")
+ (modes . '(erlang-mode))
+ (repeat . t)))
+ ;; Align records and :: specs
+ (add-to-list 'align-rules-list
+ '(erlang-record-specs
+ (regexp . "\\(\\s-*\\)\\(=\\).*\\(::\\)*\\s-*")
+ (modes . '(erlang-mode))
+ (repeat . t)))
(if (zerop (buffer-size))
(run-hooks 'erlang-new-file-hook)))
@@ -1697,10 +1714,10 @@ Personal extensions could be added to `erlang-menu-personal-items'.
This function should be called if any variable describing the
menu configuration is changed."
- (erlang-menu-install "Erlang" erlang-menu-items erlang-mode-map t))
+ (erlang-menu-install "Erlang" erlang-menu-items erlang-mode-map))
-(defun erlang-menu-install (name items keymap &optional popup)
+(defun erlang-menu-install (name items keymap)
"Install a menu in Emacs based on an abstract description.
NAME is the name of the menu.
@@ -3680,16 +3697,17 @@ retried without regard to module.
4. Arity - Integer in case of functions and macros if the number
of arguments could be found, otherwise nil."
(save-excursion
- (save-match-data
- (if (eq (char-syntax (following-char)) ? )
- (skip-chars-backward " \t"))
- (skip-chars-backward "[:word:]_:'")
- (cond ((looking-at erlang-module-function-regexp)
- (erlang-get-qualified-function-id-at-point))
- ((looking-at (concat erlang-atom-regexp ":"))
- (erlang-get-module-id-at-point))
- ((looking-at erlang-name-regexp)
- (erlang-get-some-other-id-at-point))))))
+ (let (case-fold-search)
+ (save-match-data
+ (if (eq (char-syntax (following-char)) ? )
+ (skip-chars-backward " \t"))
+ (skip-chars-backward "[:word:]_:'")
+ (cond ((looking-at erlang-module-function-regexp)
+ (erlang-get-qualified-function-id-at-point))
+ ((looking-at (concat erlang-atom-regexp ":"))
+ (erlang-get-module-id-at-point))
+ ((looking-at erlang-name-regexp)
+ (erlang-get-some-other-id-at-point)))))))
(defun erlang-get-qualified-function-id-at-point ()
(let ((kind 'qualified-function)
@@ -4193,22 +4211,18 @@ Return t if criteria fulfilled, nil otherwise."
nil)))))
-(defun erlang-in-literal (&optional lim)
+(defun erlang-in-literal ()
"Test if point is in string, quoted atom or comment.
Return one of the three atoms `atom', `string', and `comment'.
Should the point be inside none of the above mentioned types of
context, nil is returned."
(save-excursion
- (let* ((lim (or lim (save-excursion
- (erlang-beginning-of-clause)
- (point))))
- (state (funcall (symbol-function 'syntax-ppss))))
- (cond
- ((eq (nth 3 state) ?') 'atom)
- ((nth 3 state) 'string)
- ((nth 4 state) 'comment)
- (t nil)))))
+ (let ((state (funcall (symbol-function 'syntax-ppss))))
+ (cond ((eq (nth 3 state) ?') 'atom)
+ ((nth 3 state) 'string)
+ ((nth 4 state) 'comment)
+ (t nil)))))
(defun erlang-at-end-of-function-p ()
@@ -5027,7 +5041,10 @@ considered first when it is time to jump to the definition.")
(defun erlang-visit-tags-table-buffer (cont cbuf)
(if (< emacs-major-version 26)
(visit-tags-table-buffer cont)
- (visit-tags-table-buffer cont cbuf)))
+ ;; Remove this with-no-warnings when Emacs 26 is the required
+ ;; version minimum.
+ (with-no-warnings
+ (visit-tags-table-buffer cont cbuf))))
(defun erlang-xref-find-definitions-module-tag (module
tag
@@ -5522,7 +5539,7 @@ Return the position after the newly inserted command."
(+ insert-point insert-length)))
-(defun inferior-erlang-strip-delete (&optional s)
+(defun inferior-erlang-strip-delete (&optional _s)
"Remove `^H' (delete) and the characters it was supposed to remove."
(interactive)
(if (and (boundp 'comint-last-input-end)
@@ -5540,7 +5557,7 @@ Return the position after the newly inserted command."
;; Basically `comint-strip-ctrl-m', with a few extra checks.
-(defun inferior-erlang-strip-ctrl-m (&optional string)
+(defun inferior-erlang-strip-ctrl-m (&optional _string)
"Strip trailing `^M' characters from the current output group."
(interactive)
(if (and (boundp 'comint-last-input-end)
@@ -5577,8 +5594,8 @@ There exists two workarounds for this bug:
(let* ((dir (inferior-erlang-compile-outdir))
(noext (substring (erlang-local-buffer-file-name) 0 -4))
(opts (append (list (cons 'outdir dir))
- (if current-prefix-arg
- (list 'debug_info 'export_all))
+ (when arg
+ (list 'debug_info 'export_all))
erlang-compile-extra-opts))
end)
(with-current-buffer inferior-erlang-buffer
@@ -5627,7 +5644,6 @@ unless the optional NO-DISPLAY is non-nil."
(defun inferior-erlang-compute-compile-command (module-name opts)
(let ((ccfn erlang-compile-command-function-alist)
- (res (inferior-erlang-compute-erl-compile-command module-name opts))
ccfn-entry
done
result)
diff --git a/lib/tools/emacs/erlang_appwiz.el b/lib/tools/emacs/erlang_appwiz.el
index ecbce66f47..b71c180739 100644
--- a/lib/tools/emacs/erlang_appwiz.el
+++ b/lib/tools/emacs/erlang_appwiz.el
@@ -103,6 +103,10 @@
;;
;;
+(defvar appwiz-erlang-modulename "foo")
+(defvar appwiz-erlang-ext "_work")
+
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Erlang application wizard
@@ -245,13 +249,6 @@ creating the root directory and for naming application files."
(insert "Application specification file for " name ".")
(save-buffer)))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; These are setq:ed
-;;
-
-(defvar appwiz-erlang-modulename "foo")
-(defvar appwiz-erlang-ext "_work")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -468,7 +465,7 @@ Call the function `erlang-menu-init' after modifying this variable.")
The first character of DD is *not* space if the value is less than 10."
(let ((date (current-time-string)))
(format "%d %s %s"
- (string-to-int (substring date 8 10))
+ (string-to-number (substring date 8 10))
(substring date 4 7)
(substring date -4))))
diff --git a/lib/tools/priv/styles.css b/lib/tools/priv/styles.css
new file mode 100644
index 0000000000..84f00be9fd
--- /dev/null
+++ b/lib/tools/priv/styles.css
@@ -0,0 +1,96 @@
+body {
+ font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ color: #000;
+ border-top: 2px solid #ddd;
+ background-color: #fff;
+
+ min-height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+h1 {
+ width: 100%;
+ border-bottom: 1px solid #eee;
+ margin-bottom: 0;
+ font-weight: 100;
+ font-size: 1.1em;
+ letter-spacing: 1px;
+}
+
+h1 code {
+ font-size: 0.96em;
+}
+
+code {
+ font: 12px monospace;
+}
+
+footer {
+ background: #eee;
+ width: 100%;
+ padding: 10px 0;
+ text-align: right;
+ border-top: 1px solid #ddd;
+ display: flex;
+ flex: 1;
+ order: 2;
+ justify-content: center;
+}
+
+table {
+ width: 100%;
+ margin-top: 10px;
+ border-collapse: collapse;
+ border: 1px solid #cbcbcb;
+ color: #000;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+}
+table thead {
+ display: none;
+}
+table td.line,
+table td.line a,
+table td.hits {
+ width: 20px;
+ background: #eaeaea;
+ text-align: center;
+ text-decoration: none;
+ font-size: 11px;
+ padding: 0 10px;
+ color: #949494;
+}
+table td.hits {
+ width: 10px;
+ text-align: right;
+ padding: 2px 5px;
+ color: rgba(0, 0, 0, 0.6);
+ background-color: #f0f0f0;
+}
+tr.miss td.line,
+tr.miss td.line a,
+tr.miss td.hits {
+ background-color: #ffdce0;
+ border-color: #fdaeb7;
+}
+tr.miss td {
+ background-color: #ffeef0;
+}
+tr.hit td.line,
+tr.hit td.line a,
+tr.hit td.hits {
+ background-color: #cdffd8;
+ border-color: #bef5cb;
+}
+tr.hit td {
+ background-color: #e6ffed;
+}
+td.source {
+ padding-left: 15px;
+ line-height: 15px;
+ white-space: pre;
+ font: 12px monospace;
+}
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile
index 032bd612db..cc5bee9a8f 100644
--- a/lib/tools/src/Makefile
+++ b/lib/tools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -72,6 +72,9 @@ APP_TARGET = $(EBIN)/$(APP_FILE)
APPUP_SRC = $(APPUP_FILE).src
APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+PRIVDIR = ../priv
+CSS = $(PRIVDIR)/styles.css
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -110,5 +113,7 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
"$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(CSS) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index bf5faa165d..62be773fcf 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -144,6 +144,8 @@
end).
-define(SPAWN_DBG(Tag,Value),put(Tag,Value)).
+-define(STYLESHEET, "styles.css").
+-define(TOOLS_APP, tools).
-include_lib("stdlib/include/ms_transform.hrl").
@@ -167,6 +169,8 @@ start() ->
receive
{?SERVER,started} ->
{ok,Pid};
+ {?SERVER,{error,Error}} ->
+ {error,Error};
{'DOWN', Ref, _Type, _Object, Info} ->
{error,Info}
end,
@@ -628,21 +632,33 @@ remote_reply(MainNode,Reply) ->
%%%----------------------------------------------------------------------
init_main(Starter) ->
- register(?SERVER,self()),
- %% Having write concurrancy here gives a 40% performance boost
- %% when collect/1 is called.
- ?COVER_TABLE = ets:new(?COVER_TABLE, [set, public, named_table,
- {write_concurrency, true}]),
- ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public,
+ try register(?SERVER,self()) of
+ true ->
+ %% Having write concurrancy here gives a 40% performance boost
+ %% when collect/1 is called.
+ ?COVER_TABLE = ets:new(?COVER_TABLE, [set, public, named_table,
+ {write_concurrency, true}]),
+ ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public,
+ named_table]),
+ ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]),
+ ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public,
named_table]),
- ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]),
- ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public,
- named_table]),
- ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE, [set, public,
- named_table]),
- ok = net_kernel:monitor_nodes(true),
- Starter ! {?SERVER,started},
- main_process_loop(#main_state{}).
+ ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE,
+ [set, public, named_table]),
+ ok = net_kernel:monitor_nodes(true),
+ Starter ! {?SERVER,started},
+ main_process_loop(#main_state{})
+ catch
+ error:badarg ->
+ %% The server's already registered; either report that it's already
+ %% started or try again if it died before we could find its pid.
+ case whereis(?SERVER) of
+ undefined ->
+ init_main(Starter);
+ Pid ->
+ Starter ! {?SERVER, {error, {already_started, Pid}}}
+ end
+ end.
main_process_loop(State) ->
receive
@@ -2415,20 +2431,8 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
case file:open(OutFile, [write,raw,delayed_write]) of
{ok, OutFd} ->
Enc = encoding(ErlFile),
- if HTML ->
- Header =
- ["<!DOCTYPE HTML PUBLIC "
- "\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<html>\n"
- "<head>\n"
- "<meta http-equiv=\"Content-Type\""
- " content=\"text/html; charset=",
- html_encoding(Enc),"\"/>\n"
- "<title>",OutFile,"</title>\n"
- "</head>"
- "<body style='background-color: white;"
- " color: black'>\n"
- "<pre>\n"],
+ if HTML ->
+ Header = create_header(OutFile, Enc),
H1Bin = unicode:characters_to_binary(Header,Enc,Enc),
ok = file:write(OutFd,H1Bin);
true -> ok
@@ -2445,14 +2449,19 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
string:pad(integer_to_list(Mi), 2, leading, $0),
string:pad(integer_to_list(S), 2, leading, $0)]),
- H2Bin = unicode:characters_to_binary(
- ["File generated from ",ErlFile," by COVER ",
- Timestamp,"\n\n"
- "**************************************"
- "**************************************"
- "\n\n"],
- Enc, Enc),
- ok = file:write(OutFd, H2Bin),
+ OutFileInfo =
+ if HTML ->
+ create_footer(ErlFile, Timestamp);
+ true ->
+ ["File generated from ",ErlFile," by COVER ",
+ Timestamp, "\n\n",
+ "**************************************"
+ "**************************************"
+ "\n\n"]
+ end,
+
+ H2Bin = unicode:characters_to_binary(OutFileInfo,Enc,Enc),
+ ok = file:write(OutFd, H2Bin),
Pattern = {#bump{module=Module,line='$1',_='_'},'$2'},
MS = [{Pattern,[{is_integer,'$1'},{'>','$1',0}],[{{'$1','$2'}}]}],
@@ -2462,7 +2471,7 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
print_lines(Module, CovLines, InFd, OutFd, 1, HTML),
if HTML ->
- ok = file:write(OutFd, "</pre>\n</body>\n</html>\n");
+ ok = file:write(OutFd, close_html());
true -> ok
end,
@@ -2497,12 +2506,11 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
case CovLines of
[{L,N}|CovLines1] ->
if N=:=0, HTML=:=true ->
- LineNoNL = Line -- "\n",
- Str = " 0",
- %%Str = string:pad("0", 6, leading, $\s),
- RedLine = ["<font color=red>",Str,fill1(),
- LineNoNL,"</font>\n"],
- ok = file:write(OutFd, RedLine);
+ MissedLine = table_row("miss", Line, L, N),
+ ok = file:write(OutFd, MissedLine);
+ HTML=:=true ->
+ HitLine = table_row("hit", Line, L, N),
+ ok = file:write(OutFd, HitLine);
N < 1000000 ->
Str = string:pad(integer_to_list(N), 6, leading, $\s),
ok = file:write(OutFd, [Str,fill1(),Line]);
@@ -2515,7 +2523,11 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
end,
print_lines(Module, CovLines1, InFd, OutFd, L+1, HTML);
_ -> %Including comment lines
- ok = file:write(OutFd, [tab(),Line]),
+ NonCoveredContent =
+ if HTML -> table_row(Line, L);
+ true -> [tab(),Line]
+ end,
+ ok = file:write(OutFd, NonCoveredContent),
print_lines(Module, CovLines, InFd, OutFd, L+1, HTML)
end
end.
@@ -2525,6 +2537,61 @@ fill1() -> "..| ".
fill2() -> ".| ".
fill3() -> "| ".
+%% HTML sections
+create_header(OutFile, Enc) ->
+ ["<!doctype html>\n"
+ "<html>\n"
+ "<head>\n"
+ "<meta charset=\"",html_encoding(Enc),"\">\n"
+ "<title>",OutFile,"</title>\n"
+ "<style>"] ++
+ read_stylesheet() ++
+ ["</style>\n",
+ "</head>\n"
+ "<body>\n"
+ "<h1><code>",OutFile,"</code></h1>\n"].
+
+create_footer(ErlFile, Timestamp) ->
+ ["<footer><p>File generated from <code>",ErlFile,
+ "</code> by <a href=\"http://erlang.org/doc/man/cover.html\">cover</a> at ",
+ Timestamp,"</p></footer>\n<table>\n<tbody>\n"].
+
+close_html() ->
+ ["</tbody>\n",
+ "<thead>\n",
+ "<tr>\n",
+ "<th>Line</th>\n",
+ "<th>Hits</th>\n",
+ "<th>Source</th>\n",
+ "</tr>\n",
+ "</thead>\n",
+ "</table>\n",
+ "</body>\n"
+ "</html>\n"].
+
+table_row(CssClass, Line, L, N) ->
+ ["<tr class=\"",CssClass,"\">\n", table_data(Line, L, N)].
+table_row(Line, L) ->
+ ["<tr>\n", table_data(Line, L, "")].
+
+table_data(Line, L, N) ->
+ LineNoNL = Line -- "\n",
+ ["<td class=\"line\" id=\"L",integer_to_list(L),"\">",
+ "<a href=\"#L",integer_to_list(L),"\">",
+ integer_to_list(L),
+ "</a></td>\n",
+ "<td class=\"hits\">",maybe_integer_to_list(N),"</td>\n",
+ "<td class=\"source\"><code>",LineNoNL,"</code></td>\n</tr>\n"].
+
+maybe_integer_to_list(0) -> "<pre style=\"display: inline;\">:-(</pre>";
+maybe_integer_to_list(N) when is_integer(N) -> integer_to_list(N);
+maybe_integer_to_list(_) -> "".
+
+read_stylesheet() ->
+ PrivDir = code:priv_dir(?TOOLS_APP),
+ {ok, Css} = file:read_file(filename:join(PrivDir, ?STYLESHEET)),
+ [Css].
+
%%%--Export--------------------------------------------------------------
do_export(Module, OutFile, From, State) ->
case file:open(OutFile,[write,binary,raw,delayed_write]) of
diff --git a/lib/tools/src/eprof.erl b/lib/tools/src/eprof.erl
index 535ddbcd04..86e3d3a8b8 100644
--- a/lib/tools/src/eprof.erl
+++ b/lib/tools/src/eprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,11 +26,11 @@
-export([start/0,
stop/0,
- dump/0,
+ dump/0, dump_data/0,
start_profiling/1, start_profiling/2, start_profiling/3,
profile/1, profile/2, profile/3, profile/4, profile/5,
stop_profiling/0,
- analyze/0, analyze/1, analyze/2,
+ analyze/0, analyze/1, analyze/2, analyze/4,
log/1]).
%% Internal exports
@@ -117,6 +117,9 @@ profile(Rootset, M, F, A, Pattern, Options) ->
dump() ->
gen_server:call(?MODULE, dump, infinity).
+dump_data() ->
+ gen_server:call(?MODULE, dump_data, infinity).
+
log(File) ->
gen_server:call(?MODULE, {logfile, File}, infinity).
@@ -151,22 +154,18 @@ init([]) ->
%% analyze
-handle_call({analyze, _, _}, _, #state{ bpd = #bpd{ p = {0,nil}, us = 0, n = 0} = Bpd } = S) when is_record(Bpd, bpd) ->
+handle_call(
+ {analyze, _, _}, _,
+ #state{ bpd = #bpd{ p = {0,nil}, us = 0, n = 0 } } = S) ->
{reply, nothing_to_analyze, S};
-handle_call({analyze, procs, Opts}, _, #state{ bpd = #bpd{ p = Ps, us = Tus} = Bpd, fd = Fd} = S) when is_record(Bpd, bpd) ->
- lists:foreach(fun
- ({Pid, Mfas}) ->
- {Pn, Pus} = sum_bp_total_n_us(Mfas),
- format(Fd, "~n****** Process ~w -- ~s % of profiled time *** ~n", [Pid, s("~.2f", [100.0*divide(Pus,Tus)])]),
- print_bp_mfa(Mfas, {Pn,Pus}, Fd, Opts),
- ok
- end, gb_trees:to_list(Ps)),
- {reply, ok, S};
+handle_call({analyze, procs, Opts}, _, #state{ bpd = Bpd, fd = Fd } = S)
+ when is_record(Bpd, bpd) ->
+ {reply, analyze(Fd, procs, Opts, Bpd), S};
-handle_call({analyze, total, Opts}, _, #state{ bpd = #bpd{ mfa = Mfas, n = Tn, us = Tus} = Bpd, fd = Fd} = S) when is_record(Bpd, bpd) ->
- print_bp_mfa(Mfas, {Tn, Tus}, Fd, Opts),
- {reply, ok, S};
+handle_call({analyze, total, Opts}, _, #state{ bpd = Bpd, fd = Fd } = S)
+ when is_record(Bpd, bpd) ->
+ {reply, analyze(Fd, total, Opts, Bpd), S};
handle_call({analyze, Type, _Opts}, _, S) ->
{reply, {error, {undefined, Type}}, S};
@@ -260,6 +259,10 @@ handle_call({logfile, File}, _From, #state{ fd = OldFd } = S) ->
handle_call(dump, _From, #state{ bpd = Bpd } = S) when is_record(Bpd, bpd) ->
{reply, gb_trees:to_list(Bpd#bpd.p), S};
+handle_call(dump_data, _, #state{ bpd = #bpd{} = Bpd } = S)
+ when is_record(Bpd, bpd) ->
+ {reply, Bpd, S};
+
handle_call(stop, _FromTag, S) ->
{stop, normal, stopped, S}.
@@ -438,6 +441,23 @@ collect_bpdfp(Mfa, Tree, Data) ->
{PTno + Ni, PTuso + Time, Ti1}
end, {0,0, Tree}, Data).
+
+
+analyze(Fd, procs, Opts, #bpd{ p = Ps, us = Tus }) ->
+ lists:foreach(
+ fun
+ ({Pid, Mfas}) ->
+ {Pn, Pus} = sum_bp_total_n_us(Mfas),
+ format(
+ Fd,
+ "~n****** Process ~w -- ~s % of profiled time *** ~n",
+ [Pid, s("~.2f", [100.0*divide(Pus, Tus)])]),
+ print_bp_mfa(Mfas, {Pn,Pus}, Fd, Opts),
+ ok
+ end, gb_trees:to_list(Ps));
+analyze(Fd, total, Opts, #bpd{ mfa = Mfas, n = Tn, us = Tus } ) ->
+ print_bp_mfa(Mfas, {Tn, Tus}, Fd, Opts).
+
%% manipulators
sort_mfa(Bpfs, mfa) when is_list(Bpfs) ->
lists:sort(fun
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 161b0105b9..806297abdd 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -35,7 +35,8 @@ all() ->
distribution, reconnect, die_and_reconnect,
dont_reconnect_after_stop, stop_node_after_disconnect,
export_import, otp_5031, otp_6115,
- otp_8270, otp_10979_hanging_node, otp_14817],
+ otp_8270, otp_10979_hanging_node, otp_14817,
+ startup_race],
case whereis(cover_server) of
undefined ->
[coverage,StartStop ++ NoStartStop];
@@ -1742,6 +1743,32 @@ otp_13289(Config) ->
ok = file:delete(File),
ok.
+%% ERL-943; We should not crash on startup when multiple servers race to
+%% register the server name.
+startup_race(Config) when is_list(Config) ->
+ PidRefs = [spawn_monitor(fun() ->
+ case cover:start() of
+ {error, {already_started, _Pid}} ->
+ ok;
+ {ok, _Pid} ->
+ ok
+ end
+ end) || _<- lists:seq(1,8)],
+ startup_race_1(PidRefs).
+
+startup_race_1([{Pid, Ref} | PidRefs]) ->
+ receive
+ {'DOWN', Ref, process, Pid, normal} ->
+ startup_race_1(PidRefs);
+ {'DOWN', Ref, process, Pid, _Other} ->
+ ct:fail("Cover server crashed on startup.")
+ after 5000 ->
+ ct:fail("Timed out.")
+ end;
+startup_race_1([]) ->
+ cover:stop(),
+ ok.
+
%%--Auxiliary------------------------------------------------------------
analyse_expr(Expr, Config) ->
diff --git a/lib/tools/test/emacs_SUITE.erl b/lib/tools/test/emacs_SUITE.erl
index 5839f9ce5b..a6d43d1816 100644
--- a/lib/tools/test/emacs_SUITE.erl
+++ b/lib/tools/test/emacs_SUITE.erl
@@ -23,18 +23,28 @@
-export([all/0, init_per_testcase/2, end_per_testcase/2]).
--export([bif_highlight/1, indent/1]).
+-export([bif_highlight/1,
+ load_interpreted/1, compile_and_load/1,
+ indent/1,
+ tests_interpreted/1, tests_compiled/1
+ ]).
all() ->
- [bif_highlight, indent].
+ [bif_highlight, load_interpreted, compile_and_load,
+ indent,
+ tests_interpreted, tests_compiled
+ ].
-init_per_testcase(_Case, Config) ->
+init_per_testcase(Case, Config) ->
ErlangEl = filename:join([code:lib_dir(tools),"emacs","erlang.el"]),
case file:read_file_info(ErlangEl) of
- {ok, _} ->
- [{el, ErlangEl}|Config];
- _ ->
- {skip, "Could not find erlang.el"}
+ {ok, _} ->
+ case Case =:= bif_highlight orelse emacs_version_ok(24.1) of
+ false -> {skip, "Old or no emacs found"};
+ _ -> [{el, ErlangEl}|Config]
+ end;
+ _ ->
+ {skip, "Could not find erlang.el"}
end.
end_per_testcase(_Case, _Config) ->
@@ -46,26 +56,26 @@ bif_highlight(Config) ->
%% All auto-imported bifs
IntBifs = lists:usort(
- [F || {F,A} <- erlang:module_info(exports),
- erl_internal:bif(F,A)]),
+ [F || {F,A} <- erlang:module_info(exports),
+ erl_internal:bif(F,A)]),
%% all bif which need erlang: prefix and are not operands
ExtBifs = lists:usort(
- [F || {F,A} <- erlang:module_info(exports),
- not erl_internal:bif(F,A) andalso
- not is_atom(catch erl_internal:op_type(F,A))]),
+ [F || {F,A} <- erlang:module_info(exports),
+ not erl_internal:bif(F,A) andalso
+ not is_atom(catch erl_internal:op_type(F,A))]),
check_bif_highlight(Bin, <<"erlang-int-bifs">>, IntBifs),
check_bif_highlight(Bin, <<"erlang-ext-bifs">>, ExtBifs).
-
+
check_bif_highlight(Bin, Tag, Compare) ->
- [_H,IntMatch,_T] =
- re:split(Bin,<<"defvar ",Tag/binary,
- "[^(]*\\(([^)]*)">>,[]),
- EmacsIntBifs = [list_to_atom(S) ||
- S <- string:tokens(binary_to_list(IntMatch)," '\"\n")],
-
+ [_H,IntMatch,_T] =
+ re:split(Bin,<<"defvar ",Tag/binary,
+ "[^(]*\\(([^)]*)">>,[]),
+ EmacsIntBifs = [list_to_atom(S) ||
+ S <- string:tokens(binary_to_list(IntMatch)," '\"\n")],
+
ct:log("Emacs ~p",[EmacsIntBifs]),
ct:log("Int ~p",[Compare]),
@@ -73,27 +83,92 @@ check_bif_highlight(Bin, Tag, Compare) ->
ct:log("Diff2 ~p",[EmacsIntBifs -- Compare]),
[] = Compare -- EmacsIntBifs,
[] = EmacsIntBifs -- Compare.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-indent(Config) ->
- case emacs_version_ok() of
+load_interpreted(_Config) ->
+ _ = emacs(["-l erlang.el -f erlang-mode"]),
+ ok.
+
+compile_and_load(_Config) ->
+ Dir = emacs_dir(),
+ Files0 = filelib:wildcard("*.el", Dir),
+ Files = case emacs_version_ok(24.3) of
+ %% erldoc.el depends on cl-lib which was introduced in 24.3.
+ false -> Files0 -- ["erldoc.el"];
+ _ -> Files0
+ end,
+ Unforgiving =
+ case emacs_version_ok(24) of
+ Ver when Ver < 25 ->
+ "";
+ Ver when Ver < 26 ->
+ %% Workaround byte-compile-error-on-warn which seem broken in
+ %% Emacs 25.
+ "\"(advice-add #'display-warning :after "
+ "(lambda (_ f _ _) (error \"%s\" f)))\"";
+ _ ->
+ "\"(setq byte-compile-error-on-warn t)\""
+ end,
+ %% Add files here whenever they are cleaned of warnings.
+ NoWarn = ["erlang.el", "erlang-test.el", "erlang-edoc.el", "erlang-start.el", "erldoc.el"],
+ Compile = fun(File) ->
+ Pedantic = case lists:member(File, NoWarn) andalso Unforgiving /= "" of
+ true -> ["--eval ", Unforgiving, " "];
+ false -> " "
+ end,
+ emacs([Pedantic,
+ " -f batch-byte-compile ",filename:join(Dir, File)]),
+ true
+ end,
+ lists:foreach(Compile, Files),
+ emacs(["-l erlang.elc -f erlang-mode"]),
+ ok.
+
+tests_interpreted(_Config) ->
+ case emacs_version_ok(25) of
false -> {skip, "Old or no emacs found"};
- true ->
- Def = filename:dirname(code:which(?MODULE)) ++ "/" ++ ?MODULE_STRING ++ "_data",
- Dir = proplists:get_value(data_dir, Config, Def),
- OrigFs = filelib:wildcard(Dir ++ "/*"),
- io:format("Dir: ~s~nFs: ~p~n", [Dir, OrigFs]),
- Fs = [{File, unindent(File)} || File <- OrigFs,
- filename:extension(File) =:= ""],
- Indent = fun emacs/1,
- [Indent(File) || {_, File} <- Fs],
- Res = [diff(Orig, File) || {Orig, File} <- Fs],
- [file:delete(File) || {ok, File} <- Res], %% Cleanup
- [] = [Fail || {fail, Fail} <- Res],
+ _ ->
+ emacs(["-l erlang.el ",
+ "-l erlang-test.el -f ert-run-tests-batch-and-exit"]),
ok
end.
+tests_compiled(_Config) ->
+ case emacs_version_ok(25) of
+ false -> {skip, "Old or no emacs found"};
+ _ ->
+ emacs(["-l erlang.elc ",
+ "-l erlang-test.elc -f ert-run-tests-batch-and-exit"]),
+ ok
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+indent(Config) ->
+ Def = filename:dirname(code:which(?MODULE))
+ ++ "/"
+ ++ ?MODULE_STRING
+ ++ "_data",
+ Dir = proplists:get_value(data_dir, Config, Def),
+ OrigFs = filelib:wildcard(Dir ++ "/*"),
+ io:format("Dir: ~s~nFs: ~p~n", [Dir, OrigFs]),
+ Fs = [{File, unindent(File)} || File <- OrigFs,
+ filename:extension(File) =:= ""],
+ Indent = fun(File) ->
+ emacs([
+ File, " ",
+ "--eval '(indent-region (point-min) (point-max) nil)' ",
+ "--eval '(save-buffer 0)'"
+ ]),
+ ok
+ end,
+ [Indent(File) || {_, File} <- Fs],
+ Res = [diff(Orig, File) || {Orig, File} <- Fs],
+ [file:delete(File) || {ok, File} <- Res], %% Cleanup
+ [] = [Fail || {fail, Fail} <- Res],
+ ok.
+
unindent(Input) ->
Output = Input ++ ".erl",
{ok, Bin} = file:read_file(Input),
@@ -112,14 +187,13 @@ diff(Orig, File) ->
{fail, File}
end.
-emacs_version_ok() ->
+emacs_version_ok(AcceptVer) ->
case os:cmd("emacs --version | head -1") of
"GNU Emacs " ++ Ver ->
case string:to_float(Ver) of
- {Vsn, _} when Vsn >= 24.1 ->
- true;
+ {Vsn, _} when Vsn >= AcceptVer ->
+ Vsn;
_ ->
- io:format("Emacs version fail~n~s~n~n",[Ver]),
false
end;
Res ->
@@ -127,16 +201,19 @@ emacs_version_ok() ->
false
end.
-emacs(File) ->
- EmacsErlDir = filename:join([code:lib_dir(tools), "emacs"]),
+emacs(EmacsCmds) when is_list(EmacsCmds) ->
Cmd = ["emacs ",
"--batch --quick ",
- "--directory ", EmacsErlDir, " ",
- "--eval \"(require 'erlang-start)\" ",
- File, " ",
- "--eval '(indent-region (point-min) (point-max) nil)' ",
- "--eval '(save-buffer 0)'"
- ],
- _Res = os:cmd(Cmd),
- % io:format("cmd ~s:~n=> ~s~n", [Cmd, _Res]),
- ok.
+ "--directory ", emacs_dir(), " ",
+ "--eval \"(require 'erlang-start)\" "
+ | EmacsCmds],
+ Res0 = os:cmd(Cmd ++ " ; echo $?"),
+ Rows = string:lexemes(Res0, ["\r\n", $\n]),
+ Res = lists:last(Rows),
+ Output = string:join(lists:droplast(Rows), "\n"),
+ io:format("Cmd ~s:~n => ~s ~ts~n", [Cmd, Res, Output]),
+ "0" = Res,
+ Output.
+
+emacs_dir() ->
+ filename:join([code:lib_dir(tools), "emacs"]).
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 018f632948..da4f56c09b 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -2233,18 +2233,18 @@ variables(Conf) when is_list(Conf) ->
{{error, _, _}, _} = xref_base:variables(S108, [{verbose,false}]),
{ok, S109} = xref_base:set_library_path(S108, [], [{verbose,false}]),
- Tabs = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
{ok, S110} = eval("Eplus := closure E, TT := Eplus",
'closure()', S109),
{{ok, [{user, ['Eplus','TT']}]}, S111} = xref_base:variables(S110),
{ok, S112} = xref_base:forget(S111, ['TT','Eplus']),
- true = Tabs =:= length(ets:all()),
+ true = NoOfTables =:= erlang:system_info(ets_count),
{ok, NS0} = eval("Eplus := closure E", 'closure()', S112),
{{ok, [{user, ['Eplus']}]}, NS} = xref_base:variables(NS0),
ok = xref_base:delete(NS),
- true = Tabs =:= length(ets:all()),
+ true = NoOfTables =:= erlang:system_info(ets_count),
ok = file:delete(Beam),
ok.
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index bb3f4c66c0..77e2b8e00f 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 3.0
+TOOLS_VSN = 3.1.0.1
diff --git a/lib/wx/api_gen/wx_extra/added_func.h b/lib/wx/api_gen/wx_extra/added_func.h
index bffe391140..28fecbf454 100644
--- a/lib/wx/api_gen/wx_extra/added_func.h
+++ b/lib/wx/api_gen/wx_extra/added_func.h
@@ -44,3 +44,9 @@ class wxWindowGTK {
public:
double GetContentScaleFactor();
};
+
+class wxDisplay {
+ public:
+ // get the resolution of this monitor in pixels per inch
+ wxSize GetPPI() const;
+};
diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl
index cec6ac9ccf..8a00498319 100644
--- a/lib/wx/api_gen/wx_gen.erl
+++ b/lib/wx/api_gen/wx_gen.erl
@@ -701,8 +701,13 @@ parse_type2(["wxe_cb"|R],Info,Opts, T) ->
parse_type2(R,Info,Opts,T#type{name=int,base=wxe_cb});
parse_type2([const|R],Info,Opts,T=#type{mod=Mod}) ->
parse_type2(R,Info,Opts,T#type{mod=[const|Mod]});
-parse_type2(["unsigned"|R],Info,Opts,T=#type{mod=Mod}) ->
- parse_type2(R,Info,Opts,T#type{mod=[unsigned|Mod]});
+parse_type2(["unsigned"|R],Info,Opts,T=#type{mod=Mod}) ->
+ case T#type.base of
+ undefined ->
+ parse_type2(R,Info,Opts,T#type{name=int, base=int, mod=[unsigned|Mod]});
+ _ ->
+ parse_type2(R,Info,Opts,T#type{mod=[unsigned|Mod]})
+ end;
parse_type2(["int"|R],Info,Opts, T) ->
parse_type2(R,Info,Opts,T#type{name=int,base=int});
parse_type2(["wxByte"|R],Info,Opts, T) ->
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl
index 70a3530526..c6f2534380 100644
--- a/lib/wx/api_gen/wx_gen_cpp.erl
+++ b/lib/wx/api_gen/wx_gen_cpp.erl
@@ -995,8 +995,13 @@ build_ret_types(Type,Ps) ->
end,
lists:foldl(Calc, Free, Ps).
-build_ret(Name,_,#type{base={class,Class},single=true}) ->
- w(" rt.addRef(getRef((void *)~s,memenv), \"~s\");~n",[Name,Class]);
+build_ret(Name,_D,#type{base={class,Class},single=true}=_T) ->
+ case Class of
+ "wxGraphicsContext" ->
+ w(" rt.addRef(getRef((void *)~s,memenv,8), \"~s\");~n",[Name,Class]);
+ _ ->
+ w(" rt.addRef(getRef((void *)~s,memenv), \"~s\");~n",[Name,Class])
+ end;
build_ret(Name,_,#type{name="wxTreeItemId",single=true}) ->
w(" rt.add((wxUIntPtr *) ~s.m_pItem);~n",[Name]);
build_ret(Name,_,#type{name="wxTreeItemIdValue",single=true}) ->
@@ -1160,6 +1165,7 @@ gen_macros() ->
w("#include <wx/fontdlg.h>~n"),
w("#include <wx/progdlg.h>~n"),
w("#include <wx/printdlg.h>~n"),
+ w("#include <wx/display.h>~n"),
w("#include <wx/dcbuffer.h>~n"),
w("#include <wx/dcmirror.h>~n"),
w("#include <wx/glcanvas.h>~n"),
@@ -1171,6 +1177,7 @@ gen_macros() ->
w("#include <wx/sashwin.h>~n"),
w("#include <wx/laywin.h>~n"),
w("#include <wx/graphics.h>~n"),
+ w("#include <wx/dcgraph.h>~n"),
w("#include <wx/aui/aui.h>~n"),
w("#include <wx/datectrl.h>~n"),
w("#include <wx/filepicker.h>~n"),
@@ -1325,8 +1332,10 @@ encode_events(Evs) ->
w(" } else {~n"),
w(" send_res = rt.send();~n"),
w(" if(cb->skip) event->Skip();~n"),
- #class{id=MouseId} = lists:keyfind("wxMouseEvent", #class.name, Evs),
- w(" if(app->recurse_level < 1 && Etype->cID != ~p) {~n", [MouseId]),
+ #class{id=SizeId} = lists:keyfind("wxSizeEvent", #class.name, Evs),
+ #class{id=MoveId} = lists:keyfind("wxMoveEvent", #class.name, Evs),
+ w(" if(app->recurse_level < 1 && (Etype->cID == ~w || Etype->cID == ~w)) {~n",
+ [SizeId, MoveId]),
w(" app->recurse_level++;~n"),
w(" app->dispatch_cmds();~n"),
w(" app->recurse_level--;~n"),
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index c1b55b6875..9707fedf67 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -27,7 +27,7 @@
{not_const, [wxHAS_INT64,wxBYTE_ORDER,wxRETAINED,
wxFONTENCODING_UTF32,wxFONTENCODING_UTF16,
wxDEFAULT_CONTROL_BORDER,wxMOD_CMD,
- wxMAJOR_VERSION, wxMINOR_VERSION,
+ wxMAJOR_VERSION, wxMINOR_VERSION,
wxRELEASE_NUMBER,wxSUBRELEASE_NUMBER,wxBETA_NUMBER,
%%
wxALWAYS_NATIVE_DOUBLE_BUFFER,
@@ -37,16 +37,30 @@
wxCURSOR_DEFAULT,
wxCURSOR_ARROWWAIT,
wxCURSOR_MAX,
- wxLanguage
+ wxLanguage,
+ wxFONTWEIGHT_NORMAL,
+ wxFONTWEIGHT_LIGHT,
+ wxFONTWEIGHT_BOLD,
+ wxFONTWEIGHT_MAX
]}.
-{gvars,
+{gvars,
[
{wxITALIC_FONT, wxFont},
{wxNORMAL_FONT, wxFont},
{wxSMALL_FONT, wxFont},
{wxSWISS_FONT, wxFont},
-
+
+ %% Added (enum) values in 3.1.2
+ {wxFONTWEIGHT_INVALID, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+ {wxFONTWEIGHT_THIN, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+ {wxFONTWEIGHT_EXTRALIGHT, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+ {wxFONTWEIGHT_MEDIUM, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+ {wxFONTWEIGHT_SEMIBOLD, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+ {wxFONTWEIGHT_EXTRABOLD, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+ {wxFONTWEIGHT_HEAVY, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+ {wxFONTWEIGHT_EXTRAHEAVY, {test_if, "wxCHECK_VERSION(3,1,2)"}},
+
{wxBLACK_DASHED_PEN, wxPen},
{wxBLACK_PEN, wxPen},
{wxCYAN_PEN, wxPen},
@@ -2016,3 +2030,17 @@
['GetPosition', 'GetNumberOfFiles',
{'GetFiles', [{return, [{single, {list, 'm_noFiles'}}]}]}
]}.
+
+
+{class, wxDisplay, root, [{ifdef, wxUSE_DISPLAY}],
+ ['wxDisplay', '~wxDisplay',
+ 'IsOk',
+ {'GetClientArea', [{test_if, "wxCHECK_VERSION(2,8,12)"}]},
+ 'GetGeometry', 'GetName', 'IsPrimary',
+ 'GetCount', 'GetFromPoint', 'GetFromWindow',
+ {'GetPPI', [{test_if, "wxCHECK_VERSION(3,1,2)"}]}
+ ]}.
+
+{class, wxGCDC, wxDC, [{ifdef, wxUSE_GRAPHICS_CONTEXT}],
+ ['wxGCDC', '~wxGCDC', 'GetGraphicsContext', 'SetGraphicsContext'
+ ]}.
diff --git a/lib/wx/c_src/Makefile.in b/lib/wx/c_src/Makefile.in
index daa8afce83..8ec64bea7e 100644
--- a/lib/wx/c_src/Makefile.in
+++ b/lib/wx/c_src/Makefile.in
@@ -181,6 +181,7 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv"
$(INSTALL_DATA) ../priv/erlang-logo32.png "$(RELSYSDIR)/priv/"
$(INSTALL_DATA) ../priv/erlang-logo64.png "$(RELSYSDIR)/priv/"
+ $(INSTALL_DATA) ../priv/erlang-logo128.png "$(RELSYSDIR)/priv/"
$(INSTALL_PROGRAM) $(TARGET_DIR)/wxe_driver$(SO_EXT) "$(RELSYSDIR)/priv/"
$(INSTALL_PROGRAM) $(TARGET_DIR)/erl_gl$(SO_EXT) "$(RELSYSDIR)/priv/"
diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h
index fc0ae0d9fc..a7114eb188 100644
--- a/lib/wx/c_src/gen/wxe_derived_dest.h
+++ b/lib/wx/c_src/gen/wxe_derived_dest.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -799,3 +799,11 @@ class EwxDCOverlay : public wxDCOverlay {
EwxDCOverlay(wxOverlay& overlay,wxWindowDC * dc) : wxDCOverlay(overlay,dc) {};
};
+#if wxUSE_GRAPHICS_CONTEXT
+class EwxGCDC : public wxGCDC {
+ public: ~EwxGCDC() {((WxeApp *)wxTheApp)->clearPtr(this);};
+ EwxGCDC(const wxWindowDC& dc) : wxGCDC(dc) {};
+ EwxGCDC() : wxGCDC() {};
+};
+#endif // wxUSE_GRAPHICS_CONTEXT
+
diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp
index 01787c8a64..8c3283a670 100644
--- a/lib/wx/c_src/gen/wxe_events.cpp
+++ b/lib/wx/c_src/gen/wxe_events.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2019. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -910,7 +910,7 @@ case 238: {// wxDropFilesEvent
} else {
send_res = rt.send();
if(cb->skip) event->Skip();
- if(app->recurse_level < 1 && Etype->cID != 168) {
+ if(app->recurse_level < 1 && (Etype->cID == 171 || Etype->cID == 172)) {
app->recurse_level++;
app->dispatch_cmds();
app->recurse_level--;
diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp
index a7bac4cf9d..32e4bf855b 100644
--- a/lib/wx/c_src/gen/wxe_funcs.cpp
+++ b/lib/wx/c_src/gen/wxe_funcs.cpp
@@ -6147,18 +6147,18 @@ case wxGraphicsObject_IsNull: { // wxGraphicsObject::IsNull
case wxGraphicsContext_Create_1_1: { // wxGraphicsContext::Create
wxWindowDC * dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4;
wxGraphicsContext * Result = (wxGraphicsContext*)wxGraphicsContext::Create(*dc);
- rt.addRef(getRef((void *)Result,memenv), "wxGraphicsContext");
+ rt.addRef(getRef((void *)Result,memenv,8), "wxGraphicsContext");
break;
}
case wxGraphicsContext_Create_1_0: { // wxGraphicsContext::Create
wxWindow *window = (wxWindow *) getPtr(bp,memenv); bp += 4;
wxGraphicsContext * Result = (wxGraphicsContext*)wxGraphicsContext::Create(window);
- rt.addRef(getRef((void *)Result,memenv), "wxGraphicsContext");
+ rt.addRef(getRef((void *)Result,memenv,8), "wxGraphicsContext");
break;
}
case wxGraphicsContext_Create_0: { // wxGraphicsContext::Create
wxGraphicsContext * Result = (wxGraphicsContext*)wxGraphicsContext::Create();
- rt.addRef(getRef((void *)Result,memenv), "wxGraphicsContext");
+ rt.addRef(getRef((void *)Result,memenv,8), "wxGraphicsContext");
break;
}
case wxGraphicsContext_CreatePen: { // wxGraphicsContext::CreatePen
@@ -6999,7 +6999,7 @@ case wxGraphicsRenderer_CreateContext_1_1: { // wxGraphicsRenderer::CreateContex
wxWindowDC * dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4;
if(!This) throw wxe_badarg(0);
wxGraphicsContext * Result = (wxGraphicsContext*)This->CreateContext(*dc);
- rt.addRef(getRef((void *)Result,memenv), "wxGraphicsContext");
+ rt.addRef(getRef((void *)Result,memenv,8), "wxGraphicsContext");
break;
}
case wxGraphicsRenderer_CreateContext_1_0: { // wxGraphicsRenderer::CreateContext
@@ -7007,7 +7007,7 @@ case wxGraphicsRenderer_CreateContext_1_0: { // wxGraphicsRenderer::CreateContex
wxWindow *window = (wxWindow *) getPtr(bp,memenv); bp += 4;
if(!This) throw wxe_badarg(0);
wxGraphicsContext * Result = (wxGraphicsContext*)This->CreateContext(window);
- rt.addRef(getRef((void *)Result,memenv), "wxGraphicsContext");
+ rt.addRef(getRef((void *)Result,memenv,8), "wxGraphicsContext");
break;
}
@@ -32113,6 +32113,120 @@ case wxDropFilesEvent_GetFiles: { // wxDropFilesEvent::GetFiles
rt.add(tmpArrayStr);
break;
}
+#if wxUSE_DISPLAY
+case wxDisplay_new: { // wxDisplay::wxDisplay
+ int n=0;
+ while( * (int*) bp) { switch (* (int*) bp) {
+ case 1: {bp += 4;
+ n = (int)*(unsigned int *) bp; bp += 4;
+ } break;
+ }};
+ wxDisplay * Result = new wxDisplay(n);
+ newPtr((void *) Result, 239, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxDisplay");
+ break;
+}
+case wxDisplay_destruct: { // wxDisplay::~wxDisplay
+ wxDisplay *This = (wxDisplay *) getPtr(bp,memenv); bp += 4;
+ if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This);
+ delete This;}
+ break;
+}
+case wxDisplay_IsOk: { // wxDisplay::IsOk
+ wxDisplay *This = (wxDisplay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->IsOk();
+ rt.addBool(Result);
+ break;
+}
+#if wxCHECK_VERSION(2,8,12)
+case wxDisplay_GetClientArea: { // wxDisplay::GetClientArea
+ wxDisplay *This = (wxDisplay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ wxRect Result = This->GetClientArea();
+ rt.add(Result);
+ break;
+}
+#endif
+case wxDisplay_GetGeometry: { // wxDisplay::GetGeometry
+ wxDisplay *This = (wxDisplay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ wxRect Result = This->GetGeometry();
+ rt.add(Result);
+ break;
+}
+case wxDisplay_GetName: { // wxDisplay::GetName
+ wxDisplay *This = (wxDisplay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ wxString Result = This->GetName();
+ rt.add(Result);
+ break;
+}
+case wxDisplay_IsPrimary: { // wxDisplay::IsPrimary
+ wxDisplay *This = (wxDisplay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->IsPrimary();
+ rt.addBool(Result);
+ break;
+}
+case wxDisplay_GetCount: { // wxDisplay::GetCount
+ int Result = wxDisplay::GetCount();
+ rt.addUint(Result);
+ break;
+}
+case wxDisplay_GetFromPoint: { // wxDisplay::GetFromPoint
+ int * ptX = (int *) bp; bp += 4;
+ int * ptY = (int *) bp; bp += 4;
+ wxPoint pt = wxPoint(*ptX,*ptY);
+ int Result = wxDisplay::GetFromPoint(pt);
+ rt.addInt(Result);
+ break;
+}
+case wxDisplay_GetFromWindow: { // wxDisplay::GetFromWindow
+ wxWindow *window = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int Result = wxDisplay::GetFromWindow(window);
+ rt.addInt(Result);
+ break;
+}
+#if wxCHECK_VERSION(3,1,2)
+case wxDisplay_GetPPI: { // wxDisplay::GetPPI
+ wxDisplay *This = (wxDisplay *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ wxSize Result = This->GetPPI();
+ rt.add(Result);
+ break;
+}
+#endif
+#endif // wxUSE_DISPLAY
+#if wxUSE_GRAPHICS_CONTEXT
+case wxGCDC_new_1: { // wxGCDC::wxGCDC
+ wxWindowDC *dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4;
+ wxGCDC * Result = new EwxGCDC(*dc);
+ newPtr((void *) Result, 8, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxGCDC");
+ break;
+}
+case wxGCDC_new_0: { // wxGCDC::wxGCDC
+ wxGCDC * Result = new EwxGCDC();
+ newPtr((void *) Result, 8, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxGCDC");
+ break;
+}
+case wxGCDC_GetGraphicsContext: { // wxGCDC::GetGraphicsContext
+ wxGCDC *This = (wxGCDC *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ wxGraphicsContext * Result = (wxGraphicsContext*)This->GetGraphicsContext();
+ rt.addRef(getRef((void *)Result,memenv,8), "wxGraphicsContext");
+ break;
+}
+case wxGCDC_SetGraphicsContext: { // wxGCDC::SetGraphicsContext
+ wxGCDC *This = (wxGCDC *) getPtr(bp,memenv); bp += 4;
+ wxGraphicsContext *ctx = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ This->SetGraphicsContext(ctx);
+ break;
+}
+#endif // wxUSE_GRAPHICS_CONTEXT
default: {
wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false); error.addAtom("_wxe_error_");
error.addInt((int) op);
@@ -32174,6 +32288,7 @@ bool WxeApp::delete_object(void *ptr, wxeRefData *refd) {
case 231: delete (EwxLocale *) ptr; return false;
case 236: delete (wxOverlay *) ptr; break;
case 237: delete (EwxDCOverlay *) ptr; return false;
+ case 239: delete (wxDisplay *) ptr; break;
default: delete (wxObject *) ptr; return false;
}
return true;
diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp
index 6ce33a5449..5a52d69003 100644
--- a/lib/wx/c_src/gen/wxe_init.cpp
+++ b/lib/wx/c_src/gen/wxe_init.cpp
@@ -55,6 +55,14 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {
rt.addTupleCount(2);
rt.addAtom("wxFONTENCODING_UTF32"); rt.addInt(wxFONTENCODING_UTF32);
rt.addTupleCount(2);
+ rt.addAtom("wxFONTWEIGHT_BOLD"); rt.addInt(wxFONTWEIGHT_BOLD);
+ rt.addTupleCount(2);
+ rt.addAtom("wxFONTWEIGHT_LIGHT"); rt.addInt(wxFONTWEIGHT_LIGHT);
+ rt.addTupleCount(2);
+ rt.addAtom("wxFONTWEIGHT_MAX"); rt.addInt(wxFONTWEIGHT_MAX);
+ rt.addTupleCount(2);
+ rt.addAtom("wxFONTWEIGHT_NORMAL"); rt.addInt(wxFONTWEIGHT_NORMAL);
+ rt.addTupleCount(2);
rt.addAtom("wxMOD_CMD"); rt.addInt(wxMOD_CMD);
rt.addTupleCount(2);
rt.addAtom("wxLANGUAGE_ABKHAZIAN"); rt.addInt(wxLANGUAGE_ABKHAZIAN);
@@ -654,6 +662,62 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {
rt.addTupleCount(2);
rt.addAtom("wxCYAN_PEN"); rt.addRef(getRef((void *)wxCYAN_PEN,memenv),"wxPen");
rt.addTupleCount(2);
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_EXTRABOLD"); rt.addInt(wxFONTWEIGHT_EXTRABOLD);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_EXTRABOLD"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_EXTRAHEAVY"); rt.addInt(wxFONTWEIGHT_EXTRAHEAVY);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_EXTRAHEAVY"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_EXTRALIGHT"); rt.addInt(wxFONTWEIGHT_EXTRALIGHT);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_EXTRALIGHT"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_HEAVY"); rt.addInt(wxFONTWEIGHT_HEAVY);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_HEAVY"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_INVALID"); rt.addInt(wxFONTWEIGHT_INVALID);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_INVALID"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_MEDIUM"); rt.addInt(wxFONTWEIGHT_MEDIUM);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_MEDIUM"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_SEMIBOLD"); rt.addInt(wxFONTWEIGHT_SEMIBOLD);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_SEMIBOLD"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,2)
+ rt.addAtom("wxFONTWEIGHT_THIN"); rt.addInt(wxFONTWEIGHT_THIN);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wxFONTWEIGHT_THIN"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
rt.addAtom("wxGREEN"); rt.add(*(wxGREEN));
rt.addTupleCount(2);
rt.addAtom("wxGREEN_BRUSH"); rt.addRef(getRef((void *)wxGREEN_BRUSH,memenv),"wxBrush");
@@ -723,7 +787,7 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {
rt.addAtom("wx_GL_COMPAT_PROFILE"); rt.addAtom("undefined");
rt.addTupleCount(2);
#endif
- rt.endList(309);
+ rt.endList(321);
rt.addTupleCount(2);
rt.send();
}
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index 4c8e52def2..c23e8a83bd 100644
--- a/lib/wx/c_src/gen/wxe_macros.h
+++ b/lib/wx/c_src/gen/wxe_macros.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
#include <wx/fontdlg.h>
#include <wx/progdlg.h>
#include <wx/printdlg.h>
+#include <wx/display.h>
#include <wx/dcbuffer.h>
#include <wx/dcmirror.h>
#include <wx/glcanvas.h>
@@ -46,6 +47,7 @@
#include <wx/sashwin.h>
#include <wx/laywin.h>
#include <wx/graphics.h>
+#include <wx/dcgraph.h>
#include <wx/aui/aui.h>
#include <wx/datectrl.h>
#include <wx/filepicker.h>
@@ -3426,5 +3428,21 @@
#define wxDropFilesEvent_GetPosition 3597
#define wxDropFilesEvent_GetNumberOfFiles 3598
#define wxDropFilesEvent_GetFiles 3599
+#define wxDisplay_new 3600
+#define wxDisplay_destruct 3601
+#define wxDisplay_IsOk 3602
+#define wxDisplay_GetClientArea 3603
+#define wxDisplay_GetGeometry 3604
+#define wxDisplay_GetName 3605
+#define wxDisplay_IsPrimary 3606
+#define wxDisplay_GetCount 3607
+#define wxDisplay_GetFromPoint 3608
+#define wxDisplay_GetFromWindow 3609
+#define wxDisplay_GetPPI 3610
+#define wxGCDC_new_1 3611
+#define wxGCDC_new_0 3612
+#define wxGCDC_destruct 3613
+#define wxGCDC_GetGraphicsContext 3614
+#define wxGCDC_SetGraphicsContext 3615
diff --git a/lib/wx/c_src/wxe_driver.c b/lib/wx/c_src/wxe_driver.c
index 8b8c625971..c9d299e0df 100644
--- a/lib/wx/c_src/wxe_driver.c
+++ b/lib/wx/c_src/wxe_driver.c
@@ -38,10 +38,8 @@
#define TEMP_BINARY_SIZE 512
-static ErlDrvData wxe_driver_start(ErlDrvPort port, char *buff);
-static int wxe_driver_load(void);
+static ErlDrvData wxe_driver_start(ErlDrvPort port, char *command);
static void wxe_driver_stop(ErlDrvData handle);
-static void wxe_driver_unload(void);
static ErlDrvSSizeT wxe_driver_control(ErlDrvData handle,
unsigned int command,
char* buf, ErlDrvSizeT count,
@@ -63,30 +61,30 @@ char * erl_wx_privdir;
** The driver struct
*/
static ErlDrvEntry wxe_driver_entry = {
- wxe_driver_load, /* F_PTR init, called at loading */
- wxe_driver_start, /* L_PTR start, called when port is opened */
- wxe_driver_stop, /* F_PTR stop, called when port is closed */
- NULL, /* F_PTR output, called when erlang has sent */
- NULL, /* F_PTR ready_input, called when input descriptor
- ready */
- NULL, /* F_PTR ready_output, called when output
- descriptor ready */
- "wxe_driver", /* char *driver_name, the argument to open_port */
- wxe_driver_unload, /* F_PTR finish, called when unloaded */
- NULL, /* void * that is not used (BC) */
- wxe_driver_control, /* F_PTR control, port_control callback */
- NULL, /* F_PTR timeout, reserved */
- standard_outputv, /* F_PTR outputv, reserved */
- NULL, /* async */
- NULL, /* flush */
- wxe_driver_call, /* call */
- NULL, /* Event */
+ NULL, /* F_PTR init, called at loading */
+ wxe_driver_start, /* L_PTR start, called when port is opened */
+ wxe_driver_stop, /* F_PTR stop, called when port is closed */
+ NULL, /* F_PTR output, called when erlang has sent */
+ NULL, /* F_PTR ready_input, called when
+ input descriptor ready */
+ NULL, /* F_PTR ready_output, called when
+ output descriptor ready */
+ "wxe_driver", /* char *driver_name, the argument to open_port */
+ NULL, /* F_PTR finish, called when unloaded */
+ NULL, /* void * that is not used (BC) */
+ wxe_driver_control, /* F_PTR control, port_control callback */
+ NULL, /* F_PTR timeout, reserved */
+ standard_outputv, /* F_PTR outputv, reserved */
+ NULL, /* async */
+ NULL, /* flush */
+ wxe_driver_call, /* call */
+ NULL, /* Event */
ERL_DRV_EXTENDED_MARKER,
ERL_DRV_EXTENDED_MAJOR_VERSION,
ERL_DRV_EXTENDED_MINOR_VERSION,
- ERL_DRV_FLAG_USE_PORT_LOCKING, /* Port lock */
- NULL, /* Reserved Handle */
- wxe_process_died, /* Process Exited */
+ ERL_DRV_FLAG_USE_PORT_LOCKING, /* Port lock */
+ NULL, /* Reserved Handle */
+ wxe_process_died, /* Process Exited */
};
DRIVER_INIT(wxe_driver)
@@ -94,60 +92,56 @@ DRIVER_INIT(wxe_driver)
return &wxe_driver_entry;
}
-int wxe_driver_load()
-{
- if(load_native_gui())
- return 0;
- else
- return -1;
-}
-
ErlDrvPort WXE_DRV_PORT_HANDLE = 0;
ErlDrvTermData WXE_DRV_PORT = 0;
static ErlDrvData
-wxe_driver_start(ErlDrvPort port, char *buff)
-{
- wxe_data *data;
-
- data = (wxe_data *) malloc(sizeof(wxe_data));
- wxe_debug = 0;
-
- if (data == NULL) {
- fprintf(stderr, " Couldn't alloc mem\r\n");
- return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
- } else {
- ErlDrvTermData term_port = driver_mk_port(port);
- set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
- data->driver_data = NULL;
- data->bin = (WXEBinRef*) driver_alloc(sizeof(WXEBinRef)*DEF_BINS);
- data->bin[0].from = 0;
- data->bin[1].from = 0;
- data->bin[2].from = 0;
- data->max_bins = DEF_BINS;
- data->port_handle = port;
- data->port = term_port;
- data->pdl = driver_pdl_create(port);
- if(WXE_DRV_PORT_HANDLE == 0) {
- for(; *buff != 32; buff++);
- buff++;
- erl_wx_privdir = strdup(buff);
-
- WXE_DRV_PORT_HANDLE = port;
- WXE_DRV_PORT = term_port;
- wxe_master = data;
- if(!(start_native_gui(data) == 1))
- return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
- } else {
- meta_command(CREATE_PORT,data);
- }
- return (ErlDrvData) data;
- }
+wxe_driver_start(ErlDrvPort port, char *command)
+{
+ wxe_data *data;
+
+ data = (wxe_data *) malloc(sizeof(wxe_data));
+ wxe_debug = 0;
+
+ if (data == NULL) {
+ fprintf(stderr, " Couldn't alloc mem\r\n");
+ return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
+ } else {
+ ErlDrvTermData term_port = driver_mk_port(port);
+ set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
+ data->driver_data = NULL;
+ data->bin = (WXEBinRef*) driver_alloc(sizeof(WXEBinRef)*DEF_BINS);
+ data->bin[0].from = 0;
+ data->bin[1].from = 0;
+ data->bin[2].from = 0;
+ data->max_bins = DEF_BINS;
+ data->port_handle = port;
+ data->port = term_port;
+ data->pdl = driver_pdl_create(port);
+ if(WXE_DRV_PORT_HANDLE == 0) {
+ char *first_space = strchr(command, ' ');
+ if (first_space) {
+ char *priv_dir = first_space + 1;
+ erl_wx_privdir = strdup(priv_dir);
+
+ WXE_DRV_PORT_HANDLE = port;
+ WXE_DRV_PORT = term_port;
+ wxe_master = data;
+ if(start_native_gui(data) != 1)
+ return ERL_DRV_ERROR_GENERAL; /* ENOMEM */
+ } else {
+ return ERL_DRV_ERROR_BADARG;
+ }
+ } else {
+ meta_command(CREATE_PORT, data);
+ }
+ return (ErlDrvData) data;
+ }
}
static void
wxe_driver_stop(ErlDrvData handle)
-{
+{
wxe_data *sd = ((wxe_data *)handle);
if(sd->port_handle != WXE_DRV_PORT_HANDLE) {
// fprintf(stderr, "%s:%d: STOP \r\n", __FILE__,__LINE__);
@@ -155,18 +149,11 @@ wxe_driver_stop(ErlDrvData handle)
} else {
// fprintf(stderr, "%s:%d: STOP \r\n", __FILE__,__LINE__);
stop_native_gui(wxe_master);
- unload_native_gui();
free(wxe_master);
wxe_master = NULL;
}
}
-static void
-wxe_driver_unload(void)
-{
- // fprintf(stderr, "%s:%d: UNLOAD \r\n", __FILE__,__LINE__);
-}
-
static ErlDrvSSizeT
wxe_driver_control(ErlDrvData handle, unsigned op,
char* buf, ErlDrvSizeT count,
@@ -194,7 +181,7 @@ wxe_driver_call(ErlDrvData handle, unsigned int command,
if (len > rlen)
*res = driver_alloc(len);
memcpy((void *) *res, (void *) buf, len);
- return len;
+ return len;
}
@@ -219,20 +206,20 @@ standard_outputv(ErlDrvData drv_data, ErlIOVec* ev)
int i, max;
for(i = 0; i < sd->max_bins; i++) {
- if(sd->bin[i].from == 0) {
- binref = &sd->bin[i];
- break;
- }
+ if(sd->bin[i].from == 0) {
+ binref = &sd->bin[i];
+ break;
+ }
}
if(binref == NULL) { /* realloc */
- max = sd->max_bins + DEF_BINS;
- driver_realloc(sd->bin, sizeof(WXEBinRef)*max);
- for(i=sd->max_bins; i < max; i++) {
- sd->bin[i].from = 0;
- }
- binref = &sd->bin[sd->max_bins];
- sd->max_bins = max;
+ max = sd->max_bins + DEF_BINS;
+ driver_realloc(sd->bin, sizeof(WXEBinRef)*max);
+ for(i=sd->max_bins; i < max; i++) {
+ sd->bin[i].from = 0;
+ }
+ binref = &sd->bin[sd->max_bins];
+ sd->max_bins = max;
}
if(ev->size > 0) {
diff --git a/lib/wx/c_src/wxe_driver.h b/lib/wx/c_src/wxe_driver.h
index f9bca049c8..6d6a67fa85 100644
--- a/lib/wx/c_src/wxe_driver.h
+++ b/lib/wx/c_src/wxe_driver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,10 +56,8 @@ typedef struct wxe_data_def {
void init_glexts(wxe_data*);
-int load_native_gui();
int start_native_gui(wxe_data *sd);
void stop_native_gui(wxe_data *sd);
-void unload_native_gui();
#define FUNC_CALL 13
#define CREATE_PORT 14
diff --git a/lib/wx/c_src/wxe_helpers.cpp b/lib/wx/c_src/wxe_helpers.cpp
index d1f607d2af..47955494f9 100644
--- a/lib/wx/c_src/wxe_helpers.cpp
+++ b/lib/wx/c_src/wxe_helpers.cpp
@@ -101,7 +101,7 @@ wxeCommand * wxeFifo::Peek(unsigned int *i)
}
-void wxeFifo::Add(int fc, char * cbuf,int buflen, wxe_data *sd)
+int wxeFifo::Add(int fc, char * cbuf,int buflen, wxe_data *sd)
{
unsigned int pos;
wxeCommand *curr;
@@ -144,6 +144,7 @@ void wxeFifo::Add(int fc, char * cbuf,int buflen, wxe_data *sd)
} else { // No-op only PING currently
curr->buffer = NULL;
}
+ return m_n;
}
void wxeFifo::Append(wxeCommand *orig)
diff --git a/lib/wx/c_src/wxe_helpers.h b/lib/wx/c_src/wxe_helpers.h
index 70ffccdc13..a6c00e5aca 100644
--- a/lib/wx/c_src/wxe_helpers.h
+++ b/lib/wx/c_src/wxe_helpers.h
@@ -63,7 +63,7 @@ class wxeFifo {
wxeFifo(unsigned int size);
virtual ~wxeFifo();
- void Add(int fc, char * cbuf,int buflen, wxe_data *);
+ int Add(int fc, char * cbuf,int buflen, wxe_data *);
void Append(wxeCommand *Other);
wxeCommand * Get();
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 1510866f09..43b5476073 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -70,7 +70,7 @@ void push_command(int op,char * buf,int len, wxe_data *sd)
/* fprintf(stderr, "Op %d %d [%ld] %d\r\n", op, (int) driver_caller(sd->port_handle),
wxe_batch->size(), wxe_batch_caller),fflush(stderr); */
erl_drv_mutex_lock(wxe_batch_locker_m);
- wxe_queue->Add(op, buf, len, sd);
+ int n = wxe_queue->Add(op, buf, len, sd);
if(wxe_needs_signal) {
// wx-thread is waiting on batch end in cond_wait
@@ -79,7 +79,7 @@ void push_command(int op,char * buf,int len, wxe_data *sd)
} else {
// wx-thread is waiting gui-events
erl_drv_mutex_unlock(wxe_batch_locker_m);
- wxWakeUpIdle();
+ if(n < 2) wxWakeUpIdle();
}
}
@@ -267,7 +267,7 @@ int WxeApp::dispatch_cmds()
return more;
}
-#define BREAK_BATCH 10000
+#define CHECK_EVENTS 10000
int WxeApp::dispatch(wxeFifo * batch)
{
@@ -278,13 +278,14 @@ int WxeApp::dispatch(wxeFifo * batch)
erl_drv_mutex_lock(wxe_batch_locker_m);
while(true) {
while((event = batch->Get()) != NULL) {
+ wait += 1;
erl_drv_mutex_unlock(wxe_batch_locker_m);
switch(event->op) {
case WXE_BATCH_END:
if(blevel>0) {
blevel--;
if(blevel==0)
- wait += BREAK_BATCH/4;
+ wait += CHECK_EVENTS/4;
}
break;
case WXE_BATCH_BEGIN:
@@ -314,21 +315,18 @@ int WxeApp::dispatch(wxeFifo * batch)
break;
}
event->Delete();
+ if(wait > CHECK_EVENTS)
+ return 1; // Let wx check for events
erl_drv_mutex_lock(wxe_batch_locker_m);
batch->Cleanup();
}
- if(blevel <= 0 || wait >= BREAK_BATCH) {
+ if(blevel <= 0) {
erl_drv_mutex_unlock(wxe_batch_locker_m);
- if(blevel > 0) {
- return 1; // We are still in a batch but we can let wx check for events
- } else {
- return 0;
- }
+ return 0;
}
// sleep until something happens
// fprintf(stderr, "%s:%d sleep %d %d %d\r\n", __FILE__, __LINE__, batch->m_n, blevel, wait);fflush(stderr);
wxe_needs_signal = 1;
- wait += 1;
while(batch->m_n == 0) {
erl_drv_cond_wait(wxe_batch_locker_c, wxe_batch_locker_m);
}
@@ -591,7 +589,7 @@ int WxeApp::newPtr(void * ptr, int type, wxeMemEnv *memenv) {
return ref;
}
-int WxeApp::getRef(void * ptr, wxeMemEnv *memenv) {
+int WxeApp::getRef(void * ptr, wxeMemEnv *memenv, int type) {
if(!ptr) return 0; // NULL and zero is the same
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
@@ -618,7 +616,7 @@ int WxeApp::getRef(void * ptr, wxeMemEnv *memenv) {
}
memenv->ref2ptr[ref] = ptr;
- ptr2ref[ptr] = new wxeRefData(ref, 0, false, memenv);
+ ptr2ref[ptr] = new wxeRefData(ref, type, false, memenv);
return ref;
}
diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h
index 140a2bd36a..69cc81c429 100644
--- a/lib/wx/c_src/wxe_impl.h
+++ b/lib/wx/c_src/wxe_impl.h
@@ -84,7 +84,7 @@ public:
wxeMemEnv * getMemEnv(ErlDrvTermData port);
int newPtr(void * ptr, int type, wxeMemEnv *memenv);
- int getRef(void * ptr, wxeMemEnv *memenv);
+ int getRef(void * ptr, wxeMemEnv *memenv, int type = 0);
void * getPtr(char * bp, wxeMemEnv *memenv);
void clearPtr(void *ptr);
wxeRefData * getRefData(void *ptr);
diff --git a/lib/wx/c_src/wxe_main.cpp b/lib/wx/c_src/wxe_main.cpp
index c7565e33bd..5b65d8a59b 100644
--- a/lib/wx/c_src/wxe_main.cpp
+++ b/lib/wx/c_src/wxe_main.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,15 +59,9 @@ void *wxe_main_loop(void * );
* START AND STOP of driver thread
* ************************************************************/
-int load_native_gui()
-{
- return 1;
-}
-
int start_native_gui(wxe_data *sd)
{
int res;
- ErlDrvThreadOpts *opts = NULL;
wxe_status_m = erl_drv_mutex_create((char *) "wxe_status_m");
wxe_status_c = erl_drv_cond_create((char *)"wxe_status_c");
@@ -79,7 +73,7 @@ int start_native_gui(wxe_data *sd)
res = erl_drv_steal_main_thread((char *)"wxwidgets",
&wxe_thread,wxe_main_loop,(void *) sd->pdl,NULL);
#else
- opts = erl_drv_thread_opts_create((char *)"wx thread");
+ ErlDrvThreadOpts *opts = erl_drv_thread_opts_create((char *)"wx thread");
opts->suggested_stack_size = 8192;
res = erl_drv_thread_create((char *)"wxwidgets",
&wxe_thread,wxe_main_loop,(void *) sd->pdl,opts);
@@ -116,11 +110,6 @@ void stop_native_gui(wxe_data *sd)
erl_drv_cond_destroy(wxe_batch_locker_c);
}
-void unload_native_gui()
-{
-
-}
-
/* ************************************************************
* wxWidgets Thread
* ************************************************************/
diff --git a/lib/wx/c_src/wxe_ps_init.c b/lib/wx/c_src/wxe_ps_init.c
index 4b3b47a80b..62c7c51c13 100644
--- a/lib/wx/c_src/wxe_ps_init.c
+++ b/lib/wx/c_src/wxe_ps_init.c
@@ -64,6 +64,10 @@ void * wxe_ps_init2() {
size_t app_len = 127;
char app_title_buf[128];
char * app_title;
+ size_t app_icon_len = 1023;
+ char app_icon_buf[1024];
+ char * app_icon;
+
// Setup and enable gui
pool = [[NSAutoreleasePool alloc] init];
@@ -78,9 +82,15 @@ void * wxe_ps_init2() {
if(!GetCurrentProcess(&psn)) {
CPSSetProcessName(&psn, app_title?app_title:"Erlang");
}
- // Load and set icon
+ // Enable setting custom application icon for Mac OS X
+ res = erl_drv_getenv("WX_APP_ICON", app_icon_buf, &app_icon_len);
NSMutableString *file = [[NSMutableString alloc] init];
- [file appendFormat:@"%s/%s", erl_wx_privdir, "erlang-logo64.png"];
+ if (res >= 0) {
+ [file appendFormat:@"%s", app_icon_buf];
+ } else {
+ [file appendFormat:@"%s/%s", erl_wx_privdir, "erlang-logo128.png"];
+ }
+ // Load and set icon
NSImage *icon = [[NSImage alloc] initWithContentsOfFile: file];
[NSApp setApplicationIconImage: icon];
};
diff --git a/lib/wx/doc/src/Makefile b/lib/wx/doc/src/Makefile
index 70555ae1eb..f66d63f63b 100644
--- a/lib/wx/doc/src/Makefile
+++ b/lib/wx/doc/src/Makefile
@@ -121,7 +121,8 @@ $(XML_CHAPTER_FILES:%=$(XMLDIR)/%): ../overview.edoc
debug opt:
clean clean_docs:
- rm -rf $(HTMLDIR)/*
+ rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 45638dff35..33d02e22ba 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -32,6 +32,56 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 1.8.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved support for wxWidgets 3.1.3 which have changed
+ <c>wxFONTWEIGTH</c>, also added <c>wxGCDC</c> and
+ <c>wxDisplay</c> modules.</p>
+ <p>
+ Fixed a crash on Mojave and check for events more often.</p>
+ <p>
+ Own Id: OTP-15587</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 1.8.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed delayed delete bug which caused wx applications to
+ crash on Mojave.</p>
+ <p>
+ Own Id: OTP-15426 Aux Id: ERL-755 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 1.8.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed compilation warning on Darwin.</p>
+ <p>
+ Own Id: OTP-15230 Aux Id: PR-1860 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 1.8.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index 23f3b95403..2c145595ee 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -398,6 +398,14 @@
-define(wxCYAN, wxe_util:get_const(wxCYAN)).
-define(wxCYAN_BRUSH, wxe_util:get_const(wxCYAN_BRUSH)).
-define(wxCYAN_PEN, wxe_util:get_const(wxCYAN_PEN)).
+-define(wxFONTWEIGHT_EXTRABOLD, wxe_util:get_const(wxFONTWEIGHT_EXTRABOLD)).
+-define(wxFONTWEIGHT_EXTRAHEAVY, wxe_util:get_const(wxFONTWEIGHT_EXTRAHEAVY)).
+-define(wxFONTWEIGHT_EXTRALIGHT, wxe_util:get_const(wxFONTWEIGHT_EXTRALIGHT)).
+-define(wxFONTWEIGHT_HEAVY, wxe_util:get_const(wxFONTWEIGHT_HEAVY)).
+-define(wxFONTWEIGHT_INVALID, wxe_util:get_const(wxFONTWEIGHT_INVALID)).
+-define(wxFONTWEIGHT_MEDIUM, wxe_util:get_const(wxFONTWEIGHT_MEDIUM)).
+-define(wxFONTWEIGHT_SEMIBOLD, wxe_util:get_const(wxFONTWEIGHT_SEMIBOLD)).
+-define(wxFONTWEIGHT_THIN, wxe_util:get_const(wxFONTWEIGHT_THIN)).
-define(wxGREEN, wxe_util:get_const(wxGREEN)).
-define(wxGREEN_BRUSH, wxe_util:get_const(wxGREEN_BRUSH)).
-define(wxGREEN_PEN, wxe_util:get_const(wxGREEN_PEN)).
@@ -1685,10 +1693,10 @@
-define(wxFONTSTYLE_SLANT, ?wxSLANT).
-define(wxFONTSTYLE_MAX, (?wxSLANT+1)).
% From "font.h": wxFontWeight
--define(wxFONTWEIGHT_NORMAL, ?wxNORMAL).
--define(wxFONTWEIGHT_LIGHT, ?wxLIGHT).
--define(wxFONTWEIGHT_BOLD, ?wxBOLD).
--define(wxFONTWEIGHT_MAX, (?wxBOLD+1)).
+-define(wxFONTWEIGHT_NORMAL, wxe_util:get_const(wxFONTWEIGHT_NORMAL)).
+-define(wxFONTWEIGHT_LIGHT, wxe_util:get_const(wxFONTWEIGHT_LIGHT)).
+-define(wxFONTWEIGHT_BOLD, wxe_util:get_const(wxFONTWEIGHT_BOLD)).
+-define(wxFONTWEIGHT_MAX, wxe_util:get_const(wxFONTWEIGHT_MAX)).
% From "fontenc.h": wxFontEncoding
-define(wxFONTENCODING_SYSTEM, -1).
-define(wxFONTENCODING_DEFAULT, 0).
diff --git a/lib/wx/src/gen/wxDisplay.erl b/lib/wx/src/gen/wxDisplay.erl
new file mode 100644
index 0000000000..b6a2bf22ac
--- /dev/null
+++ b/lib/wx/src/gen/wxDisplay.erl
@@ -0,0 +1,131 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%% This file is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html">wxDisplay</a>.
+%% @type wxDisplay(). An object reference, The representation is internal
+%% and can be changed without notice. It can't be used for comparsion
+%% stored on disc or distributed for use on other nodes.
+
+-module(wxDisplay).
+-include("wxe.hrl").
+-export([destroy/1,getClientArea/1,getCount/0,getFromPoint/1,getFromWindow/1,
+ getGeometry/1,getName/1,getPPI/1,isOk/1,isPrimary/1,new/0,new/1]).
+
+%% inherited exports
+-export([parent_class/1]).
+
+-export_type([wxDisplay/0]).
+%% @hidden
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxDisplay() :: wx:wx_object().
+%% @equiv new([])
+-spec new() -> wxDisplay().
+
+new() ->
+ new([]).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaywxdisplay">external documentation</a>.
+-spec new([Option]) -> wxDisplay() when
+ Option :: {'n', integer()}.
+new(Options)
+ when is_list(Options) ->
+ MOpts = fun({n, N}, Acc) -> [<<1:32/?UI,N:32/?UI>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:construct(?wxDisplay_new,
+ <<BinOpt/binary>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplayisok">external documentation</a>.
+-spec isOk(This) -> boolean() when
+ This::wxDisplay().
+isOk(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxDisplay),
+ wxe_util:call(?wxDisplay_IsOk,
+ <<ThisRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaygetclientarea">external documentation</a>.
+-spec getClientArea(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxDisplay().
+getClientArea(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxDisplay),
+ wxe_util:call(?wxDisplay_GetClientArea,
+ <<ThisRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaygetgeometry">external documentation</a>.
+-spec getGeometry(This) -> {X::integer(), Y::integer(), W::integer(), H::integer()} when
+ This::wxDisplay().
+getGeometry(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxDisplay),
+ wxe_util:call(?wxDisplay_GetGeometry,
+ <<ThisRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaygetname">external documentation</a>.
+-spec getName(This) -> unicode:charlist() when
+ This::wxDisplay().
+getName(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxDisplay),
+ wxe_util:call(?wxDisplay_GetName,
+ <<ThisRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplayisprimary">external documentation</a>.
+-spec isPrimary(This) -> boolean() when
+ This::wxDisplay().
+isPrimary(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxDisplay),
+ wxe_util:call(?wxDisplay_IsPrimary,
+ <<ThisRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaygetcount">external documentation</a>.
+-spec getCount() -> integer().
+getCount() ->
+ wxe_util:call(?wxDisplay_GetCount,
+ <<>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaygetfrompoint">external documentation</a>.
+-spec getFromPoint(Pt) -> integer() when
+ Pt::{X::integer(), Y::integer()}.
+getFromPoint({PtX,PtY})
+ when is_integer(PtX),is_integer(PtY) ->
+ wxe_util:call(?wxDisplay_GetFromPoint,
+ <<PtX:32/?UI,PtY:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaygetfromwindow">external documentation</a>.
+-spec getFromWindow(Window) -> integer() when
+ Window::wxWindow:wxWindow().
+getFromWindow(#wx_ref{type=WindowT,ref=WindowRef}) ->
+ ?CLASS(WindowT,wxWindow),
+ wxe_util:call(?wxDisplay_GetFromWindow,
+ <<WindowRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdisplay.html#wxdisplaygetppi">external documentation</a>.
+-spec getPPI(This) -> {W::integer(), H::integer()} when
+ This::wxDisplay().
+getPPI(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxDisplay),
+ wxe_util:call(?wxDisplay_GetPPI,
+ <<ThisRef:32/?UI>>).
+
+%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxDisplay()) -> 'ok'.
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxDisplay),
+ wxe_util:destroy(?wxDisplay_destruct,Obj),
+ ok.
diff --git a/lib/wx/src/gen/wxGCDC.erl b/lib/wx/src/gen/wxGCDC.erl
new file mode 100644
index 0000000000..467013b14e
--- /dev/null
+++ b/lib/wx/src/gen/wxGCDC.erl
@@ -0,0 +1,287 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%% This file is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxgcdc.html">wxGCDC</a>.
+%% <p>This class is derived (and can use functions) from:
+%% <br />{@link wxDC}
+%% </p>
+%% @type wxGCDC(). An object reference, The representation is internal
+%% and can be changed without notice. It can't be used for comparsion
+%% stored on disc or distributed for use on other nodes.
+
+-module(wxGCDC).
+-include("wxe.hrl").
+-export([destroy/1,getGraphicsContext/1,new/0,new/1,setGraphicsContext/2]).
+
+%% inherited exports
+-export([blit/5,blit/6,calcBoundingBox/3,clear/1,computeScaleAndOrigin/1,crossHair/2,
+ destroyClippingRegion/1,deviceToLogicalX/2,deviceToLogicalXRel/2,
+ deviceToLogicalY/2,deviceToLogicalYRel/2,drawArc/4,drawBitmap/3,drawBitmap/4,
+ drawCheckMark/2,drawCircle/3,drawEllipse/2,drawEllipse/3,drawEllipticArc/5,
+ drawIcon/3,drawLabel/3,drawLabel/4,drawLine/3,drawLines/2,drawLines/3,
+ drawPoint/2,drawPolygon/2,drawPolygon/3,drawRectangle/2,drawRectangle/3,
+ drawRotatedText/4,drawRoundedRectangle/3,drawRoundedRectangle/4,
+ drawText/3,endDoc/1,endPage/1,floodFill/3,floodFill/4,getBackground/1,
+ getBackgroundMode/1,getBrush/1,getCharHeight/1,getCharWidth/1,getClippingBox/1,
+ getFont/1,getLayoutDirection/1,getLogicalFunction/1,getMapMode/1,
+ getMultiLineTextExtent/2,getMultiLineTextExtent/3,getPPI/1,getPartialTextExtents/2,
+ getPen/1,getPixel/2,getSize/1,getSizeMM/1,getTextBackground/1,getTextExtent/2,
+ getTextExtent/3,getTextForeground/1,getUserScale/1,gradientFillConcentric/4,
+ gradientFillConcentric/5,gradientFillLinear/4,gradientFillLinear/5,
+ isOk/1,logicalToDeviceX/2,logicalToDeviceXRel/2,logicalToDeviceY/2,
+ logicalToDeviceYRel/2,maxX/1,maxY/1,minX/1,minY/1,parent_class/1,resetBoundingBox/1,
+ setAxisOrientation/3,setBackground/2,setBackgroundMode/2,setBrush/2,
+ setClippingRegion/2,setClippingRegion/3,setDeviceOrigin/3,setFont/2,
+ setLayoutDirection/2,setLogicalFunction/2,setMapMode/2,setPalette/2,
+ setPen/2,setTextBackground/2,setTextForeground/2,setUserScale/3,startDoc/2,
+ startPage/1]).
+
+-export_type([wxGCDC/0]).
+-compile([{nowarn_deprecated_function, {wxDC,computeScaleAndOrigin,1}}]).
+
+%% @hidden
+parent_class(wxDC) -> true;
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+-type wxGCDC() :: wx:wx_object().
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxgcdc.html#wxgcdcwxgcdc">external documentation</a>.
+-spec new() -> wxGCDC().
+new() ->
+ wxe_util:construct(?wxGCDC_new_0,
+ <<>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxgcdc.html#wxgcdcwxgcdc">external documentation</a>.
+-spec new(Dc) -> wxGCDC() when
+ Dc::wxWindowDC:wxWindowDC().
+new(#wx_ref{type=DcT,ref=DcRef}) ->
+ ?CLASS(DcT,wxWindowDC),
+ wxe_util:construct(?wxGCDC_new_1,
+ <<DcRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxgcdc.html#wxgcdcgetgraphicscontext">external documentation</a>.
+-spec getGraphicsContext(This) -> wxGraphicsContext:wxGraphicsContext() when
+ This::wxGCDC().
+getGraphicsContext(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxGCDC),
+ wxe_util:call(?wxGCDC_GetGraphicsContext,
+ <<ThisRef:32/?UI>>).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxgcdc.html#wxgcdcsetgraphicscontext">external documentation</a>.
+-spec setGraphicsContext(This, Ctx) -> 'ok' when
+ This::wxGCDC(), Ctx::wxGraphicsContext:wxGraphicsContext().
+setGraphicsContext(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CtxT,ref=CtxRef}) ->
+ ?CLASS(ThisT,wxGCDC),
+ ?CLASS(CtxT,wxGraphicsContext),
+ wxe_util:cast(?wxGCDC_SetGraphicsContext,
+ <<ThisRef:32/?UI,CtxRef:32/?UI>>).
+
+%% @doc Destroys this object, do not use object again
+-spec destroy(This::wxGCDC()) -> 'ok'.
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxGCDC),
+ wxe_util:destroy(?DESTROY_OBJECT,Obj),
+ ok.
+ %% From wxDC
+%% @hidden
+startPage(This) -> wxDC:startPage(This).
+%% @hidden
+startDoc(This,Message) -> wxDC:startDoc(This,Message).
+%% @hidden
+setUserScale(This,X,Y) -> wxDC:setUserScale(This,X,Y).
+%% @hidden
+setTextForeground(This,Colour) -> wxDC:setTextForeground(This,Colour).
+%% @hidden
+setTextBackground(This,Colour) -> wxDC:setTextBackground(This,Colour).
+%% @hidden
+setPen(This,Pen) -> wxDC:setPen(This,Pen).
+%% @hidden
+setPalette(This,Palette) -> wxDC:setPalette(This,Palette).
+%% @hidden
+setMapMode(This,Mode) -> wxDC:setMapMode(This,Mode).
+%% @hidden
+setLogicalFunction(This,Function) -> wxDC:setLogicalFunction(This,Function).
+%% @hidden
+setLayoutDirection(This,Dir) -> wxDC:setLayoutDirection(This,Dir).
+%% @hidden
+setFont(This,Font) -> wxDC:setFont(This,Font).
+%% @hidden
+setDeviceOrigin(This,X,Y) -> wxDC:setDeviceOrigin(This,X,Y).
+%% @hidden
+setClippingRegion(This,Pt,Sz) -> wxDC:setClippingRegion(This,Pt,Sz).
+%% @hidden
+setClippingRegion(This,Region) -> wxDC:setClippingRegion(This,Region).
+%% @hidden
+setBrush(This,Brush) -> wxDC:setBrush(This,Brush).
+%% @hidden
+setBackgroundMode(This,Mode) -> wxDC:setBackgroundMode(This,Mode).
+%% @hidden
+setBackground(This,Brush) -> wxDC:setBackground(This,Brush).
+%% @hidden
+setAxisOrientation(This,XLeftRight,YBottomUp) -> wxDC:setAxisOrientation(This,XLeftRight,YBottomUp).
+%% @hidden
+resetBoundingBox(This) -> wxDC:resetBoundingBox(This).
+%% @hidden
+isOk(This) -> wxDC:isOk(This).
+%% @hidden
+minY(This) -> wxDC:minY(This).
+%% @hidden
+minX(This) -> wxDC:minX(This).
+%% @hidden
+maxY(This) -> wxDC:maxY(This).
+%% @hidden
+maxX(This) -> wxDC:maxX(This).
+%% @hidden
+logicalToDeviceYRel(This,Y) -> wxDC:logicalToDeviceYRel(This,Y).
+%% @hidden
+logicalToDeviceY(This,Y) -> wxDC:logicalToDeviceY(This,Y).
+%% @hidden
+logicalToDeviceXRel(This,X) -> wxDC:logicalToDeviceXRel(This,X).
+%% @hidden
+logicalToDeviceX(This,X) -> wxDC:logicalToDeviceX(This,X).
+%% @hidden
+gradientFillLinear(This,Rect,InitialColour,DestColour, Options) -> wxDC:gradientFillLinear(This,Rect,InitialColour,DestColour, Options).
+%% @hidden
+gradientFillLinear(This,Rect,InitialColour,DestColour) -> wxDC:gradientFillLinear(This,Rect,InitialColour,DestColour).
+%% @hidden
+gradientFillConcentric(This,Rect,InitialColour,DestColour,CircleCenter) -> wxDC:gradientFillConcentric(This,Rect,InitialColour,DestColour,CircleCenter).
+%% @hidden
+gradientFillConcentric(This,Rect,InitialColour,DestColour) -> wxDC:gradientFillConcentric(This,Rect,InitialColour,DestColour).
+%% @hidden
+getUserScale(This) -> wxDC:getUserScale(This).
+%% @hidden
+getTextForeground(This) -> wxDC:getTextForeground(This).
+%% @hidden
+getTextExtent(This,String, Options) -> wxDC:getTextExtent(This,String, Options).
+%% @hidden
+getTextExtent(This,String) -> wxDC:getTextExtent(This,String).
+%% @hidden
+getTextBackground(This) -> wxDC:getTextBackground(This).
+%% @hidden
+getSizeMM(This) -> wxDC:getSizeMM(This).
+%% @hidden
+getSize(This) -> wxDC:getSize(This).
+%% @hidden
+getPPI(This) -> wxDC:getPPI(This).
+%% @hidden
+getPixel(This,Pt) -> wxDC:getPixel(This,Pt).
+%% @hidden
+getPen(This) -> wxDC:getPen(This).
+%% @hidden
+getPartialTextExtents(This,Text) -> wxDC:getPartialTextExtents(This,Text).
+%% @hidden
+getMultiLineTextExtent(This,String, Options) -> wxDC:getMultiLineTextExtent(This,String, Options).
+%% @hidden
+getMultiLineTextExtent(This,String) -> wxDC:getMultiLineTextExtent(This,String).
+%% @hidden
+getMapMode(This) -> wxDC:getMapMode(This).
+%% @hidden
+getLogicalFunction(This) -> wxDC:getLogicalFunction(This).
+%% @hidden
+getLayoutDirection(This) -> wxDC:getLayoutDirection(This).
+%% @hidden
+getFont(This) -> wxDC:getFont(This).
+%% @hidden
+getClippingBox(This) -> wxDC:getClippingBox(This).
+%% @hidden
+getCharWidth(This) -> wxDC:getCharWidth(This).
+%% @hidden
+getCharHeight(This) -> wxDC:getCharHeight(This).
+%% @hidden
+getBrush(This) -> wxDC:getBrush(This).
+%% @hidden
+getBackgroundMode(This) -> wxDC:getBackgroundMode(This).
+%% @hidden
+getBackground(This) -> wxDC:getBackground(This).
+%% @hidden
+floodFill(This,Pt,Col, Options) -> wxDC:floodFill(This,Pt,Col, Options).
+%% @hidden
+floodFill(This,Pt,Col) -> wxDC:floodFill(This,Pt,Col).
+%% @hidden
+endPage(This) -> wxDC:endPage(This).
+%% @hidden
+endDoc(This) -> wxDC:endDoc(This).
+%% @hidden
+drawText(This,Text,Pt) -> wxDC:drawText(This,Text,Pt).
+%% @hidden
+drawRoundedRectangle(This,Pt,Sz,Radius) -> wxDC:drawRoundedRectangle(This,Pt,Sz,Radius).
+%% @hidden
+drawRoundedRectangle(This,R,Radius) -> wxDC:drawRoundedRectangle(This,R,Radius).
+%% @hidden
+drawRotatedText(This,Text,Pt,Angle) -> wxDC:drawRotatedText(This,Text,Pt,Angle).
+%% @hidden
+drawRectangle(This,Pt,Sz) -> wxDC:drawRectangle(This,Pt,Sz).
+%% @hidden
+drawRectangle(This,Rect) -> wxDC:drawRectangle(This,Rect).
+%% @hidden
+drawPoint(This,Pt) -> wxDC:drawPoint(This,Pt).
+%% @hidden
+drawPolygon(This,Points, Options) -> wxDC:drawPolygon(This,Points, Options).
+%% @hidden
+drawPolygon(This,Points) -> wxDC:drawPolygon(This,Points).
+%% @hidden
+drawLines(This,Points, Options) -> wxDC:drawLines(This,Points, Options).
+%% @hidden
+drawLines(This,Points) -> wxDC:drawLines(This,Points).
+%% @hidden
+drawLine(This,Pt1,Pt2) -> wxDC:drawLine(This,Pt1,Pt2).
+%% @hidden
+drawLabel(This,Text,Rect, Options) -> wxDC:drawLabel(This,Text,Rect, Options).
+%% @hidden
+drawLabel(This,Text,Rect) -> wxDC:drawLabel(This,Text,Rect).
+%% @hidden
+drawIcon(This,Icon,Pt) -> wxDC:drawIcon(This,Icon,Pt).
+%% @hidden
+drawEllipticArc(This,Pt,Sz,Sa,Ea) -> wxDC:drawEllipticArc(This,Pt,Sz,Sa,Ea).
+%% @hidden
+drawEllipse(This,Pt,Sz) -> wxDC:drawEllipse(This,Pt,Sz).
+%% @hidden
+drawEllipse(This,Rect) -> wxDC:drawEllipse(This,Rect).
+%% @hidden
+drawCircle(This,Pt,Radius) -> wxDC:drawCircle(This,Pt,Radius).
+%% @hidden
+drawCheckMark(This,Rect) -> wxDC:drawCheckMark(This,Rect).
+%% @hidden
+drawBitmap(This,Bmp,Pt, Options) -> wxDC:drawBitmap(This,Bmp,Pt, Options).
+%% @hidden
+drawBitmap(This,Bmp,Pt) -> wxDC:drawBitmap(This,Bmp,Pt).
+%% @hidden
+drawArc(This,Pt1,Pt2,Centre) -> wxDC:drawArc(This,Pt1,Pt2,Centre).
+%% @hidden
+deviceToLogicalYRel(This,Y) -> wxDC:deviceToLogicalYRel(This,Y).
+%% @hidden
+deviceToLogicalY(This,Y) -> wxDC:deviceToLogicalY(This,Y).
+%% @hidden
+deviceToLogicalXRel(This,X) -> wxDC:deviceToLogicalXRel(This,X).
+%% @hidden
+deviceToLogicalX(This,X) -> wxDC:deviceToLogicalX(This,X).
+%% @hidden
+destroyClippingRegion(This) -> wxDC:destroyClippingRegion(This).
+%% @hidden
+crossHair(This,Pt) -> wxDC:crossHair(This,Pt).
+%% @hidden
+computeScaleAndOrigin(This) -> wxDC:computeScaleAndOrigin(This).
+%% @hidden
+clear(This) -> wxDC:clear(This).
+%% @hidden
+calcBoundingBox(This,X,Y) -> wxDC:calcBoundingBox(This,X,Y).
+%% @hidden
+blit(This,DestPt,Sz,Source,SrcPt, Options) -> wxDC:blit(This,DestPt,Sz,Source,SrcPt, Options).
+%% @hidden
+blit(This,DestPt,Sz,Source,SrcPt) -> wxDC:blit(This,DestPt,Sz,Source,SrcPt).
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index 533f9f2df0..b64a1b4c61 100644
--- a/lib/wx/src/gen/wxe_debug.hrl
+++ b/lib/wx/src/gen/wxe_debug.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -3377,6 +3377,22 @@ wxdebug_table() ->
{3597, {wxDropFilesEvent, getPosition, 0}},
{3598, {wxDropFilesEvent, getNumberOfFiles, 0}},
{3599, {wxDropFilesEvent, getFiles, 0}},
+ {3600, {wxDisplay, new, 1}},
+ {3601, {wxDisplay, destruct, 0}},
+ {3602, {wxDisplay, isOk, 0}},
+ {3603, {wxDisplay, getClientArea, 0}},
+ {3604, {wxDisplay, getGeometry, 0}},
+ {3605, {wxDisplay, getName, 0}},
+ {3606, {wxDisplay, isPrimary, 0}},
+ {3607, {wxDisplay, getCount, 0}},
+ {3608, {wxDisplay, getFromPoint, 1}},
+ {3609, {wxDisplay, getFromWindow, 1}},
+ {3610, {wxDisplay, getPPI, 0}},
+ {3611, {wxGCDC, new_1, 1}},
+ {3612, {wxGCDC, new_0, 0}},
+ {3613, {wxGCDC, destruct, 0}},
+ {3614, {wxGCDC, getGraphicsContext, 0}},
+ {3615, {wxGCDC, setGraphicsContext, 1}},
{-1, {mod, func, -1}}
].
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index 14b5545676..030f7f117d 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -3374,3 +3374,19 @@
-define(wxDropFilesEvent_GetPosition, 3597).
-define(wxDropFilesEvent_GetNumberOfFiles, 3598).
-define(wxDropFilesEvent_GetFiles, 3599).
+-define(wxDisplay_new, 3600).
+-define(wxDisplay_destruct, 3601).
+-define(wxDisplay_IsOk, 3602).
+-define(wxDisplay_GetClientArea, 3603).
+-define(wxDisplay_GetGeometry, 3604).
+-define(wxDisplay_GetName, 3605).
+-define(wxDisplay_IsPrimary, 3606).
+-define(wxDisplay_GetCount, 3607).
+-define(wxDisplay_GetFromPoint, 3608).
+-define(wxDisplay_GetFromWindow, 3609).
+-define(wxDisplay_GetPPI, 3610).
+-define(wxGCDC_new_1, 3611).
+-define(wxGCDC_new_0, 3612).
+-define(wxGCDC_destruct, 3613).
+-define(wxGCDC_GetGraphicsContext, 3614).
+-define(wxGCDC_SetGraphicsContext, 3615).
diff --git a/lib/wx/test/wxt b/lib/wx/test/wxt
index e720ed94f4..94513e88e9 100755
--- a/lib/wx/test/wxt
+++ b/lib/wx/test/wxt
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
#
# %CopyrightEnd%
#
-# Usage: mt <args to erlang startup script>
+# Usage: wxt <args to erlang startup script>
log=test_log_$$
latest=test_log_latest
@@ -27,7 +27,7 @@ erlcmd="erl -sname test_server -smp -pa ../ebin $p $args -wx_test_verbose true -
echo "Give the following command in order to see the outcome:"
echo ""
-echo " less test_log$$"
+echo " less $log"
rm "$latest" 2>/dev/null
ln -s "$log" "$latest"
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 37a5477631..dac219fa98 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 1.8.4
+WX_VSN = 1.8.7
diff --git a/lib/xmerl/doc/src/Makefile b/lib/xmerl/doc/src/Makefile
index d87677d0a7..0def492246 100644
--- a/lib/xmerl/doc/src/Makefile
+++ b/lib/xmerl/doc/src/Makefile
@@ -140,6 +140,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(XMERL_XML_FILES)
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index b7d1db7dfc..63070ea316 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -32,6 +32,75 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.3.20.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>xmerl_sax_parser</c> crashed during charset detection
+ when the xml declarations attribute values was missing
+ the closing quotation (&apos; or &quot;).</p>
+ <p>
+ Own Id: OTP-15826</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.20</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Handling of character references in attributes are fixed.</p>
+ <p>
+ Own Id: OTP-15684 Aux Id: ERL-837 </p>
+ </item>
+ <item>
+ <p>
+ Normalization of whitespace characters in attributes are
+ fixed so it works when character references are used.</p>
+ <p>
+ Own Id: OTP-15685 Aux Id: ERL-475 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.19</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The charset detection parsing crash in some cases when
+ the XML directive is not syntactic correct.</p>
+ <p>
+ Own Id: OTP-15492 Aux Id: ERIERL-283 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.3.17</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -47,6 +116,21 @@
</section>
+<section><title>Xmerl 1.3.16.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The charset detection parsing crash in some cases when
+ the XML directive is not syntactic correct.</p>
+ <p>
+ Own Id: OTP-15492 Aux Id: ERIERL-283 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.3.16</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1397,4 +1481,3 @@
</section>
</section>
</chapter>
-
diff --git a/lib/xmerl/doc/src/xmerl_sax_parser.xml b/lib/xmerl/doc/src/xmerl_sax_parser.xml
index 8ea197e209..2390779028 100644
--- a/lib/xmerl/doc/src/xmerl_sax_parser.xml
+++ b/lib/xmerl/doc/src/xmerl_sax_parser.xml
@@ -31,7 +31,7 @@
<rev></rev>
</header>
- <module>xmerl_sax_parser</module>
+ <module since="">xmerl_sax_parser</module>
<modulesummary>XML SAX parser API</modulesummary>
<description>
@@ -325,7 +325,7 @@
<funcs>
<func>
- <name>file(Filename, Options) -> Result</name>
+ <name since="">file(Filename, Options) -> Result</name>
<fsummary>Parse file containing an XML document.</fsummary>
<type>
<v>Filename = string()</v>
@@ -347,7 +347,7 @@
</func>
<func>
- <name>stream(Xml, Options) -> Result</name>
+ <name since="">stream(Xml, Options) -> Result</name>
<fsummary>Parse a stream containing an XML document.</fsummary>
<type>
<v>Xml = unicode_binary() | latin1_binary() | [unicode_char()]</v>
@@ -381,7 +381,7 @@
<funcs>
<func>
- <name>ContinuationFun(State) -> {NewBytes, NewState}</name>
+ <name since="">ContinuationFun(State) -> {NewBytes, NewState}</name>
<fsummary>Continuation call back function.</fsummary>
<type>
<v>State = NewState = term()</v>
@@ -402,7 +402,7 @@
</func>
<func>
- <name>EventFun(Event, Location, State) -> NewState</name>
+ <name since="">EventFun(Event, Location, State) -> NewState</name>
<fsummary>Event call back function.</fsummary>
<type>
<v>Event = event()</v>
diff --git a/lib/xmerl/src/xmerl_sax_parser.erl b/lib/xmerl/src/xmerl_sax_parser.erl
index e383c4c349..2767d02552 100644
--- a/lib/xmerl/src/xmerl_sax_parser.erl
+++ b/lib/xmerl/src/xmerl_sax_parser.erl
@@ -1,8 +1,8 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
+%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
@@ -14,13 +14,13 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-%%
+%%
%% %CopyrightEnd%
%%----------------------------------------------------------------------
%% File : xmerl_sax_parser.erl
%% Description : XML SAX parse API module.
%%
-%% Created : 4 Jun 2008
+%% Created : 4 Jun 2008
%%----------------------------------------------------------------------
-module(xmerl_sax_parser).
@@ -72,9 +72,9 @@ file(Name,Options) ->
CL = filename:absname(Dir),
File = filename:basename(Name),
ContinuationFun = fun default_continuation_cb/1,
- Res = stream(<<>>,
+ Res = stream(<<>>,
[{continuation_fun, ContinuationFun},
- {continuation_state, FD},
+ {continuation_state, FD},
{current_location, CL},
{entity, File}
|Options],
@@ -101,39 +101,39 @@ stream(Xml, Options, InputType) when is_list(Xml), is_list(Options) ->
State = parse_options(Options, initial_state()),
case State#xmerl_sax_parser_state.file_type of
dtd ->
- xmerl_sax_parser_list:parse_dtd(Xml,
+ xmerl_sax_parser_list:parse_dtd(Xml,
State#xmerl_sax_parser_state{encoding = list,
input_type = InputType});
normal ->
- xmerl_sax_parser_list:parse(Xml,
+ xmerl_sax_parser_list:parse(Xml,
State#xmerl_sax_parser_state{encoding = list,
input_type = InputType})
end;
stream(Xml, Options, InputType) when is_binary(Xml), is_list(Options) ->
- case parse_options(Options, initial_state()) of
+ case parse_options(Options, initial_state()) of
{error, Reason} -> {error, Reason};
State ->
- ParseFunction =
+ ParseFunction =
case State#xmerl_sax_parser_state.file_type of
dtd ->
parse_dtd;
normal ->
parse
end,
- try
+ try
{Xml1, State1} = detect_charset(Xml, State),
parse_binary(Xml1,
State1#xmerl_sax_parser_state{input_type = InputType},
ParseFunction)
catch
throw:{fatal_error, {State2, Reason}} ->
- {fatal_error,
+ {fatal_error,
{
State2#xmerl_sax_parser_state.current_location,
- State2#xmerl_sax_parser_state.entity,
+ State2#xmerl_sax_parser_state.entity,
1
},
- Reason, [],
+ Reason, [],
State2#xmerl_sax_parser_state.event_state}
end
end.
@@ -157,7 +157,7 @@ parse_binary(Xml, #xmerl_sax_parser_state{encoding={utf16,big}}=State, F) ->
xmerl_sax_parser_utf16be:F(Xml, State);
parse_binary(Xml, #xmerl_sax_parser_state{encoding=latin1}=State, F) ->
xmerl_sax_parser_latin1:F(Xml, State);
-parse_binary(_, #xmerl_sax_parser_state{encoding=Enc}, State) ->
+parse_binary(_, #xmerl_sax_parser_state{encoding=Enc}, State) ->
?fatal_error(State, lists:flatten(io_lib:format("Charcter set ~p not supported", [Enc]))).
%%----------------------------------------------------------------------
@@ -177,9 +177,9 @@ initial_state() ->
%%----------------------------------------------------------------------
%% Function: parse_options(Options, State)
%% Input: Options = [Option]
-%% Option = {event_state, term()} | {event_fun, fun()} |
+%% Option = {event_state, term()} | {event_fun, fun()} |
%% {continuation_state, term()} | {continuation_fun, fun()} |
-%% {encoding, Encoding} | {file_type, FT}
+%% {encoding, Encoding} | {file_type, FT}
%% FT = normal | dtd
%% Encoding = utf8 | utf16le | utf16be | list | iso8859
%% State = #xmerl_sax_parser_state{}
@@ -200,7 +200,7 @@ parse_options([{file_type, FT} |Options], State) when FT==normal; FT==dtd ->
parse_options(Options, State#xmerl_sax_parser_state{file_type = FT});
parse_options([{encoding, E} |Options], State) ->
case check_encoding_option(E) of
- {error, Reason} ->
+ {error, Reason} ->
{error, Reason};
Enc ->
parse_options(Options, State#xmerl_sax_parser_state{encoding = Enc})
@@ -231,7 +231,7 @@ check_encoding_option(E) ->
%% Description: Detects which character set is used in a binary stream.
%%----------------------------------------------------------------------
detect_charset(<<>>, #xmerl_sax_parser_state{continuation_fun = undefined} = State) ->
- ?fatal_error(State, "Can't detect character encoding due to lack of indata");
+ ?fatal_error(State, "Can't detect character encoding due to lack of indata");
detect_charset(<<>>, State) ->
cf(<<>>, State, fun detect_charset/2);
detect_charset(Bytes, State) ->
@@ -269,22 +269,14 @@ detect_charset_1(<<16#3C, 16#3F, 16#78, 16#6D>> = Xml, State) ->
cf(Xml, State, fun detect_charset_1/2);
detect_charset_1(<<16#3C, 16#3F, 16#78, 16#6D, 16#6C, Xml2/binary>>, State) ->
{Xml3, State1} = read_until_end_of_xml_directive(Xml2, State),
- case parse_xml_directive(Xml3) of
- {error, Reason} ->
- ?fatal_error(State, Reason);
- AttrList ->
- case lists:keysearch("encoding", 1, AttrList) of
- {value, {_, E}} ->
- case convert_encoding(E) of
- {error, Reason} ->
- ?fatal_error(State, Reason);
- Enc ->
- {<<16#3C, 16#3F, 16#78, 16#6D, 16#6C, Xml3/binary>>,
- State1#xmerl_sax_parser_state{encoding=Enc}}
- end;
- _ ->
- {<<16#3C, 16#3F, 16#78, 16#6D, 16#6C, Xml3/binary>>, State1}
- end
+ AttrList = parse_xml_directive(Xml3, State),
+ case lists:keysearch("encoding", 1, AttrList) of
+ {value, {_, E}} ->
+ Enc = convert_encoding(E, State),
+ {<<16#3C, 16#3F, 16#78, 16#6D, 16#6C, Xml3/binary>>,
+ State1#xmerl_sax_parser_state{encoding=Enc}};
+ _ ->
+ {<<16#3C, 16#3F, 16#78, 16#6D, 16#6C, Xml3/binary>>, State1}
end;
detect_charset_1(Xml, State) ->
{Xml, State}.
@@ -295,7 +287,7 @@ detect_charset_1(Xml, State) ->
%% Output: utf8 | iso8859
%% Description: Converting 7,8 bit and utf8 encoding strings to internal format.
%%----------------------------------------------------------------------
-convert_encoding(Enc) -> %% Just for 7,8 bit + utf8
+convert_encoding(Enc, State) -> %% Just for 7,8 bit + utf8
case string:to_lower(Enc) of
"utf-8" -> utf8;
"us-ascii" -> utf8;
@@ -309,19 +301,19 @@ convert_encoding(Enc) -> %% Just for 7,8 bit + utf8
"iso-8859-7" -> latin1;
"iso-8859-8" -> latin1;
"iso-8859-9" -> latin1;
- _ -> {error, "Unknown encoding: " ++ Enc}
+ _ -> ?fatal_error(State, "Unknown encoding: " ++ Enc)
end.
%%----------------------------------------------------------------------
%% Function: parse_xml_directive(Xml)
%% Input: Xml = binary()
%% Acc = list()
-%% Output:
+%% Output:
%% Description: Parsing the xml declaration from the input stream.
%%----------------------------------------------------------------------
-parse_xml_directive(<<C, Rest/binary>>) when ?is_whitespace(C) ->
- parse_xml_directive_1(Rest, []).
-
+parse_xml_directive(<<C, Rest/binary>>, State) when ?is_whitespace(C) ->
+ parse_xml_directive_1(Rest, [], State).
+
%%----------------------------------------------------------------------
%% Function: parse_xml_directive_1(Xml, Acc) -> [{Name, Value}]
%% Input: Xml = binary()
@@ -331,20 +323,20 @@ parse_xml_directive(<<C, Rest/binary>>) when ?is_whitespace(C) ->
%% Output: see above
%% Description: Parsing the xml declaration from the input stream.
%%----------------------------------------------------------------------
-parse_xml_directive_1(<<C, Rest/binary>>, Acc) when ?is_whitespace(C) ->
- parse_xml_directive_1(Rest, Acc);
-parse_xml_directive_1(<<"?>", _/binary>>, Acc) ->
+parse_xml_directive_1(<<C, Rest/binary>>, Acc, State) when ?is_whitespace(C) ->
+ parse_xml_directive_1(Rest, Acc, State);
+parse_xml_directive_1(<<"?>", _/binary>>, Acc, _State) ->
Acc;
-parse_xml_directive_1(<<C, Rest/binary>>, Acc) when 97 =< C, C =< 122 ->
+parse_xml_directive_1(<<C, Rest/binary>>, Acc, State) when 97 =< C, C =< 122 ->
{Name, Rest1} = parse_name(Rest, [C]),
- Rest2 = parse_eq(Rest1),
- {Value, Rest3} = parse_value(Rest2),
- parse_xml_directive_1(Rest3, [{Name, Value} |Acc]);
-parse_xml_directive_1(_, _) ->
- {error, "Unknown attribute in xml directive"}.
+ Rest2 = parse_eq(Rest1, State),
+ {Value, Rest3} = parse_value(Rest2, State),
+ parse_xml_directive_1(Rest3, [{Name, Value} |Acc], State);
+parse_xml_directive_1(_, _, State) ->
+ ?fatal_error(State, "Unknown attribute in xml directive").
%%----------------------------------------------------------------------
-%% Function: parse_xml_directive_1(Xml, Acc) -> Name
+%% Function: parse_name(Xml, Acc) -> Name
%% Input: Xml = binary()
%% Acc = string()
%% Output: Name = string()
@@ -361,10 +353,12 @@ parse_name(Rest, Acc) ->
%% Output: Rest = binary()
%% Description: Reads an '=' from the stream.
%%----------------------------------------------------------------------
-parse_eq(<<C, Rest/binary>>) when ?is_whitespace(C) ->
- parse_eq(Rest);
-parse_eq(<<"=", Rest/binary>>) ->
- Rest.
+parse_eq(<<C, Rest/binary>>, State) when ?is_whitespace(C) ->
+ parse_eq(Rest, State);
+parse_eq(<<"=", Rest/binary>>, _State) ->
+ Rest;
+parse_eq(_, State) ->
+ ?fatal_error(State, "expecting = or whitespace").
%%----------------------------------------------------------------------
%% Function: parse_value(Xml) -> {Value, Rest}
@@ -373,10 +367,12 @@ parse_eq(<<"=", Rest/binary>>) ->
%% Rest = binary()
%% Description: Parsing an attribute value from the stream.
%%----------------------------------------------------------------------
-parse_value(<<C, Rest/binary>>) when ?is_whitespace(C) ->
- parse_value(Rest);
-parse_value(<<C, Rest/binary>>) when C == $'; C == $" ->
- parse_value_1(Rest, C, []).
+parse_value(<<C, Rest/binary>>, State) when ?is_whitespace(C) ->
+ parse_value(Rest, State);
+parse_value(<<C, Rest/binary>>, State) when C == $'; C == $" ->
+ parse_value_1(Rest, C, [], State);
+parse_value(_, State) ->
+ ?fatal_error(State, "\', \" or whitespace expected").
%%----------------------------------------------------------------------
%% Function: parse_value_1(Xml, Stop, Acc) -> {Value, Rest}
@@ -387,10 +383,12 @@ parse_value(<<C, Rest/binary>>) when C == $'; C == $" ->
%% Rest = binary()
%% Description: Parsing an attribute value from the stream.
%%----------------------------------------------------------------------
-parse_value_1(<<Stop, Rest/binary>>, Stop, Acc) ->
+parse_value_1(<<Stop, Rest/binary>>, Stop, Acc, _State) ->
{lists:reverse(Acc), Rest};
-parse_value_1(<<C, Rest/binary>>, Stop, Acc) ->
- parse_value_1(Rest, Stop, [C |Acc]).
+parse_value_1(<<C, Rest/binary>>, Stop, Acc, State) ->
+ parse_value_1(Rest, Stop, [C |Acc], State);
+parse_value_1(_, _Stop, _Acc, State) ->
+ ?fatal_error(State, "end of input and no \' or \" found").
%%======================================================================
%% Default functions
@@ -431,7 +429,7 @@ read_until_end_of_xml_directive(Rest, State) ->
nomatch ->
case cf(Rest, State) of
{<<>>, _} ->
- ?fatal_error(State, "Can't detect character encoding due to lack of indata");
+ ?fatal_error(State, "Can't detect character encoding due to lack of indata");
{NewBytes, NewState} ->
read_until_end_of_xml_directive(NewBytes, NewState)
end;
@@ -450,9 +448,9 @@ read_until_end_of_xml_directive(Rest, State) ->
%% input stream and calls the fun in NextCall.
%%----------------------------------------------------------------------
cf(_Rest, #xmerl_sax_parser_state{continuation_fun = undefined} = State) ->
- ?fatal_error(State, "Continuation function undefined");
+ ?fatal_error(State, "Continuation function undefined");
cf(Rest, #xmerl_sax_parser_state{continuation_fun = CFun, continuation_state = CState} = State) ->
- Result =
+ Result =
try
CFun(CState)
catch
@@ -463,9 +461,9 @@ cf(Rest, #xmerl_sax_parser_state{continuation_fun = CFun, continuation_state = C
end,
case Result of
{<<>>, _} ->
- ?fatal_error(State, "Can't detect character encoding due to lack of indata");
+ ?fatal_error(State, "Can't detect character encoding due to lack of indata");
{NewBytes, NewContState} ->
- {<<Rest/binary, NewBytes/binary>>,
+ {<<Rest/binary, NewBytes/binary>>,
State#xmerl_sax_parser_state{continuation_state = NewContState}}
end.
@@ -479,10 +477,10 @@ cf(Rest, #xmerl_sax_parser_state{continuation_fun = CFun, continuation_state = C
%% input stream and calls the fun in NextCall.
%%----------------------------------------------------------------------
cf(_Rest, #xmerl_sax_parser_state{continuation_fun = undefined} = State, _) ->
- ?fatal_error(State, "Continuation function undefined");
-cf(Rest, #xmerl_sax_parser_state{continuation_fun = CFun, continuation_state = CState} = State,
+ ?fatal_error(State, "Continuation function undefined");
+cf(Rest, #xmerl_sax_parser_state{continuation_fun = CFun, continuation_state = CState} = State,
NextCall) ->
- Result =
+ Result =
try
CFun(CState)
catch
@@ -493,8 +491,8 @@ cf(Rest, #xmerl_sax_parser_state{continuation_fun = CFun, continuation_state = C
end,
case Result of
{<<>>, _} ->
- ?fatal_error(State, "Can't detect character encoding due to lack of indata");
+ ?fatal_error(State, "Can't detect character encoding due to lack of indata");
{NewBytes, NewContState} ->
- NextCall(<<Rest/binary, NewBytes/binary>>,
+ NextCall(<<Rest/binary, NewBytes/binary>>,
State#xmerl_sax_parser_state{continuation_state = NewContState})
end.
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index a1f6ad4e2c..d76ed5c820 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -279,7 +279,7 @@ int_file_decl(F, Options,_ExtCharset) ->
%% @spec string(Text::list()) -> {xmlElement(),Rest}
%% Rest = list()
-%% @equiv string(Test, [])
+%% @equiv string(Text, [])
string(Str) ->
string(Str, []).
@@ -2410,15 +2410,22 @@ scan_att_chars("&" ++ T, S0, Delim, Acc, TmpAcc,AT,IsNorm) -> % Reference
true ->
scan_att_chars(T1,S1,Delim,[ExpRef|Acc],[ExpRef|TmpAcc],AT,IsNorm);
_ ->
- Ch = string_to_char_set(S#xmerl_scanner.encoding, ExpRef),
case T of
"#" ++ _ ->
%% normalization rules (sec 3.3.3) require that for
%% character references, the referenced character be
%% added directly to the normalized value
- scan_att_chars(T1, S1, Delim, Ch ++ Acc,TmpAcc, AT,IsNorm);
+ {T2,S2,IsNorm2} =
+ if
+ ?whitespace(hd(ExpRef)) ->
+ normalize(T1, S1, IsNorm);
+ true ->
+ {T1, S1, IsNorm}
+ end,
+ scan_att_chars(T2, S2, Delim, ExpRef ++ Acc, TmpAcc, AT, IsNorm2);
_ ->
- scan_att_chars(Ch ++ T1, S1, Delim, Acc,TmpAcc, AT,IsNorm)
+ Ch = string_to_char_set(S#xmerl_scanner.encoding, ExpRef),
+ scan_att_chars(Ch ++ T1, S1, Delim, Acc, TmpAcc, AT, IsNorm)
end
end;
scan_att_chars("<" ++ _T, S0, _Delim, _Acc,_, _,_) -> % Tags not allowed here
@@ -3964,7 +3971,7 @@ normalize(T,S,IsNorm) ->
{_,T,S} ->
{T,S,IsNorm};
{_,T1,S1} ->
- {T1,S1,true}
+ normalize(T1,S1,true)
end.
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index be11935f2f..3c97615e1e 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.3.17
+XMERL_VSN = 1.3.20.1