aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml10
-rw-r--r--bootstrap/bin/no_dot_erlang.bootbin6544 -> 6563 bytes
-rw-r--r--bootstrap/bin/start.bootbin6544 -> 6563 bytes
-rw-r--r--bootstrap/bin/start_clean.bootbin6544 -> 6563 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin11052 -> 11052 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa.beambin12168 -> 12252 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_bsm.beambin17888 -> 17892 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_codegen.beambin37688 -> 37932 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_dead.beambin12004 -> 12424 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_opt.beambin39960 -> 40080 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beambin45604 -> 46536 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_share.beambin5348 -> 5372 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_type.beambin28636 -> 28480 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin50216 -> 50352 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin41388 -> 41392 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.app2
-rw-r--r--bootstrap/lib/compiler/ebin/core_pp.beambin11472 -> 11452 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_alias.beambin5548 -> 5556 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin50668 -> 50688 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code.beambin12688 -> 12920 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_1.beambin22352 -> 22348 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_udp.beambin1324 -> 1636 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin14200 -> 14196 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/hipe_unified_loader.beambin12336 -> 12340 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin23232 -> 23300 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_udp.beambin1720 -> 2104 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin25360 -> 25360 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_gethost_native.beambin9708 -> 9704 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin13396 -> 13424 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_udp.beambin1908 -> 2188 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.app3
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.beambin3628 -> 3644 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/local_udp.beambin1372 -> 1388 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_std_h.beambin9544 -> 9616 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net.beambin0 -> 1624 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin10980 -> 10980 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_drv.beambin11020 -> 10948 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin16968 -> 16988 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin45360 -> 45356 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph_utils.beambin6732 -> 6736 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin35048 -> 35024 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin86340 -> 86348 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin25696 -> 25692 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin30972 -> 30976 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin21604 -> 21608 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_pretty.beambin21116 -> 21136 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ordsets.beambin1940 -> 1848 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/rand.beambin29048 -> 29048 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/re.beambin12308 -> 12388 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sofs.beambin35276 -> 35284 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/stdlib.app4
-rw-r--r--bootstrap/lib/stdlib/ebin/string.beambin35872 -> 35740 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sys.beambin9104 -> 9116 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/uri_string.beambin25084 -> 25072 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/zip.beambin24188 -> 24208 bytes
-rw-r--r--erts/doc/src/erlang.xml1
-rw-r--r--erts/doc/src/socket.xml42
-rw-r--r--erts/doc/src/socket_usage.xml23
-rw-r--r--erts/emulator/beam/beam_bif_load.c72
-rw-r--r--erts/emulator/beam/binary.c80
-rw-r--r--erts/emulator/beam/bs_instrs.tab23
-rw-r--r--erts/emulator/beam/copy.c49
-rw-r--r--erts/emulator/beam/dist.c28
-rw-r--r--erts/emulator/beam/dist.h16
-rw-r--r--erts/emulator/beam/erl_alloc.types1
-rw-r--r--erts/emulator/beam/erl_alloc_util.c69
-rw-r--r--erts/emulator/beam/erl_bif_binary.c184
-rw-r--r--erts/emulator/beam/erl_bif_info.c26
-rw-r--r--erts/emulator/beam/erl_bif_persistent.c99
-rw-r--r--erts/emulator/beam/erl_binary.h118
-rw-r--r--erts/emulator/beam/erl_bits.c95
-rw-r--r--erts/emulator/beam/erl_bits.h18
-rw-r--r--erts/emulator/beam/erl_db.c15
-rw-r--r--erts/emulator/beam/erl_db.h4
-rw-r--r--erts/emulator/beam/erl_db_catree.c28
-rw-r--r--erts/emulator/beam/erl_db_catree.h3
-rw-r--r--erts/emulator/beam/erl_db_hash.c6
-rw-r--r--erts/emulator/beam/erl_db_hash.h3
-rw-r--r--erts/emulator/beam/erl_db_tree.c6
-rw-r--r--erts/emulator/beam/erl_db_tree.h4
-rw-r--r--erts/emulator/beam/erl_gc.c10
-rw-r--r--erts/emulator/beam/erl_monitor_link.c49
-rw-r--r--erts/emulator/beam/erl_monitor_link.h17
-rw-r--r--erts/emulator/beam/erl_node_tables.c247
-rw-r--r--erts/emulator/beam/erl_node_tables.h39
-rw-r--r--erts/emulator/beam/erl_printf_term.c29
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c8
-rw-r--r--erts/emulator/beam/erl_process.c76
-rw-r--r--erts/emulator/beam/erl_process.h7
-rw-r--r--erts/emulator/beam/erl_trace.c62
-rw-r--r--erts/emulator/beam/erl_trace.h8
-rw-r--r--erts/emulator/beam/global.h42
-rw-r--r--erts/emulator/nifs/common/socket_nif.c5964
-rw-r--r--erts/emulator/nifs/common/socket_util.c18
-rw-r--r--erts/emulator/sys/unix/sys_drivers.c26
-rw-r--r--erts/emulator/test/binary_SUITE.erl17
-rwxr-xr-xerts/emulator/test/esock_ttest/esock-ttest4
-rwxr-xr-xerts/emulator/test/esock_ttest/esock-ttest-client29
-rwxr-xr-xerts/emulator/test/esock_ttest/esock-ttest-server-sock14
-rw-r--r--erts/emulator/test/fun_SUITE.erl10
-rw-r--r--erts/emulator/test/node_container_SUITE.erl44
-rw-r--r--erts/emulator/test/socket_SUITE.erl2969
-rw-r--r--erts/emulator/test/socket_test_lib.erl201
-rw-r--r--erts/emulator/test/socket_test_ttest_tcp_client.erl5
-rw-r--r--erts/emulator/test/socket_test_ttest_tcp_client_socket.erl22
-rw-r--r--erts/emulator/test/socket_test_ttest_tcp_gen.erl26
-rw-r--r--erts/emulator/test/socket_test_ttest_tcp_server.erl104
-rw-r--r--erts/emulator/test/socket_test_ttest_tcp_socket.erl14
-rw-r--r--erts/etc/unix/etp-commands.in75
-rw-r--r--erts/lib_src/pthread/ethread.c4
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin81424 -> 81508 bytes
-rw-r--r--erts/preloaded/ebin/socket.beambin76064 -> 75892 bytes
-rw-r--r--erts/preloaded/src/Makefile10
-rw-r--r--erts/preloaded/src/prim_inet.erl2
-rw-r--r--erts/preloaded/src/socket.erl77
-rw-r--r--lib/compiler/src/beam_except.erl32
-rw-r--r--lib/compiler/src/beam_ssa_codegen.erl18
-rw-r--r--lib/compiler/src/beam_ssa_dead.erl87
-rw-r--r--lib/compiler/src/beam_ssa_opt.erl18
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl62
-rw-r--r--lib/compiler/src/beam_ssa_share.erl8
-rw-r--r--lib/compiler/src/beam_ssa_type.erl4
-rw-r--r--lib/compiler/src/beam_validator.erl73
-rw-r--r--lib/compiler/src/compile.erl7
-rw-r--r--lib/compiler/test/Makefile15
-rw-r--r--lib/compiler/test/beam_except_SUITE.erl14
-rw-r--r--lib/compiler/test/beam_ssa_SUITE.erl55
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl25
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl22
-rw-r--r--lib/compiler/test/receive_SUITE.erl35
-rw-r--r--lib/compiler/test/test_lib.erl3
-rw-r--r--lib/erl_interface/src/decode/decode_fun.c5
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java8
-rw-r--r--lib/kernel/doc/src/logger_disk_log_h.xml2
-rw-r--r--lib/kernel/test/global_SUITE.erl13
-rw-r--r--lib/kernel/test/interactive_shell_SUITE.erl60
-rw-r--r--lib/kernel/test/interactive_shell_SUITE_data/.gitignore1
-rw-r--r--lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl6
-rw-r--r--lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl6
-rw-r--r--lib/megaco/test/Makefile5
-rw-r--r--lib/megaco/test/megaco_SUITE.erl32
-rw-r--r--lib/megaco/test/megaco_actions_test.erl46
-rw-r--r--lib/megaco/test/megaco_app_test.erl17
-rw-r--r--lib/megaco/test/megaco_appup_test.erl25
-rw-r--r--lib/megaco/test/megaco_call_flow_test.erl94
-rw-r--r--lib/megaco/test/megaco_codec_test.erl15
-rw-r--r--lib/megaco/test/megaco_codec_test_lib.erl10
-rw-r--r--lib/megaco/test/megaco_config_test.erl99
-rw-r--r--lib/megaco/test/megaco_digit_map_test.erl74
-rw-r--r--lib/megaco/test/megaco_examples_test.erl15
-rw-r--r--lib/megaco/test/megaco_flex_test.erl17
-rw-r--r--lib/megaco/test/megaco_load_test.erl119
-rw-r--r--lib/megaco/test/megaco_mess_test.erl179
-rw-r--r--lib/megaco/test/megaco_mess_user_test.erl16
-rw-r--r--lib/megaco/test/megaco_mib_test.erl35
-rw-r--r--lib/megaco/test/megaco_mreq_test.erl68
-rw-r--r--lib/megaco/test/megaco_pending_limit_test.erl46
-rw-r--r--lib/megaco/test/megaco_segment_test.erl51
-rw-r--r--lib/megaco/test/megaco_tcp_test.erl141
-rw-r--r--lib/megaco/test/megaco_test_deliver.erl4
-rw-r--r--lib/megaco/test/megaco_test_generator.erl54
-rw-r--r--lib/megaco/test/megaco_test_generic_transport.erl20
-rw-r--r--lib/megaco/test/megaco_test_lib.erl44
-rw-r--r--lib/megaco/test/megaco_test_lib.hrl11
-rw-r--r--lib/megaco/test/megaco_test_megaco_generator.erl15
-rw-r--r--lib/megaco/test/megaco_test_mg.erl96
-rw-r--r--lib/megaco/test/megaco_test_mgc.erl103
-rw-r--r--lib/megaco/test/megaco_timer_test.erl4
-rw-r--r--lib/megaco/test/megaco_trans_test.erl35
-rw-r--r--lib/megaco/test/megaco_udp_test.erl17
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap7.xmlsrc2
-rw-r--r--lib/mnesia/src/mnesia_controller.erl81
-rw-r--r--lib/mnesia/src/mnesia_locker.erl2
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl6
-rw-r--r--lib/mnesia/src/mnesia_schema.erl70
-rw-r--r--lib/mnesia/src/mnesia_tm.erl99
-rw-r--r--lib/mnesia/test/mnesia_isolation_test.erl91
-rwxr-xr-xlib/mnesia/test/mt38
-rw-r--r--lib/observer/src/cdv_bin_cb.erl37
-rw-r--r--lib/observer/src/cdv_html_wx.erl15
-rw-r--r--lib/observer/src/cdv_mod_cb.erl3
-rw-r--r--lib/observer/src/cdv_persistent_cb.erl5
-rw-r--r--lib/observer/src/cdv_proc_cb.erl2
-rw-r--r--lib/observer/src/cdv_term_cb.erl23
-rw-r--r--lib/observer/src/cdv_virtual_list_wx.erl9
-rw-r--r--lib/observer/src/cdv_wx.erl3
-rw-r--r--lib/observer/src/observer_app_wx.erl30
-rw-r--r--lib/observer/src/observer_defs.hrl1
-rw-r--r--lib/observer/src/observer_html_lib.erl76
-rw-r--r--lib/observer/src/observer_lib.erl60
-rw-r--r--lib/observer/src/observer_perf_wx.erl30
-rw-r--r--lib/observer/src/observer_port_wx.erl14
-rw-r--r--lib/observer/src/observer_pro_wx.erl2
-rw-r--r--lib/observer/src/observer_procinfo.erl19
-rw-r--r--lib/observer/src/observer_tv_table.erl5
-rw-r--r--lib/observer/src/observer_tv_wx.erl2
-rw-r--r--lib/observer/test/crashdump_helper.erl6
-rw-r--r--lib/os_mon/c_src/cpu_sup.c2
-rw-r--r--lib/snmp/src/agent/snmpa_supervisor.erl35
-rw-r--r--lib/snmp/src/manager/snmpm.erl11
-rw-r--r--lib/snmp/src/manager/snmpm_supervisor.erl40
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl13
-rw-r--r--lib/snmp/test/snmp_manager_test.erl398
-rw-r--r--lib/snmp/test/snmp_test_lib.erl108
-rw-r--r--lib/snmp/test/snmp_test_lib.hrl10
-rw-r--r--lib/ssh/doc/src/ssh_client_channel.xml14
-rw-r--r--lib/ssh/doc/src/ssh_connection.xml446
-rw-r--r--lib/ssh/doc/src/ssh_server_channel.xml8
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml468
-rw-r--r--lib/ssh/doc/src/ssh_sftpd.xml33
-rw-r--r--lib/ssh/doc/src/using_ssh.xml14
-rw-r--r--lib/ssh/src/ssh.erl2
-rw-r--r--lib/ssh/src/ssh_client_channel.erl2
-rw-r--r--lib/ssh/src/ssh_connect.hrl3
-rw-r--r--lib/ssh/src/ssh_connection.erl222
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl116
-rw-r--r--lib/ssh/src/ssh_server_channel.erl2
-rw-r--r--lib/ssh/src/ssh_sftp.erl376
-rw-r--r--lib/ssh/src/ssh_sftpd.erl12
-rw-r--r--lib/ssl/doc/src/ssl.xml23
-rw-r--r--lib/ssl/src/dtls_handshake.erl3
-rw-r--r--lib/ssl/src/ssl.erl10
-rw-r--r--lib/ssl/src/ssl_cipher.erl30
-rw-r--r--lib/ssl/src/ssl_connection.erl11
-rw-r--r--lib/ssl/src/ssl_handshake.erl154
-rw-r--r--lib/ssl/src/tls_handshake.erl4
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl71
-rw-r--r--lib/ssl/src/tls_handshake_1_3.hrl47
-rw-r--r--lib/ssl/src/tls_record_1_3.erl9
-rw-r--r--lib/ssl/test/Makefile27
-rw-r--r--lib/ssl/test/openssl_alpn_SUITE.erl421
-rw-r--r--lib/ssl/test/openssl_cipher_suite_SUITE.erl (renamed from lib/ssl/test/openssl_server_cipher_suite_SUITE.erl)40
-rw-r--r--lib/ssl/test/openssl_client_cert_SUITE.erl350
-rw-r--r--lib/ssl/test/openssl_npn_SUITE.erl311
-rw-r--r--lib/ssl/test/openssl_reject_SUITE.erl209
-rw-r--r--lib/ssl/test/openssl_renegotiate_SUITE.erl342
-rw-r--r--lib/ssl/test/openssl_server_cert_SUITE.erl373
-rw-r--r--lib/ssl/test/openssl_session_SUITE.erl258
-rw-r--r--lib/ssl/test/openssl_sni_SUITE.erl251
-rw-r--r--lib/ssl/test/openssl_tls_1_3_version_SUITE.erl172
-rw-r--r--lib/ssl/test/property_test/ssl_eqc_handshake.erl105
-rw-r--r--lib/ssl/test/ssl_alert_SUITE.erl100
-rw-r--r--lib/ssl/test/ssl_alpn_SUITE.erl (renamed from lib/ssl/test/ssl_alpn_handshake_SUITE.erl)28
-rw-r--r--lib/ssl/test/ssl_api_SUITE.erl1976
-rw-r--r--lib/ssl/test/ssl_api_SUITE_data/dHParam.pem (renamed from lib/ssl/test/ssl_basic_SUITE_data/dHParam.pem)0
-rw-r--r--lib/ssl/test/ssl_app_env_SUITE.erl171
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl6841
-rw-r--r--lib/ssl/test/ssl_bench_SUITE.erl7
-rw-r--r--lib/ssl/test/ssl_cert_SUITE.erl563
-rw-r--r--lib/ssl/test/ssl_cert_tests.erl386
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl612
-rw-r--r--lib/ssl/test/ssl_cipher_suite_SUITE.erl20
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl4
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_npn_SUITE.erl (renamed from lib/ssl/test/ssl_npn_handshake_SUITE.erl)2
-rw-r--r--lib/ssl/test/ssl_npn_hello_SUITE.erl9
-rw-r--r--lib/ssl/test/ssl_pem_cache_SUITE.erl55
-rw-r--r--lib/ssl/test/ssl_renegotiate_SUITE.erl499
-rw-r--r--lib/ssl/test/ssl_session_SUITE.erl377
-rw-r--r--lib/ssl/test/ssl_sni_SUITE.erl68
-rw-r--r--lib/ssl/test/ssl_socket_SUITE.erl437
-rw-r--r--lib/ssl/test/ssl_test_lib.erl395
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl2021
-rw-r--r--lib/ssl/test/tls_1_3_record_SUITE.erl973
-rw-r--r--lib/ssl/test/tls_1_3_version_SUITE.erl153
-rw-r--r--lib/ssl/test/tls_api_SUITE.erl880
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl32
-rwxr-xr-xscripts/build-otp2
268 files changed, 20931 insertions, 15316 deletions
diff --git a/.travis.yml b/.travis.yml
index 00fe85fc04..51453639b0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,8 @@ sudo: false
os:
- linux
+dist: xenial
+
addons:
apt:
packages:
@@ -12,10 +14,8 @@ addons:
- libncurses-dev
- build-essential
- libssl-dev
- - libwxgtk2.8-dev
- - libgl1-mesa-dev
+ - libwxgtk3.0-dev
- libglu1-mesa-dev
- - libpng3
- default-jdk
- g++
- xsltproc
@@ -64,9 +64,7 @@ matrix:
- build-essential
- libssl-dev
- libwxgtk3.0-dev
- - libgl1-mesa-dev
- libglu1-mesa-dev
- - libpng3
- default-jdk
- g++
- xsltproc
@@ -80,7 +78,7 @@ matrix:
repo: erlang/cd
target-branch: master
skip-cleanup: true
- keep-history: true
+ keep-history: false
verbose: true
github-token: $ERLANG_CD_GITHUB_TOKEN
on:
diff --git a/bootstrap/bin/no_dot_erlang.boot b/bootstrap/bin/no_dot_erlang.boot
index 1f7f088a77..26cd9e4d5e 100644
--- a/bootstrap/bin/no_dot_erlang.boot
+++ b/bootstrap/bin/no_dot_erlang.boot
Binary files differ
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index 1f7f088a77..26cd9e4d5e 100644
--- a/bootstrap/bin/start.boot
+++ b/bootstrap/bin/start.boot
Binary files differ
diff --git a/bootstrap/bin/start_clean.boot b/bootstrap/bin/start_clean.boot
index 1f7f088a77..26cd9e4d5e 100644
--- a/bootstrap/bin/start_clean.boot
+++ b/bootstrap/bin/start_clean.boot
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index 07acbb1da7..78b75359a6 100644
--- a/bootstrap/lib/compiler/ebin/beam_asm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_asm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa.beam b/bootstrap/lib/compiler/ebin/beam_ssa.beam
index 9ba124a92d..0327230a58 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam b/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam
index 50412bc8de..b9bb997cc7 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam b/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam
index e59340de4f..cb06630012 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam b/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam
index f6bd1b7a69..782073698e 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam b/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam
index c9838883ef..b8588725b4 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam b/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam
index 3de363dbb6..e22cb5c846 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_share.beam b/bootstrap/lib/compiler/ebin/beam_ssa_share.beam
index ea8e83d919..d975cebf48 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_share.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_share.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_type.beam b/bootstrap/lib/compiler/ebin/beam_ssa_type.beam
index c13b25bac3..0403230604 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_type.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_type.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam
index 9d0c34a94a..050789f481 100644
--- a/bootstrap/lib/compiler/ebin/beam_validator.beam
+++ b/bootstrap/lib/compiler/ebin/beam_validator.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index 57cfc6b932..ebe42547ee 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compiler.app b/bootstrap/lib/compiler/ebin/compiler.app
index c0483e7801..e086da1b68 100644
--- a/bootstrap/lib/compiler/ebin/compiler.app
+++ b/bootstrap/lib/compiler/ebin/compiler.app
@@ -19,7 +19,7 @@
{application, compiler,
[{description, "ERTS CXC 138 10"},
- {vsn, "7.3.2"},
+ {vsn, "7.4.4"},
{modules, [
beam_a,
beam_asm,
diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam
index 2423c9b2ea..a2b3167e10 100644
--- a/bootstrap/lib/compiler/ebin/core_pp.beam
+++ b/bootstrap/lib/compiler/ebin/core_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_alias.beam b/bootstrap/lib/compiler/ebin/sys_core_alias.beam
index 622221a8b0..b769b6be41 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_alias.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_alias.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index 243b911ac6..3cbbdfd88b 100644
--- a/bootstrap/lib/compiler/ebin/v3_core.beam
+++ b/bootstrap/lib/compiler/ebin/v3_core.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code.beam b/bootstrap/lib/kernel/ebin/code.beam
index 41e4bd4ab2..204b15fcf2 100644
--- a/bootstrap/lib/kernel/ebin/code.beam
+++ b/bootstrap/lib/kernel/ebin/code.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_1.beam b/bootstrap/lib/kernel/ebin/disk_log_1.beam
index 17f65d6ceb..0a781001dc 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_1.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_1.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_udp.beam b/bootstrap/lib/kernel/ebin/gen_udp.beam
index f6022dca19..0d6541ee53 100644
--- a/bootstrap/lib/kernel/ebin/gen_udp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index 396f1166f1..dcec55421c 100644
--- a/bootstrap/lib/kernel/ebin/group.beam
+++ b/bootstrap/lib/kernel/ebin/group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
index 7ff507242b..de7d9c2e57 100644
--- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
+++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index b0c67afe90..f64311e166 100644
--- a/bootstrap/lib/kernel/ebin/inet.beam
+++ b/bootstrap/lib/kernel/ebin/inet.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_udp.beam b/bootstrap/lib/kernel/ebin/inet6_udp.beam
index c12c6f4afc..ac4be100e8 100644
--- a/bootstrap/lib/kernel/ebin/inet6_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam
index 20d795e75f..a835fa1a74 100644
--- a/bootstrap/lib/kernel/ebin/inet_db.beam
+++ b/bootstrap/lib/kernel/ebin/inet_db.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
index afc4999c42..8166eca5de 100644
--- a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
+++ b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index 84c0169d4b..e8935134b5 100644
--- a/bootstrap/lib/kernel/ebin/inet_parse.beam
+++ b/bootstrap/lib/kernel/ebin/inet_parse.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_udp.beam b/bootstrap/lib/kernel/ebin/inet_udp.beam
index 62156a3284..5853bde54f 100644
--- a/bootstrap/lib/kernel/ebin/inet_udp.beam
+++ b/bootstrap/lib/kernel/ebin/inet_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel.app b/bootstrap/lib/kernel/ebin/kernel.app
index 5ec7c41dbe..cb13db1a89 100644
--- a/bootstrap/lib/kernel/ebin/kernel.app
+++ b/bootstrap/lib/kernel/ebin/kernel.app
@@ -22,7 +22,7 @@
{application, kernel,
[
{description, "ERTS CXC 138 10"},
- {vsn, "6.3.1"},
+ {vsn, "6.4.1"},
{modules, [application,
application_controller,
application_master,
@@ -74,6 +74,7 @@
logger_simple_h,
logger_std_h,
logger_sup,
+ net,
net_adm,
net_kernel,
os,
diff --git a/bootstrap/lib/kernel/ebin/kernel.beam b/bootstrap/lib/kernel/ebin/kernel.beam
index 11be83a49e..2832938d95 100644
--- a/bootstrap/lib/kernel/ebin/kernel.beam
+++ b/bootstrap/lib/kernel/ebin/kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/local_udp.beam b/bootstrap/lib/kernel/ebin/local_udp.beam
index cc5f46f746..33ed76e5cd 100644
--- a/bootstrap/lib/kernel/ebin/local_udp.beam
+++ b/bootstrap/lib/kernel/ebin/local_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_std_h.beam b/bootstrap/lib/kernel/ebin/logger_std_h.beam
index b0f56d9a62..c8eb73a076 100644
--- a/bootstrap/lib/kernel/ebin/logger_std_h.beam
+++ b/bootstrap/lib/kernel/ebin/logger_std_h.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net.beam b/bootstrap/lib/kernel/ebin/net.beam
new file mode 100644
index 0000000000..44b1f10603
--- /dev/null
+++ b/bootstrap/lib/kernel/ebin/net.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user.beam b/bootstrap/lib/kernel/ebin/user.beam
index f3573d95af..8214d9d6aa 100644
--- a/bootstrap/lib/kernel/ebin/user.beam
+++ b/bootstrap/lib/kernel/ebin/user.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_drv.beam b/bootstrap/lib/kernel/ebin/user_drv.beam
index 1b59423b71..43df5afa36 100644
--- a/bootstrap/lib/kernel/ebin/user_drv.beam
+++ b/bootstrap/lib/kernel/ebin/user_drv.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index c61132b2de..17e061b1d0 100644
--- a/bootstrap/lib/stdlib/ebin/c.beam
+++ b/bootstrap/lib/stdlib/ebin/c.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v9.beam b/bootstrap/lib/stdlib/ebin/dets_v9.beam
index 046de3bd5a..f73509ae3f 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v9.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v9.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph_utils.beam b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
index 772332cd08..fabe782d90 100644
--- a/bootstrap/lib/stdlib/ebin/digraph_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index 90b3858207..5ef1521371 100644
--- a/bootstrap/lib/stdlib/ebin/erl_eval.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_eval.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 62838ed771..c73ecdf942 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam
index 3b30d3e8c7..18538620b7 100644
--- a/bootstrap/lib/stdlib/ebin/erl_scan.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index 3c5004871d..871ccd82d4 100644
--- a/bootstrap/lib/stdlib/ebin/erl_tar.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_tar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam
index b1cf286cea..350316dfcc 100644
--- a/bootstrap/lib/stdlib/ebin/ets.beam
+++ b/bootstrap/lib/stdlib/ebin/ets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
index 57c700cb31..b0f4177d71 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ordsets.beam b/bootstrap/lib/stdlib/ebin/ordsets.beam
index 9e49566404..44f9e5d8b5 100644
--- a/bootstrap/lib/stdlib/ebin/ordsets.beam
+++ b/bootstrap/lib/stdlib/ebin/ordsets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/rand.beam b/bootstrap/lib/stdlib/ebin/rand.beam
index f4d803b1ee..7f1e6140bf 100644
--- a/bootstrap/lib/stdlib/ebin/rand.beam
+++ b/bootstrap/lib/stdlib/ebin/rand.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/re.beam b/bootstrap/lib/stdlib/ebin/re.beam
index 5662594d4c..e16327b906 100644
--- a/bootstrap/lib/stdlib/ebin/re.beam
+++ b/bootstrap/lib/stdlib/ebin/re.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam
index f64faafa52..3a90a07add 100644
--- a/bootstrap/lib/stdlib/ebin/sofs.beam
+++ b/bootstrap/lib/stdlib/ebin/sofs.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/stdlib.app b/bootstrap/lib/stdlib/ebin/stdlib.app
index ffb56f8306..41c1f14bbc 100644
--- a/bootstrap/lib/stdlib/ebin/stdlib.app
+++ b/bootstrap/lib/stdlib/ebin/stdlib.app
@@ -20,7 +20,7 @@
%%
{application, stdlib,
[{description, "ERTS CXC 138 10"},
- {vsn, "3.8.1"},
+ {vsn, "3.9.2"},
{modules, [array,
base64,
beam_lib,
@@ -108,7 +108,7 @@
dets]},
{applications, [kernel]},
{env, []},
- {runtime_dependencies, ["sasl-3.0","kernel-6.0","erts-@OTP-15128@","crypto-3.3",
+ {runtime_dependencies, ["sasl-3.0","kernel-6.0","erts-@OTP-15831:OTP-15836:OTP-15889@","crypto-3.3",
"compiler-5.0"]}
]}.
diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam
index 5d1d66892b..ee19fb41a4 100644
--- a/bootstrap/lib/stdlib/ebin/string.beam
+++ b/bootstrap/lib/stdlib/ebin/string.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sys.beam b/bootstrap/lib/stdlib/ebin/sys.beam
index a46ade8602..a3f46b5983 100644
--- a/bootstrap/lib/stdlib/ebin/sys.beam
+++ b/bootstrap/lib/stdlib/ebin/sys.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/uri_string.beam b/bootstrap/lib/stdlib/ebin/uri_string.beam
index b57c84a302..7255fdca63 100644
--- a/bootstrap/lib/stdlib/ebin/uri_string.beam
+++ b/bootstrap/lib/stdlib/ebin/uri_string.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/zip.beam b/bootstrap/lib/stdlib/ebin/zip.beam
index cd6274efe5..75c2289f47 100644
--- a/bootstrap/lib/stdlib/ebin/zip.beam
+++ b/bootstrap/lib/stdlib/ebin/zip.beam
Binary files differ
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 0e82ceba7d..2183f75487 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -2553,6 +2553,7 @@ os_prompt%</pre>
true
> is_map_key(value,Map).
false</code>
+ <p>Allowed in guard tests.</p>
</desc>
</func>
diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml
index da049b1a7f..2f7ff2fc07 100644
--- a/erts/doc/src/socket.xml
+++ b/erts/doc/src/socket.xml
@@ -47,14 +47,16 @@
<seealso marker="#recv_async"><c>recv/3</c></seealso>
function with Timeout set to <c>nowait</c> (<c>recv(Sock, 0, nowait)</c>)
when there is actually nothing to read, it will return with
- <c>{ok, </c>
- <seealso marker="#type-select_info"><c>SelectInfo</c></seealso><c>}</c>.
+ <c>{select, </c>
+ <seealso marker="#type-select_info"><c>SelectInfo</c></seealso><c>}</c>
+ (<c>SelectInfo</c> contains the
+ <seealso marker="socket#type-select_ref">SelectRef</seealso>).
When data eventually arrives a 'select' message
will be sent to the caller: </p>
<taglist>
<!-- NOTE THAT THE EMPTY TAG IS INTENTIONAL -->
<tag></tag>
- <item><c>{'$socket', socket(), select, select_ref()}</c></item>
+ <item><c>{'$socket', socket(), select, SelectRef}</c></item>
</taglist>
<p>The caller can now make another
call to the recv function and now expect data.</p>
@@ -70,7 +72,7 @@
<p>This message indicates
that the (asynchronous) operation has been aborted.
If, for instance, the socket has been closed (by another process),
- <c>Info</c> will be <c>{select_ref(), closed}</c>. </p>
+ <c>Info</c> will be <c>{SelectRef, closed}</c>. </p>
</note>
<note>
<p>There is currently <em>no</em> support for Windows. </p>
@@ -338,7 +340,9 @@
<p>In the case when there is no connections waiting, the function
will return with the <c>SelectInfo</c>. The caller can then await a
select message, <c>{'$socket', Socket, select, Info}</c> (where
- <c>Info</c> is the <c>select_ref()</c> from the <c>SelectInfo</c>),
+ <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the <c>SelectInfo</c>),
when a client connects (a subsequent call to accept will then return
the socket). </p>
</desc>
@@ -410,7 +414,9 @@
<seealso marker="#type-select_info"><c>SelectInfo</c></seealso>.
The caller can then await a
select message, <c>{'$socket', Socket, select, Info}</c> (where
- <c>Info</c> is the <c>select_ref()</c> from the <c>SelectInfo</c>,
+ <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the <c>SelectInfo</c>,
a subsequent call to connect will then
establish the connection). </p>
</desc>
@@ -551,7 +557,9 @@
<p>In the case when there is no data waiting, the function
will return with the <c>SelectInfo</c>. The caller can then await a
select message, <c>{'$socket', Socket, select, Info}</c> (where
- <c>Info</c> is the <c>select_ref()</c> from the <c>SelectInfo</c>),
+ <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the <c>SelectInfo</c>),
when data has arrived (a subsequent call to recv will then return
the data). </p>
<p>Note that if a length (<c>> 0</c>) is specified, and only part
@@ -610,7 +618,9 @@
<p>In the case when there is no data waiting, the function
will return with the <c>SelectInfo</c>. The caller can then await a
select message, <c>{'$socket', Socket, select, Info}</c> (where
- <c>Info</c> is the <c>select_ref()</c> from the <c>SelectInfo</c>),
+ <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the <c>SelectInfo</c>),
when data has arrived (a subsequent call to recvfrom will then return
the data). </p>
</desc>
@@ -686,7 +696,9 @@
<p>In the case when there is no data waiting, the function
will return with the <c>SelectInfo</c>. The caller can then await a
select message, <c>{'$socket', Socket, select, Info}</c> (where
- <c>Info</c> is the <c>select_ref()</c> from the <c>SelectInfo</c>),
+ <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the <c>SelectInfo</c>),
when data has arrived (a subsequent call to recvmsg will then return
the data). </p>
</desc>
@@ -714,7 +726,9 @@
the function will return with the <c>SelectInfo</c>. The caller
can then await a select message,
<c>{'$socket', Socket, select, Info}</c>
- (where <c>Info</c> is the <c>select_ref()</c> from the
+ (where <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the
<c>SelectInfo</c>), when there is room for more data (a subsequent
call to send will then send the data). </p>
<p>Note that if not all the data was sent, the function will return
@@ -772,7 +786,9 @@
the function will return with the <c>SelectInfo</c>. The caller
can then await a select message,
<c>{'$socket', Socket, select, Info}</c>
- (where <c>Info</c> is the <c>select_ref()</c> from the
+ (where <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the
<c>SelectInfo</c>), when there is room for more data (a subsequent
call to sendmsg will then send the data). </p>
</desc>
@@ -800,7 +816,9 @@
the function will return with the <c>SelectInfo</c>. The caller
can then await a select message,
<c>{'$socket', Socket, select, Info}</c>
- (where <c>Info</c> is the <c>select_ref()</c> from the
+ (where <c>Info</c> is the
+ <seealso marker="socket#type-select_ref"><c>ref</c></seealso>
+ field from the
<c>SelectInfo</c>), when there is room for more data (a subsequent
call to sendto will then send the data). </p>
</desc>
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml
index 7e65bcbf70..c3cda9a615 100644
--- a/erts/doc/src/socket_usage.xml
+++ b/erts/doc/src/socket_usage.xml
@@ -56,23 +56,20 @@
function with Timeout set to <c>nowait</c> (i.e.
<c>recv(Sock, 0, nowait)</c>)
when there is actually nothing to read, it will return with
- <c>{ok, </c>
- <seealso marker="socket#type-select_info"><c>SelectInfo</c></seealso><c>}</c>.
+ <c>{select, </c>
+ <seealso marker="socket#type-select_info"><c>SelectInfo</c></seealso><c>}</c>
+ (<c>SelectInfo</c> contains the
+ <seealso marker="socket#type-select_ref">SelectRef</seealso>).
When data eventually arrives a 'select message'
will be sent to the caller:</p>
<taglist>
<!-- NOTE THAT THE EMPTY TAG IS INTENTIONAL -->
<tag></tag>
- <item><c>{'$socket', socket(), select, select_ref()}</c></item>
+ <item><c>{'$socket', socket(), select, SelectRef}</c></item>
</taglist>
<p>The caller can then make another
call to the recv function and now expect data.</p>
<p>The user must also be prepared to receive an abort message: </p>
- <!--
- <list type="ordered">
- <item><c>{'$socket', Sock, abort, Info}</c></item>
- </list>
- -->
<taglist>
<!-- NOTE THAT THE EMPTY TAG IS INTENTIONAL -->
<tag></tag>
@@ -81,7 +78,7 @@
<p>If the operation is aborted
for whatever reason (e.g. if the socket is closed "by someone else").
The <c>Info</c> part contains the abort reason (in this case that
- the socket has been closed <c>Info = {select_ref(), closed}</c>). </p>
+ the socket has been closed <c>Info = {SelectRef, closed}</c>). </p>
<p>Note that all other users are <em>locked out</em> until the
'current user' has called the function (recv in this case). So either
immediately call the function or
@@ -197,7 +194,7 @@
<cell><em>Other Requirements and comments</em></cell>
</row>
<row>
- <cell>acceptcon</cell>
+ <cell>acceptconn</cell>
<cell>boolean()</cell>
<cell>no</cell>
<cell>yes</cell>
@@ -208,7 +205,9 @@
<cell>string()</cell>
<cell>yes</cell>
<cell>yes</cell>
- <cell>none</cell>
+ <cell>Before Linux 3.8, this socket option could be set, but not get.
+ Only works for some socket types (e.g. <c>inet</c>).
+ If empty value is set, the binding is removed.</cell>
</row>
<row>
<cell>broadcast</cell>
@@ -222,7 +221,7 @@
<cell>integer()</cell>
<cell>yes</cell>
<cell>yes</cell>
- <cell>requires admin capability</cell>
+ <cell>may require admin capability</cell>
</row>
<row>
<cell>domain</cell>
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index bb1b2e5b27..4c8ee5178a 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -1799,6 +1799,78 @@ erts_queue_release_literals(Process* c_p, ErtsLiteralArea* literals)
}
}
+struct debug_la_oh {
+ void (*func)(ErlOffHeap *, void *);
+ void *arg;
+};
+
+static void debug_later_cleanup_literal_area_off_heap(void *vfap,
+ ErtsThrPrgrVal val,
+ void *vlrlap)
+{
+ struct debug_la_oh *fap = vfap;
+ ErtsLaterReleasLiteralArea *lrlap = vlrlap;
+ ErtsLiteralArea *lap = lrlap->la;
+ if (!erts_debug_have_accessed_literal_area(lap)) {
+ ErlOffHeap oh;
+ ERTS_INIT_OFF_HEAP(&oh);
+ oh.first = lap->off_heap;
+ (*fap->func)(&oh, fap->arg);
+ erts_debug_save_accessed_literal_area(lap);
+ }
+}
+
+static void debug_later_complete_literal_area_switch_off_heap(void *vfap,
+ ErtsThrPrgrVal val,
+ void *vlap)
+{
+ struct debug_la_oh *fap = vfap;
+ ErtsLiteralArea *lap = vlap;
+ if (lap && !erts_debug_have_accessed_literal_area(lap)) {
+ ErlOffHeap oh;
+ ERTS_INIT_OFF_HEAP(&oh);
+ oh.first = lap->off_heap;
+ (*fap->func)(&oh, fap->arg);
+ erts_debug_save_accessed_literal_area(lap);
+ }
+}
+
+
+void
+erts_debug_foreach_release_literal_area_off_heap(void (*func)(ErlOffHeap *, void *), void *arg)
+{
+ ErtsLiteralArea *lap;
+ ErlOffHeap oh;
+ ErtsLiteralAreaRef *ref;
+ struct debug_la_oh fa;
+ erts_mtx_lock(&release_literal_areas.mtx);
+ for (ref = release_literal_areas.first; ref; ref = ref->next) {
+ lap = ref->literal_area;
+ if (!erts_debug_have_accessed_literal_area(lap)) {
+ ERTS_INIT_OFF_HEAP(&oh);
+ oh.first = lap->off_heap;
+ (*func)(&oh, arg);
+ erts_debug_save_accessed_literal_area(lap);
+ }
+ }
+ erts_mtx_unlock(&release_literal_areas.mtx);
+ lap = ERTS_COPY_LITERAL_AREA();
+ if (lap && !erts_debug_have_accessed_literal_area(lap)) {
+ ERTS_INIT_OFF_HEAP(&oh);
+ oh.first = lap->off_heap;
+ (*func)(&oh, arg);
+ erts_debug_save_accessed_literal_area(lap);
+ }
+ fa.func = func;
+ fa.arg = arg;
+ erts_debug_later_op_foreach(later_release_literal_area,
+ debug_later_cleanup_literal_area_off_heap,
+ (void *) &fa);
+ erts_debug_later_op_foreach(complete_literal_area_switch,
+ debug_later_complete_literal_area_switch_off_heap,
+ (void *) &fa);
+}
+
/*
* Move code from current to old and null all export entries for the module
*/
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index a18228b84a..4ddf59092a 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -1153,51 +1153,47 @@ BIF_RETTYPE list_to_bitstring_1(BIF_ALIST_1)
BIF_RETTYPE split_binary_2(BIF_ALIST_2)
{
- Uint pos;
- ErlSubBin* sb1;
- ErlSubBin* sb2;
- size_t orig_size;
- Eterm orig;
- Uint offset;
- Uint bit_offset;
- Uint bit_size;
- Eterm* hp;
+ size_t orig_size, left_size, right_size;
+ Uint byte_offset, bit_offset, bit_size;
+ Uint split_at;
+
+ Eterm *hp, *hp_end;
+ Eterm left, right;
+ Eterm real_bin;
+ Eterm result;
+ byte *bptr;
if (is_not_binary(BIF_ARG_1)) {
- goto error;
- }
- if (!term_to_Uint(BIF_ARG_2, &pos)) {
- goto error;
- }
- if ((orig_size = binary_size(BIF_ARG_1)) < pos) {
- goto error;
+ BIF_ERROR(BIF_P, BADARG);
+ } else if (!term_to_Uint(BIF_ARG_2, &split_at)) {
+ BIF_ERROR(BIF_P, BADARG);
+ } else if ((orig_size = binary_size(BIF_ARG_1)) < split_at) {
+ BIF_ERROR(BIF_P, BADARG);
}
- hp = HAlloc(BIF_P, 2*ERL_SUB_BIN_SIZE+3);
- ERTS_GET_REAL_BIN(BIF_ARG_1, orig, offset, bit_offset, bit_size);
- sb1 = (ErlSubBin *) hp;
- sb1->thing_word = HEADER_SUB_BIN;
- sb1->size = pos;
- sb1->offs = offset;
- sb1->orig = orig;
- sb1->bitoffs = bit_offset;
- sb1->bitsize = 0;
- sb1->is_writable = 0;
- hp += ERL_SUB_BIN_SIZE;
-
- sb2 = (ErlSubBin *) hp;
- sb2->thing_word = HEADER_SUB_BIN;
- sb2->size = orig_size - pos;
- sb2->offs = offset + pos;
- sb2->orig = orig;
- sb2->bitoffs = bit_offset;
- sb2->bitsize = bit_size; /* The extra bits go into the second binary. */
- sb2->is_writable = 0;
- hp += ERL_SUB_BIN_SIZE;
-
- return TUPLE2(hp, make_binary(sb1), make_binary(sb2));
-
- error:
- BIF_ERROR(BIF_P, BADARG);
+
+ left_size = split_at;
+ right_size = orig_size - split_at;
+
+ ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, byte_offset, bit_offset, bit_size);
+ bptr = binary_bytes(real_bin);
+
+ hp = HAlloc(BIF_P, EXTRACT_SUB_BIN_HEAP_NEED * 2 + 3);
+ hp_end = hp + (EXTRACT_SUB_BIN_HEAP_NEED * 2 + 3);
+
+ left = erts_extract_sub_binary(&hp, real_bin, bptr,
+ byte_offset * 8 + bit_offset,
+ left_size * 8);
+
+ right = erts_extract_sub_binary(&hp, real_bin, bptr,
+ (byte_offset + split_at) * 8 + bit_offset,
+ right_size * 8 + bit_size);
+
+ result = TUPLE2(hp, left, right);
+ hp += 3;
+
+ HRelease(BIF_P, hp_end, hp);
+
+ return result;
}
diff --git a/erts/emulator/beam/bs_instrs.tab b/erts/emulator/beam/bs_instrs.tab
index bd1ad91e45..5f25bc2ad3 100644
--- a/erts/emulator/beam/bs_instrs.tab
+++ b/erts/emulator/beam/bs_instrs.tab
@@ -149,7 +149,7 @@ i_bs_get_binary_all2.execute(Fail, Live, Unit, Dst) {
ErlBinMatchBuffer *_mb;
Eterm _result;
- $GC_TEST_PRESERVE(ERL_SUB_BIN_SIZE, $Live, context);
+ $GC_TEST_PRESERVE(EXTRACT_SUB_BIN_HEAP_NEED, $Live, context);
_mb = ms_matchbuffer(context);
if (((_mb->size - _mb->offset) % $Unit) == 0) {
LIGHT_SWAPOUT;
@@ -179,7 +179,7 @@ i_bs_get_binary2.execute(Fail, Live, Sz, Flags, Dst) {
Eterm _result;
Uint _size;
$BS_GET_FIELD_SIZE($Sz, (($Flags) >> 3), $FAIL($Fail), _size);
- $GC_TEST_PRESERVE(ERL_SUB_BIN_SIZE, $Live, context);
+ $GC_TEST_PRESERVE(EXTRACT_SUB_BIN_HEAP_NEED, $Live, context);
_mb = ms_matchbuffer(context);
LIGHT_SWAPOUT;
_result = erts_bs_get_binary_2(c_p, _size, $Flags, _mb);
@@ -206,8 +206,7 @@ i_bs_get_binary_imm2.fetch(Ctx) {
i_bs_get_binary_imm2.execute(Fail, Live, Sz, Flags, Dst) {
ErlBinMatchBuffer *_mb;
Eterm _result;
- $GC_TEST_PRESERVE(heap_bin_size(ERL_ONHEAP_BIN_LIMIT),
- $Live, context);
+ $GC_TEST_PRESERVE(EXTRACT_SUB_BIN_HEAP_NEED, $Live, context);
_mb = ms_matchbuffer(context);
LIGHT_SWAPOUT;
_result = erts_bs_get_binary_2(c_p, $Sz, $Flags, _mb);
@@ -876,9 +875,7 @@ bs_start_match.execute(Fail, Live, Slots, Dst) {
result = erts_bs_start_match_2(c_p, context, slots);
HTOP = HEAP_TOP(c_p);
HEAP_SPACE_VERIFIED(0);
- if (is_non_value(result)) {
- $FAIL($Fail);
- }
+
$REFRESH_GEN_DEST();
$Dst = result;
} else {
@@ -1296,10 +1293,6 @@ i_bs_start_match3_gp.execute(Live, Fail, Dst, Pos) {
HTOP = HEAP_TOP(c_p);
HEAP_SPACE_VERIFIED(0);
- if (ms == NULL) {
- $FAIL($Fail);
- }
-
$REFRESH_GEN_DEST();
$Dst = make_matchstate(ms);
position = ms->mb.offset;
@@ -1348,10 +1341,6 @@ i_bs_start_match3.execute(Live, Fail, Dst) {
HTOP = HEAP_TOP(c_p);
HEAP_SPACE_VERIFIED(0);
- if (ms == NULL) {
- $FAIL($Fail);
- }
-
$REFRESH_GEN_DEST();
$Dst = make_matchstate(ms);
} else {
@@ -1523,10 +1512,6 @@ i_bs_start_match3.execute(Live, Fail, Dst) {
HTOP = HEAP_TOP(c_p);
HEAP_SPACE_VERIFIED(0);
- if (is_non_value(result)) {
- $FAIL($Fail);
- }
-
$REFRESH_GEN_DEST();
$Dst = result;
} else {
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index db74b06cc5..9bbcba6f3b 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -604,7 +604,12 @@ cleanup:
/*
* Copy a structure to a heap.
*/
-Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint *bsz, erts_literal_area_t *litopt)
+Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
+ Uint *bsz, erts_literal_area_t *litopt
+#ifdef ERTS_COPY_REGISTER_LOCATION
+ , char *file, int line
+#endif
+ )
{
char* hstart;
Uint hsize;
@@ -854,7 +859,11 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint
case EXTERNAL_REF_SUBTAG:
{
ExternalThing *etp = (ExternalThing *) objp;
+#if defined(ERTS_COPY_REGISTER_LOCATION) && defined(ERL_NODE_BOOKKEEP)
+ erts_ref_node_entry__(etp->node, 2, make_boxed(htop), file, line);
+#else
erts_ref_node_entry(etp->node, 2, make_boxed(htop));
+#endif
}
L_off_heap_node_container_common:
{
@@ -1326,8 +1335,13 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
* Copy object "obj" preserving sharing.
* Second half: copy and restore the object.
*/
-Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info,
- Eterm** hpp, ErlOffHeap* off_heap) {
+Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
+ Eterm** hpp, ErlOffHeap* off_heap
+#ifdef ERTS_COPY_REGISTER_LOCATION
+ , char *file, int line
+#endif
+ )
+{
Uint e;
unsigned sz;
Eterm* ptr;
@@ -1393,7 +1407,11 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info,
*resp = obj;
} else {
Uint bsz = 0;
- *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL); /* copy literal */
+ *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL
+#ifdef ERTS_COPY_REGISTER_LOCATION
+ , file, line
+#endif
+ ); /* copy literal */
hbot -= bsz;
}
goto cleanup_next;
@@ -1461,7 +1479,11 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info,
*resp = obj;
} else {
Uint bsz = 0;
- *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL); /* copy literal */
+ *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL
+#ifdef ERTS_COPY_REGISTER_LOCATION
+ , file, line
+#endif
+ ); /* copy literal */
hbot -= bsz;
}
goto cleanup_next;
@@ -1660,7 +1682,12 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info,
case EXTERNAL_REF_SUBTAG:
{
ExternalThing *etp = (ExternalThing *) ptr;
+
+#if defined(ERTS_COPY_REGISTER_LOCATION) && defined(ERL_NODE_BOOKKEEP)
+ erts_ref_node_entry__(etp->node, 2, make_boxed(hp), file, line);
+#else
erts_ref_node_entry(etp->node, 2, make_boxed(hp));
+#endif
}
off_heap_node_container_common:
{
@@ -1823,8 +1850,12 @@ all_clean:
*
* NOTE: Assumes that term is a tuple (ptr is an untagged tuple ptr).
*/
-Eterm copy_shallow(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp,
- ErlOffHeap* off_heap)
+Eterm
+copy_shallow_x(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap
+#ifdef ERTS_COPY_REGISTER_LOCATION
+ , char *file, int line
+#endif
+ )
{
Eterm* tp = ptr;
Eterm* hp = *hpp;
@@ -1866,7 +1897,11 @@ Eterm copy_shallow(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp,
case EXTERNAL_REF_SUBTAG:
{
ExternalThing* etp = (ExternalThing *) (tp-1);
+#if defined(ERTS_COPY_REGISTER_LOCATION) && defined(ERL_NODE_BOOKKEEP)
+ erts_ref_node_entry__(etp->node, 2, make_boxed(hp-1), file, line);
+#else
erts_ref_node_entry(etp->node, 2, make_boxed(hp-1));
+#endif
}
off_heap_common:
{
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 4537e3e569..eb9e749a08 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -1266,18 +1266,6 @@ erts_dsig_send_group_leader(ErtsDSigSendContext *ctx, Eterm leader, Eterm remote
return dsig_send_ctl(ctx, ctl);
}
-struct dist_sequences {
- ErlHeapFragment hfrag;
- struct dist_sequences *parent;
- struct dist_sequences *left;
- struct dist_sequences *right;
- char is_red;
-
- Uint64 seq_id;
- int cnt;
- Sint ctl_len;
-};
-
#define ERTS_RBT_PREFIX dist_seq
#define ERTS_RBT_T DistSeqNode
#define ERTS_RBT_KEY_T Uint
@@ -1312,25 +1300,25 @@ struct dist_sequences {
#include "erl_rbtree.h"
-struct erts_dist_seq_tree_foreach_iter_arg {
- int (*func)(ErtsDistExternal *, void *, Sint);
+struct erts_debug_dist_seq_tree_foreach_iter_arg {
+ int (*func)(DistSeqNode *, void *, Sint);
void *arg;
};
static int
-erts_dist_seq_tree_foreach_iter(DistSeqNode *seq, void *arg, Sint reds)
+erts_debug_dist_seq_tree_foreach_iter(DistSeqNode *seq, void *arg, Sint reds)
{
- struct erts_dist_seq_tree_foreach_iter_arg *state = arg;
- return state->func(erts_get_dist_ext(&seq->hfrag), state->arg, reds);
+ struct erts_debug_dist_seq_tree_foreach_iter_arg *state = arg;
+ return state->func(seq, state->arg, reds);
}
void
-erts_dist_seq_tree_foreach(DistEntry *dep, int (*func)(ErtsDistExternal *, void *, Sint), void *arg)
+erts_debug_dist_seq_tree_foreach(DistEntry *dep, int (*func)(DistSeqNode *, void *, Sint), void *arg)
{
- struct erts_dist_seq_tree_foreach_iter_arg state;
+ struct erts_debug_dist_seq_tree_foreach_iter_arg state;
state.func = func;
state.arg = arg;
- dist_seq_rbt_foreach(dep->sequences, erts_dist_seq_tree_foreach_iter, &state);
+ dist_seq_rbt_foreach(dep->sequences, erts_debug_dist_seq_tree_foreach_iter, &state);
}
static int dist_seq_cleanup(DistSeqNode *seq, void *unused, Sint reds)
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 067028634b..a33fb7efcf 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -274,6 +274,18 @@ typedef struct erts_dsig_send_context {
typedef struct dist_sequences DistSeqNode;
+struct dist_sequences {
+ ErlHeapFragment hfrag;
+ struct dist_sequences *parent;
+ struct dist_sequences *left;
+ struct dist_sequences *right;
+ char is_red;
+
+ Uint64 seq_id;
+ int cnt;
+ Sint ctl_len;
+};
+
/*
* erts_dsig_send_* return values.
*/
@@ -306,9 +318,9 @@ extern Uint erts_dist_cache_size(void);
extern Sint erts_abort_connection_rwunlock(DistEntry *dep);
-extern void erts_dist_seq_tree_foreach(
+extern void erts_debug_dist_seq_tree_foreach(
DistEntry *dep,
- int (*func)(ErtsDistExternal *, void*, Sint), void *args);
+ int (*func)(DistSeqNode *, void*, Sint), void *args);
extern int erts_dsig_prepare(ErtsDSigSendContext *,
DistEntry*,
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index 92e5069c71..21941ba96e 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -149,6 +149,7 @@ type MODULE_TABLE LONG_LIVED CODE module_tab
type TAINT LONG_LIVED CODE taint_list
type MODULE_REFS STANDARD CODE module_refs
type NC_TMP TEMPORARY SYSTEM nc_tmp
+type NC_STD STANDARD SYSTEM nc_std
type TMP TEMPORARY SYSTEM tmp
type UNDEF SYSTEM SYSTEM undefined
type DCACHE STANDARD SYSTEM dcache
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index 25ac3bc5af..bfc2f5992c 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -7112,12 +7112,21 @@ static int blockscan_cpool_yielding(blockscan_t *state)
return 0;
}
-static int blockscan_yield_helper(blockscan_t *state,
- int (*yielding_op)(blockscan_t*))
+/* */
+
+static int blockscan_finish(blockscan_t *state)
{
- /* Note that we don't check whether to abort here; only yielding_op knows
- * whether the carrier is still in the list/pool. */
+ if (ERTS_PROC_IS_EXITING(state->process)) {
+ state->abort(state->user_data);
+ return 0;
+ }
+ state->current_op = blockscan_finish;
+
+ return state->finish(state->user_data);
+}
+
+static void blockscan_lock_helper(blockscan_t *state) {
if ((state->allocator)->thread_safe) {
/* Locked scans have to be as short as possible. */
state->reductions = 1;
@@ -7126,34 +7135,18 @@ static int blockscan_yield_helper(blockscan_t *state,
} else {
state->reductions = BLOCKSCAN_REDUCTIONS;
}
+}
- if (yielding_op(state)) {
- state->next_op = state->current_op;
- }
-
+static void blockscan_unlock_helper(blockscan_t *state) {
if ((state->allocator)->thread_safe) {
erts_mtx_unlock(&(state->allocator)->mutex);
}
-
- return 1;
-}
-
-/* */
-
-static int blockscan_finish(blockscan_t *state)
-{
- if (ERTS_PROC_IS_EXITING(state->process)) {
- state->abort(state->user_data);
- return 0;
- }
-
- state->current_op = blockscan_finish;
-
- return state->finish(state->user_data);
}
static int blockscan_sweep_sbcs(blockscan_t *state)
{
+ blockscan_lock_helper(state);
+
if (state->current_op != blockscan_sweep_sbcs) {
SET_CARRIER_HDR(&state->dummy_carrier, 0, SCH_SBC, state->allocator);
state->current_clist = &(state->allocator)->sbc_list;
@@ -7163,11 +7156,19 @@ static int blockscan_sweep_sbcs(blockscan_t *state)
state->current_op = blockscan_sweep_sbcs;
state->next_op = blockscan_finish;
- return blockscan_yield_helper(state, blockscan_clist_yielding);
+ if (blockscan_clist_yielding(state)) {
+ state->next_op = state->current_op;
+ }
+
+ blockscan_unlock_helper(state);
+
+ return 1;
}
static int blockscan_sweep_mbcs(blockscan_t *state)
{
+ blockscan_lock_helper(state);
+
if (state->current_op != blockscan_sweep_mbcs) {
SET_CARRIER_HDR(&state->dummy_carrier, 0, SCH_MBC, state->allocator);
state->current_clist = &(state->allocator)->mbc_list;
@@ -7177,11 +7178,19 @@ static int blockscan_sweep_mbcs(blockscan_t *state)
state->current_op = blockscan_sweep_mbcs;
state->next_op = blockscan_sweep_sbcs;
- return blockscan_yield_helper(state, blockscan_clist_yielding);
+ if (blockscan_clist_yielding(state)) {
+ state->next_op = state->current_op;
+ }
+
+ blockscan_unlock_helper(state);
+
+ return 1;
}
static int blockscan_sweep_cpool(blockscan_t *state)
{
+ blockscan_lock_helper(state);
+
if (state->current_op != blockscan_sweep_cpool) {
SET_CARRIER_HDR(&state->dummy_carrier, 0, SCH_MBC, state->allocator);
state->cpool_cursor = (state->allocator)->cpool.sentinel;
@@ -7190,7 +7199,13 @@ static int blockscan_sweep_cpool(blockscan_t *state)
state->current_op = blockscan_sweep_cpool;
state->next_op = blockscan_sweep_mbcs;
- return blockscan_yield_helper(state, blockscan_cpool_yielding);
+ if (blockscan_cpool_yielding(state)) {
+ state->next_op = state->current_op;
+ }
+
+ blockscan_unlock_helper(state);
+
+ return 1;
}
static int blockscan_get_specific_allocator(int allocator_num,
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 4d6d31cd76..b8e56390c1 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -1750,9 +1750,8 @@ static Eterm do_split_single_result(Process *p, Eterm subject, BinaryFindContext
Uint offset;
Uint bit_offset;
Uint bit_size;
- ErlSubBin *sb1;
- ErlSubBin *sb2;
- Eterm *hp;
+ Uint hp_need;
+ Eterm *hp, *hp_end;
Eterm ret;
pos = ff->pos;
@@ -1765,57 +1764,58 @@ static Eterm do_split_single_result(Process *p, Eterm subject, BinaryFindContext
if (pos == 0) {
ret = NIL;
} else {
- hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2));
+ Eterm extracted;
+
+ hp_need = EXTRACT_SUB_BIN_HEAP_NEED + 2;
+
+ hp = HAlloc(p, hp_need);
+ hp_end = hp + hp_need;
+
ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
- sb1 = (ErlSubBin *) hp;
- sb1->thing_word = HEADER_SUB_BIN;
- sb1->size = pos;
- sb1->offs = offset;
- sb1->orig = orig;
- sb1->bitoffs = bit_offset;
- sb1->bitsize = bit_size;
- sb1->is_writable = 0;
- hp += ERL_SUB_BIN_SIZE;
-
- ret = CONS(hp, make_binary(sb1), NIL);
+ extracted = erts_extract_sub_binary(&hp, orig, binary_bytes(orig),
+ offset * 8 + bit_offset,
+ pos * 8 + bit_size);
+
+ ret = CONS(hp, extracted, NIL);
hp += 2;
+
+ HRelease(p, hp_end, hp);
+
+ return ret;
}
} else {
- if ((ctx->flags & BF_FLAG_SPLIT_TRIM_ALL) && (pos == 0)) {
- hp = HAlloc(p, 1 * (ERL_SUB_BIN_SIZE + 2));
- ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
- sb1 = NULL;
- } else {
- hp = HAlloc(p, 2 * (ERL_SUB_BIN_SIZE + 2));
- ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
- sb1 = (ErlSubBin *) hp;
- sb1->thing_word = HEADER_SUB_BIN;
- sb1->size = pos;
- sb1->offs = offset;
- sb1->orig = orig;
- sb1->bitoffs = bit_offset;
- sb1->bitsize = 0;
- sb1->is_writable = 0;
- hp += ERL_SUB_BIN_SIZE;
- }
-
- sb2 = (ErlSubBin *) hp;
- sb2->thing_word = HEADER_SUB_BIN;
- sb2->size = orig_size - pos - len;
- sb2->offs = offset + pos + len;
- sb2->orig = orig;
- sb2->bitoffs = bit_offset;
- sb2->bitsize = bit_size;
- sb2->is_writable = 0;
- hp += ERL_SUB_BIN_SIZE;
-
- ret = CONS(hp, make_binary(sb2), NIL);
- hp += 2;
- if (sb1 != NULL) {
- ret = CONS(hp, make_binary(sb1), ret);
- hp += 2;
- }
+ Eterm first, rest;
+
+ hp_need = (EXTRACT_SUB_BIN_HEAP_NEED + 2) * 2;
+
+ hp = HAlloc(p, hp_need);
+ hp_end = hp + hp_need;
+
+ ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size);
+
+ if ((ctx->flags & BF_FLAG_SPLIT_TRIM_ALL) && (pos == 0)) {
+ first = NIL;
+ } else {
+ first = erts_extract_sub_binary(&hp, orig, binary_bytes(orig),
+ offset * 8 + bit_offset,
+ pos * 8);
+ }
+
+ rest = erts_extract_sub_binary(&hp, orig, binary_bytes(orig),
+ (offset + pos + len) * 8 + bit_offset,
+ (orig_size - pos - len) * 8 + bit_size);
+
+ ret = CONS(hp, rest, NIL);
+ hp += 2;
+
+ if (first != NIL) {
+ ret = CONS(hp, first, ret);
+ hp += 2;
+ }
+
+ HRelease(p, hp_end, hp);
}
+
return ret;
}
@@ -1829,7 +1829,9 @@ static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindContext
Uint offset;
Uint bit_offset;
Uint bit_size;
- ErlSubBin *sb;
+ Uint extracted_offset;
+ Uint extracted_size;
+ Eterm extracted;
Uint do_trim;
Sint i;
register Uint reds = ctx->reds;
@@ -1852,7 +1854,8 @@ static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindContext
*ctxp = ctx;
fa = &(ctx->u.fa);
}
- erts_factory_proc_prealloc_init(&(fa->factory), p, (fa->size + 1) * (ERL_SUB_BIN_SIZE + 2));
+ erts_factory_proc_prealloc_init(&(fa->factory), p, (fa->size + 1) *
+ (EXTRACT_SUB_BIN_HEAP_NEED + 2));
ctx->state = BFResult;
}
@@ -1871,39 +1874,39 @@ static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindContext
}
return THE_NON_VALUE;
}
- sb = (ErlSubBin *)(fa->factory.hp);
- sb->size = fa->end_pos - (fad[i].pos + fad[i].len);
- if (!(sb->size == 0 && do_trim)) {
- sb->thing_word = HEADER_SUB_BIN;
- sb->offs = offset + fad[i].pos + fad[i].len;
- sb->orig = orig;
- sb->bitoffs = bit_offset;
- sb->bitsize = 0;
- sb->is_writable = 0;
- fa->factory.hp += ERL_SUB_BIN_SIZE;
- fa->term = CONS(fa->factory.hp, make_binary(sb), fa->term);
- fa->factory.hp += 2;
- do_trim &= ~BF_FLAG_SPLIT_TRIM;
- }
- fa->end_pos = fad[i].pos;
+
+ extracted_offset = (offset + fad[i].pos + fad[i].len) * 8 + bit_offset;
+ extracted_size = (fa->end_pos - (fad[i].pos + fad[i].len)) * 8;
+
+ if (!(extracted_size == 0 && do_trim)) {
+ extracted = erts_extract_sub_binary(&fa->factory.hp, orig,
+ binary_bytes(orig),
+ extracted_offset,
+ extracted_size);
+ fa->term = CONS(fa->factory.hp, extracted, fa->term);
+ fa->factory.hp += 2;
+
+ do_trim &= ~BF_FLAG_SPLIT_TRIM;
+ }
+
+ fa->end_pos = fad[i].pos;
}
fa->head = i;
ctx->reds = reds;
- sb = (ErlSubBin *)(fa->factory.hp);
- sb->size = fad[0].pos;
- if (!(sb->size == 0 && do_trim)) {
- sb->thing_word = HEADER_SUB_BIN;
- sb->offs = offset;
- sb->orig = orig;
- sb->bitoffs = bit_offset;
- sb->bitsize = 0;
- sb->is_writable = 0;
- fa->factory.hp += ERL_SUB_BIN_SIZE;
- fa->term = CONS(fa->factory.hp, make_binary(sb), fa->term);
- fa->factory.hp += 2;
+ extracted_offset = offset * 8 + bit_offset;
+ extracted_size = fad[0].pos * 8;
+
+ if (!(extracted_size == 0 && do_trim)) {
+ extracted = erts_extract_sub_binary(&fa->factory.hp, orig,
+ binary_bytes(orig),
+ extracted_offset,
+ extracted_size);
+ fa->term = CONS(fa->factory.hp, extracted, fa->term);
+ fa->factory.hp += 2;
}
+
erts_factory_close(&(fa->factory));
return fa->term;
@@ -1937,8 +1940,8 @@ BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen)
Uint offset;
Uint bit_offset;
Uint bit_size;
- Eterm* hp;
- ErlSubBin* sb;
+ Eterm *hp, *hp_end;
+ Eterm result;
if (is_not_binary(binary)) {
goto badarg;
@@ -1970,19 +1973,18 @@ BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen)
goto badarg;
}
- hp = HeapFragOnlyAlloc(p, ERL_SUB_BIN_SIZE);
+ hp = HeapFragOnlyAlloc(p, EXTRACT_SUB_BIN_HEAP_NEED);
+ hp_end = hp + EXTRACT_SUB_BIN_HEAP_NEED;
ERTS_GET_REAL_BIN(binary, orig, offset, bit_offset, bit_size);
- sb = (ErlSubBin *) hp;
- sb->thing_word = HEADER_SUB_BIN;
- sb->size = len;
- sb->offs = offset + pos;
- sb->orig = orig;
- sb->bitoffs = bit_offset;
- sb->bitsize = 0;
- sb->is_writable = 0;
-
- BIF_RET(make_binary(sb));
+
+ result = erts_extract_sub_binary(&hp, orig, binary_bytes(orig),
+ (offset + pos) * 8 + bit_offset,
+ len * 8);
+
+ HRelease(p, hp_end, hp);
+
+ BIF_RET(result);
badarg:
BIF_ERROR(p, BADARG);
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 0339589b79..4d8c3eb9dd 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -162,10 +162,10 @@ static Eterm current_stacktrace(ErtsHeapFactory *hfact, Process* rp,
Uint reserve_size);
static Eterm
-bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh)
+bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh, Eterm tail)
{
struct erl_off_heap_header* ohh;
- Eterm res = NIL;
+ Eterm res = tail;
Eterm tuple;
for (ohh = oh->first; ohh; ohh = ohh->next) {
@@ -1864,11 +1864,25 @@ process_info_aux(Process *c_p,
break;
case ERTS_PI_IX_BINARY: {
- Uint sz = 0;
- (void) bld_bin_list(NULL, &sz, &MSO(rp));
+ ErlHeapFragment *hfrag;
+ Uint sz;
+
+ res = NIL;
+ sz = 0;
+
+ (void)bld_bin_list(NULL, &sz, &MSO(rp), NIL);
+ for (hfrag = rp->mbuf; hfrag != NULL; hfrag = hfrag->next) {
+ (void)bld_bin_list(NULL, &sz, &hfrag->off_heap, NIL);
+ }
+
hp = erts_produce_heap(hfact, sz, reserve_size);
- res = bld_bin_list(&hp, NULL, &MSO(rp));
- break;
+
+ res = bld_bin_list(&hp, NULL, &MSO(rp), NIL);
+ for (hfrag = rp->mbuf; hfrag != NULL; hfrag = hfrag->next) {
+ res = bld_bin_list(&hp, NULL, &hfrag->off_heap, res);
+ }
+
+ break;
}
case ERTS_PI_IX_SEQUENTIAL_TRACE_TOKEN: {
diff --git a/erts/emulator/beam/erl_bif_persistent.c b/erts/emulator/beam/erl_bif_persistent.c
index f38e0cc5cb..8662a9e33a 100644
--- a/erts/emulator/beam/erl_bif_persistent.c
+++ b/erts/emulator/beam/erl_bif_persistent.c
@@ -1234,3 +1234,102 @@ next_to_delete(void)
erts_mtx_unlock(&delete_queue_mtx);
return table;
}
+
+/*
+ * test/debug functionality follow...
+ */
+
+static Uint accessed_literal_areas_size;
+static Uint accessed_no_literal_areas;
+static ErtsLiteralArea **accessed_literal_areas;
+
+int
+erts_debug_have_accessed_literal_area(ErtsLiteralArea *lap)
+{
+ Uint i;
+ for (i = 0; i < accessed_no_literal_areas; i++) {
+ if (accessed_literal_areas[i] == lap)
+ return !0;
+ }
+ return 0;
+}
+
+void
+erts_debug_save_accessed_literal_area(ErtsLiteralArea *lap)
+{
+ if (accessed_no_literal_areas == accessed_literal_areas_size) {
+ accessed_literal_areas_size += 10;
+ accessed_literal_areas = erts_realloc(ERTS_ALC_T_TMP,
+ accessed_literal_areas,
+ (sizeof(ErtsLiteralArea *)
+ *accessed_literal_areas_size));
+ }
+ accessed_literal_areas[accessed_no_literal_areas++] = lap;
+}
+
+static void debug_foreach_off_heap(HashTable *tbl, void (*func)(ErlOffHeap *, void *), void *arg)
+{
+ int i;
+
+ for (i = 0; i < tbl->allocated; i++) {
+ Eterm term = tbl->term[i];
+ if (is_tuple_arity(term, 2)) {
+ ErtsLiteralArea *lap = term_to_area(term);
+ ErlOffHeap oh;
+ if (!erts_debug_have_accessed_literal_area(lap)) {
+ ERTS_INIT_OFF_HEAP(&oh);
+ oh.first = lap->off_heap;
+ (*func)(&oh, arg);
+ erts_debug_save_accessed_literal_area(lap);
+ }
+ }
+ }
+}
+
+struct debug_la_oh {
+ void (*func)(ErlOffHeap *, void *);
+ void *arg;
+};
+
+static void debug_handle_table(void *vfap,
+ ErtsThrPrgrVal val,
+ void *vtbl)
+{
+ struct debug_la_oh *fap = vfap;
+ HashTable *tbl = vtbl;
+ debug_foreach_off_heap(tbl, fap->func, fap->arg);
+}
+
+void
+erts_debug_foreach_persistent_term_off_heap(void (*func)(ErlOffHeap *, void *), void *arg)
+{
+ HashTable *tbl;
+ struct debug_la_oh fa;
+ accessed_no_literal_areas = 0;
+ accessed_literal_areas_size = 10;
+ accessed_literal_areas = erts_alloc(ERTS_ALC_T_TMP,
+ (sizeof(ErtsLiteralArea *)
+ * accessed_literal_areas_size));
+
+ tbl = (HashTable *) erts_atomic_read_nob(&the_hash_table);
+ debug_foreach_off_heap(tbl, func, arg);
+ erts_mtx_lock(&delete_queue_mtx);
+ for (tbl = delete_queue_head; tbl; tbl = tbl->delete_next)
+ debug_foreach_off_heap(tbl, func, arg);
+ erts_mtx_unlock(&delete_queue_mtx);
+ fa.func = func;
+ fa.arg = arg;
+ erts_debug_later_op_foreach(table_updater,
+ debug_handle_table,
+ (void *) &fa);
+ erts_debug_later_op_foreach(table_deleter,
+ debug_handle_table,
+ (void *) &fa);
+ erts_debug_foreach_release_literal_area_off_heap(func, arg);
+
+ erts_free(ERTS_ALC_T_TMP, accessed_literal_areas);
+ accessed_no_literal_areas = 0;
+ accessed_literal_areas_size = 0;
+ accessed_literal_areas = NULL;
+}
+
diff --git a/erts/emulator/beam/erl_binary.h b/erts/emulator/beam/erl_binary.h
index c9c047255a..66b59ef1a3 100644
--- a/erts/emulator/beam/erl_binary.h
+++ b/erts/emulator/beam/erl_binary.h
@@ -351,6 +351,19 @@ erts_free_aligned_binary_bytes(byte* buf)
erts_free_aligned_binary_bytes_extra(buf,ERTS_ALC_T_TMP);
}
+/* A binary's size in bits must fit into a word for matching to work. We used
+ * to allow creating larger binaries than this, but they acted really strangely
+ * in Erlang code and were pretty much only usable in drivers and NIFs.
+ *
+ * This check also ensures, indirectly, that there won't be an overflow when
+ * the size is bumped by CHICKEN_PAD and the binary struct itself. */
+#define BINARY_OVERFLOW_CHECK(BYTE_SIZE) \
+ do { \
+ if (ERTS_UNLIKELY(BYTE_SIZE > ERTS_UWORD_MAX / CHAR_BIT)) { \
+ return NULL; \
+ } \
+ } while(0)
+
/* Explicit extra bytes allocated to counter buggy drivers.
** These extra bytes where earlier (< R13B04) added by an alignment-bug
** in this code. Do we dare remove this in some major release (R14?) maybe?
@@ -364,86 +377,107 @@ erts_free_aligned_binary_bytes(byte* buf)
ERTS_GLB_INLINE Binary *
erts_bin_drv_alloc_fnf(Uint size)
{
- Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
Binary *res;
+ Uint bsize;
+
+ BINARY_OVERFLOW_CHECK(size);
+ bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
- if (bsize < size) /* overflow */
- return NULL;
res = erts_alloc_fnf(ERTS_ALC_T_DRV_BINARY, bsize);
ERTS_CHK_BIN_ALIGNMENT(res);
+
if (res) {
- res->orig_size = size;
- res->intern.flags = BIN_FLAG_DRV;
+ res->orig_size = size;
+ res->intern.flags = BIN_FLAG_DRV;
erts_refc_init(&res->intern.refc, 1);
}
+
return res;
}
ERTS_GLB_INLINE Binary *
erts_bin_drv_alloc(Uint size)
{
- Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
+ Binary *res = erts_bin_drv_alloc_fnf(size);
+
+ if (res) {
+ return res;
+ }
+
+ erts_alloc_enomem(ERTS_ALC_T_DRV_BINARY, size);
+}
+
+ERTS_GLB_INLINE Binary *
+erts_bin_nrml_alloc_fnf(Uint size)
+{
Binary *res;
+ Uint bsize;
- if (bsize < size) /* overflow */
- erts_alloc_enomem(ERTS_ALC_T_DRV_BINARY, size);
- res = erts_alloc(ERTS_ALC_T_DRV_BINARY, bsize);
+ BINARY_OVERFLOW_CHECK(size);
+ bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
+
+ res = erts_alloc_fnf(ERTS_ALC_T_BINARY, bsize);
ERTS_CHK_BIN_ALIGNMENT(res);
- res->orig_size = size;
- res->intern.flags = BIN_FLAG_DRV;
- erts_refc_init(&res->intern.refc, 1);
+
+ if (res) {
+ res->orig_size = size;
+ res->intern.flags = 0;
+ erts_refc_init(&res->intern.refc, 1);
+ }
+
return res;
}
ERTS_GLB_INLINE Binary *
erts_bin_nrml_alloc(Uint size)
{
- Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
- Binary *res;
+ Binary *res = erts_bin_drv_alloc_fnf(size);
- if (bsize < size) /* overflow */
- erts_alloc_enomem(ERTS_ALC_T_BINARY, size);
- res = erts_alloc(ERTS_ALC_T_BINARY, bsize);
- ERTS_CHK_BIN_ALIGNMENT(res);
- res->orig_size = size;
- res->intern.flags = 0;
- erts_refc_init(&res->intern.refc, 1);
- return res;
+ if (res) {
+ return res;
+ }
+
+ erts_alloc_enomem(ERTS_ALC_T_BINARY, size);
}
ERTS_GLB_INLINE Binary *
erts_bin_realloc_fnf(Binary *bp, Uint size)
{
+ ErtsAlcType_t type;
Binary *nbp;
- Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
- ErtsAlcType_t type = (bp->intern.flags & BIN_FLAG_DRV) ? ERTS_ALC_T_DRV_BINARY
- : ERTS_ALC_T_BINARY;
+ Uint bsize;
+
+ type = (bp->intern.flags & BIN_FLAG_DRV) ? ERTS_ALC_T_DRV_BINARY
+ : ERTS_ALC_T_BINARY;
ASSERT((bp->intern.flags & BIN_FLAG_MAGIC) == 0);
- if (bsize < size) /* overflow */
- return NULL;
+
+ BINARY_OVERFLOW_CHECK(size);
+ bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
+
nbp = erts_realloc_fnf(type, (void *) bp, bsize);
ERTS_CHK_BIN_ALIGNMENT(nbp);
- if (nbp)
- nbp->orig_size = size;
+
+ if (nbp) {
+ nbp->orig_size = size;
+ }
+
return nbp;
}
ERTS_GLB_INLINE Binary *
erts_bin_realloc(Binary *bp, Uint size)
{
- Binary *nbp;
- Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD;
- ErtsAlcType_t type = (bp->intern.flags & BIN_FLAG_DRV) ? ERTS_ALC_T_DRV_BINARY
- : ERTS_ALC_T_BINARY;
- ASSERT((bp->intern.flags & BIN_FLAG_MAGIC) == 0);
- if (bsize < size) /* overflow */
- erts_realloc_enomem(type, bp, size);
- nbp = erts_realloc_fnf(type, (void *) bp, bsize);
- if (!nbp)
- erts_realloc_enomem(type, bp, bsize);
- ERTS_CHK_BIN_ALIGNMENT(nbp);
- nbp->orig_size = size;
- return nbp;
+ Binary *nbp = erts_bin_realloc_fnf(bp, size);
+
+ if (nbp) {
+ return nbp;
+ }
+
+ if (bp->intern.flags & BIN_FLAG_DRV) {
+ erts_realloc_enomem(ERTS_ALC_T_DRV_BINARY, bp, size);
+ } else {
+ erts_realloc_enomem(ERTS_ALC_T_BINARY, bp, size);
+ }
}
ERTS_GLB_INLINE void
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index f5807d25d7..a0edbc81a4 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -124,10 +124,10 @@ erts_bs_start_match_2(Process *p, Eterm Binary, Uint Max)
ProcBin* pb;
ASSERT(is_binary(Binary));
+
total_bin_size = binary_size(Binary);
- if ((total_bin_size >> (8*sizeof(Uint)-3)) != 0) {
- return THE_NON_VALUE;
- }
+ ASSERT(total_bin_size <= ERTS_UWORD_MAX / CHAR_BIT);
+
NeededSize = ERL_BIN_MATCHSTATE_SIZE(Max);
hp = HeapOnlyAlloc(p, NeededSize);
ms = (ErlBinMatchState *) hp;
@@ -157,10 +157,9 @@ ErlBinMatchState *erts_bs_start_match_3(Process *p, Eterm Binary)
ProcBin* pb;
ASSERT(is_binary(Binary));
+
total_bin_size = binary_size(Binary);
- if ((total_bin_size >> (8*sizeof(Uint)-3)) != 0) {
- return NULL;
- }
+ ASSERT(total_bin_size <= ERTS_UWORD_MAX / CHAR_BIT);
NeededSize = ERL_BIN_MATCHSTATE_SIZE(0);
hp = HeapOnlyAlloc(p, NeededSize);
@@ -459,29 +458,25 @@ erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuff
Eterm
erts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb)
{
- ErlSubBin* sb;
+ Eterm result;
CHECK_MATCH_BUFFER(mb);
- if (mb->size - mb->offset < num_bits) { /* Asked for too many bits. */
- return THE_NON_VALUE;
+ if (mb->size - mb->offset < num_bits) {
+ /* Asked for too many bits. */
+ return THE_NON_VALUE;
}
/*
* From now on, we can't fail.
*/
- sb = (ErlSubBin *) HeapOnlyAlloc(p, ERL_SUB_BIN_SIZE);
-
- sb->thing_word = HEADER_SUB_BIN;
- sb->orig = mb->orig;
- sb->size = BYTE_OFFSET(num_bits);
- sb->bitsize = BIT_OFFSET(num_bits);
- sb->offs = BYTE_OFFSET(mb->offset);
- sb->bitoffs = BIT_OFFSET(mb->offset);
- sb->is_writable = 0;
+ result = erts_extract_sub_binary(&HEAP_TOP(p),
+ mb->orig, mb->base,
+ mb->offset, num_bits);
+
mb->offset += num_bits;
-
- return make_binary(sb);
+
+ return result;
}
Eterm
@@ -545,21 +540,19 @@ erts_bs_get_float_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer
Eterm
erts_bs_get_binary_all_2(Process *p, ErlBinMatchBuffer* mb)
{
- ErlSubBin* sb;
- Uint size;
+ Uint bit_size;
+ Eterm result;
CHECK_MATCH_BUFFER(mb);
- size = mb->size-mb->offset;
- sb = (ErlSubBin *) HeapOnlyAlloc(p, ERL_SUB_BIN_SIZE);
- sb->thing_word = HEADER_SUB_BIN;
- sb->size = BYTE_OFFSET(size);
- sb->bitsize = BIT_OFFSET(size);
- sb->offs = BYTE_OFFSET(mb->offset);
- sb->bitoffs = BIT_OFFSET(mb->offset);
- sb->is_writable = 0;
- sb->orig = mb->orig;
- mb->offset = mb->size;
- return make_binary(sb);
+ bit_size = mb->size - mb->offset;
+
+ result = erts_extract_sub_binary(&HEAP_TOP(p),
+ mb->orig, mb->base,
+ mb->offset, bit_size);
+
+ mb->offset = mb->size;
+
+ return result;
}
/****************************************************************
@@ -2097,3 +2090,39 @@ erts_copy_bits(byte* src, /* Base pointer to source. */
}
}
+Eterm erts_extract_sub_binary(Eterm **hp, Eterm base_bin, byte *base_data,
+ Uint bit_offset, Uint bit_size)
+{
+ Uint byte_offset, byte_size;
+
+ ERTS_CT_ASSERT(ERL_SUB_BIN_SIZE <= ERL_ONHEAP_BIN_LIMIT);
+
+ byte_offset = BYTE_OFFSET(bit_offset);
+ byte_size = BYTE_OFFSET(bit_size);
+
+ if (BIT_OFFSET(bit_size) == 0 && byte_size <= ERL_ONHEAP_BIN_LIMIT) {
+ ErlHeapBin *hb = (ErlHeapBin*)*hp;
+ *hp += heap_bin_size(byte_size);
+
+ hb->thing_word = header_heap_bin(byte_size);
+ hb->size = byte_size;
+
+ copy_binary_to_buffer(hb->data, 0, base_data, bit_offset, bit_size);
+
+ return make_binary(hb);
+ } else {
+ ErlSubBin *sb = (ErlSubBin*)*hp;
+ *hp += ERL_SUB_BIN_SIZE;
+
+ sb->thing_word = HEADER_SUB_BIN;
+ sb->size = byte_size;
+ sb->offs = byte_offset;
+ sb->orig = base_bin;
+ sb->bitoffs = BIT_OFFSET(bit_offset);
+ sb->bitsize = BIT_OFFSET(bit_size);
+ sb->is_writable = 0;
+
+ return make_binary(sb);
+ }
+}
+
diff --git a/erts/emulator/beam/erl_bits.h b/erts/emulator/beam/erl_bits.h
index 50d353e1fa..0b2a6f3760 100644
--- a/erts/emulator/beam/erl_bits.h
+++ b/erts/emulator/beam/erl_bits.h
@@ -116,7 +116,7 @@ typedef struct erl_bin_match_struct{
do { \
if (BIT_OFFSET(DstBufOffset) == 0 && (SrcBufferOffset == 0) && \
(BIT_OFFSET(NumBits)==0) && (NumBits != 0)) { \
- sys_memcpy(DstBuffer+BYTE_OFFSET(DstBufOffset), \
+ sys_memcpy(((byte*)DstBuffer)+BYTE_OFFSET(DstBufOffset), \
SrcBuffer, NBYTES(NumBits)); \
} else { \
erts_copy_bits(SrcBuffer, SrcBufferOffset, 1, \
@@ -150,8 +150,11 @@ void erts_bits_destroy_state(ERL_BITS_PROTO_0);
Eterm erts_bs_start_match_2(Process *p, Eterm Bin, Uint Max);
ErlBinMatchState *erts_bs_start_match_3(Process *p, Eterm Bin);
Eterm erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb);
-Eterm erts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb);
Eterm erts_bs_get_float_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb);
+
+/* These will create heap binaries when appropriate, so they require free space
+ * up to EXTRACT_SUB_BIN_HEAP_NEED. */
+Eterm erts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb);
Eterm erts_bs_get_binary_all_2(Process *p, ErlBinMatchBuffer* mb);
/*
@@ -182,6 +185,17 @@ void erts_copy_bits(byte* src, size_t soffs, int sdir,
byte* dst, size_t doffs,int ddir, size_t n);
int erts_cmp_bits(byte* a_ptr, size_t a_offs, byte* b_ptr, size_t b_offs, size_t size);
+
+/* Extracts a region from base_bin as a sub-binary or heap binary, whichever
+ * is the most appropriate.
+ *
+ * The caller must ensure that there's enough free space at *hp */
+Eterm erts_extract_sub_binary(Eterm **hp, Eterm base_bin, byte *base_data,
+ Uint bit_offset, Uint num_bits);
+
+/* Pessimistic estimate of the words required for erts_extract_sub_binary */
+#define EXTRACT_SUB_BIN_HEAP_NEED (heap_bin_size(ERL_ONHEAP_BIN_LIMIT))
+
/*
* Flags for bs_get_* / bs_put_* / bs_init* instructions.
*/
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index d24f30f126..3c74ef493b 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -4415,7 +4415,7 @@ void db_info(fmtfn_t to, void *to_arg, int show) /* Called by break handler *
pdbi.to_arg = to_arg;
pdbi.show = show;
- erts_db_foreach_table(db_info_print, &pdbi);
+ erts_db_foreach_table(db_info_print, &pdbi, !0);
}
Uint
@@ -4428,7 +4428,7 @@ erts_get_ets_misc_mem_size(void)
/* SMP Note: May only be used when system is locked */
void
-erts_db_foreach_table(void (*func)(DbTable *, void *), void *arg)
+erts_db_foreach_table(void (*func)(DbTable *, void *), void *arg, int alive_only)
{
int ix;
@@ -4440,7 +4440,7 @@ erts_db_foreach_table(void (*func)(DbTable *, void *), void *arg)
if (first) {
DbTable *tb = first;
do {
- if (is_table_alive(tb))
+ if (!alive_only || is_table_alive(tb))
(*func)(tb, arg);
tb = tb->common.all.next;
} while (tb != first);
@@ -4457,6 +4457,15 @@ erts_db_foreach_offheap(DbTable *tb,
tb->common.meth->db_foreach_offheap(tb, func, arg);
}
+void
+erts_db_foreach_thr_prgr_offheap(void (*func)(ErlOffHeap *, void *),
+ void *arg)
+{
+ erts_db_foreach_thr_prgr_offheap_hash(func, arg);
+ erts_db_foreach_thr_prgr_offheap_tree(func, arg);
+ erts_db_foreach_thr_prgr_offheap_catree(func, arg);
+}
+
/* retrieve max number of ets tables */
Uint
erts_db_get_max_tabs()
diff --git a/erts/emulator/beam/erl_db.h b/erts/emulator/beam/erl_db.h
index b3dc1b9ba3..c604744687 100644
--- a/erts/emulator/beam/erl_db.h
+++ b/erts/emulator/beam/erl_db.h
@@ -114,10 +114,12 @@ void init_db(ErtsDbSpinCount);
int erts_db_process_exiting(Process *, ErtsProcLocks, void **);
int erts_db_execute_free_fixation(Process*, DbFixation*);
void db_info(fmtfn_t, void *, int);
-void erts_db_foreach_table(void (*)(DbTable *, void *), void *);
+void erts_db_foreach_table(void (*)(DbTable *, void *), void *, int);
void erts_db_foreach_offheap(DbTable *,
void (*func)(ErlOffHeap *, void *),
void *);
+void erts_db_foreach_thr_prgr_offheap(void (*func)(ErlOffHeap *, void *),
+ void *);
extern int erts_ets_rwmtx_spin_count;
extern int user_requested_db_max_tabs; /* set in erl_init */
diff --git a/erts/emulator/beam/erl_db_catree.c b/erts/emulator/beam/erl_db_catree.c
index fed4b44a9b..8a89eb72df 100644
--- a/erts/emulator/beam/erl_db_catree.c
+++ b/erts/emulator/beam/erl_db_catree.c
@@ -2395,6 +2395,34 @@ void db_calc_stats_catree(DbTableCATree* tb, DbCATreeStats* stats)
} while (depth > 0);
}
+struct debug_catree_fa {
+ void (*func)(ErlOffHeap *, void *);
+ void *arg;
+};
+
+static void debug_free_route_node(void *vfap, ErtsThrPrgrVal val, void *vnp)
+{
+ DbTableCATreeNode *np = vnp;
+ if (np->u.route.key.oh) {
+ struct debug_catree_fa *fap = vfap;
+ ErlOffHeap oh;
+ ERTS_INIT_OFF_HEAP(&oh);
+ oh.first = np->u.route.key.oh;
+ (*fap->func)(&oh, fap->arg);
+ }
+}
+
+void
+erts_db_foreach_thr_prgr_offheap_catree(void (*func)(ErlOffHeap *, void *),
+ void *arg)
+{
+ struct debug_catree_fa fa;
+ fa.func = func;
+ fa.arg = arg;
+ erts_debug_later_op_foreach(do_free_route_node, debug_free_route_node, &fa);
+}
+
+
#ifdef HARDDEBUG
/*
diff --git a/erts/emulator/beam/erl_db_catree.h b/erts/emulator/beam/erl_db_catree.h
index c2c884eee3..2ede85e04e 100644
--- a/erts/emulator/beam/erl_db_catree.h
+++ b/erts/emulator/beam/erl_db_catree.h
@@ -132,6 +132,9 @@ typedef struct {
Uint max_depth;
} DbCATreeStats;
void db_calc_stats_catree(DbTableCATree*, DbCATreeStats*);
+void
+erts_db_foreach_thr_prgr_offheap_catree(void (*func)(ErlOffHeap *, void *),
+ void *arg);
#endif /* _DB_CATREE_H */
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index ceaccf7e44..4904d3fa42 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -3262,6 +3262,12 @@ Eterm erts_ets_hash_sizeof_ext_segtab(void)
return make_small(((SIZEOF_EXT_SEGTAB(0)-1) / sizeof(UWord)) + 1);
}
+void
+erts_db_foreach_thr_prgr_offheap_hash(void (*func)(ErlOffHeap *, void *),
+ void *arg)
+{
+}
+
#ifdef ERTS_ENABLE_LOCK_COUNT
void erts_lcnt_enable_db_hash_lock_count(DbTableHash *tb, int enable) {
int i;
diff --git a/erts/emulator/beam/erl_db_hash.h b/erts/emulator/beam/erl_db_hash.h
index eae5537ba4..9759d8b466 100644
--- a/erts/emulator/beam/erl_db_hash.h
+++ b/erts/emulator/beam/erl_db_hash.h
@@ -110,6 +110,9 @@ typedef struct {
void db_calc_stats_hash(DbTableHash* tb, DbHashStats*);
Eterm erts_ets_hash_sizeof_ext_segtab(void);
+void
+erts_db_foreach_thr_prgr_offheap_hash(void (*func)(ErlOffHeap *, void *),
+ void *arg);
#ifdef ERTS_ENABLE_LOCK_COUNT
void erts_lcnt_enable_db_hash_lock_count(DbTableHash *tb, int enable);
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index 492ea81b63..19b94b0634 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -3936,6 +3936,12 @@ static int doit_select_replace(DbTableCommon *tb, TreeDbTerm **this,
return 1;
}
+void
+erts_db_foreach_thr_prgr_offheap_tree(void (*func)(ErlOffHeap *, void *),
+ void *arg)
+{
+}
+
#ifdef TREE_DEBUG
static void do_dump_tree2(DbTableCommon* tb, int to, void *to_arg, int show,
TreeDbTerm *t, int offset)
diff --git a/erts/emulator/beam/erl_db_tree.h b/erts/emulator/beam/erl_db_tree.h
index 54da2a6bc1..06e0005801 100644
--- a/erts/emulator/beam/erl_db_tree.h
+++ b/erts/emulator/beam/erl_db_tree.h
@@ -53,4 +53,8 @@ void db_initialize_tree(void);
int db_create_tree(Process *p, DbTable *tbl);
+void
+erts_db_foreach_thr_prgr_offheap_tree(void (*func)(ErlOffHeap *, void *),
+ void *arg);
+
#endif /* _DB_TREE_H */
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 7ab8034606..13b1f8ab4d 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -2887,7 +2887,7 @@ sweep_off_heap(Process *p, int fullsweep)
if (is_external_header(((struct erl_off_heap_header*) boxed_val(ptr->thing_word))->thing_word))
erts_node_bookkeep(((ExternalThing*)ptr)->node,
make_boxed(&ptr->thing_word),
- ERL_NODE_DEC);
+ ERL_NODE_DEC, __FILE__, __LINE__);
*prev = ptr = (struct erl_off_heap_header*) boxed_val(ptr->thing_word);
ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
switch (ptr->thing_word) {
@@ -2918,7 +2918,7 @@ sweep_off_heap(Process *p, int fullsweep)
if (is_external_header(ptr->thing_word)) {
erts_node_bookkeep(((ExternalThing*)ptr)->node,
make_boxed(&ptr->thing_word),
- ERL_NODE_INC);
+ ERL_NODE_INC, __FILE__, __LINE__);
}
prev = &ptr->next;
ptr = ptr->next;
@@ -3089,9 +3089,11 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
if (is_external_header(oh->thing_word)) {
erts_node_bookkeep(((ExternalThing*)oh)->node,
- make_boxed(((Eterm*)oh)-offs), ERL_NODE_DEC);
+ make_boxed(((Eterm*)oh)-offs),
+ ERL_NODE_DEC, __FILE__, __LINE__);
erts_node_bookkeep(((ExternalThing*)oh)->node,
- make_boxed((Eterm*)oh), ERL_NODE_INC);
+ make_boxed((Eterm*)oh), ERL_NODE_INC,
+ __FILE__, __LINE__);
}
if (ErtsInArea(oh->next, area, area_size)) {
diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c
index 1c6b4afaa3..43028be39d 100644
--- a/erts/emulator/beam/erl_monitor_link.c
+++ b/erts/emulator/beam/erl_monitor_link.c
@@ -671,6 +671,24 @@ erts_monitor_tree_foreach(ErtsMonitor *root,
arg);
}
+void
+erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp)
+{
+ void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
+ sizeof(ErtsMonLnkYieldState));
+ Sint reds;
+ sys_memcpy(tmp_vysp, tmp_vysp, sizeof(ErtsMonLnkYieldState));
+ do {
+ reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root,
+ (ErtsMonLnkNodeFunc) func,
+ arg, &tmp_vysp, (Sint) INT_MAX);
+ } while (reds <= 0);
+ ERTS_ML_ASSERT(!tmp_vysp);
+}
+
int
erts_monitor_tree_foreach_yielding(ErtsMonitor *root,
ErtsMonitorFunc func,
@@ -716,6 +734,19 @@ erts_monitor_list_foreach(ErtsMonitor *list,
arg, &ystate, (Sint) INT_MAX));
}
+void
+erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp)
+{
+ void *tmp_vysp = vysp;
+ while (!ml_dl_list_foreach_yielding((ErtsMonLnkNode *) list,
+ (int (*)(ErtsMonLnkNode *, void *, Sint)) func,
+ arg, &tmp_vysp, (Sint) INT_MAX));
+ ERTS_ML_ASSERT(!tmp_vysp);
+}
+
int
erts_monitor_list_foreach_yielding(ErtsMonitor *list,
ErtsMonitorFunc func,
@@ -1080,6 +1111,24 @@ erts_link_tree_foreach(ErtsLink *root,
}
+void
+erts_debug_link_tree_destroying_foreach(ErtsLink *root,
+ ErtsLinkFunc func,
+ void *arg,
+ void *vysp)
+{
+ void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
+ sizeof(ErtsMonLnkYieldState));
+ Sint reds;
+ sys_memcpy(tmp_vysp, vysp, sizeof(ErtsMonLnkYieldState));
+ do {
+ reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root,
+ (ErtsMonLnkNodeFunc) func,
+ arg, &tmp_vysp, (Sint) INT_MAX);
+ } while (reds <= 0);
+ ERTS_ML_ASSERT(!tmp_vysp);
+}
+
int
erts_link_tree_foreach_yielding(ErtsLink *root,
ErtsLinkFunc func,
diff --git a/erts/emulator/beam/erl_monitor_link.h b/erts/emulator/beam/erl_monitor_link.h
index eff861fce8..86be400c09 100644
--- a/erts/emulator/beam/erl_monitor_link.h
+++ b/erts/emulator/beam/erl_monitor_link.h
@@ -1509,6 +1509,17 @@ ERTS_GLB_INLINE ErtsMonitorSuspend *erts_monitor_suspend(ErtsMonitor *mon)
#endif
+void
+erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp);
+void
+erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp);
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Link Operations *
\* */
@@ -2365,4 +2376,10 @@ erts_link_dist_delete(ErtsLink *lnk)
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+void
+erts_debug_link_tree_destroying_foreach(ErtsLink *root,
+ ErtsLinkFunc func,
+ void *arg,
+ void *vysp);
+
#endif /* ERL_MONITOR_LINK_H__ */
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 4eb6c3e214..50e9812534 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -932,7 +932,8 @@ static void try_delete_node(void *venp)
*
* If refc > 0, the entry is in use. Keep the entry.
*/
- erts_node_bookkeep(enp, THE_NON_VALUE, ERL_NODE_DEC);
+ erts_node_bookkeep(enp, THE_NON_VALUE, ERL_NODE_DEC,
+ __FILE__, __LINE__);
refc = erts_refc_dectest(&enp->refc, -1);
if (refc == -1)
(void) hash_erase(&erts_node_table, (void *) enp);
@@ -1164,6 +1165,12 @@ void erts_lcnt_update_distribution_locks(int enable) {
* can damage the real-time properties of the system. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#ifdef ERL_NODE_BOOKKEEP
+#define ERTS_DBG_NC_ALLOC_TYPE ERTS_ALC_T_NC_STD
+#else
+#define ERTS_DBG_NC_ALLOC_TYPE ERTS_ALC_T_NC_TMP
+#endif
+
#include "erl_db.h"
#undef INIT_AM
@@ -1188,10 +1195,12 @@ static Eterm AM_delayed_delete_timer;
static Eterm AM_thread_progress_delete_timer;
static Eterm AM_sequence;
static Eterm AM_signal;
+static Eterm AM_persistent_term;
static void setup_reference_table(void);
static Eterm reference_table_term(Uint **hpp, ErlOffHeap *ohp, Uint *szp);
static void delete_reference_table(void);
+static void clear_system(void);
#undef ERTS_MAX__
#define ERTS_MAX__(A, B) ((A) > (B) ? (A) : (B))
@@ -1244,11 +1253,11 @@ typedef struct inserted_bin_ {
Binary *bin_val;
} InsertedBin;
-static ReferredNode *referred_nodes;
+static ReferredNode *referred_nodes = NULL;
static int no_referred_nodes;
-static ReferredDist *referred_dists;
+static ReferredDist *referred_dists = NULL;
static int no_referred_dists;
-static InsertedBin *inserted_bins;
+static InsertedBin *inserted_bins = NULL;
Eterm
erts_get_node_and_dist_references(struct process *proc)
@@ -1284,9 +1293,15 @@ erts_get_node_and_dist_references(struct process *proc)
INIT_AM(thread_progress_delete_timer);
INIT_AM(signal);
INIT_AM(sequence);
+ INIT_AM(persistent_term);
references_atoms_need_init = 0;
}
+#ifdef ERL_NODE_BOOKKEEP
+ if (referred_nodes || referred_dists || inserted_bins)
+ delete_reference_table();
+#endif
+
setup_reference_table();
/* Get term size */
@@ -1304,7 +1319,11 @@ erts_get_node_and_dist_references(struct process *proc)
ASSERT(endp == hp);
+#ifndef ERL_NODE_BOOKKEEP
delete_reference_table();
+#endif
+
+ clear_system();
erts_thr_progress_unblock();
erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
@@ -1339,7 +1358,7 @@ insert_dist_referrer(ReferredDist *referred_dist,
break;
if(!drp) {
- drp = (DistReferrer *) erts_alloc(ERTS_ALC_T_NC_TMP,
+ drp = (DistReferrer *) erts_alloc(ERTS_DBG_NC_ALLOC_TYPE,
sizeof(DistReferrer));
drp->next = referred_dist->referrers;
referred_dist->referrers = drp;
@@ -1402,7 +1421,7 @@ insert_node_referrer(ReferredNode *referred_node, int type, Eterm id)
break;
if(!nrp) {
- nrp = (NodeReferrer *) erts_alloc(ERTS_ALC_T_NC_TMP,
+ nrp = (NodeReferrer *) erts_alloc(ERTS_DBG_NC_ALLOC_TYPE,
sizeof(NodeReferrer));
nrp->next = referred_node->referrers;
ERTS_INIT_OFF_HEAP(&nrp->off_heap);
@@ -1516,7 +1535,8 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id)
erts_match_prog_foreach_offheap((Binary *) u.mref->mb,
insert_offheap2,
(void *) &a);
- nib = erts_alloc(ERTS_ALC_T_NC_TMP, sizeof(InsertedBin));
+ nib = erts_alloc(ERTS_DBG_NC_ALLOC_TYPE,
+ sizeof(InsertedBin));
nib->bin_val = (Binary *) u.mref->mb;
nib->next = inserted_bins;
inserted_bins = nib;
@@ -1574,18 +1594,6 @@ static int clear_visited_monitor(ErtsMonitor *mon, void *p, Sint reds)
}
static void
-insert_p_monitors(ErtsPTabElementCommon *p)
-{
- Eterm id = p->id;
- erts_monitor_tree_foreach(p->u.alive.monitors,
- insert_monitor,
- (void *) &id);
- erts_monitor_list_foreach(p->u.alive.lt_monitors,
- insert_monitor,
- (void *) &id);
-}
-
-static void
insert_dist_monitors(DistEntry *dep)
{
if (dep->mld) {
@@ -1600,8 +1608,10 @@ insert_dist_monitors(DistEntry *dep)
static int
-insert_sequence(ErtsDistExternal *edep, void *arg, Sint reds)
+insert_sequence(DistSeqNode *seq, void *arg, Sint reds)
{
+ ErtsDistExternal *edep = erts_get_dist_ext(&seq->hfrag);
+ insert_offheap(&seq->hfrag.off_heap, SEQUENCE_REF, *(Eterm*)arg);
insert_dist_entry(edep->dep, SEQUENCE_REF, *(Eterm*)arg, 0);
return 1;
}
@@ -1609,18 +1619,7 @@ insert_sequence(ErtsDistExternal *edep, void *arg, Sint reds)
static void
insert_dist_sequences(DistEntry *dep)
{
- erts_dist_seq_tree_foreach(dep, insert_sequence, (void *) &dep->sysname);
-}
-
-static void
-clear_visited_p_monitors(ErtsPTabElementCommon *p)
-{
- erts_monitor_tree_foreach(p->u.alive.monitors,
- clear_visited_monitor,
- NULL);
- erts_monitor_list_foreach(p->u.alive.lt_monitors,
- clear_visited_monitor,
- NULL);
+ erts_debug_dist_seq_tree_foreach(dep, insert_sequence, (void *) &dep->sysname);
}
static void
@@ -1667,13 +1666,6 @@ static int clear_visited_link(ErtsLink *lnk, void *p, Sint reds)
}
static void
-insert_p_links(ErtsPTabElementCommon *p)
-{
- Eterm id = p->id;
- erts_link_tree_foreach(p->u.alive.links, insert_link, (void *) &id);
-}
-
-static void
insert_dist_links(DistEntry *dep)
{
if (dep->mld)
@@ -1683,14 +1675,6 @@ insert_dist_links(DistEntry *dep)
}
static void
-clear_visited_p_links(ErtsPTabElementCommon *p)
-{
- erts_link_tree_foreach(p->u.alive.links,
- clear_visited_link,
- NULL);
-}
-
-static void
clear_visited_dist_links(DistEntry *dep)
{
if (dep->mld)
@@ -1885,15 +1869,11 @@ insert_process(Process *proc)
insert_sig_ext,
(void *) proc);
- /* If the process is FREE, the proc->common field has been
- re-used by the ptab delete, so we cannot trust it. */
- if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) {
- /* Insert links */
- insert_p_links(&proc->common);
-
- /* Insert monitors */
- insert_p_monitors(&proc->common);
- }
+ /* Insert monitors and links... */
+ erts_debug_proc_monitor_link_foreach(proc,
+ insert_monitor,
+ insert_link,
+ (void *) &proc->common.id);
{
DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(proc);
@@ -1906,6 +1886,12 @@ insert_process(Process *proc)
}
static void
+insert_process2(Process *proc, void *arg)
+{
+ insert_process(proc);
+}
+
+static void
insert_dist_suspended_procs(DistEntry *dep)
{
ErtsProcList *plist = erts_proclist_peek_first(dep->suspended);
@@ -1916,16 +1902,47 @@ insert_dist_suspended_procs(DistEntry *dep)
}
}
+static void clear_process(Process *proc);
+
+static void
+clear_dist_suspended_procs(DistEntry *dep)
+{
+ ErtsProcList *plist = erts_proclist_peek_first(dep->suspended);
+ while (plist) {
+ if (is_not_immed(plist->u.pid))
+ clear_process(plist->u.p);
+ plist = erts_proclist_peek_next(dep->suspended, plist);
+ }
+}
+
+static void
+insert_persistent_term(ErlOffHeap *ohp, void *arg)
+{
+ Eterm heap[3];
+ insert_offheap(ohp, SYSTEM_REF,
+ TUPLE2(&heap[0], AM_system, AM_persistent_term));
+}
+
+static void
+insert_ets_offheap_thr_prgr(ErlOffHeap *ohp, void *arg)
+{
+ Eterm heap[3];
+ insert_offheap(ohp, ETS_REF,
+ TUPLE2(&heap[0], AM_system, AM_ets));
+}
+
#ifdef ERL_NODE_BOOKKEEP
void
-erts_node_bookkeep(ErlNode *np, Eterm term, int what)
+erts_node_bookkeep(ErlNode *np, Eterm term, int what, char *f, int l)
{
- erts_aint_t slot = (erts_atomic_inc_read_nob(&np->slot) - 1) % 1024;
+ erts_aint_t slot = (erts_atomic_inc_read_nob(&np->slot) - 1) % ERTS_BOOKKEEP_SIZE;
ErtsSchedulerData *esdp = erts_get_scheduler_data();
Eterm who = THE_NON_VALUE;
ASSERT(np);
np->books[slot].what = what;
np->books[slot].term = term;
+ np->books[slot].file = f;
+ np->books[slot].line = l;
if (esdp->current_process) {
who = esdp->current_process->common.id;
} else if (esdp->current_port) {
@@ -1946,14 +1963,14 @@ setup_reference_table(void)
inserted_bins = NULL;
hash_get_info(&hi, &erts_node_table);
- referred_nodes = erts_alloc(ERTS_ALC_T_NC_TMP,
+ referred_nodes = erts_alloc(ERTS_DBG_NC_ALLOC_TYPE,
hi.objs*sizeof(ReferredNode));
no_referred_nodes = 0;
hash_foreach(&erts_node_table, init_referred_node, NULL);
ASSERT(no_referred_nodes == hi.objs);
hash_get_info(&hi, &erts_dist_table);
- referred_dists = erts_alloc(ERTS_ALC_T_NC_TMP,
+ referred_dists = erts_alloc(ERTS_DBG_NC_ALLOC_TYPE,
hi.objs*sizeof(ReferredDist));
no_referred_dists = 0;
hash_foreach(&erts_dist_table, init_referred_dist, NULL);
@@ -1990,8 +2007,9 @@ setup_reference_table(void)
if (proc)
insert_process(proc);
}
+ erts_debug_free_process_foreach(insert_process2, NULL);
- erts_foreach_sys_msg_in_q(insert_sys_msg);
+ erts_debug_foreach_sys_msg_in_q(insert_sys_msg);
/* Insert all ports */
max = erts_ptab_max(&erts_port);
@@ -2008,10 +2026,18 @@ setup_reference_table(void)
if (state & ERTS_PORT_SFLGS_DEAD)
continue;
- /* Insert links */
- insert_p_links(&prt->common);
- /* Insert monitors */
- insert_p_monitors(&prt->common);
+ /* Insert links */
+ erts_link_tree_foreach(ERTS_P_LINKS(prt),
+ insert_link,
+ (void *) &prt->common.id);
+ /* Insert monitors */
+ erts_monitor_tree_foreach(ERTS_P_MONITORS(prt),
+ insert_monitor,
+ (void *) &prt->common.id);
+ /* Insert local target monitors */
+ erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt),
+ insert_monitor,
+ (void *) &prt->common.id);
/* Insert port data */
ohp = erts_port_data_offheap(prt);
if (ohp)
@@ -2091,11 +2117,16 @@ setup_reference_table(void)
}
/* Insert all ets tables */
- erts_db_foreach_table(insert_ets_table, NULL);
+ erts_db_foreach_table(insert_ets_table, NULL, 0);
+ erts_db_foreach_thr_prgr_offheap(insert_ets_offheap_thr_prgr, NULL);
/* Insert all bif timers */
erts_debug_bif_timer_foreach(insert_bif_timer, NULL);
+ /* Insert persistent term storage */
+ erts_debug_foreach_persistent_term_off_heap(insert_persistent_term,
+ NULL);
+
/* Insert node table (references to dist) */
hash_foreach(&erts_node_table, insert_erl_node, NULL);
}
@@ -2348,8 +2379,7 @@ static void noop_sig_ext(ErtsDistExternal *ext, void *arg)
static void
delete_reference_table(void)
{
- DistEntry *dep;
- int i, max;
+ int i;
for(i = 0; i < no_referred_nodes; i++) {
NodeReferrer *nrp;
NodeReferrer *tnrp;
@@ -2358,11 +2388,13 @@ delete_reference_table(void)
erts_cleanup_offheap(&nrp->off_heap);
tnrp = nrp;
nrp = nrp->next;
- erts_free(ERTS_ALC_T_NC_TMP, (void *) tnrp);
+ erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) tnrp);
}
}
- if (referred_nodes)
- erts_free(ERTS_ALC_T_NC_TMP, (void *) referred_nodes);
+ if (referred_nodes) {
+ erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) referred_nodes);
+ referred_nodes = NULL;
+ }
for(i = 0; i < no_referred_dists; i++) {
DistReferrer *drp;
@@ -2371,34 +2403,57 @@ delete_reference_table(void)
while(drp) {
tdrp = drp;
drp = drp->next;
- erts_free(ERTS_ALC_T_NC_TMP, (void *) tdrp);
+ erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) tdrp);
}
}
- if (referred_dists)
- erts_free(ERTS_ALC_T_NC_TMP, (void *) referred_dists);
+ if (referred_dists) {
+ erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) referred_dists);
+ referred_dists = NULL;
+ }
while(inserted_bins) {
InsertedBin *ib = inserted_bins;
inserted_bins = inserted_bins->next;
- erts_free(ERTS_ALC_T_NC_TMP, (void *)ib);
+ erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *)ib);
}
+}
+
+static void clear_process(Process *proc)
+{
+ erts_proc_sig_debug_foreach_sig(proc,
+ noop_sig_msg,
+ noop_sig_offheap,
+ clear_visited_monitor,
+ clear_visited_link,
+ noop_sig_ext,
+ (void *) proc);
+
+
+ /* Clear monitors and links... */
+ erts_debug_proc_monitor_link_foreach(proc,
+ clear_visited_monitor,
+ clear_visited_link,
+ (void *) &proc->common.id);
+}
+
+static void clear_process2(Process *proc, void *arg)
+{
+ clear_process(proc);
+}
- /* Cleanup... */
+static void
+clear_system(void)
+{
+ DistEntry *dep;
+ int i, max;
+ /* Clear... */
max = erts_ptab_max(&erts_proc);
for (i = 0; i < max; i++) {
Process *proc = erts_pix2proc(i);
- if (proc) {
- clear_visited_p_links(&proc->common);
- clear_visited_p_monitors(&proc->common);
- erts_proc_sig_debug_foreach_sig(proc,
- noop_sig_msg,
- noop_sig_offheap,
- clear_visited_monitor,
- clear_visited_link,
- noop_sig_ext,
- (void *) proc);
- }
+ if (proc)
+ clear_process(proc);
}
+ erts_debug_free_process_foreach(clear_process2, NULL);
max = erts_ptab_max(&erts_port);
for (i = 0; i < max; i++) {
@@ -2413,28 +2468,42 @@ delete_reference_table(void)
if (state & ERTS_PORT_SFLGS_DEAD)
continue;
- clear_visited_p_links(&prt->common);
- clear_visited_p_monitors(&prt->common);
+ /* Clear links */
+ erts_link_tree_foreach(ERTS_P_LINKS(prt),
+ clear_visited_link,
+ (void *) &prt->common.id);
+ /* Clear monitors */
+ erts_monitor_tree_foreach(ERTS_P_MONITORS(prt),
+ clear_visited_monitor,
+ (void *) &prt->common.id);
+ /* Clear local target monitors */
+ erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt),
+ clear_visited_monitor,
+ (void *) &prt->common.id);
}
for(dep = erts_visible_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
for(dep = erts_hidden_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
for(dep = erts_pending_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
for(dep = erts_not_connected_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
}
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index aa8af12555..ffaafbbbea 100644
--- a/erts/emulator/beam/erl_node_tables.h
+++ b/erts/emulator/beam/erl_node_tables.h
@@ -187,6 +187,7 @@ set pagination off
set $i = 0
set $node = referred_nodes[$node_ix].node
while $i < $node->slot.counter
+ printf "%s:%d ", $node->books[$i].file, $node->books[$i].line
printf "%p: ", $node->books[$i].term
etp-1 $node->books[$i].who
printf " "
@@ -211,8 +212,12 @@ lists:usort(lists:filter(fun({V,N}) -> N /= 0 end, maps:to_list(Accs))).
struct erl_node_bookkeeping {
Eterm who;
Eterm term;
+ char *file;
+ int line;
enum { ERL_NODE_INC, ERL_NODE_DEC } what;
};
+
+#define ERTS_BOOKKEEP_SIZE (1024)
#endif
typedef struct erl_node_ {
@@ -222,7 +227,7 @@ typedef struct erl_node_ {
Uint32 creation; /* Creation */
DistEntry *dist_entry; /* Corresponding dist entry */
#ifdef ERL_NODE_BOOKKEEP
- struct erl_node_bookkeeping books[1024];
+ struct erl_node_bookkeeping books[ERTS_BOOKKEEP_SIZE];
erts_atomic_t slot;
#endif
} ErlNode;
@@ -276,14 +281,21 @@ Eterm erts_build_dhandle(Eterm **hpp, ErlOffHeap*, DistEntry*, Uint32 conn_id);
Eterm erts_make_dhandle(Process *c_p, DistEntry*, Uint32 conn_id);
ERTS_GLB_INLINE void erts_init_node_entry(ErlNode *np, erts_aint_t val);
+#ifdef ERL_NODE_BOOKKEEP
+#define erts_ref_node_entry(NP, MIN, T) erts_ref_node_entry__((NP), (MIN), (T), __FILE__, __LINE__)
+#define erts_deref_node_entry(NP, T) erts_deref_node_entry__((NP), (T), __FILE__, __LINE__)
+ERTS_GLB_INLINE erts_aint_t erts_ref_node_entry__(ErlNode *np, int min_val, Eterm term, char *file, int line);
+ERTS_GLB_INLINE void erts_deref_node_entry__(ErlNode *np, Eterm term, char *file, int line);
+#else
ERTS_GLB_INLINE erts_aint_t erts_ref_node_entry(ErlNode *np, int min_val, Eterm term);
ERTS_GLB_INLINE void erts_deref_node_entry(ErlNode *np, Eterm term);
+#endif
ERTS_GLB_INLINE void erts_de_rlock(DistEntry *dep);
ERTS_GLB_INLINE void erts_de_runlock(DistEntry *dep);
ERTS_GLB_INLINE void erts_de_rwlock(DistEntry *dep);
ERTS_GLB_INLINE void erts_de_rwunlock(DistEntry *dep);
#ifdef ERL_NODE_BOOKKEEP
-void erts_node_bookkeep(ErlNode *, Eterm , int);
+void erts_node_bookkeep(ErlNode *, Eterm , int, char *file, int line);
#else
#define erts_node_bookkeep(...)
#endif
@@ -296,21 +308,40 @@ erts_init_node_entry(ErlNode *np, erts_aint_t val)
erts_refc_init(&np->refc, val);
}
+#ifdef ERL_NODE_BOOKKEEP
+
+ERTS_GLB_INLINE erts_aint_t
+erts_ref_node_entry__(ErlNode *np, int min_val, Eterm term, char *file, int line)
+{
+ erts_node_bookkeep(np, term, ERL_NODE_INC, file, line);
+ return erts_refc_inctest(&np->refc, min_val);
+}
+
+ERTS_GLB_INLINE void
+erts_deref_node_entry__(ErlNode *np, Eterm term, char *file, int line)
+{
+ erts_node_bookkeep(np, term, ERL_NODE_DEC, file, line);
+ if (erts_refc_dectest(&np->refc, 0) == 0)
+ erts_schedule_delete_node(np);
+}
+
+#else
+
ERTS_GLB_INLINE erts_aint_t
erts_ref_node_entry(ErlNode *np, int min_val, Eterm term)
{
- erts_node_bookkeep(np, term, ERL_NODE_INC);
return erts_refc_inctest(&np->refc, min_val);
}
ERTS_GLB_INLINE void
erts_deref_node_entry(ErlNode *np, Eterm term)
{
- erts_node_bookkeep(np, term, ERL_NODE_DEC);
if (erts_refc_dectest(&np->refc, 0) == 0)
erts_schedule_delete_node(np);
}
+#endif
+
ERTS_GLB_INLINE void
erts_de_rlock(DistEntry *dep)
{
diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c
index 2e33a8a782..67c486a0db 100644
--- a/erts/emulator/beam/erl_printf_term.c
+++ b/erts/emulator/beam/erl_printf_term.c
@@ -533,13 +533,34 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) {
case EXPORT_DEF:
{
Export* ep = *((Export **) (export_val(wobj) + 1));
- Atom* module = atom_tab(atom_val(ep->info.mfa.module));
- Atom* name = atom_tab(atom_val(ep->info.mfa.function));
+ long tdcount;
+ int tres;
PRINT_STRING(res, fn, arg, "fun ");
- PRINT_BUF(res, fn, arg, module->name, module->len);
+
+ /* We pass a temporary 'dcount' and adjust the real one later to ensure
+ * that the fun doesn't get split up between the module and function
+ * name. */
+ tdcount = MAX_ATOM_SZ_LIMIT;
+ tres = print_atom_name(fn, arg, ep->info.mfa.module, &tdcount);
+ if (tres < 0) {
+ res = tres;
+ goto L_done;
+ }
+ *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount);
+ res += tres;
+
PRINT_CHAR(res, fn, arg, ':');
- PRINT_BUF(res, fn, arg, name->name, name->len);
+
+ tdcount = MAX_ATOM_SZ_LIMIT;
+ tres = print_atom_name(fn, arg, ep->info.mfa.function, &tdcount);
+ if (tres < 0) {
+ res = tres;
+ goto L_done;
+ }
+ *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount);
+ res += tres;
+
PRINT_CHAR(res, fn, arg, '/');
PRINT_SWORD(res, fn, arg, 'd', 0, 1,
(ErlPfSWord) ep->info.mfa.arity);
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index fb900ca7ba..d5e0e3b218 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -4689,10 +4689,12 @@ erts_proc_sig_debug_foreach_sig(Process *c_p,
case ERTS_SIG_Q_OP_MONITOR_DOWN:
switch (type) {
case ERTS_SIG_Q_TYPE_GEN_EXIT:
- if (ERTS_SIG_IS_GEN_EXIT_EXTERNAL(sig))
- debug_foreach_sig_external(sig, ext_func, arg);
- else
+ if (!ERTS_SIG_IS_GEN_EXIT_EXTERNAL(sig))
debug_foreach_sig_heap_frags(&sig->hfrag, oh_func, arg);
+ else {
+ oh_func(&sig->hfrag.off_heap, arg);
+ debug_foreach_sig_external(sig, ext_func, arg);
+ }
break;
case ERTS_LNK_TYPE_PORT:
case ERTS_LNK_TYPE_PROC:
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index de0564292d..1c1ef1db84 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -13468,3 +13468,79 @@ erts_debug_later_op_foreach(void (*callback)(void*),
}
}
}
+
+void
+erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg)
+{
+ ErtsRunQueue *rq;
+ int ix, prio;
+ for (ix = 0; ix < erts_no_run_queues; ix++) {
+ rq = ERTS_RUNQ_IX(ix);
+ for (prio = PRIORITY_MAX; prio < PRIORITY_LOW; prio++) {
+ Process *p = rq->procs.prio[prio].first;
+ for (; p; p = p->next) {
+ if (ERTS_PSFLG_FREE & erts_atomic32_read_nob(&p->state))
+ (*func)(p, arg);
+ }
+ }
+ }
+}
+
+void
+erts_debug_proc_monitor_link_foreach(Process *proc,
+ int (*monitor_func)(ErtsMonitor *, void *, Sint ),
+ int (*link_func)(ErtsLink *, void *, Sint ),
+ void *arg)
+{
+ if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) {
+ /* For all links */
+ erts_link_tree_foreach(ERTS_P_LINKS(proc),
+ link_func,
+ arg);
+ /* For all monitors */
+ erts_monitor_tree_foreach(ERTS_P_MONITORS(proc),
+ monitor_func,
+ arg);
+ /* For all local target monitors */
+ erts_monitor_list_foreach(ERTS_P_LT_MONITORS(proc),
+ monitor_func,
+ arg);
+ }
+ else {
+ struct continue_exit_state *ce_state = proc->u.terminate;
+
+ /* For all links */
+ if (ce_state->phase == ERTS_CONTINUE_EXIT_LINKS)
+ erts_debug_link_tree_destroying_foreach(ce_state->links,
+ link_func,
+ arg,
+ ce_state->yield_state);
+ else
+ erts_link_tree_foreach(ce_state->links,
+ link_func,
+ arg);
+
+ /* For all monitors */
+ if (ce_state->phase == ERTS_CONTINUE_EXIT_MONITORS)
+ erts_debug_monitor_tree_destroying_foreach(ce_state->monitors,
+ monitor_func,
+ arg,
+ ce_state->yield_state);
+ else
+ erts_monitor_tree_foreach(ce_state->monitors,
+ monitor_func,
+ arg);
+
+ /* For all local target monitors */
+ if (ce_state->phase == ERTS_CONTINUE_EXIT_LT_MONITORS)
+ erts_debug_monitor_list_destroying_foreach(ce_state->lt_monitors,
+ monitor_func,
+ arg,
+ ce_state->yield_state);
+ else
+ erts_monitor_list_foreach(ce_state->lt_monitors,
+ monitor_func,
+ arg);
+
+ }
+}
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 745a2a482c..c0d7cfd13d 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -701,6 +701,13 @@ void
erts_debug_later_op_foreach(void (*callback)(void*),
void (*func)(void *, ErtsThrPrgrVal, void *),
void *arg);
+void
+erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg);
+void
+erts_debug_proc_monitor_link_foreach(Process *proc,
+ int (*monitor_func)(ErtsMonitor *, void *, Sint ),
+ int (*link_func)(ErtsLink *, void *, Sint ),
+ void *arg);
#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 9c835ac357..f6f177887c 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -2194,11 +2194,12 @@ sys_msg_dispatcher_wait(void *vwait_p)
erts_mtx_unlock(&smq_mtx);
}
+static ErtsSysMsgQ *local_sys_message_queue = NULL;
+
static void *
sys_msg_dispatcher_func(void *unused)
{
ErtsThrPrgrCallbacks callbacks;
- ErtsSysMsgQ *local_sys_message_queue = NULL;
ErtsThrPrgrData *tpd;
int wait = 0;
@@ -2206,6 +2207,8 @@ sys_msg_dispatcher_func(void *unused)
erts_lc_set_thread_name("system message dispatcher");
#endif
+ local_sys_message_queue = NULL;
+
callbacks.arg = (void *) &wait;
callbacks.wakeup = sys_msg_dispatcher_wakeup;
callbacks.prepare_wait = sys_msg_dispatcher_prep_wait;
@@ -2262,6 +2265,8 @@ sys_msg_dispatcher_func(void *unused)
Process *proc = NULL;
Port *port = NULL;
+ ASSERT(is_value(smqp->msg));
+
if (erts_thr_progress_update(tpd))
erts_thr_progress_leader_update(tpd);
@@ -2374,6 +2379,7 @@ sys_msg_dispatcher_func(void *unused)
erts_fprintf(stderr, "dropped\n");
#endif
}
+ smqp->msg = THE_NON_VALUE;
}
}
@@ -2381,32 +2387,38 @@ sys_msg_dispatcher_func(void *unused)
}
void
-erts_foreach_sys_msg_in_q(void (*func)(Eterm,
- Eterm,
- Eterm,
- ErlHeapFragment *))
+erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm,
+ Eterm,
+ Eterm,
+ ErlHeapFragment *))
{
- ErtsSysMsgQ *sm;
- erts_mtx_lock(&smq_mtx);
- for (sm = sys_message_queue; sm; sm = sm->next) {
- Eterm to;
- switch (sm->type) {
- case SYS_MSG_TYPE_SYSMON:
- to = erts_get_system_monitor();
- break;
- case SYS_MSG_TYPE_SYSPROF:
- to = erts_get_system_profile();
- break;
- case SYS_MSG_TYPE_ERRLGR:
- to = erts_get_system_logger();
- break;
- default:
- to = NIL;
- break;
- }
- (*func)(sm->from, to, sm->msg, sm->bp);
+ ErtsSysMsgQ *smq[] = {sys_message_queue, local_sys_message_queue};
+ int i;
+
+ ERTS_LC_ASSERT(erts_thr_progress_is_blocking());
+
+ for (i = 0; i < sizeof(smq)/sizeof(smq[0]); i++) {
+ ErtsSysMsgQ *sm;
+ for (sm = smq[i]; sm; sm = sm->next) {
+ Eterm to;
+ switch (sm->type) {
+ case SYS_MSG_TYPE_SYSMON:
+ to = erts_get_system_monitor();
+ break;
+ case SYS_MSG_TYPE_SYSPROF:
+ to = erts_get_system_profile();
+ break;
+ case SYS_MSG_TYPE_ERRLGR:
+ to = erts_get_system_logger();
+ break;
+ default:
+ to = NIL;
+ break;
+ }
+ if (is_value(sm->msg))
+ (*func)(sm->from, to, sm->msg, sm->bp);
+ }
}
- erts_mtx_unlock(&smq_mtx);
}
diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h
index b7844d1cb0..af38ef52db 100644
--- a/erts/emulator/beam/erl_trace.h
+++ b/erts/emulator/beam/erl_trace.h
@@ -90,10 +90,10 @@ int erts_is_tracer_valid(Process* p);
void erts_check_my_tracer_proc(Process *);
void erts_block_sys_msg_dispatcher(void);
void erts_release_sys_msg_dispatcher(void);
-void erts_foreach_sys_msg_in_q(void (*func)(Eterm,
- Eterm,
- Eterm,
- ErlHeapFragment *));
+void erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm,
+ Eterm,
+ Eterm,
+ ErlHeapFragment *));
Eterm erts_set_system_logger(Eterm);
Eterm erts_get_system_logger(void);
void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *);
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 4c8d3d3dbe..0c2cf98033 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -907,7 +907,8 @@ Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2);
/* beam_bif_load.c */
Eterm erts_check_process_code(Process *c_p, Eterm module, int *redsp, int fcalls);
Eterm erts_proc_copy_literal_area(Process *c_p, int *redsp, int fcalls, int gc_allowed);
-
+void erts_debug_foreach_release_literal_area_off_heap(void (*func)(ErlOffHeap *, void *),
+ void *arg);
typedef struct ErtsLiteralArea_ {
struct erl_off_heap_header *off_heap;
Eterm *end;
@@ -1072,17 +1073,46 @@ Uint size_object_x(Eterm, erts_literal_area_t*);
#define size_object_litopt(Term,LitArea) size_object_x(Term,LitArea)
Uint copy_shared_calculate(Eterm, erts_shcopy_t*);
-Eterm copy_shared_perform(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*);
-
Uint size_shared(Eterm);
+/* #define ERTS_COPY_REGISTER_LOCATION */
+
+#ifdef ERTS_COPY_REGISTER_LOCATION
+
+#define copy_shared_perform(U, V, X, Y, Z) \
+ copy_shared_perform_x((U), (V), (X), (Y), (Z), __FILE__, __LINE__)
+Eterm copy_shared_perform_x(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*,
+ char *file, int line);
+
+Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint*, erts_literal_area_t*,
+ char *file, int line);
+#define copy_struct(Obj,Sz,HPP,OH) \
+ copy_struct_x(Obj,Sz,HPP,OH,NULL,NULL,__FILE__,__LINE__)
+#define copy_struct_litopt(Obj,Sz,HPP,OH,LitArea) \
+ copy_struct_x(Obj,Sz,HPP,OH,NULL,LitArea,__FILE__,__LINE__)
+
+#define copy_shallow(R, SZ, HPP, OH) \
+ copy_shallow_x((R), (SZ), (HPP), (OH), __FILE__, __LINE__)
+Eterm copy_shallow_x(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*,
+ char *file, int line);
+
+#else
+
+#define copy_shared_perform(U, V, X, Y, Z) \
+ copy_shared_perform_x((U), (V), (X), (Y), (Z))
+Eterm copy_shared_perform_x(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*);
+
Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint*, erts_literal_area_t*);
#define copy_struct(Obj,Sz,HPP,OH) \
copy_struct_x(Obj,Sz,HPP,OH,NULL,NULL)
#define copy_struct_litopt(Obj,Sz,HPP,OH,LitArea) \
copy_struct_x(Obj,Sz,HPP,OH,NULL,LitArea)
-Eterm copy_shallow(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*);
+#define copy_shallow(R, SZ, HPP, OH) \
+ copy_shallow_x((R), (SZ), (HPP), (OH))
+Eterm copy_shallow_x(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*);
+
+#endif
void erts_move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first,
Eterm* refs, unsigned nrefs, int literals);
@@ -1257,6 +1287,10 @@ Uint erts_persistent_term_count(void);
void erts_init_persistent_dumping(void);
extern ErtsLiteralArea** erts_persistent_areas;
extern Uint erts_num_persistent_areas;
+void erts_debug_foreach_persistent_term_off_heap(void (*func)(ErlOffHeap *, void *),
+ void *arg);
+int erts_debug_have_accessed_literal_area(ErtsLiteralArea *lap);
+void erts_debug_save_accessed_literal_area(ErtsLiteralArea *lap);
/* external.c */
void erts_init_external(void);
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index 211f21cb40..bbeb8b6cdd 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -24,7 +24,7 @@
* The first function is called 'nif_<something>', e.g. nif_open.
* This does the initial validation and argument processing and then
* calls the function that does the actual work. This is called
- * 'n<something>'.
+ * 'esock_<something>'.
* ----------------------------------------------------------------------
*
*
@@ -354,11 +354,11 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
/* Debug stuff... */
-#define SOCKET_GLOBAL_DEBUG_DEFAULT FALSE
-#define SOCKET_DEBUG_DEFAULT FALSE
+#define ESOCK_GLOBAL_DEBUG_DEFAULT FALSE
+#define ESOCK_DEBUG_DEFAULT FALSE
/* Counters and stuff (Don't know where to sent this stuff anyway) */
-#define SOCKET_NIF_IOW_DEFAULT FALSE
+#define ESOCK_NIF_IOW_DEFAULT FALSE
@@ -398,10 +398,10 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
#if defined(TCP_CA_NAME_MAX)
-#define SOCKET_OPT_TCP_CONGESTION_NAME_MAX TCP_CA_NAME_MAX
+#define ESOCK_OPT_TCP_CONGESTION_NAME_MAX TCP_CA_NAME_MAX
#else
/* This is really excessive, but just in case... */
-#define SOCKET_OPT_TCP_CONGESTION_NAME_MAX 256
+#define ESOCK_OPT_TCP_CONGESTION_NAME_MAX 256
#endif
@@ -414,25 +414,25 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
/* *** Socket state defs *** */
-#define SOCKET_FLAG_OPEN 0x0001
-#define SOCKET_FLAG_ACTIVE 0x0004
-#define SOCKET_FLAG_LISTEN 0x0008
-#define SOCKET_FLAG_CON 0x0010
-#define SOCKET_FLAG_ACC 0x0020
-#define SOCKET_FLAG_BUSY 0x0040
-#define SOCKET_FLAG_CLOSE 0x0080
-
-#define SOCKET_STATE_CLOSED (0)
-#define SOCKET_STATE_OPEN (SOCKET_FLAG_OPEN)
-#define SOCKET_STATE_CONNECTED (SOCKET_STATE_OPEN | SOCKET_FLAG_ACTIVE)
-#define SOCKET_STATE_LISTENING (SOCKET_STATE_OPEN | SOCKET_FLAG_LISTEN)
-#define SOCKET_STATE_CONNECTING (SOCKET_STATE_OPEN | SOCKET_FLAG_CON)
-#define SOCKET_STATE_ACCEPTING (SOCKET_STATE_LISTENING | SOCKET_FLAG_ACC)
-#define SOCKET_STATE_CLOSING (SOCKET_FLAG_CLOSE)
-#define SOCKET_STATE_DTOR (0xFFFF)
+#define ESOCK_FLAG_OPEN 0x0001
+#define ESOCK_FLAG_ACTIVE 0x0004
+#define ESOCK_FLAG_LISTEN 0x0008
+#define ESOCK_FLAG_CON 0x0010
+#define ESOCK_FLAG_ACC 0x0020
+#define ESOCK_FLAG_BUSY 0x0040
+#define ESOCK_FLAG_CLOSE 0x0080
+
+#define ESOCK_STATE_CLOSED (0)
+#define ESOCK_STATE_OPEN (ESOCK_FLAG_OPEN)
+#define ESOCK_STATE_CONNECTED (ESOCK_STATE_OPEN | ESOCK_FLAG_ACTIVE)
+#define ESOCK_STATE_LISTENING (ESOCK_STATE_OPEN | ESOCK_FLAG_LISTEN)
+#define ESOCK_STATE_CONNECTING (ESOCK_STATE_OPEN | ESOCK_FLAG_CON)
+#define ESOCK_STATE_ACCEPTING (ESOCK_STATE_LISTENING | ESOCK_FLAG_ACC)
+#define ESOCK_STATE_CLOSING (ESOCK_FLAG_CLOSE)
+#define ESOCK_STATE_DTOR (0xFFFF)
#define IS_CLOSED(d) \
- ((d)->state == SOCKET_STATE_CLOSED)
+ ((d)->state == ESOCK_STATE_CLOSED)
/*
#define IS_STATE(d, f) \
@@ -440,55 +440,59 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
*/
#define IS_CLOSING(d) \
- (((d)->state & SOCKET_STATE_CLOSING) == SOCKET_STATE_CLOSING)
+ (((d)->state & ESOCK_STATE_CLOSING) == ESOCK_STATE_CLOSING)
#define IS_OPEN(d) \
- (((d)->state & SOCKET_FLAG_OPEN) == SOCKET_FLAG_OPEN)
+ (((d)->state & ESOCK_FLAG_OPEN) == ESOCK_FLAG_OPEN)
#define IS_CONNECTED(d) \
- (((d)->state & SOCKET_STATE_CONNECTED) == SOCKET_STATE_CONNECTED)
+ (((d)->state & ESOCK_STATE_CONNECTED) == ESOCK_STATE_CONNECTED)
#define IS_CONNECTING(d) \
- (((d)->state & SOCKET_FLAG_CON) == SOCKET_FLAG_CON)
+ (((d)->state & ESOCK_FLAG_CON) == ESOCK_FLAG_CON)
/*
#define IS_BUSY(d) \
- (((d)->state & SOCKET_FLAG_BUSY) == SOCKET_FLAG_BUSY)
+ (((d)->state & ESOCK_FLAG_BUSY) == ESOCK_FLAG_BUSY)
*/
-#define SOCKET_SEND_FLAG_CONFIRM 0
-#define SOCKET_SEND_FLAG_DONTROUTE 1
-#define SOCKET_SEND_FLAG_EOR 2
-#define SOCKET_SEND_FLAG_MORE 3
-#define SOCKET_SEND_FLAG_NOSIGNAL 4
-#define SOCKET_SEND_FLAG_OOB 5
-#define SOCKET_SEND_FLAG_LOW SOCKET_SEND_FLAG_CONFIRM
-#define SOCKET_SEND_FLAG_HIGH SOCKET_SEND_FLAG_OOB
-
-#define SOCKET_RECV_FLAG_CMSG_CLOEXEC 0
-#define SOCKET_RECV_FLAG_ERRQUEUE 1
-#define SOCKET_RECV_FLAG_OOB 2
-#define SOCKET_RECV_FLAG_PEEK 3
-#define SOCKET_RECV_FLAG_TRUNC 4
-#define SOCKET_RECV_FLAG_LOW SOCKET_RECV_FLAG_CMSG_CLOEXEC
-#define SOCKET_RECV_FLAG_HIGH SOCKET_RECV_FLAG_TRUNC
-
-#define SOCKET_RECV_BUFFER_SIZE_DEFAULT 8192
-#define SOCKET_RECV_CTRL_BUFFER_SIZE_DEFAULT 1024
-#define SOCKET_SEND_CTRL_BUFFER_SIZE_DEFAULT 1024
-
-#define VT2S(__VT__) (((__VT__) == SOCKET_OPT_VALUE_TYPE_UNSPEC) ? "unspec" : \
- (((__VT__) == SOCKET_OPT_VALUE_TYPE_INT) ? "int" : \
- ((__VT__) == SOCKET_OPT_VALUE_TYPE_BOOL) ? "bool" : \
+#define ESOCK_GET_RESOURCE(ENV, REF, RES) \
+ enif_get_resource((ENV), (REF), esocks, (RES))
+
+#define ESOCK_SEND_FLAG_CONFIRM 0
+#define ESOCK_SEND_FLAG_DONTROUTE 1
+#define ESOCK_SEND_FLAG_EOR 2
+#define ESOCK_SEND_FLAG_MORE 3
+#define ESOCK_SEND_FLAG_NOSIGNAL 4
+#define ESOCK_SEND_FLAG_OOB 5
+#define ESOCK_SEND_FLAG_LOW ESOCK_SEND_FLAG_CONFIRM
+#define ESOCK_SEND_FLAG_HIGH ESOCK_SEND_FLAG_OOB
+
+#define ESOCK_RECV_FLAG_CMSG_CLOEXEC 0
+#define ESOCK_RECV_FLAG_ERRQUEUE 1
+#define ESOCK_RECV_FLAG_OOB 2
+#define ESOCK_RECV_FLAG_PEEK 3
+#define ESOCK_RECV_FLAG_TRUNC 4
+#define ESOCK_RECV_FLAG_LOW ESOCK_RECV_FLAG_CMSG_CLOEXEC
+#define ESOCK_RECV_FLAG_HIGH ESOCK_RECV_FLAG_TRUNC
+
+#define ESOCK_RECV_BUFFER_SIZE_DEFAULT 8192
+#define ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT 1024
+#define ESOCK_SEND_CTRL_BUFFER_SIZE_DEFAULT 1024
+
+#define VT2S(__VT__) (((__VT__) == ESOCK_OPT_VALUE_TYPE_UNSPEC) ? "unspec" : \
+ (((__VT__) == ESOCK_OPT_VALUE_TYPE_INT) ? "int" : \
+ ((__VT__) == ESOCK_OPT_VALUE_TYPE_BOOL) ? "bool" : \
"undef"))
-#define SOCKET_OPT_VALUE_TYPE_UNSPEC 0
-#define SOCKET_OPT_VALUE_TYPE_INT 1
-#define SOCKET_OPT_VALUE_TYPE_BOOL 2
+#define ESOCK_OPT_VALUE_TYPE_UNSPEC 0
+#define ESOCK_OPT_VALUE_TYPE_INT 1
+#define ESOCK_OPT_VALUE_TYPE_BOOL 2
#define ESOCK_DESC_PATTERN_CREATED 0x03030303
#define ESOCK_DESC_PATTERN_DTOR 0xC0C0C0C0
+/*
typedef union {
struct {
// 0 = not open, 1 = open
@@ -501,15 +505,16 @@ typedef union {
unsigned int listen:2;
// unsigned int listening:1;
// unsigned int accepting:1;
- /* Room for more... */
+ / * Room for more... * /
} flags;
unsigned int field; // Make it easy to reset all flags...
} SocketState;
+*/
/*
#define IS_OPEN(d) ((d)->state.flags.open)
-#define IS_CONNECTED(d) ((d)->state.flags.connect == SOCKET_STATE_CONNECTED)
-#define IS_CONNECTING(d) ((d)->state.flags.connect == SOCKET_STATE_CONNECTING)
+#define IS_CONNECTED(d) ((d)->state.flags.connect == ESOCK_STATE_CONNECTED)
+#define IS_CONNECTING(d) ((d)->state.flags.connect == ESOCK_STATE_CONNECTING)
*/
@@ -520,151 +525,151 @@ typedef union {
*/
/* domain */
-#define SOCKET_DOMAIN_LOCAL 1
-#define SOCKET_DOMAIN_INET 2
-#define SOCKET_DOMAIN_INET6 3
+#define ESOCK_DOMAIN_LOCAL 1
+#define ESOCK_DOMAIN_INET 2
+#define ESOCK_DOMAIN_INET6 3
/* type */
-#define SOCKET_TYPE_STREAM 1
-#define SOCKET_TYPE_DGRAM 2
-#define SOCKET_TYPE_RAW 3
-// #define SOCKET_TYPE_RDM 4
-#define SOCKET_TYPE_SEQPACKET 5
+#define ESOCK_TYPE_STREAM 1
+#define ESOCK_TYPE_DGRAM 2
+#define ESOCK_TYPE_RAW 3
+// #define ESOCK_TYPE_RDM 4
+#define ESOCK_TYPE_SEQPACKET 5
/* protocol */
-#define SOCKET_PROTOCOL_DEFAULT 0
-#define SOCKET_PROTOCOL_IP 1
-#define SOCKET_PROTOCOL_TCP 2
-#define SOCKET_PROTOCOL_UDP 3
-#define SOCKET_PROTOCOL_SCTP 4
-#define SOCKET_PROTOCOL_ICMP 5
-#define SOCKET_PROTOCOL_IGMP 6
+#define ESOCK_PROTOCOL_DEFAULT 0
+#define ESOCK_PROTOCOL_IP 1
+#define ESOCK_PROTOCOL_TCP 2
+#define ESOCK_PROTOCOL_UDP 3
+#define ESOCK_PROTOCOL_SCTP 4
+#define ESOCK_PROTOCOL_ICMP 5
+#define ESOCK_PROTOCOL_IGMP 6
/* shutdown how */
-#define SOCKET_SHUTDOWN_HOW_RD 0
-#define SOCKET_SHUTDOWN_HOW_WR 1
-#define SOCKET_SHUTDOWN_HOW_RDWR 2
-
-
-#define SOCKET_OPT_LEVEL_OTP 0
-#define SOCKET_OPT_LEVEL_SOCKET 1
-#define SOCKET_OPT_LEVEL_IP 2
-#define SOCKET_OPT_LEVEL_IPV6 3
-#define SOCKET_OPT_LEVEL_TCP 4
-#define SOCKET_OPT_LEVEL_UDP 5
-#define SOCKET_OPT_LEVEL_SCTP 6
-
-#define SOCKET_OPT_OTP_DEBUG 1
-#define SOCKET_OPT_OTP_IOW 2
-#define SOCKET_OPT_OTP_CTRL_PROC 3
-#define SOCKET_OPT_OTP_RCVBUF 4
-#define SOCKET_OPT_OTP_RCVCTRLBUF 6
-#define SOCKET_OPT_OTP_SNDCTRLBUF 7
-#define SOCKET_OPT_OTP_FD 8
-#define SOCKET_OPT_OTP_DOMAIN 0xFF01 // INTERNAL AND ONLY GET
-#define SOCKET_OPT_OTP_TYPE 0xFF02 // INTERNAL AND ONLY GET
-#define SOCKET_OPT_OTP_PROTOCOL 0xFF03 // INTERNAL AND ONLY GET
-
-#define SOCKET_OPT_SOCK_ACCEPTCONN 1
-#define SOCKET_OPT_SOCK_BINDTODEVICE 3
-#define SOCKET_OPT_SOCK_BROADCAST 4
-#define SOCKET_OPT_SOCK_DEBUG 6
-#define SOCKET_OPT_SOCK_DOMAIN 7
-#define SOCKET_OPT_SOCK_DONTROUTE 8
-#define SOCKET_OPT_SOCK_KEEPALIVE 10
-#define SOCKET_OPT_SOCK_LINGER 11
-#define SOCKET_OPT_SOCK_OOBINLINE 13
-#define SOCKET_OPT_SOCK_PEEK_OFF 15
-#define SOCKET_OPT_SOCK_PRIORITY 17
-#define SOCKET_OPT_SOCK_PROTOCOL 18
-#define SOCKET_OPT_SOCK_RCVBUF 19
-#define SOCKET_OPT_SOCK_RCVLOWAT 21
-#define SOCKET_OPT_SOCK_RCVTIMEO 22
-#define SOCKET_OPT_SOCK_REUSEADDR 23
-#define SOCKET_OPT_SOCK_REUSEPORT 24
-#define SOCKET_OPT_SOCK_SNDBUF 27
-#define SOCKET_OPT_SOCK_SNDLOWAT 29
-#define SOCKET_OPT_SOCK_SNDTIMEO 30
-#define SOCKET_OPT_SOCK_TIMESTAMP 31
-#define SOCKET_OPT_SOCK_TYPE 32
-
-#define SOCKET_OPT_IP_ADD_MEMBERSHIP 1
-#define SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP 2
-#define SOCKET_OPT_IP_BLOCK_SOURCE 3
-#define SOCKET_OPT_IP_DROP_MEMBERSHIP 5
-#define SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP 6
-#define SOCKET_OPT_IP_FREEBIND 7
-#define SOCKET_OPT_IP_HDRINCL 8
-#define SOCKET_OPT_IP_MINTTL 9
-#define SOCKET_OPT_IP_MSFILTER 10
-#define SOCKET_OPT_IP_MTU 11
-#define SOCKET_OPT_IP_MTU_DISCOVER 12
-#define SOCKET_OPT_IP_MULTICAST_ALL 13
-#define SOCKET_OPT_IP_MULTICAST_IF 14
-#define SOCKET_OPT_IP_MULTICAST_LOOP 15
-#define SOCKET_OPT_IP_MULTICAST_TTL 16
-#define SOCKET_OPT_IP_NODEFRAG 17
-#define SOCKET_OPT_IP_PKTINFO 19
-#define SOCKET_OPT_IP_RECVDSTADDR 20
-#define SOCKET_OPT_IP_RECVERR 21
-#define SOCKET_OPT_IP_RECVIF 22
-#define SOCKET_OPT_IP_RECVOPTS 23
-#define SOCKET_OPT_IP_RECVORIGDSTADDR 24
-#define SOCKET_OPT_IP_RECVTOS 25
-#define SOCKET_OPT_IP_RECVTTL 26
-#define SOCKET_OPT_IP_RETOPTS 27
-#define SOCKET_OPT_IP_ROUTER_ALERT 28
-#define SOCKET_OPT_IP_SENDSRCADDR 29 // Same as IP_RECVDSTADDR?
-#define SOCKET_OPT_IP_TOS 30
-#define SOCKET_OPT_IP_TRANSPARENT 31
-#define SOCKET_OPT_IP_TTL 32
-#define SOCKET_OPT_IP_UNBLOCK_SOURCE 33
-
-#define SOCKET_OPT_IPV6_ADDRFORM 1
-#define SOCKET_OPT_IPV6_ADD_MEMBERSHIP 2
-#define SOCKET_OPT_IPV6_AUTHHDR 3
-#define SOCKET_OPT_IPV6_DROP_MEMBERSHIP 6
-#define SOCKET_OPT_IPV6_DSTOPTS 7
-#define SOCKET_OPT_IPV6_FLOWINFO 11
-#define SOCKET_OPT_IPV6_HOPLIMIT 12
-#define SOCKET_OPT_IPV6_HOPOPTS 13
-#define SOCKET_OPT_IPV6_MTU 17
-#define SOCKET_OPT_IPV6_MTU_DISCOVER 18
-#define SOCKET_OPT_IPV6_MULTICAST_HOPS 19
-#define SOCKET_OPT_IPV6_MULTICAST_IF 20
-#define SOCKET_OPT_IPV6_MULTICAST_LOOP 21
-#define SOCKET_OPT_IPV6_RECVERR 24
-#define SOCKET_OPT_IPV6_RECVPKTINFO 25 // PKTINFO on FreeBSD
-#define SOCKET_OPT_IPV6_ROUTER_ALERT 27
-#define SOCKET_OPT_IPV6_RTHDR 28
-#define SOCKET_OPT_IPV6_UNICAST_HOPS 30
-#define SOCKET_OPT_IPV6_V6ONLY 32
-
-#define SOCKET_OPT_TCP_CONGESTION 1
-#define SOCKET_OPT_TCP_CORK 2
-#define SOCKET_OPT_TCP_MAXSEG 7
-#define SOCKET_OPT_TCP_NODELAY 9
-
-#define SOCKET_OPT_UDP_CORK 1
-
-#define SOCKET_OPT_SCTP_ASSOCINFO 2
-#define SOCKET_OPT_SCTP_AUTOCLOSE 8
-#define SOCKET_OPT_SCTP_DISABLE_FRAGMENTS 12
-#define SOCKET_OPT_SCTP_EVENTS 14
-#define SOCKET_OPT_SCTP_INITMSG 18
-#define SOCKET_OPT_SCTP_MAXSEG 21
-#define SOCKET_OPT_SCTP_NODELAY 23
-#define SOCKET_OPT_SCTP_RTOINFO 29
+#define ESOCK_SHUTDOWN_HOW_RD 0
+#define ESOCK_SHUTDOWN_HOW_WR 1
+#define ESOCK_SHUTDOWN_HOW_RDWR 2
+
+
+#define ESOCK_OPT_LEVEL_OTP 0
+#define ESOCK_OPT_LEVEL_SOCKET 1
+#define ESOCK_OPT_LEVEL_IP 2
+#define ESOCK_OPT_LEVEL_IPV6 3
+#define ESOCK_OPT_LEVEL_TCP 4
+#define ESOCK_OPT_LEVEL_UDP 5
+#define ESOCK_OPT_LEVEL_SCTP 6
+
+#define ESOCK_OPT_OTP_DEBUG 1
+#define ESOCK_OPT_OTP_IOW 2
+#define ESOCK_OPT_OTP_CTRL_PROC 3
+#define ESOCK_OPT_OTP_RCVBUF 4
+#define ESOCK_OPT_OTP_RCVCTRLBUF 6
+#define ESOCK_OPT_OTP_SNDCTRLBUF 7
+#define ESOCK_OPT_OTP_FD 8
+#define ESOCK_OPT_OTP_DOMAIN 0xFF01 // INTERNAL AND ONLY GET
+#define ESOCK_OPT_OTP_TYPE 0xFF02 // INTERNAL AND ONLY GET
+#define ESOCK_OPT_OTP_PROTOCOL 0xFF03 // INTERNAL AND ONLY GET
+
+#define ESOCK_OPT_SOCK_ACCEPTCONN 1
+#define ESOCK_OPT_SOCK_BINDTODEVICE 3
+#define ESOCK_OPT_SOCK_BROADCAST 4
+#define ESOCK_OPT_SOCK_DEBUG 6
+#define ESOCK_OPT_SOCK_DOMAIN 7
+#define ESOCK_OPT_SOCK_DONTROUTE 8
+#define ESOCK_OPT_SOCK_KEEPALIVE 10
+#define ESOCK_OPT_SOCK_LINGER 11
+#define ESOCK_OPT_SOCK_OOBINLINE 13
+#define ESOCK_OPT_SOCK_PEEK_OFF 15
+#define ESOCK_OPT_SOCK_PRIORITY 17
+#define ESOCK_OPT_SOCK_PROTOCOL 18
+#define ESOCK_OPT_SOCK_RCVBUF 19
+#define ESOCK_OPT_SOCK_RCVLOWAT 21
+#define ESOCK_OPT_SOCK_RCVTIMEO 22
+#define ESOCK_OPT_SOCK_REUSEADDR 23
+#define ESOCK_OPT_SOCK_REUSEPORT 24
+#define ESOCK_OPT_SOCK_SNDBUF 27
+#define ESOCK_OPT_SOCK_SNDLOWAT 29
+#define ESOCK_OPT_SOCK_SNDTIMEO 30
+#define ESOCK_OPT_SOCK_TIMESTAMP 31
+#define ESOCK_OPT_SOCK_TYPE 32
+
+#define ESOCK_OPT_IP_ADD_MEMBERSHIP 1
+#define ESOCK_OPT_IP_ADD_SOURCE_MEMBERSHIP 2
+#define ESOCK_OPT_IP_BLOCK_SOURCE 3
+#define ESOCK_OPT_IP_DROP_MEMBERSHIP 5
+#define ESOCK_OPT_IP_DROP_SOURCE_MEMBERSHIP 6
+#define ESOCK_OPT_IP_FREEBIND 7
+#define ESOCK_OPT_IP_HDRINCL 8
+#define ESOCK_OPT_IP_MINTTL 9
+#define ESOCK_OPT_IP_MSFILTER 10
+#define ESOCK_OPT_IP_MTU 11
+#define ESOCK_OPT_IP_MTU_DISCOVER 12
+#define ESOCK_OPT_IP_MULTICAST_ALL 13
+#define ESOCK_OPT_IP_MULTICAST_IF 14
+#define ESOCK_OPT_IP_MULTICAST_LOOP 15
+#define ESOCK_OPT_IP_MULTICAST_TTL 16
+#define ESOCK_OPT_IP_NODEFRAG 17
+#define ESOCK_OPT_IP_PKTINFO 19
+#define ESOCK_OPT_IP_RECVDSTADDR 20
+#define ESOCK_OPT_IP_RECVERR 21
+#define ESOCK_OPT_IP_RECVIF 22
+#define ESOCK_OPT_IP_RECVOPTS 23
+#define ESOCK_OPT_IP_RECVORIGDSTADDR 24
+#define ESOCK_OPT_IP_RECVTOS 25
+#define ESOCK_OPT_IP_RECVTTL 26
+#define ESOCK_OPT_IP_RETOPTS 27
+#define ESOCK_OPT_IP_ROUTER_ALERT 28
+#define ESOCK_OPT_IP_SENDSRCADDR 29 // Same as IP_RECVDSTADDR?
+#define ESOCK_OPT_IP_TOS 30
+#define ESOCK_OPT_IP_TRANSPARENT 31
+#define ESOCK_OPT_IP_TTL 32
+#define ESOCK_OPT_IP_UNBLOCK_SOURCE 33
+
+#define ESOCK_OPT_IPV6_ADDRFORM 1
+#define ESOCK_OPT_IPV6_ADD_MEMBERSHIP 2
+#define ESOCK_OPT_IPV6_AUTHHDR 3
+#define ESOCK_OPT_IPV6_DROP_MEMBERSHIP 6
+#define ESOCK_OPT_IPV6_DSTOPTS 7
+#define ESOCK_OPT_IPV6_FLOWINFO 11
+#define ESOCK_OPT_IPV6_HOPLIMIT 12
+#define ESOCK_OPT_IPV6_HOPOPTS 13
+#define ESOCK_OPT_IPV6_MTU 17
+#define ESOCK_OPT_IPV6_MTU_DISCOVER 18
+#define ESOCK_OPT_IPV6_MULTICAST_HOPS 19
+#define ESOCK_OPT_IPV6_MULTICAST_IF 20
+#define ESOCK_OPT_IPV6_MULTICAST_LOOP 21
+#define ESOCK_OPT_IPV6_RECVERR 24
+#define ESOCK_OPT_IPV6_RECVPKTINFO 25 // PKTINFO on FreeBSD
+#define ESOCK_OPT_IPV6_ROUTER_ALERT 27
+#define ESOCK_OPT_IPV6_RTHDR 28
+#define ESOCK_OPT_IPV6_UNICAST_HOPS 30
+#define ESOCK_OPT_IPV6_V6ONLY 32
+
+#define ESOCK_OPT_TCP_CONGESTION 1
+#define ESOCK_OPT_TCP_CORK 2
+#define ESOCK_OPT_TCP_MAXSEG 7
+#define ESOCK_OPT_TCP_NODELAY 9
+
+#define ESOCK_OPT_UDP_CORK 1
+
+#define ESOCK_OPT_SCTP_ASSOCINFO 2
+#define ESOCK_OPT_SCTP_AUTOCLOSE 8
+#define ESOCK_OPT_SCTP_DISABLE_FRAGMENTS 12
+#define ESOCK_OPT_SCTP_EVENTS 14
+#define ESOCK_OPT_SCTP_INITMSG 18
+#define ESOCK_OPT_SCTP_MAXSEG 21
+#define ESOCK_OPT_SCTP_NODELAY 23
+#define ESOCK_OPT_SCTP_RTOINFO 29
/* We should *eventually* use this instead of hard-coding the size (to 1) */
#define ESOCK_RECVMSG_IOVEC_SZ 1
-#define SOCKET_CMD_DEBUG 0x0001
+#define ESOCK_CMD_DEBUG 0x0001
-#define SOCKET_SUPPORTS_OPTIONS 0x0001
-#define SOCKET_SUPPORTS_SCTP 0x0002
-#define SOCKET_SUPPORTS_IPV6 0x0003
-#define SOCKET_SUPPORTS_LOCAL 0x0004
+#define ESOCK_SUPPORTS_OPTIONS 0x0001
+#define ESOCK_SUPPORTS_SCTP 0x0002
+#define ESOCK_SUPPORTS_IPV6 0x0003
+#define ESOCK_SUPPORTS_LOCAL 0x0004
#define ESOCK_WHICH_PROTO_ERROR -1
#define ESOCK_WHICH_PROTO_UNSUP -2
@@ -1021,10 +1026,10 @@ static BOOLEAN_T ecommand2command(ErlNifEnv* env,
ERL_NIF_TERM ecommand,
Uint16* command,
ERL_NIF_TERM* edata);
-static ERL_NIF_TERM ncommand(ErlNifEnv* env,
- Uint16 cmd,
- ERL_NIF_TERM ecdata);
-static ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata);
+static ERL_NIF_TERM esock_command(ErlNifEnv* env,
+ Uint16 cmd,
+ ERL_NIF_TERM ecdata);
+static ERL_NIF_TERM esock_command_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata);
static ERL_NIF_TERM esock_global_info(ErlNifEnv* env);
static ERL_NIF_TERM esock_socket_info(ErlNifEnv* env,
@@ -1048,1109 +1053,1109 @@ static ERL_NIF_TERM socket_info_reqs(ErlNifEnv* env,
ESockRequestor* crp,
ESockRequestQueue* q);
-static ERL_NIF_TERM nsupports(ErlNifEnv* env, int key);
-static ERL_NIF_TERM nsupports_options(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env);
-static ERL_NIF_TERM nsupports_local(ErlNifEnv* env);
-
-static ERL_NIF_TERM nopen(ErlNifEnv* env,
+static ERL_NIF_TERM esock_supports(ErlNifEnv* env, int key);
+static ERL_NIF_TERM esock_supports_options(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_options_socket(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_options_ip(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_options_ipv6(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_options_tcp(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_options_udp(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_options_sctp(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_sctp(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_ipv6(ErlNifEnv* env);
+static ERL_NIF_TERM esock_supports_local(ErlNifEnv* env);
+
+static ERL_NIF_TERM esock_open(ErlNifEnv* env,
int domain,
int type,
int protocol,
char* netns);
-static BOOLEAN_T nopen_which_protocol(SOCKET sock, int* proto);
+static BOOLEAN_T esock_open_which_protocol(SOCKET sock, int* proto);
-static ERL_NIF_TERM nbind(ErlNifEnv* env,
- ESockDescriptor* descP,
- ESockAddress* sockAddrP,
- unsigned int addrLen);
-static ERL_NIF_TERM nconnect(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM nlisten(ErlNifEnv* env,
- ESockDescriptor* descP,
- int backlog);
-static ERL_NIF_TERM naccept(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
+static ERL_NIF_TERM esock_bind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ESockAddress* sockAddrP,
+ unsigned int addrLen);
+static ERL_NIF_TERM esock_connect(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM esock_listen(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int backlog);
+static ERL_NIF_TERM esock_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM esock_accept_listening(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef,
+ ErlNifPid caller,
+ int save_errno);
+static ERL_NIF_TERM esock_accept_listening_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ SOCKET accSock,
+ ErlNifPid caller,
+ ESockAddress* remote);
+static ERL_NIF_TERM esock_accept_accepting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM esock_accept_accepting_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref);
+static ERL_NIF_TERM esock_accept_accepting_current_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ SOCKET accSock,
+ ESockAddress* remote);
+static ERL_NIF_TERM esock_accept_accepting_current_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
+ int save_errno);
+static ERL_NIF_TERM esock_accept_accepting_other(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ErlNifPid caller);
+static ERL_NIF_TERM esock_accept_busy_retry(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM accRef,
- ErlNifPid caller,
- int save_errno);
-static ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
- ESockDescriptor* descP,
- SOCKET accSock,
- ErlNifPid caller,
- ESockAddress* remote);
-static ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref);
-static ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- SOCKET accSock,
- ESockAddress* remote);
-static ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef,
- int save_errno);
-static ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid caller);
-static ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
+ ErlNifPid* pid,
+ unsigned int nextState);
+static BOOLEAN_T esock_accept_accepted(ErlNifEnv* env,
ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM accRef,
- ErlNifPid* pid,
- unsigned int nextState);
-static BOOLEAN_T naccept_accepted(ErlNifEnv* env,
+ SOCKET accSock,
+ ErlNifPid pid,
+ ESockAddress* remote,
+ ERL_NIF_TERM* result);
+static ERL_NIF_TERM esock_send(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* dataP,
+ int flags);
+static ERL_NIF_TERM esock_sendto(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* dataP,
+ int flags,
+ ESockAddress* toAddrP,
+ unsigned int toAddrLen);
+static ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env,
ESockDescriptor* descP,
- SOCKET accSock,
- ErlNifPid pid,
- ESockAddress* remote,
- ERL_NIF_TERM* result);
-static ERL_NIF_TERM nsend(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* dataP,
- int flags);
-static ERL_NIF_TERM nsendto(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* dataP,
- int flags,
- ESockAddress* toAddrP,
- unsigned int toAddrLen);
-static ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ERL_NIF_TERM eMsgHdr,
- int flags);
-static ERL_NIF_TERM nrecv(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sendRef,
- ERL_NIF_TERM recvRef,
- int len,
- int flags);
-static ERL_NIF_TERM nrecvfrom(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 bufSz,
- int flags);
-static ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 bufLen,
- Uint16 ctrlLen,
- int flags);
-static ERL_NIF_TERM nclose(ErlNifEnv* env,
- ESockDescriptor* descP);
-static BOOLEAN_T nclose_check(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM* reason);
-static ERL_NIF_TERM nclose_do(ErlNifEnv* env,
- ESockDescriptor* descP);
-static ERL_NIF_TERM nshutdown(ErlNifEnv* env,
- ESockDescriptor* descP,
- int how);
-static ERL_NIF_TERM nsetopt(ErlNifEnv* env,
- ESockDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal);
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ERL_NIF_TERM eMsgHdr,
+ int flags);
+static ERL_NIF_TERM esock_recv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sendRef,
+ ERL_NIF_TERM recvRef,
+ int len,
+ int flags);
+static ERL_NIF_TERM esock_recvfrom(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 bufSz,
+ int flags);
+static ERL_NIF_TERM esock_recvmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 bufLen,
+ Uint16 ctrlLen,
+ int flags);
+static ERL_NIF_TERM esock_close(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static BOOLEAN_T esock_close_check(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM* reason);
+static ERL_NIF_TERM esock_close_do(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM esock_shutdown(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int how);
+static ERL_NIF_TERM esock_setopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal);
/* Set OTP level options */
-static ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
-/* *** nsetopt_otp_debug ***
- * *** nsetopt_otp_iow ***
- * *** nsetopt_otp_ctrl_proc ***
- * *** nsetopt_otp_rcvbuf ***
- * *** nsetopt_otp_rcvctrlbuf ***
- * *** nsetopt_otp_sndctrlbuf ***
- */
-#define NSETOPT_OTP_FUNCS \
- NSETOPT_OTP_FUNC_DEF(debug); \
- NSETOPT_OTP_FUNC_DEF(iow); \
- NSETOPT_OTP_FUNC_DEF(ctrl_proc); \
- NSETOPT_OTP_FUNC_DEF(rcvbuf); \
- NSETOPT_OTP_FUNC_DEF(rcvctrlbuf); \
- NSETOPT_OTP_FUNC_DEF(sndctrlbuf);
-#define NSETOPT_OTP_FUNC_DEF(F) \
- static ERL_NIF_TERM nsetopt_otp_##F(ErlNifEnv* env, \
- ESockDescriptor* descP, \
- ERL_NIF_TERM eVal)
-NSETOPT_OTP_FUNCS
-#undef NSETOPT_OTP_FUNC_DEF
+static ERL_NIF_TERM esock_setopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
+/* *** esock_setopt_otp_debug ***
+ * *** esock_setopt_otp_iow ***
+ * *** esock_setopt_otp_ctrl_proc ***
+ * *** esock_setopt_otp_rcvbuf ***
+ * *** esock_setopt_otp_rcvctrlbuf ***
+ * *** esock_setopt_otp_sndctrlbuf ***
+ */
+#define ESOCK_SETOPT_OTP_FUNCS \
+ ESOCK_SETOPT_OTP_FUNC_DEF(debug); \
+ ESOCK_SETOPT_OTP_FUNC_DEF(iow); \
+ ESOCK_SETOPT_OTP_FUNC_DEF(ctrl_proc); \
+ ESOCK_SETOPT_OTP_FUNC_DEF(rcvbuf); \
+ ESOCK_SETOPT_OTP_FUNC_DEF(rcvctrlbuf); \
+ ESOCK_SETOPT_OTP_FUNC_DEF(sndctrlbuf);
+#define ESOCK_SETOPT_OTP_FUNC_DEF(F) \
+ static ERL_NIF_TERM esock_setopt_otp_##F(ErlNifEnv* env, \
+ ESockDescriptor* descP, \
+ ERL_NIF_TERM eVal)
+ESOCK_SETOPT_OTP_FUNCS
+#undef ESOCK_SETOPT_OTP_FUNC_DEF
/* Set native options */
-static ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
+static ERL_NIF_TERM esock_setopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_level(ErlNifEnv* env,
ESockDescriptor* descP,
+ int level,
int eOpt,
ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
/* *** Handling set of socket options for level = socket *** */
#if defined(SO_BINDTODEVICE)
-static ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_BROADCAST)
-static ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_DEBUG)
-static ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_DONTROUTE)
-static ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_KEEPALIVE)
-static ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_LINGER)
-static ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_OOBINLINE)
-static ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_PEEK_OFF)
-static ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_PRIORITY)
-static ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_RCVBUF)
-static ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_RCVLOWAT)
-static ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_RCVTIMEO)
-static ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_REUSEADDR)
-static ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_REUSEPORT)
-static ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_SNDBUF)
-static ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_SNDLOWAT)
-static ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_SNDTIMEO)
-static ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SO_TIMESTAMP)
-static ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
-static ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
/* *** Handling set of socket options for level = ip *** */
#if defined(IP_ADD_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_ADD_SOURCE_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_add_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_BLOCK_SOURCE)
-static ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_block_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_DROP_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_DROP_SOURCE_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_FREEBIND)
-static ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_HDRINCL)
-static ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MINTTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE)
-static ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_msfilter(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
static BOOLEAN_T decode_ip_msfilter_mode(ErlNifEnv* env,
ERL_NIF_TERM eVal,
Uint32* mode);
-static ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env,
- SOCKET sock,
- struct ip_msfilter* msfP,
- SOCKLEN_T optLen);
+static ERL_NIF_TERM esock_setopt_lvl_ip_msfilter_set(ErlNifEnv* env,
+ SOCKET sock,
+ struct ip_msfilter* msfP,
+ SOCKLEN_T optLen);
#endif
#if defined(IP_MTU_DISCOVER)
-static ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_ALL)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_IF)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_LOOP)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_MULTICAST_TTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_NODEFRAG)
-static ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_PKTINFO)
-static ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVDSTADDR)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVERR)
-static ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVIF)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVORIGDSTADDR)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVTOS)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RECVTTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_RETOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
-#endif
-#if defined(IP_ROUTER_ALERT)
-static ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
+static ERL_NIF_TERM esock_setopt_lvl_ip_retopts(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM eVal);
#endif
+#if defined(IP_ROUTER_ALERT)
+static ERL_NIF_TERM esock_setopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
+#endif
#if defined(IP_SENDSRCADDR)
-static ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_TOS)
-static ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_TRANSPARENT)
-static ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_TTL)
-static ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_UNBLOCK_SOURCE)
-static ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ip_unblock_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IP_DROP_MEMBERSHIP) || defined(IP_ADD_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt);
+ERL_NIF_TERM esock_setopt_lvl_ip_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt);
#endif
#if defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(IP_DROP_SOURCE_MEMBERSHIP) || defined(IP_BLOCK_SOURCE) || defined(IP_UNBLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt);
+ERL_NIF_TERM esock_setopt_lvl_ip_update_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt);
#endif
/* *** Handling set of socket options for level = ipv6 *** */
#if defined(HAVE_IPV6)
-static ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
#if defined(IPV6_ADDRFORM)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_addrform(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_ADD_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_AUTHHDR)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_DROP_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_DSTOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_FLOWINFO)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_HOPLIMIT)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_HOPOPTS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MTU)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MTU_DISCOVER)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MULTICAST_HOPS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MULTICAST_IF)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_MULTICAST_LOOP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_RECVERR)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_ROUTER_ALERT)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_RTHDR)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_UNICAST_HOPS)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_V6ONLY)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP)
-static ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt);
+static ERL_NIF_TERM esock_setopt_lvl_ipv6_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt);
#endif
#endif // defined(HAVE_IPV6)
-static ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
#if defined(TCP_CONGESTION)
-static ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(TCP_MAXSEG)
-static ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(TCP_NODELAY)
-static ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
-static ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
-#if defined(UDP_CORK)
-static ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env,
+static ERL_NIF_TERM esock_setopt_lvl_udp(ErlNifEnv* env,
ESockDescriptor* descP,
+ int eOpt,
ERL_NIF_TERM eVal);
+#if defined(UDP_CORK)
+static ERL_NIF_TERM esock_setopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(HAVE_SCTP)
-static ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal);
#if defined(SCTP_ASSOCINFO)
-static ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_AUTOCLOSE)
-static ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_DISABLE_FRAGMENTS)
-static ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_EVENTS)
-static ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_events(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_INITMSG)
-static ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_MAXSEG)
-static ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_NODELAY)
-static ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#if defined(SCTP_RTOINFO)
-static ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal);
#endif
#endif // defined(HAVE_SCTP)
-static ERL_NIF_TERM ngetopt(ErlNifEnv* env,
- ESockDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- ERL_NIF_TERM eOpt);
+static ERL_NIF_TERM esock_getopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ ERL_NIF_TERM eOpt);
-static ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt);
-/* *** ngetopt_otp_debug ***
- * *** ngetopt_otp_iow ***
- * *** ngetopt_otp_ctrl_proc ***
- * *** ngetopt_otp_rcvbuf ***
- * *** ngetopt_otp_rcvctrlbuf ***
- * *** ngetopt_otp_sndctrlbuf ***
- * *** ngetopt_otp_fd ***
- * *** ngetopt_otp_domain ***
- * *** ngetopt_otp_type ***
- * *** ngetopt_otp_protocol ***
- */
-#define NGETOPT_OTP_FUNCS \
- NGETOPT_OTP_FUNC_DEF(debug); \
- NGETOPT_OTP_FUNC_DEF(iow); \
- NGETOPT_OTP_FUNC_DEF(ctrl_proc); \
- NGETOPT_OTP_FUNC_DEF(rcvbuf); \
- NGETOPT_OTP_FUNC_DEF(rcvctrlbuf); \
- NGETOPT_OTP_FUNC_DEF(sndctrlbuf); \
- NGETOPT_OTP_FUNC_DEF(fd); \
- NGETOPT_OTP_FUNC_DEF(domain); \
- NGETOPT_OTP_FUNC_DEF(type); \
- NGETOPT_OTP_FUNC_DEF(protocol);
-#define NGETOPT_OTP_FUNC_DEF(F) \
- static ERL_NIF_TERM ngetopt_otp_##F(ErlNifEnv* env, \
- ESockDescriptor* descP)
-NGETOPT_OTP_FUNCS
-#undef NGETOPT_OTP_FUNC_DEF
+static ERL_NIF_TERM esock_getopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
+/* *** esock_getopt_otp_debug ***
+ * *** esock_getopt_otp_iow ***
+ * *** esock_getopt_otp_ctrl_proc ***
+ * *** esock_getopt_otp_rcvbuf ***
+ * *** esock_getopt_otp_rcvctrlbuf ***
+ * *** esock_getopt_otp_sndctrlbuf ***
+ * *** esock_getopt_otp_fd ***
+ * *** esock_getopt_otp_domain ***
+ * *** esock_getopt_otp_type ***
+ * *** esock_getopt_otp_protocol ***
+ */
+#define ESOCK_GETOPT_OTP_FUNCS \
+ ESOCK_GETOPT_OTP_FUNC_DEF(debug); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(iow); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(ctrl_proc); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(rcvbuf); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(rcvctrlbuf); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(sndctrlbuf); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(fd); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(domain); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(type); \
+ ESOCK_GETOPT_OTP_FUNC_DEF(protocol);
+#define ESOCK_GETOPT_OTP_FUNC_DEF(F) \
+ static ERL_NIF_TERM esock_getopt_otp_##F(ErlNifEnv* env, \
+ ESockDescriptor* descP)
+ESOCK_GETOPT_OTP_FUNCS
+#undef ESOCK_GETOPT_OTP_FUNC_DEF
-static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- ERL_NIF_TERM eOpt);
-static ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- SOCKOPTLEN_T valueSz);
-static ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int eOpt);
-static ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
+static ERL_NIF_TERM esock_getopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ ERL_NIF_TERM eOpt);
+static ERL_NIF_TERM esock_getopt_native_unspec(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ SOCKOPTLEN_T valueSz);
+static ERL_NIF_TERM esock_getopt_level(ErlNifEnv* env,
ESockDescriptor* descP,
+ int level,
int eOpt);
+static ERL_NIF_TERM esock_getopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(SO_ACCEPTCONN)
-static ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_acceptconn(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_BINDTODEVICE)
-static ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_BROADCAST)
-static ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_DEBUG)
-static ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_DOMAIN)
-static ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_domain(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_DONTROUTE)
-static ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_KEEPALIVE)
-static ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_LINGER)
-static ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_OOBINLINE)
-static ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_PEEK_OFF)
-static ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_PRIORITY)
-static ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_PROTOCOL)
-static ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_protocol(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_RCVBUF)
-static ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_RCVLOWAT)
-static ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_RCVTIMEO)
-static ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_REUSEADDR)
-static ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_REUSEPORT)
-static ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_SNDBUF)
-static ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_SNDLOWAT)
-static ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_SNDTIMEO)
-static ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_TIMESTAMP)
-static ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SO_TYPE)
-static ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sock_type(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
-static ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM esock_getopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(IP_FREEBIND)
-static ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_HDRINCL)
-static ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MINTTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MTU)
-static ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MTU_DISCOVER)
-static ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_ALL)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_IF)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_LOOP)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_MULTICAST_TTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_NODEFRAG)
-static ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_PKTINFO)
-static ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVDSTADDR)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVERR)
-static ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVIF)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVORIGDSTADDR)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVTOS)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RECVTTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_RETOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_retopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_ROUTER_ALERT)
-static ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_SENDSRCADDR)
-static ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_TOS)
-static ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_TRANSPARENT)
-static ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IP_TTL)
-static ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(HAVE_IPV6)
-static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(IPV6_AUTHHDR)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_DSTOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_FLOWINFO)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_HOPLIMIT)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_HOPOPTS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MTU)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MTU_DISCOVER)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MULTICAST_HOPS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MULTICAST_IF)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_MULTICAST_LOOP)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_RECVERR)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_ROUTER_ALERT)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_RTHDR)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_UNICAST_HOPS)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(IPV6_V6ONLY)
-static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#endif // defined(HAVE_IPV6)
-static ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM esock_getopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(TCP_CONGESTION)
-static ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(TCP_MAXSEG)
-static ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(TCP_NODELAY)
-static ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
-static ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM esock_getopt_lvl_udp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(UDP_CORK)
-static ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(HAVE_SCTP)
-static ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt);
+static ERL_NIF_TERM esock_getopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt);
#if defined(SCTP_ASSOCINFO)
-static ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_AUTOCLOSE)
-static ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_DISABLE_FRAGMENTS)
-static ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_MAXSEG)
-static ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_INITMSG)
-static ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_NODELAY)
-static ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#if defined(SCTP_RTOINFO)
-static ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- ESockDescriptor* descP);
+static ERL_NIF_TERM esock_getopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP);
#endif
#endif // defined(HAVE_SCTP)
-static ERL_NIF_TERM nsockname(ErlNifEnv* env,
- ESockDescriptor* descP);
-static ERL_NIF_TERM npeername(ErlNifEnv* env,
- ESockDescriptor* descP);
-static ERL_NIF_TERM ncancel(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM op,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
+static ERL_NIF_TERM esock_sockname(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM esock_peername(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM esock_cancel(ErlNifEnv* env,
ESockDescriptor* descP,
+ ERL_NIF_TERM op,
ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
+static ERL_NIF_TERM esock_cancel_connect(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env,
+static ERL_NIF_TERM esock_cancel_accept(ErlNifEnv* env,
ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef);
-static ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef,
- int smode,
- int rmode);
+static ERL_NIF_TERM esock_cancel_accept_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM esock_cancel_accept_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM esock_cancel_send(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM esock_cancel_send_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM esock_cancel_send_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM esock_cancel_recv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM esock_cancel_recv_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef);
+static ERL_NIF_TERM esock_cancel_recv_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM esock_cancel_read_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM esock_cancel_write_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef);
+static ERL_NIF_TERM esock_cancel_mode_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef,
+ int smode,
+ int rmode);
#if defined(USE_SETOPT_STR_OPT)
-static ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- int max,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max,
+ ERL_NIF_TERM eVal);
#endif
-static ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal);
-static ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal);
+static ERL_NIF_TERM esock_setopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal);
#if defined(USE_GETOPT_STR_OPT)
-static ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- int max);
+static ERL_NIF_TERM esock_getopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max);
#endif
-static ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt);
-static ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt);
-static ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt);
+static ERL_NIF_TERM esock_getopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt);
+static ERL_NIF_TERM esock_getopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt);
+static ERL_NIF_TERM esock_getopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt);
static BOOLEAN_T send_check_writer(ErlNifEnv* env,
ESockDescriptor* descP,
@@ -2281,10 +2286,10 @@ static ERL_NIF_TERM recvmsg_check_msg(ErlNifEnv* env,
ErlNifBinary* ctrlBufP,
ERL_NIF_TERM sockRef);
-static ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
+static ERL_NIF_TERM esock_finalize_connection(ErlNifEnv* env,
+ ESockDescriptor* descP);
+static ERL_NIF_TERM esock_finalize_close(ErlNifEnv* env,
ESockDescriptor* descP);
-static ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
- ESockDescriptor* descP);
extern char* encode_msghdr(ErlNifEnv* env,
ESockDescriptor* descP,
@@ -2417,11 +2422,11 @@ static BOOLEAN_T decode_native_get_opt(ErlNifEnv* env,
// static void encode_bool(BOOLEAN_T val, ERL_NIF_TERM* eVal);
static ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val);
-static void socket_stop_handle_current(ErlNifEnv* env,
- const char* role,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ESockRequestor* reqP);
+static void esock_stop_handle_current(ErlNifEnv* env,
+ const char* role,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ESockRequestor* reqP);
static void inform_waiting_procs(ErlNifEnv* env,
const char* role,
ESockDescriptor* descP,
@@ -2560,30 +2565,30 @@ static size_t my_strnlen(const char *s, size_t maxlen);
#endif
*/
-static void socket_dtor(ErlNifEnv* env, void* obj);
-static void socket_stop(ErlNifEnv* env,
- void* obj,
- int fd,
- int is_direct_call);
-static void socket_down(ErlNifEnv* env,
- void* obj,
- const ErlNifPid* pid,
- const ErlNifMonitor* mon);
+static void esock_dtor(ErlNifEnv* env, void* obj);
+static void esock_stop(ErlNifEnv* env,
+ void* obj,
+ int fd,
+ int is_direct_call);
+static void esock_down(ErlNifEnv* env,
+ void* obj,
+ const ErlNifPid* pid,
+ const ErlNifMonitor* mon);
#if !defined(__WIN32__)
-static void socket_down_acceptor(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid);
-static void socket_down_writer(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid);
-static void socket_down_reader(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- const ErlNifPid* pid);
+static void esock_down_acceptor(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid);
+static void esock_down_writer(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid);
+static void esock_down_reader(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ const ErlNifPid* pid);
static char* esock_send_wrap_msg(ErlNifEnv* env,
ESockDescriptor* descP,
@@ -2995,11 +3000,11 @@ LOCAL_ERROR_REASON_ATOMS
/* *** Sockets *** */
-static ErlNifResourceType* sockets;
-static ErlNifResourceTypeInit socketInit = {
- socket_dtor,
- socket_stop,
- (ErlNifResourceDown*) socket_down
+static ErlNifResourceType* esocks;
+static ErlNifResourceTypeInit esockInit = {
+ esock_dtor,
+ esock_stop,
+ (ErlNifResourceDown*) esock_down
};
// Initiated when the nif is loaded
@@ -3100,7 +3105,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env,
{
ESockDescriptor* descP;
- if (!enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ if (!ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) {
return enif_make_badarg(env);
}
SSDBG( descP, ("SOCKET", "nif_info -> get socket info\r\n") );
@@ -3297,7 +3302,7 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env,
"\r\n (e) command data: %T"
"\r\n", cmd, ecdata) );
- result = ncommand(env, cmd, ecdata);
+ result = esock_command(env, cmd, ecdata);
SGDBG( ("SOCKET", "nif_command -> done with result: "
"\r\n %T"
@@ -3311,15 +3316,15 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM ncommand(ErlNifEnv* env, Uint16 cmd, ERL_NIF_TERM ecdata)
+ERL_NIF_TERM esock_command(ErlNifEnv* env, Uint16 cmd, ERL_NIF_TERM ecdata)
{
ERL_NIF_TERM result;
- SGDBG( ("SOCKET", "ncommand -> entry with 0x%lX\r\n", cmd) );
+ SGDBG( ("SOCKET", "esock_command -> entry with 0x%lX\r\n", cmd) );
switch (cmd) {
- case SOCKET_CMD_DEBUG:
- result = ncommand_debug(env, ecdata);
+ case ESOCK_CMD_DEBUG:
+ result = esock_command_debug(env, ecdata);
break;
default:
@@ -3333,7 +3338,7 @@ ERL_NIF_TERM ncommand(ErlNifEnv* env, Uint16 cmd, ERL_NIF_TERM ecdata)
static
-ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata)
+ERL_NIF_TERM esock_command_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata)
{
ERL_NIF_TERM result;
@@ -3346,7 +3351,7 @@ ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata)
data.dbg = FALSE;
result = esock_atom_ok;
} else {
- SGDBG( ("SOCKET", "ncommand_debug -> invalid debug value: %T\r\n",
+ SGDBG( ("SOCKET", "esock_command_debug -> invalid debug value: %T\r\n",
ecdata) );
result = esock_make_error(env, esock_atom_einval);
}
@@ -3366,20 +3371,20 @@ ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata)
*/
#if !defined(__WIN32__)
-#define SOCKET_INFO_REQ_FUNCS \
- SOCKET_INFO_REQ_FUNC_DECL(readers, readMtx, currentReaderP, readersQ) \
- SOCKET_INFO_REQ_FUNC_DECL(writers, writeMtx, currentWriterP, writersQ) \
- SOCKET_INFO_REQ_FUNC_DECL(acceptors, accMtx, currentAcceptorP, acceptorsQ)
+#define ESOCK_INFO_REQ_FUNCS \
+ ESOCK_INFO_REQ_FUNC_DECL(readers, readMtx, currentReaderP, readersQ) \
+ ESOCK_INFO_REQ_FUNC_DECL(writers, writeMtx, currentWriterP, writersQ) \
+ ESOCK_INFO_REQ_FUNC_DECL(acceptors, accMtx, currentAcceptorP, acceptorsQ)
-#define SOCKET_INFO_REQ_FUNC_DECL(F, MTX, CRP, Q) \
+#define ESOCK_INFO_REQ_FUNC_DECL(F, MTX, CRP, Q) \
static \
ERL_NIF_TERM esock_socket_info_##F(ErlNifEnv* env, \
ESockDescriptor* descP) \
{ \
return socket_info_reqs(env, descP, descP->MTX, descP->CRP, &descP->Q); \
}
-SOCKET_INFO_REQ_FUNCS
-#undef SOCKET_INFO_REQ_FUNC_DECL
+ESOCK_INFO_REQ_FUNCS
+#undef ESOCK_INFO_REQ_FUNC_DECL
static
@@ -3461,40 +3466,40 @@ ERL_NIF_TERM nif_supports(ErlNifEnv* env,
return enif_make_badarg(env);
}
- return nsupports(env, key);
+ return esock_supports(env, key);
#endif
}
-/* nsupports - what features do we support
+/* esock_supports - what features do we support
*
* This is to prove information about what features actually
* work on the current platform.
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports(ErlNifEnv* env, int key)
+ERL_NIF_TERM esock_supports(ErlNifEnv* env, int key)
{
ERL_NIF_TERM result;
- SGDBG( ("SOCKET", "nsupports -> entry with 0x%lX\r\n", key) );
+ SGDBG( ("SOCKET", "esock_supports -> entry with 0x%lX\r\n", key) );
switch (key) {
- case SOCKET_SUPPORTS_OPTIONS:
- result = nsupports_options(env);
+ case ESOCK_SUPPORTS_OPTIONS:
+ result = esock_supports_options(env);
break;
- case SOCKET_SUPPORTS_SCTP:
- result = nsupports_sctp(env);
+ case ESOCK_SUPPORTS_SCTP:
+ result = esock_supports_sctp(env);
break;
- case SOCKET_SUPPORTS_IPV6:
- result = nsupports_ipv6(env);
+ case ESOCK_SUPPORTS_IPV6:
+ result = esock_supports_ipv6(env);
break;
- case SOCKET_SUPPORTS_LOCAL:
- result = nsupports_local(env);
+ case ESOCK_SUPPORTS_LOCAL:
+ result = esock_supports_local(env);
break;
default:
@@ -3509,19 +3514,19 @@ ERL_NIF_TERM nsupports(ErlNifEnv* env, int key)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_options(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_options(ErlNifEnv* env)
{
- ERL_NIF_TERM sockOpts = nsupports_options_socket(env);
+ ERL_NIF_TERM sockOpts = esock_supports_options_socket(env);
ERL_NIF_TERM sockOptsT = MKT2(env, esock_atom_socket, sockOpts);
- ERL_NIF_TERM ipOpts = nsupports_options_ip(env);
+ ERL_NIF_TERM ipOpts = esock_supports_options_ip(env);
ERL_NIF_TERM ipOptsT = MKT2(env, esock_atom_ip, ipOpts);
- ERL_NIF_TERM ipv6Opts = nsupports_options_ipv6(env);
+ ERL_NIF_TERM ipv6Opts = esock_supports_options_ipv6(env);
ERL_NIF_TERM ipv6OptsT = MKT2(env, esock_atom_ipv6, ipv6Opts);
- ERL_NIF_TERM tcpOpts = nsupports_options_tcp(env);
+ ERL_NIF_TERM tcpOpts = esock_supports_options_tcp(env);
ERL_NIF_TERM tcpOptsT = MKT2(env, esock_atom_tcp, tcpOpts);
- ERL_NIF_TERM udpOpts = nsupports_options_udp(env);
+ ERL_NIF_TERM udpOpts = esock_supports_options_udp(env);
ERL_NIF_TERM udpOptsT = MKT2(env, esock_atom_udp, udpOpts);
- ERL_NIF_TERM sctpOpts = nsupports_options_sctp(env);
+ ERL_NIF_TERM sctpOpts = esock_supports_options_sctp(env);
ERL_NIF_TERM sctpOptsT = MKT2(env, esock_atom_sctp, sctpOpts);
ERL_NIF_TERM optsA[] = {sockOptsT,
ipOptsT, ipv6OptsT,
@@ -3537,13 +3542,13 @@ ERL_NIF_TERM nsupports_options(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_options_socket(ErlNifEnv* env)
{
SocketTArray opts = TARRAY_CREATE(128);
ERL_NIF_TERM tmp, optsL;
- /* *** SOCKET_OPT_SOCK_ACCEPTCONN => SO_ACCEPTCONN *** */
+ /* *** ESOCK_OPT_SOCK_ACCEPTCONN => SO_ACCEPTCONN *** */
#if defined(SO_ACCEPTCONN)
tmp = MKT2(env, esock_atom_acceptconn, esock_atom_true);
#else
@@ -3552,12 +3557,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_ACCEPTFILTER => SO_ACCEPTFILTER *** */
+ /* *** ESOCK_OPT_SOCK_ACCEPTFILTER => SO_ACCEPTFILTER *** */
tmp = MKT2(env, esock_atom_acceptfilter, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_BINDTODEVICE => SO_BINDTODEVICE *** */
+ /* *** ESOCK_OPT_SOCK_BINDTODEVICE => SO_BINDTODEVICE *** */
#if defined(SO_BINDTODEVICE)
tmp = MKT2(env, esock_atom_bindtodevice, esock_atom_true);
#else
@@ -3566,7 +3571,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_BROADCAST => SO_BROADCAST *** */
+ /* *** ESOCK_OPT_SOCK_BROADCAST => SO_BROADCAST *** */
#if defined(SO_BROADCAST)
tmp = MKT2(env, esock_atom_broadcast, esock_atom_true);
#else
@@ -3575,12 +3580,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_BUSY_POLL => SO_BUSY_POLL *** */
+ /* *** ESOCK_OPT_SOCK_BUSY_POLL => SO_BUSY_POLL *** */
tmp = MKT2(env, esock_atom_busy_poll, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_DEBUG => SO_DEBUG *** */
+ /* *** ESOCK_OPT_SOCK_DEBUG => SO_DEBUG *** */
#if defined(SO_DEBUG)
tmp = MKT2(env, esock_atom_debug, esock_atom_true);
#else
@@ -3589,7 +3594,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_DOMAIN => SO_DOMAIN *** */
+ /* *** ESOCK_OPT_SOCK_DOMAIN => SO_DOMAIN *** */
#if defined(SO_DOMAIN)
tmp = MKT2(env, esock_atom_domain, esock_atom_true);
#else
@@ -3598,7 +3603,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_DONTROUTE => SO_DONTROUTE *** */
+ /* *** ESOCK_OPT_SOCK_DONTROUTE => SO_DONTROUTE *** */
#if defined(SO_DONTROUTE)
tmp = MKT2(env, esock_atom_dontroute, esock_atom_true);
#else
@@ -3607,12 +3612,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_ERROR => SO_ERROR *** */
+ /* *** ESOCK_OPT_SOCK_ERROR => SO_ERROR *** */
tmp = MKT2(env, esock_atom_error, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_KEEPALIVE => SO_KEEPALIVE *** */
+ /* *** ESOCK_OPT_SOCK_KEEPALIVE => SO_KEEPALIVE *** */
#if defined(SO_KEEPALIVE)
tmp = MKT2(env, esock_atom_keepalive, esock_atom_true);
#else
@@ -3621,7 +3626,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_LINGER => SO_LINGER *** */
+ /* *** ESOCK_OPT_SOCK_LINGER => SO_LINGER *** */
#if defined(SO_LINGER)
tmp = MKT2(env, esock_atom_linger, esock_atom_true);
#else
@@ -3630,12 +3635,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_MARK => SO_MARK *** */
+ /* *** ESOCK_OPT_SOCK_MARK => SO_MARK *** */
tmp = MKT2(env, esock_atom_mark, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_OOBINLINE => SO_OOBINLINE *** */
+ /* *** ESOCK_OPT_SOCK_OOBINLINE => SO_OOBINLINE *** */
#if defined(SO_OOBINLINE)
tmp = MKT2(env, esock_atom_oobinline, esock_atom_true);
#else
@@ -3644,12 +3649,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_PASSCRED => SO_PASSCRED *** */
+ /* *** ESOCK_OPT_PASSCRED => SO_PASSCRED *** */
tmp = MKT2(env, esock_atom_passcred, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_PEEK_OFF => SO_PEEK_OFF *** */
+ /* *** ESOCK_OPT_SOCK_PEEK_OFF => SO_PEEK_OFF *** */
#if defined(SO_PEEK_OFF)
tmp = MKT2(env, esock_atom_peek_off, esock_atom_true);
#else
@@ -3658,12 +3663,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_PEEKCRED => SO_PEEKCRED *** */
+ /* *** ESOCK_OPT_SOCK_PEEKCRED => SO_PEEKCRED *** */
tmp = MKT2(env, esock_atom_peekcred, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_PRIORITY => SO_PRIORITY *** */
+ /* *** ESOCK_OPT_SOCK_PRIORITY => SO_PRIORITY *** */
#if defined(SO_PRIORITY)
tmp = MKT2(env, esock_atom_priority, esock_atom_true);
#else
@@ -3672,7 +3677,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_PROTOCOL => SO_PROTOCOL *** */
+ /* *** ESOCK_OPT_SOCK_PROTOCOL => SO_PROTOCOL *** */
#if defined(SO_PROTOCOL)
tmp = MKT2(env, esock_atom_protocol, esock_atom_true);
#else
@@ -3681,7 +3686,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_RCVBUF => SO_RCVBUF *** */
+ /* *** ESOCK_OPT_SOCK_RCVBUF => SO_RCVBUF *** */
#if defined(SO_RCVBUF)
tmp = MKT2(env, esock_atom_rcvbuf, esock_atom_true);
#else
@@ -3690,12 +3695,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_RCVBUFFORCE => SO_RCVBUFFORCE *** */
+ /* *** ESOCK_OPT_SOCK_RCVBUFFORCE => SO_RCVBUFFORCE *** */
tmp = MKT2(env, esock_atom_rcvbufforce, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_RCVLOWAT => SO_RCVLOWAT *** */
+ /* *** ESOCK_OPT_SOCK_RCVLOWAT => SO_RCVLOWAT *** */
#if defined(SO_RCVLOWAT)
tmp = MKT2(env, esock_atom_rcvlowat, esock_atom_true);
#else
@@ -3704,7 +3709,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_RCVTIMEO => SO_RCVTIMEO *** */
+ /* *** ESOCK_OPT_SOCK_RCVTIMEO => SO_RCVTIMEO *** */
#if defined(SO_RCVTIMEO)
tmp = MKT2(env, esock_atom_rcvtimeo, esock_atom_true);
#else
@@ -3713,7 +3718,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_REUSEADDR => SO_REUSEADDR *** */
+ /* *** ESOCK_OPT_SOCK_REUSEADDR => SO_REUSEADDR *** */
#if defined(SO_REUSEADDR)
tmp = MKT2(env, esock_atom_reuseaddr, esock_atom_true);
#else
@@ -3722,7 +3727,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_REUSEPORT => SO_REUSEPORT *** */
+ /* *** ESOCK_OPT_SOCK_REUSEPORT => SO_REUSEPORT *** */
#if defined(SO_REUSEPORT)
tmp = MKT2(env, esock_atom_reuseport, esock_atom_true);
#else
@@ -3731,17 +3736,17 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_RXQ_OVFL => SO_RXQ_OVFL *** */
+ /* *** ESOCK_OPT_SOCK_RXQ_OVFL => SO_RXQ_OVFL *** */
tmp = MKT2(env, esock_atom_rxq_ovfl, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_SETFIB => SO_SETFIB *** */
+ /* *** ESOCK_OPT_SOCK_SETFIB => SO_SETFIB *** */
tmp = MKT2(env, esock_atom_setfib, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_SNDBUF => SO_SNDBUF *** */
+ /* *** ESOCK_OPT_SOCK_SNDBUF => SO_SNDBUF *** */
#if defined(SO_SNDBUF)
tmp = MKT2(env, esock_atom_sndbuf, esock_atom_true);
#else
@@ -3750,12 +3755,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_SNDBUFFORCE => SO_SNDBUFFORCE *** */
+ /* *** ESOCK_OPT_SOCK_SNDBUFFORCE => SO_SNDBUFFORCE *** */
tmp = MKT2(env, esock_atom_sndbufforce, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_SNDLOWAT => SO_SNDLOWAT *** */
+ /* *** ESOCK_OPT_SOCK_SNDLOWAT => SO_SNDLOWAT *** */
#if defined(SO_SNDLOWAT)
tmp = MKT2(env, esock_atom_sndlowat, esock_atom_true);
#else
@@ -3764,7 +3769,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_SNDTIMEO => SO_SNDTIMEO *** */
+ /* *** ESOCK_OPT_SOCK_SNDTIMEO => SO_SNDTIMEO *** */
#if defined(SO_SNDTIMEO)
tmp = MKT2(env, esock_atom_sndtimeo, esock_atom_true);
#else
@@ -3773,7 +3778,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_TIMESTAMP => SO_TIMESTAMP *** */
+ /* *** ESOCK_OPT_SOCK_TIMESTAMP => SO_TIMESTAMP *** */
#if defined(SO_TIMESTAMP)
tmp = MKT2(env, esock_atom_timestamp, esock_atom_true);
#else
@@ -3782,7 +3787,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SOCK_TYPE => SO_TYPE *** */
+ /* *** ESOCK_OPT_SOCK_TYPE => SO_TYPE *** */
#if defined(SO_TYPE)
tmp = MKT2(env, esock_atom_type, esock_atom_true);
#else
@@ -3801,13 +3806,13 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_options_ip(ErlNifEnv* env)
{
SocketTArray opts = TARRAY_CREATE(128);
ERL_NIF_TERM tmp, optsL;
- /* *** SOCKET_OPT_IP_ADD_MEMBERSHIP => IP_ADD_MEMBERSHIP *** */
+ /* *** ESOCK_OPT_IP_ADD_MEMBERSHIP => IP_ADD_MEMBERSHIP *** */
#if defined(IP_ADD_MEMBERSHIP)
tmp = MKT2(env, esock_atom_add_membership, esock_atom_true);
#else
@@ -3816,7 +3821,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP => IP_ADD_SOURCE_MEMBERSHIP *** */
+ /* *** ESOCK_OPT_IP_ADD_SOURCE_MEMBERSHIP => IP_ADD_SOURCE_MEMBERSHIP *** */
#if defined(IP_ADD_SOURCE_MEMBERSHIP)
tmp = MKT2(env, esock_atom_add_source_membership, esock_atom_true);
#else
@@ -3825,7 +3830,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_BLOCK_SOURCE => IP_BLOCK_SOURCE *** */
+ /* *** ESOCK_OPT_IP_BLOCK_SOURCE => IP_BLOCK_SOURCE *** */
#if defined(IP_BLOCK_SOURCE)
tmp = MKT2(env, esock_atom_block_source, esock_atom_true);
#else
@@ -3834,12 +3839,12 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_DONTFRAG => IP_DONTFRAG *** */
+ /* *** ESOCK_OPT_IP_DONTFRAG => IP_DONTFRAG *** */
tmp = MKT2(env, esock_atom_dontfrag, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_DROP_MEMBERSHIP => IP_DROP_MEMBERSHIP *** */
+ /* *** ESOCK_OPT_IP_DROP_MEMBERSHIP => IP_DROP_MEMBERSHIP *** */
#if defined(IP_DROP_MEMBERSHIP)
tmp = MKT2(env, esock_atom_drop_membership, esock_atom_true);
#else
@@ -3848,7 +3853,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP => IP_DROP_SOURCE_MEMBERSHIP *** */
+ /* *** ESOCK_OPT_IP_DROP_SOURCE_MEMBERSHIP => IP_DROP_SOURCE_MEMBERSHIP *** */
#if defined(IP_DROP_SOURCE_MEMBERSHIP)
tmp = MKT2(env, esock_atom_drop_source_membership, esock_atom_true);
#else
@@ -3857,7 +3862,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_FREEBIND => IP_FREEBIND *** */
+ /* *** ESOCK_OPT_IP_FREEBIND => IP_FREEBIND *** */
#if defined(IP_FREEBIND)
tmp = MKT2(env, esock_atom_freebind, esock_atom_true);
#else
@@ -3866,7 +3871,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_HDRINCL => IP_HDRINCL *** */
+ /* *** ESOCK_OPT_IP_HDRINCL => IP_HDRINCL *** */
#if defined(IP_HDRINCL)
tmp = MKT2(env, esock_atom_hdrincl, esock_atom_true);
#else
@@ -3875,7 +3880,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MINTTL => IP_MINTTL *** */
+ /* *** ESOCK_OPT_IP_MINTTL => IP_MINTTL *** */
#if defined(IP_MINTTL)
tmp = MKT2(env, esock_atom_minttl, esock_atom_true);
#else
@@ -3884,7 +3889,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MSFILTER => IP_MSFILTER / IP_MSFILTER_SIZE *** */
+ /* *** ESOCK_OPT_IP_MSFILTER => IP_MSFILTER / IP_MSFILTER_SIZE *** */
#if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE)
tmp = MKT2(env, esock_atom_msfilter, esock_atom_true);
#else
@@ -3893,12 +3898,12 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MTU => IP_MTU *** */
+ /* *** ESOCK_OPT_IP_MTU => IP_MTU *** */
tmp = MKT2(env, esock_atom_mtu, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MTU_DISCOVER => IP_MTU_DISCOVER *** */
+ /* *** ESOCK_OPT_IP_MTU_DISCOVER => IP_MTU_DISCOVER *** */
#if defined(IP_MTU_DISCOVER)
tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_true);
#else
@@ -3907,7 +3912,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MULTICAST_ALL => IP_MULTICAST_ALL *** */
+ /* *** ESOCK_OPT_IP_MULTICAST_ALL => IP_MULTICAST_ALL *** */
#if defined(IP_MULTICAST_ALL)
tmp = MKT2(env, esock_atom_multicast_all, esock_atom_true);
#else
@@ -3916,7 +3921,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MULTICAST_IF => IP_MULTICAST_IF *** */
+ /* *** ESOCK_OPT_IP_MULTICAST_IF => IP_MULTICAST_IF *** */
#if defined(IP_MULTICAST_IF)
tmp = MKT2(env, esock_atom_multicast_if, esock_atom_true);
#else
@@ -3925,7 +3930,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MULTICAST_LOOP => IP_MULTICAST_LOOP *** */
+ /* *** ESOCK_OPT_IP_MULTICAST_LOOP => IP_MULTICAST_LOOP *** */
#if defined(IP_MULTICAST_LOOP)
tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_true);
#else
@@ -3934,7 +3939,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_MULTICAST_TTL => IP_MULTICAST_TTL *** */
+ /* *** ESOCK_OPT_IP_MULTICAST_TTL => IP_MULTICAST_TTL *** */
#if defined(IP_MULTICAST_TTL)
tmp = MKT2(env, esock_atom_multicast_ttl, esock_atom_true);
#else
@@ -3943,7 +3948,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_NODEFRAG => IP_NODEFRAG *** */
+ /* *** ESOCK_OPT_IP_NODEFRAG => IP_NODEFRAG *** */
#if defined(IP_NODEFRAG)
tmp = MKT2(env, esock_atom_nodefrag, esock_atom_true);
#else
@@ -3952,12 +3957,12 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_OPTIONS => IP_OPTIONS *** */
+ /* *** ESOCK_OPT_IP_OPTIONS => IP_OPTIONS *** */
tmp = MKT2(env, esock_atom_options, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_PKTINFO => IP_PKTINFO *** */
+ /* *** ESOCK_OPT_IP_PKTINFO => IP_PKTINFO *** */
#if defined(IP_PKTINFO)
tmp = MKT2(env, esock_atom_pktinfo, esock_atom_true);
#else
@@ -3966,7 +3971,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RECVDSTADDR => IP_RECVDSTADDR *** */
+ /* *** ESOCK_OPT_IP_RECVDSTADDR => IP_RECVDSTADDR *** */
#if defined(IP_RECVDSTADDR)
tmp = MKT2(env, esock_atom_recvdstaddr, esock_atom_true);
#else
@@ -3975,7 +3980,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RECVERR => IP_RECVERR *** */
+ /* *** ESOCK_OPT_IP_RECVERR => IP_RECVERR *** */
#if defined(IP_RECVERR)
tmp = MKT2(env, esock_atom_recverr, esock_atom_true);
#else
@@ -3984,7 +3989,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RECVIF => IP_RECVIF *** */
+ /* *** ESOCK_OPT_IP_RECVIF => IP_RECVIF *** */
#if defined(IP_RECVIF)
tmp = MKT2(env, esock_atom_recvif, esock_atom_true);
#else
@@ -3993,7 +3998,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RECVOPTS => IP_RECVOPTS *** */
+ /* *** ESOCK_OPT_IP_RECVOPTS => IP_RECVOPTS *** */
#if defined(IP_RECVOPTS)
tmp = MKT2(env, esock_atom_recvopts, esock_atom_true);
#else
@@ -4002,7 +4007,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RECVORIGDSTADDR => IP_RECVORIGDSTADDR *** */
+ /* *** ESOCK_OPT_IP_RECVORIGDSTADDR => IP_RECVORIGDSTADDR *** */
#if defined(IP_RECVORIGDSTADDR)
tmp = MKT2(env, esock_atom_recvorigdstaddr, esock_atom_true);
#else
@@ -4011,7 +4016,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RECVTOS => IP_RECVTOS *** */
+ /* *** ESOCK_OPT_IP_RECVTOS => IP_RECVTOS *** */
#if defined(IP_RECVTOS)
tmp = MKT2(env, esock_atom_recvtos, esock_atom_true);
#else
@@ -4020,7 +4025,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RECVTTL => IP_RECVTTL *** */
+ /* *** ESOCK_OPT_IP_RECVTTL => IP_RECVTTL *** */
#if defined(IP_RECVTTL)
tmp = MKT2(env, esock_atom_recvttl, esock_atom_true);
#else
@@ -4029,7 +4034,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_RETOPTS => IP_RETOPTS *** */
+ /* *** ESOCK_OPT_IP_RETOPTS => IP_RETOPTS *** */
#if defined(IP_RETOPTS)
tmp = MKT2(env, esock_atom_retopts, esock_atom_true);
#else
@@ -4038,7 +4043,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_ROUTER_ALERT => IP_ROUTER_ALERT *** */
+ /* *** ESOCK_OPT_IP_ROUTER_ALERT => IP_ROUTER_ALERT *** */
#if defined(IP_ROUTER_ALERT)
tmp = MKT2(env, esock_atom_router_alert, esock_atom_true);
#else
@@ -4047,7 +4052,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_SENDSRCADDR => IP_SENDSRCADDR *** */
+ /* *** ESOCK_OPT_IP_SENDSRCADDR => IP_SENDSRCADDR *** */
#if defined(IP_SENDSRCADDR)
tmp = MKT2(env, esock_atom_sendsrcaddr, esock_atom_true);
#else
@@ -4056,7 +4061,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_TOS => IP_TOS *** */
+ /* *** ESOCK_OPT_IP_TOS => IP_TOS *** */
#if defined(IP_TOS)
tmp = MKT2(env, esock_atom_tos, esock_atom_true);
#else
@@ -4065,7 +4070,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_TRANSPARENT => IP_TRANSPARENT *** */
+ /* *** ESOCK_OPT_IP_TRANSPARENT => IP_TRANSPARENT *** */
#if defined(IP_TRANSPARENT)
tmp = MKT2(env, esock_atom_transparent, esock_atom_true);
#else
@@ -4074,7 +4079,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_TTL => IP_TTL *** */
+ /* *** ESOCK_OPT_IP_TTL => IP_TTL *** */
#if defined(IP_TTL)
tmp = MKT2(env, esock_atom_ttl, esock_atom_true);
#else
@@ -4083,7 +4088,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IP_UNBLOCK_SOURCE => IP_UNBLOCK_SOURCE *** */
+ /* *** ESOCK_OPT_IP_UNBLOCK_SOURCE => IP_UNBLOCK_SOURCE *** */
#if defined(IP_UNBLOCK_SOURCE)
tmp = MKT2(env, esock_atom_unblock_source, esock_atom_true);
#else
@@ -4102,13 +4107,13 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_options_ipv6(ErlNifEnv* env)
{
SocketTArray opts = TARRAY_CREATE(128);
ERL_NIF_TERM tmp, optsL;
- /* *** SOCKET_OPT_IPV6_ADDRFORM => IPV6_ADDRFORM *** */
+ /* *** ESOCK_OPT_IPV6_ADDRFORM => IPV6_ADDRFORM *** */
#if defined(IPV6_ADDRFORM)
tmp = MKT2(env, esock_atom_addrform, esock_atom_true);
#else
@@ -4117,7 +4122,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_ADD_MEMBERSHIP => IPV6_ADD_MEMBERSHIP *** */
+ /* *** ESOCK_OPT_IPV6_ADD_MEMBERSHIP => IPV6_ADD_MEMBERSHIP *** */
#if defined(IPV6_ADD_MEMBERSHIP)
tmp = MKT2(env, esock_atom_add_membership, esock_atom_true);
#else
@@ -4126,7 +4131,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_AUTHHDR => IPV6_AUTHHDR *** */
+ /* *** ESOCK_OPT_IPV6_AUTHHDR => IPV6_AUTHHDR *** */
#if defined(IPV6_AUTHHDR)
tmp = MKT2(env, esock_atom_authhdr, esock_atom_true);
#else
@@ -4135,17 +4140,17 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_AUTH_LEVEL => IPV6_AUTH_LEVEL *** */
+ /* *** ESOCK_OPT_IPV6_AUTH_LEVEL => IPV6_AUTH_LEVEL *** */
tmp = MKT2(env, esock_atom_auth_level, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_CHECKSUM => IPV6_CHECKSUM *** */
+ /* *** ESOCK_OPT_IPV6_CHECKSUM => IPV6_CHECKSUM *** */
tmp = MKT2(env, esock_atom_checksum, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_DROP_MEMBERSHIP => IPV6_DROP_MEMBERSHIP *** */
+ /* *** ESOCK_OPT_IPV6_DROP_MEMBERSHIP => IPV6_DROP_MEMBERSHIP *** */
#if defined(IPV6_DROP_MEMBERSHIP)
tmp = MKT2(env, esock_atom_drop_membership, esock_atom_true);
#else
@@ -4154,7 +4159,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_DSTOPTS => IPV6_DSTOPTS *** */
+ /* *** ESOCK_OPT_IPV6_DSTOPTS => IPV6_DSTOPTS *** */
#if defined(IPV6_DSTOPTS)
tmp = MKT2(env, esock_atom_dstopts, esock_atom_true);
#else
@@ -4163,22 +4168,22 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL => IPV6_ESP_NETWORK_LEVEL *** */
+ /* *** ESOCK_OPT_IPV6_ESP_NETWORK_LEVEL => IPV6_ESP_NETWORK_LEVEL *** */
tmp = MKT2(env, esock_atom_esp_network_level, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_ESP_TRANS_LEVEL => IPV6_ESP_TRANS_LEVEL *** */
+ /* *** ESOCK_OPT_IPV6_ESP_TRANS_LEVEL => IPV6_ESP_TRANS_LEVEL *** */
tmp = MKT2(env, esock_atom_esp_trans_level, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_FAITH => IPV6_FAITH *** */
+ /* *** ESOCK_OPT_IPV6_FAITH => IPV6_FAITH *** */
tmp = MKT2(env, esock_atom_faith, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_FLOWINFO => IPV6_FLOWINFO *** */
+ /* *** ESOCK_OPT_IPV6_FLOWINFO => IPV6_FLOWINFO *** */
#if defined(IPV6_FLOWINFO)
tmp = MKT2(env, esock_atom_flowinfo, esock_atom_true);
#else
@@ -4187,7 +4192,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_HOPLIMIT => IPV6_HOPLIMIT *** */
+ /* *** ESOCK_OPT_IPV6_HOPLIMIT => IPV6_HOPLIMIT *** */
#if defined(IPV6_HOPLIMIT)
tmp = MKT2(env, esock_atom_hoplimit, esock_atom_true);
#else
@@ -4196,7 +4201,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_HOPOPTS => IPV6_HOPOPTS *** */
+ /* *** ESOCK_OPT_IPV6_HOPOPTS => IPV6_HOPOPTS *** */
#if defined(IPV6_HOPOPTS)
tmp = MKT2(env, esock_atom_hopopts, esock_atom_true);
#else
@@ -4205,22 +4210,22 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_IPCOMP_LEVEL => IPV6_IPCOMP_LEVEL *** */
+ /* *** ESOCK_OPT_IPV6_IPCOMP_LEVEL => IPV6_IPCOMP_LEVEL *** */
tmp = MKT2(env, esock_atom_ipcomp_level, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_JOIN_GROUP => IPV6_JOIN_GROUP *** */
+ /* *** ESOCK_OPT_IPV6_JOIN_GROUP => IPV6_JOIN_GROUP *** */
tmp = MKT2(env, esock_atom_join_group, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_LEAVE_GROUP => IPV6_LEAVE_GROUP *** */
+ /* *** ESOCK_OPT_IPV6_LEAVE_GROUP => IPV6_LEAVE_GROUP *** */
tmp = MKT2(env, esock_atom_leave_group, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_MTU => IPV6_MTU *** */
+ /* *** ESOCK_OPT_IPV6_MTU => IPV6_MTU *** */
#if defined(IPV6_MTU)
tmp = MKT2(env, esock_atom_mtu, esock_atom_true);
#else
@@ -4229,7 +4234,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_MTU_DISCOVER => IPV6_MTU_DISCOVER *** */
+ /* *** ESOCK_OPT_IPV6_MTU_DISCOVER => IPV6_MTU_DISCOVER *** */
#if defined(IPV6_MTU_DISCOVER)
tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_true);
#else
@@ -4238,7 +4243,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_MULTICAST_HOPS => IPV6_MULTICAST_HOPS *** */
+ /* *** ESOCK_OPT_IPV6_MULTICAST_HOPS => IPV6_MULTICAST_HOPS *** */
#if defined(IPV6_MULTICAST_HOPS)
tmp = MKT2(env, esock_atom_multicast_hops, esock_atom_true);
#else
@@ -4247,7 +4252,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_MULTICAST_IF => IPV6_MULTICAST_IF *** */
+ /* *** ESOCK_OPT_IPV6_MULTICAST_IF => IPV6_MULTICAST_IF *** */
#if defined(IPV6_MULTICAST_IF)
tmp = MKT2(env, esock_atom_multicast_if, esock_atom_true);
#else
@@ -4256,7 +4261,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_MULTICAST_LOOP => IPV6_MULTICAST_LOOP *** */
+ /* *** ESOCK_OPT_IPV6_MULTICAST_LOOP => IPV6_MULTICAST_LOOP *** */
#if defined(IPV6_MULTICAST_LOOP)
tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_true);
#else
@@ -4265,17 +4270,17 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_PORTRANGE => IPV6_PORTRANGE *** */
+ /* *** ESOCK_OPT_IPV6_PORTRANGE => IPV6_PORTRANGE *** */
tmp = MKT2(env, esock_atom_portrange, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_PKTOPTIONS => IPV6_PKTOPTIONS *** */
+ /* *** ESOCK_OPT_IPV6_PKTOPTIONS => IPV6_PKTOPTIONS *** */
tmp = MKT2(env, esock_atom_pktoptions, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_RECVERR => IPV6_RECVERR *** */
+ /* *** ESOCK_OPT_IPV6_RECVERR => IPV6_RECVERR *** */
#if defined(IPV6_RECVERR)
tmp = MKT2(env, esock_atom_recverr, esock_atom_true);
#else
@@ -4284,7 +4289,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_RECVPKTINFO => IPV6_RECVPKTINFO *** */
+ /* *** ESOCK_OPT_IPV6_RECVPKTINFO => IPV6_RECVPKTINFO *** */
#if defined(IPV6_RECVPKTINFO)
tmp = MKT2(env, esock_atom_recvpktinfo, esock_atom_true);
#else
@@ -4293,12 +4298,12 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_RECVTCLASS => IPV6_RECVTCLASS *** */
+ /* *** ESOCK_OPT_IPV6_RECVTCLASS => IPV6_RECVTCLASS *** */
tmp = MKT2(env, esock_atom_recvtclass, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_ROUTER_ALERT => IPV6_ROUTER_ALERT *** */
+ /* *** ESOCK_OPT_IPV6_ROUTER_ALERT => IPV6_ROUTER_ALERT *** */
#if defined(IPV6_ROUTER_ALERT)
tmp = MKT2(env, esock_atom_router_alert, esock_atom_true);
#else
@@ -4307,7 +4312,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_RTHDR => IPV6_RTHDR *** */
+ /* *** ESOCK_OPT_IPV6_RTHDR => IPV6_RTHDR *** */
#if defined(IPV6_RTHDR)
tmp = MKT2(env, esock_atom_rthdr, esock_atom_true);
#else
@@ -4316,12 +4321,12 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_TCLASS => IPV6_TCLASS *** */
+ /* *** ESOCK_OPT_IPV6_TCLASS => IPV6_TCLASS *** */
tmp = MKT2(env, esock_atom_tclass, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_UNICAST_HOPS => IPV6_UNICAST_HOPS *** */
+ /* *** ESOCK_OPT_IPV6_UNICAST_HOPS => IPV6_UNICAST_HOPS *** */
#if defined(IPV6_UNICAST_HOPS)
tmp = MKT2(env, esock_atom_unicast_hops, esock_atom_true);
#else
@@ -4330,12 +4335,12 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_USE_MIN_MTU => IPV6_USE_MIN_MTU *** */
+ /* *** ESOCK_OPT_IPV6_USE_MIN_MTU => IPV6_USE_MIN_MTU *** */
tmp = MKT2(env, esock_atom_use_min_mtu, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_IPV6_V6ONLY => IPV6_V6ONLY *** */
+ /* *** ESOCK_OPT_IPV6_V6ONLY => IPV6_V6ONLY *** */
#if defined(IPV6_V6ONLY)
tmp = MKT2(env, esock_atom_v6only, esock_atom_true);
#else
@@ -4354,13 +4359,13 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_options_tcp(ErlNifEnv* env)
{
SocketTArray opts = TARRAY_CREATE(32);
ERL_NIF_TERM tmp, optsL;
- /* *** SOCKET_OPT_TCP_CONGESTION => TCP_CONGESTION *** */
+ /* *** ESOCK_OPT_TCP_CONGESTION => TCP_CONGESTION *** */
#if defined(TCP_CONGESTION)
tmp = MKT2(env, esock_atom_congestion, esock_atom_true);
#else
@@ -4369,7 +4374,7 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_CORK => TCP_CORK *** */
+ /* *** ESOCK_OPT_TCP_CORK => TCP_CORK *** */
#if defined(TCP_CORK)
tmp = MKT2(env, esock_atom_cork, esock_atom_true);
#else
@@ -4378,27 +4383,27 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_INFO => TCP_INFO *** */
+ /* *** ESOCK_OPT_TCP_INFO => TCP_INFO *** */
tmp = MKT2(env, esock_atom_info, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_KEEPCNT => TCP_KEEPCNT *** */
+ /* *** ESOCK_OPT_TCP_KEEPCNT => TCP_KEEPCNT *** */
tmp = MKT2(env, esock_atom_keepcnt, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_KEEPIDLE => TCP_KEEPIDLE *** */
+ /* *** ESOCK_OPT_TCP_KEEPIDLE => TCP_KEEPIDLE *** */
tmp = MKT2(env, esock_atom_keepidle, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_KEEPINTVL => TCP_KEEPINTVL *** */
+ /* *** ESOCK_OPT_TCP_KEEPINTVL => TCP_KEEPINTVL *** */
tmp = MKT2(env, esock_atom_keepintvl, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_MAXSEG => TCP_MAXSEG *** */
+ /* *** ESOCK_OPT_TCP_MAXSEG => TCP_MAXSEG *** */
#if defined(TCP_MAXSEG)
tmp = MKT2(env, esock_atom_maxseg, esock_atom_true);
#else
@@ -4407,12 +4412,12 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_MD5SIG => TCP_MD5SIG *** */
+ /* *** ESOCK_OPT_TCP_MD5SIG => TCP_MD5SIG *** */
tmp = MKT2(env, esock_atom_md5sig, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_NODELAY => TCP_NODELAY *** */
+ /* *** ESOCK_OPT_TCP_NODELAY => TCP_NODELAY *** */
#if defined(TCP_NODELAY)
tmp = MKT2(env, esock_atom_nodelay, esock_atom_true);
#else
@@ -4421,22 +4426,22 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_NOOPT => TCP_NOOPT *** */
+ /* *** ESOCK_OPT_TCP_NOOPT => TCP_NOOPT *** */
tmp = MKT2(env, esock_atom_noopt, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_NOPUSH => TCP_NOPUSH *** */
+ /* *** ESOCK_OPT_TCP_NOPUSH => TCP_NOPUSH *** */
tmp = MKT2(env, esock_atom_nopush, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_SYNCNT => TCP_SYNCNT *** */
+ /* *** ESOCK_OPT_TCP_SYNCNT => TCP_SYNCNT *** */
tmp = MKT2(env, esock_atom_syncnt, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_TCP_USER_TIMEOUT => TCP_USER_TIMEOUT *** */
+ /* *** ESOCK_OPT_TCP_USER_TIMEOUT => TCP_USER_TIMEOUT *** */
tmp = MKT2(env, esock_atom_user_timeout, esock_atom_false);
TARRAY_ADD(opts, tmp);
@@ -4451,13 +4456,13 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_options_udp(ErlNifEnv* env)
{
SocketTArray opts = TARRAY_CREATE(8);
ERL_NIF_TERM tmp, optsL;
- /* *** SOCKET_OPT_UDP_CORK => UDP_CORK *** */
+ /* *** ESOCK_OPT_UDP_CORK => UDP_CORK *** */
#if defined(UDP_CORK)
tmp = MKT2(env, esock_atom_cork, esock_atom_true);
#else
@@ -4476,18 +4481,18 @@ ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_options_sctp(ErlNifEnv* env)
{
SocketTArray opts = TARRAY_CREATE(64);
ERL_NIF_TERM tmp, optsL;
- /* *** SOCKET_OPT_SCTP_ADAPTION_LAYER => SCTP_ADAPTION_LAYER *** */
+ /* *** ESOCK_OPT_SCTP_ADAPTION_LAYER => SCTP_ADAPTION_LAYER *** */
tmp = MKT2(env, esock_atom_adaption_layer, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_ASSOCINFO => SCTP_ASSOCINFO *** */
+ /* *** ESOCK_OPT_SCTP_ASSOCINFO => SCTP_ASSOCINFO *** */
#if defined(SCTP_ASSOCINFO)
tmp = MKT2(env, esock_atom_associnfo, esock_atom_true);
#else
@@ -4496,32 +4501,32 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_AUTH_ACTIVE_KEY => SCTP_AUTH_ACTIVE_KEY *** */
+ /* *** ESOCK_OPT_SCTP_AUTH_ACTIVE_KEY => SCTP_AUTH_ACTIVE_KEY *** */
tmp = MKT2(env, esock_atom_auth_active_key, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_AUTH_ASCONF => SCTP_AUTH_ASCONF *** */
+ /* *** ESOCK_OPT_SCTP_AUTH_ASCONF => SCTP_AUTH_ASCONF *** */
tmp = MKT2(env, esock_atom_auth_asconf, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_AUTH_CHUNK => SCTP_AUTH_CHUNK *** */
+ /* *** ESOCK_OPT_SCTP_AUTH_CHUNK => SCTP_AUTH_CHUNK *** */
tmp = MKT2(env, esock_atom_auth_chunk, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_AUTH_DELETE_KEY => SCTP_AUTH_DELETE_KEY *** */
+ /* *** ESOCK_OPT_SCTP_AUTH_DELETE_KEY => SCTP_AUTH_DELETE_KEY *** */
tmp = MKT2(env, esock_atom_auth_delete_key, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_AUTH_KEY => SCTP_AUTH_KEY *** */
+ /* *** ESOCK_OPT_SCTP_AUTH_KEY => SCTP_AUTH_KEY *** */
tmp = MKT2(env, esock_atom_auth_key, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_AUTOCLOSE => SCTP_AUTOCLOSE *** */
+ /* *** ESOCK_OPT_SCTP_AUTOCLOSE => SCTP_AUTOCLOSE *** */
#if defined(SCTP_AUTOCLOSE)
tmp = MKT2(env, esock_atom_autoclose, esock_atom_true);
#else
@@ -4530,22 +4535,22 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_CONTEXT => SCTP_CONTEXT *** */
+ /* *** ESOCK_OPT_SCTP_CONTEXT => SCTP_CONTEXT *** */
tmp = MKT2(env, esock_atom_context, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_DEFAULT_SEND_PARAMS => SCTP_DEFAULT_SEND_PARAMS *** */
+ /* *** ESOCK_OPT_SCTP_DEFAULT_SEND_PARAMS => SCTP_DEFAULT_SEND_PARAMS *** */
tmp = MKT2(env, esock_atom_default_send_params, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_DELAYED_ACK_TIME => SCTP_DELAYED_ACK_TIME *** */
+ /* *** ESOCK_OPT_SCTP_DELAYED_ACK_TIME => SCTP_DELAYED_ACK_TIME *** */
tmp = MKT2(env, esock_atom_delayed_ack_time, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_DISABLE_FRAGMENTS => SCTP_DISABLE_FRAGMENTS *** */
+ /* *** ESOCK_OPT_SCTP_DISABLE_FRAGMENTS => SCTP_DISABLE_FRAGMENTS *** */
#if defined(SCTP_DISABLE_FRAGMENTS)
tmp = MKT2(env, esock_atom_disable_fragments, esock_atom_true);
#else
@@ -4554,12 +4559,12 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_HMAC_IDENT => SCTP_HMAC_IDENT *** */
+ /* *** ESOCK_OPT_SCTP_HMAC_IDENT => SCTP_HMAC_IDENT *** */
tmp = MKT2(env, esock_atom_hmac_ident, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_EVENTS => SCTP_EVENTS *** */
+ /* *** ESOCK_OPT_SCTP_EVENTS => SCTP_EVENTS *** */
#if defined(SCTP_EVENTS)
tmp = MKT2(env, esock_atom_events, esock_atom_true);
#else
@@ -4568,22 +4573,22 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_EXPLICIT_EOR => SCTP_EXPLICIT_EOR *** */
+ /* *** ESOCK_OPT_SCTP_EXPLICIT_EOR => SCTP_EXPLICIT_EOR *** */
tmp = MKT2(env, esock_atom_explicit_eor, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_FRAGMENT_INTERLEAVE => SCTP_FRAGMENT_INTERLEAVE *** */
+ /* *** ESOCK_OPT_SCTP_FRAGMENT_INTERLEAVE => SCTP_FRAGMENT_INTERLEAVE *** */
tmp = MKT2(env, esock_atom_fragment_interleave, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_GET_PEER_ADDR_INFO => SCTP_GET_PEER_ADDR_INFO *** */
+ /* *** ESOCK_OPT_SCTP_GET_PEER_ADDR_INFO => SCTP_GET_PEER_ADDR_INFO *** */
tmp = MKT2(env, esock_atom_get_peer_addr_info, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_INITMSG => SCTP_INITMSG *** */
+ /* *** ESOCK_OPT_SCTP_INITMSG => SCTP_INITMSG *** */
#if defined(SCTP_INITMSG)
tmp = MKT2(env, esock_atom_initmsg, esock_atom_true);
#else
@@ -4592,17 +4597,17 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_I_WANT_MAPPED_V4_ADDR => SCTP_I_WANT_MAPPED_V4_ADDR *** */
+ /* *** ESOCK_OPT_SCTP_I_WANT_MAPPED_V4_ADDR => SCTP_I_WANT_MAPPED_V4_ADDR *** */
tmp = MKT2(env, esock_atom_i_want_mapped_v4_addr, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_LOCAL_AUTH_CHUNKS => SCTP_LOCAL_AUTH_CHUNKS *** */
+ /* *** ESOCK_OPT_SCTP_LOCAL_AUTH_CHUNKS => SCTP_LOCAL_AUTH_CHUNKS *** */
tmp = MKT2(env, esock_atom_local_auth_chunks, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_MAXSEG => SCTP_MAXSEG *** */
+ /* *** ESOCK_OPT_SCTP_MAXSEG => SCTP_MAXSEG *** */
#if defined(SCTP_MAXSEG)
tmp = MKT2(env, esock_atom_maxseg, esock_atom_true);
#else
@@ -4611,12 +4616,12 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_MAXBURST => SCTP_MAXBURST *** */
+ /* *** ESOCK_OPT_SCTP_MAXBURST => SCTP_MAXBURST *** */
tmp = MKT2(env, esock_atom_maxburst, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_NODELAY => SCTP_NODELAY *** */
+ /* *** ESOCK_OPT_SCTP_NODELAY => SCTP_NODELAY *** */
#if defined(SCTP_NODELAY)
tmp = MKT2(env, esock_atom_nodelay, esock_atom_true);
#else
@@ -4625,32 +4630,32 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_PARTIAL_DELIVERY_POINT => SCTP_PARTIAL_DELIVERY_POINT *** */
+ /* *** ESOCK_OPT_SCTP_PARTIAL_DELIVERY_POINT => SCTP_PARTIAL_DELIVERY_POINT *** */
tmp = MKT2(env, esock_atom_partial_delivery_point, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_PEER_ADDR_PARAMS => SCTP_PEER_ADDR_PARAMS *** */
+ /* *** ESOCK_OPT_SCTP_PEER_ADDR_PARAMS => SCTP_PEER_ADDR_PARAMS *** */
tmp = MKT2(env, esock_atom_peer_addr_params, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_PEER_AUTH_CHUNKS => SCTP_PEER_AUTH_CHUNKS *** */
+ /* *** ESOCK_OPT_SCTP_PEER_AUTH_CHUNKS => SCTP_PEER_AUTH_CHUNKS *** */
tmp = MKT2(env, esock_atom_peer_auth_chunks, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_PRIMARY_ADDR => SCTP_PRIMARY_ADDR *** */
+ /* *** ESOCK_OPT_SCTP_PRIMARY_ADDR => SCTP_PRIMARY_ADDR *** */
tmp = MKT2(env, esock_atom_primary_addr, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_RESET_STREAMS => SCTP_RESET_STREAMS *** */
+ /* *** ESOCK_OPT_SCTP_RESET_STREAMS => SCTP_RESET_STREAMS *** */
tmp = MKT2(env, esock_atom_reset_streams, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_RTOINFO => SCTP_RTOINFO *** */
+ /* *** ESOCK_OPT_SCTP_RTOINFO => SCTP_RTOINFO *** */
#if defined(SCTP_RTOINFO)
tmp = MKT2(env, esock_atom_rtoinfo, esock_atom_true);
#else
@@ -4659,17 +4664,17 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_SET_PEER_PRIMARY_ADDR => SCTP_SET_PEER_PRIMARY_ADDR *** */
+ /* *** ESOCK_OPT_SCTP_SET_PEER_PRIMARY_ADDR => SCTP_SET_PEER_PRIMARY_ADDR *** */
tmp = MKT2(env, esock_atom_set_peer_primary_addr, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_STATUS => SCTP_STATUS *** */
+ /* *** ESOCK_OPT_SCTP_STATUS => SCTP_STATUS *** */
tmp = MKT2(env, esock_atom_status, esock_atom_false);
TARRAY_ADD(opts, tmp);
- /* *** SOCKET_OPT_SCTP_USE_EXT_RECVINFO => SCTP_USE_EXT_RECVINFO *** */
+ /* *** ESOCK_OPT_SCTP_USE_EXT_RECVINFO => SCTP_USE_EXT_RECVINFO *** */
tmp = MKT2(env, esock_atom_use_ext_recvinfo, esock_atom_false);
TARRAY_ADD(opts, tmp);
@@ -4684,7 +4689,7 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_sctp(ErlNifEnv* env)
{
ERL_NIF_TERM supports;
@@ -4702,7 +4707,7 @@ ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_ipv6(ErlNifEnv* env)
{
ERL_NIF_TERM supports;
@@ -4721,7 +4726,7 @@ ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env)
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsupports_local(ErlNifEnv* env)
+ERL_NIF_TERM esock_supports_local(ErlNifEnv* env)
{
ERL_NIF_TERM supports;
@@ -4813,7 +4818,7 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env,
#endif
- result = nopen(env, domain, type, proto, netns);
+ result = esock_open(env, domain, type, proto, netns);
SGDBG( ("SOCKET", "nif_open -> done with result: "
"\r\n %T"
@@ -4825,7 +4830,7 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env,
}
-/* nopen - create an endpoint for communication
+/* esock_open - create an endpoint for communication
*
* Assumes the input has been validated.
*
@@ -4836,9 +4841,9 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nopen(ErlNifEnv* env,
- int domain, int type, int protocol,
- char* netns)
+ERL_NIF_TERM esock_open(ErlNifEnv* env,
+ int domain, int type, int protocol,
+ char* netns)
{
ESockDescriptor* descP;
ERL_NIF_TERM res;
@@ -4849,7 +4854,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
int current_ns = 0;
#endif
- SGDBG( ("SOCKET", "nopen -> entry with"
+ SGDBG( ("SOCKET", "esock_open -> entry with"
"\r\n domain: %d"
"\r\n type: %d"
"\r\n protocol: %d"
@@ -4865,7 +4870,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
if ((sock = sock_open(domain, type, proto)) == INVALID_SOCKET)
return esock_make_error_errno(env, sock_errno());
- SGDBG( ("SOCKET", "nopen -> open success: %d\r\n", sock) );
+ SGDBG( ("SOCKET", "esock_open -> open success: %d\r\n", sock) );
/* NOTE that if the protocol = 0 (default) and the domain is not
@@ -4877,7 +4882,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
&& (domain != AF_LOCAL)
#endif
)
- if (!nopen_which_protocol(sock, &proto)) {
+ if (!esock_open_which_protocol(sock, &proto)) {
if (proto == ESOCK_WHICH_PROTO_ERROR) {
save_errno = sock_errno();
while ((sock_close(sock) == INVALID_SOCKET) &&
@@ -4907,7 +4912,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
return esock_make_error_errno(env, save_errno);
}
- SGDBG( ("SOCKET", "nopen -> event success: %d\r\n", event) );
+ SGDBG( ("SOCKET", "esock_open -> event success: %d\r\n", event) );
SET_NONBLOCKING(sock);
@@ -4919,7 +4924,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
return enif_make_badarg(env);
}
- descP->state = SOCKET_STATE_OPEN;
+ descP->state = ESOCK_STATE_OPEN;
descP->domain = domain;
descP->type = type;
descP->protocol = proto;
@@ -4948,7 +4953,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
if (enif_self(env, &descP->ctrlPid) == NULL)
return esock_make_error(env, atom_exself);
- if (MONP("nopen -> ctrl",
+ if (MONP("esock_open -> ctrl",
env, descP,
&descP->ctrlPid,
&descP->ctrlMon) != 0)
@@ -4962,7 +4967,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
static
-BOOLEAN_T nopen_which_protocol(SOCKET sock, int* proto)
+BOOLEAN_T esock_open_which_protocol(SOCKET sock, int* proto)
{
#if defined(SO_PROTOCOL)
int val;
@@ -5121,7 +5126,7 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 2) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) {
return enif_make_badarg(env);
}
eSockAddr = argv[1];
@@ -5138,13 +5143,13 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env,
/* Make sure we are ready
* Not sure how this would even happen, but...
*/
- if (descP->state != SOCKET_STATE_OPEN)
+ if (descP->state != ESOCK_STATE_OPEN)
return esock_make_error(env, atom_exbadstate);
if ((xres = esock_decode_sockaddr(env, eSockAddr, &sockAddr, &addrLen)) != NULL)
return esock_make_error_str(env, xres);
- return nbind(env, descP, &sockAddr, addrLen);
+ return esock_bind(env, descP, &sockAddr, addrLen);
#endif // if defined(__WIN32__)
}
@@ -5152,24 +5157,24 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nbind(ErlNifEnv* env,
- ESockDescriptor* descP,
- ESockAddress* sockAddrP,
- unsigned int addrLen)
+ERL_NIF_TERM esock_bind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ESockAddress* sockAddrP,
+ unsigned int addrLen)
{
int port, ntohs_port;
- SSDBG( descP, ("SOCKET", "nbind -> try bind\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_bind -> try bind\r\n") );
if (IS_SOCKET_ERROR(sock_bind(descP->sock,
(struct sockaddr*) sockAddrP, addrLen))) {
return esock_make_error_errno(env, sock_errno());
}
- SSDBG( descP, ("SOCKET", "nbind -> bound - get port\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_bind -> bound - get port\r\n") );
port = which_address_port(sockAddrP);
- SSDBG( descP, ("SOCKET", "nbind -> port: %d\r\n", port) );
+ SSDBG( descP, ("SOCKET", "esock_bind -> port: %d\r\n", port) );
if (port == 0) {
SOCKLEN_T len = sizeof(ESockAddress);
sys_memzero((char *) sockAddrP, len);
@@ -5181,7 +5186,8 @@ ERL_NIF_TERM nbind(ErlNifEnv* env,
ntohs_port = sock_ntohs(port);
- SSDBG( descP, ("SOCKET", "nbind -> done with port = %d\r\n", ntohs_port) );
+ SSDBG( descP, ("SOCKET",
+ "esock_bind -> done with port = %d\r\n", ntohs_port) );
return esock_make_ok2(env, MKI(env, ntohs_port));
@@ -5221,7 +5227,7 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env,
sockRef = argv[0];
if ((argc != 2) ||
- !enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
eSockAddr = argv[1];
@@ -5248,7 +5254,7 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env,
MLOCK(descP->writeMtx);
MLOCK(descP->cfgMtx);
- res = nconnect(env, descP, sockRef);
+ res = esock_connect(env, descP, sockRef);
MUNLOCK(descP->cfgMtx);
MUNLOCK(descP->writeMtx);
@@ -5262,9 +5268,9 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nconnect(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM esock_connect(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res, ref;
int code, sres, save_errno = 0;
@@ -5277,17 +5283,17 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
return esock_make_error(env, atom_closed);
if (!IS_OPEN(descP)) {
- SSDBG( descP, ("SOCKET", "nconnect -> not open\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_connect -> not open\r\n") );
return esock_make_error(env, atom_exbadstate);
}
if (IS_CONNECTED(descP)) {
- SSDBG( descP, ("SOCKET", "nconnect -> already connected\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_connect -> already connected\r\n") );
return esock_make_error(env, atom_eisconn);
}
if (IS_CONNECTING(descP) && !is_connector(env, descP)) {
- SSDBG( descP, ("SOCKET", "nconnect -> already connecting\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_connect -> already connecting\r\n") );
return esock_make_error(env, esock_atom_einval);
}
@@ -5301,14 +5307,15 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
descP->addrLen);
save_errno = sock_errno();
- SSDBG( descP, ("SOCKET", "nconnect -> connect result: %d, %d\r\n",
+ SSDBG( descP, ("SOCKET", "esock_connect -> connect result: %d, %d\r\n",
code, save_errno) );
if (IS_SOCKET_ERROR(code)) {
switch (save_errno) {
case ERRNO_BLOCK: /* Winsock2 */
case EINPROGRESS: /* Unix & OSE!! */
- SSDBG( descP, ("SOCKET", "nconnect -> would block => select\r\n") );
+ SSDBG( descP, ("SOCKET",
+ "esock_connect -> would block => select\r\n") );
ref = MKREF(env);
@@ -5322,13 +5329,13 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
if (enif_self(env, &descP->connPid) == NULL)
return esock_make_error(env, atom_exself);
- if (MONP("nconnect -> conn",
+ if (MONP("esock_connect -> conn",
env, descP,
&descP->connPid,
&descP->connMon) != 0)
return esock_make_error(env, atom_exmon);
- descP->state = SOCKET_STATE_CONNECTING;
+ descP->state = ESOCK_STATE_CONNECTING;
if ((sres = esock_select_write(env, descP->sock, descP, NULL,
sockRef, ref)) < 0) {
@@ -5343,18 +5350,19 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
break;
case EISCONN:
- SSDBG( descP, ("SOCKET", "nconnect -> *already* connected\r\n") );
+ SSDBG( descP, ("SOCKET",
+ "esock_connect -> *already* connected\r\n") );
{
/* This is ***strange*** so make sure */
int err = 0;
if (!verify_is_connected(descP, &err)) {
- descP->state = SOCKET_STATE_OPEN; /* restore state */
+ descP->state = ESOCK_STATE_OPEN; /* restore state */
res = esock_make_error_errno(env, err);
} else {
- descP->state = SOCKET_STATE_CONNECTED;
+ descP->state = ESOCK_STATE_CONNECTED;
/* And just to be on the safe side, reset these */
enif_set_pid_undefined(&descP->connPid);
- DEMONP("nconnect -> connected",
+ DEMONP("esock_connect -> connected",
env, descP, &descP->connMon);
descP->isReadable = TRUE;
descP->isWritable = TRUE;
@@ -5364,7 +5372,7 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
break;
default:
- SSDBG( descP, ("SOCKET", "nconnect -> other error(1): %d\r\n",
+ SSDBG( descP, ("SOCKET", "esock_connect -> other error(1): %d\r\n",
save_errno) );
res = esock_make_error_errno(env, save_errno);
break;
@@ -5372,11 +5380,11 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
} else if (code == 0) { /* ok we are connected */
- SSDBG( descP, ("SOCKET", "nconnect -> connected\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_connect -> connected\r\n") );
- descP->state = SOCKET_STATE_CONNECTED;
+ descP->state = ESOCK_STATE_CONNECTED;
enif_set_pid_undefined(&descP->connPid);
- DEMONP("nconnect -> connected", env, descP, &descP->connMon);
+ DEMONP("esock_connect -> connected", env, descP, &descP->connMon);
descP->isReadable = TRUE;
descP->isWritable = TRUE;
@@ -5385,7 +5393,7 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env,
} else {
/* Do we really need this case? */
- SSDBG( descP, ("SOCKET", "nconnect -> other error(2): %d\r\n",
+ SSDBG( descP, ("SOCKET", "esock_connect -> other error(2): %d\r\n",
save_errno) );
res = esock_make_error_errno(env, save_errno);
@@ -5422,23 +5430,23 @@ ERL_NIF_TERM nif_finalize_connection(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 1) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) {
return enif_make_badarg(env);
}
- return nfinalize_connection(env, descP);
+ return esock_finalize_connection(env, descP);
#endif
}
-/* *** nfinalize_connection ***
+/* *** esock_finalize_connection ***
* Perform the final check to verify a connection.
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_finalize_connection(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
int error;
@@ -5446,13 +5454,14 @@ ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env,
return esock_make_error(env, atom_enotconn);
if (!verify_is_connected(descP, &error)) {
- descP->state = SOCKET_STATE_OPEN; /* restore state */
+ descP->state = ESOCK_STATE_OPEN; /* restore state */
return esock_make_error_errno(env, error);
}
- descP->state = SOCKET_STATE_CONNECTED;
+ descP->state = ESOCK_STATE_CONNECTED;
enif_set_pid_undefined(&descP->connPid);
- DEMONP("nfinalize_connection -> connected", env, descP, &descP->connMon);
+ DEMONP("esock_finalize_connection -> connected",
+ env, descP, &descP->connMon);
descP->isReadable = TRUE;
descP->isWritable = TRUE;
@@ -5565,7 +5574,7 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 2) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP) ||
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) ||
!GET_INT(env, argv[1], &backlog)) {
return enif_make_badarg(env);
}
@@ -5576,7 +5585,7 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env,
"\r\n backlog: %d"
"\r\n", descP->sock, argv[0], backlog) );
- return nlisten(env, descP, backlog);
+ return esock_listen(env, descP, backlog);
#endif // if defined(__WIN32__)
}
@@ -5585,9 +5594,9 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nlisten(ErlNifEnv* env,
- ESockDescriptor* descP,
- int backlog)
+ERL_NIF_TERM esock_listen(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int backlog)
{
/*
@@ -5597,7 +5606,7 @@ ERL_NIF_TERM nlisten(ErlNifEnv* env,
if (IS_CLOSED(descP) || IS_CLOSING(descP))
return esock_make_error(env, atom_closed);
- if (descP->state == SOCKET_STATE_CLOSED)
+ if (descP->state == ESOCK_STATE_CLOSED)
return esock_make_error(env, atom_exbadstate);
if (!IS_OPEN(descP))
@@ -5611,7 +5620,7 @@ ERL_NIF_TERM nlisten(ErlNifEnv* env,
if (IS_SOCKET_ERROR(sock_listen(descP->sock, backlog)))
return esock_make_error_errno(env, sock_errno());
- descP->state = SOCKET_STATE_LISTENING;
+ descP->state = ESOCK_STATE_LISTENING;
return esock_atom_ok;
@@ -5648,7 +5657,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
sockRef = argv[0];
if ((argc != 2) ||
- !enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
ref = argv[1];
@@ -5669,15 +5678,15 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
"\r\n",
descP->sock,
sockRef, ref,
- ((descP->state == SOCKET_STATE_LISTENING) ? "listening" :
- ((descP->state == SOCKET_STATE_ACCEPTING) ? "accepting" : "other")),
+ ((descP->state == ESOCK_STATE_LISTENING) ? "listening" :
+ ((descP->state == ESOCK_STATE_ACCEPTING) ? "accepting" : "other")),
descP->currentAcceptorP,
descP->currentAcceptor.pid,
esock_make_monitor_term(env, &descP->currentAcceptor.mon),
descP->currentAcceptor.env,
descP->currentAcceptor.ref) );
- res = naccept(env, descP, sockRef, ref);
+ res = esock_accept(env, descP, sockRef, ref);
MUNLOCK(descP->accMtx);
@@ -5689,10 +5698,10 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref)
+ERL_NIF_TERM esock_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref)
{
ERL_NIF_TERM res;
@@ -5700,12 +5709,12 @@ ERL_NIF_TERM naccept(ErlNifEnv* env,
return esock_make_error(env, atom_closed);
switch (descP->state) {
- case SOCKET_STATE_LISTENING:
- res = naccept_listening(env, descP, sockRef, ref);
+ case ESOCK_STATE_LISTENING:
+ res = esock_accept_listening(env, descP, sockRef, ref);
break;
- case SOCKET_STATE_ACCEPTING:
- res = naccept_accepting(env, descP, sockRef, ref);
+ case ESOCK_STATE_ACCEPTING:
+ res = esock_accept_accepting(env, descP, sockRef, ref);
break;
default:
@@ -5718,16 +5727,16 @@ ERL_NIF_TERM naccept(ErlNifEnv* env,
#endif // if !defined(__WIN32__)
-/* *** naccept_listening ***
+/* *** esock_accept_listening ***
*
* We have no active acceptor (and therefor no acceptors in queue).
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM accRef)
+ERL_NIF_TERM esock_accept_listening(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef)
{
ESockAddress remote;
unsigned int n;
@@ -5736,14 +5745,14 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
ErlNifPid caller;
ERL_NIF_TERM res;
- SSDBG( descP, ("SOCKET", "naccept_listening -> get caller\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_accept_listening -> get caller\r\n") );
if (enif_self(env, &caller) == NULL)
return esock_make_error(env, atom_exself);
n = sizeof(remote);
sys_memzero((char *) &remote, n);
- SSDBG( descP, ("SOCKET", "naccept_listening -> try accept\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_accept_listening -> try accept\r\n") );
accSock = sock_accept(descP->sock, (struct sockaddr*) &remote, &n);
if (accSock == INVALID_SOCKET) {
@@ -5751,10 +5760,11 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
SSDBG( descP,
("SOCKET",
- "naccept_listening -> accept failed (%d)\r\n", save_errno) );
+ "esock_accept_listening -> accept failed (%d)\r\n",
+ save_errno) );
- res = naccept_listening_error(env, descP, sockRef, accRef,
- caller, save_errno);
+ res = esock_accept_listening_error(env, descP, sockRef, accRef,
+ caller, save_errno);
} else {
@@ -5762,9 +5772,9 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
* We got one
*/
- SSDBG( descP, ("SOCKET", "naccept_listening -> success\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_accept_listening -> success\r\n") );
- res = naccept_listening_accept(env, descP, accSock, caller, &remote);
+ res = esock_accept_listening_accept(env, descP, accSock, caller, &remote);
}
@@ -5772,7 +5782,7 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
}
-/* *** naccept_listening_error ***
+/* *** esock_accept_listening_error ***
*
* The accept call resultet in an error - handle it.
* There are only two cases:
@@ -5780,12 +5790,12 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env,
* 2) Other => Return the value (converted to an atom)
*/
static
-ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM accRef,
- ErlNifPid caller,
- int save_errno)
+ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef,
+ ErlNifPid caller,
+ int save_errno)
{
ERL_NIF_TERM res;
@@ -5794,10 +5804,10 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
/* *** Try again later *** */
SSDBG( descP,
- ("SOCKET", "naccept_listening_error -> would block\r\n") );
+ ("SOCKET", "esock_accept_listening_error -> would block\r\n") );
descP->currentAcceptor.pid = caller;
- if (MONP("naccept_listening -> current acceptor",
+ if (MONP("esock_accept_listening -> current acceptor",
env, descP,
&descP->currentAcceptor.pid,
&descP->currentAcceptor.mon) != 0) {
@@ -5809,14 +5819,14 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
descP->currentAcceptor.ref = CP_TERM(descP->currentAcceptor.env,
accRef);
descP->currentAcceptorP = &descP->currentAcceptor;
- res = naccept_busy_retry(env, descP,
- sockRef, accRef,
- NULL, SOCKET_STATE_ACCEPTING);
+ res = esock_accept_busy_retry(env, descP,
+ sockRef, accRef,
+ NULL, ESOCK_STATE_ACCEPTING);
}
} else {
SSDBG( descP,
("SOCKET",
- "naccept_listening -> errno: %d\r\n", save_errno) );
+ "esock_accept_listening -> errno: %d\r\n", save_errno) );
res = esock_make_error_errno(env, save_errno);
}
@@ -5824,20 +5834,20 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env,
}
-/* *** naccept_listening_accept ***
+/* *** esock_accept_listening_accept ***
*
* The accept call was successful (accepted) - handle the new connection.
*/
static
-ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
- ESockDescriptor* descP,
- SOCKET accSock,
- ErlNifPid caller,
- ESockAddress* remote)
+ERL_NIF_TERM esock_accept_listening_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ SOCKET accSock,
+ ErlNifPid caller,
+ ESockAddress* remote)
{
ERL_NIF_TERM res;
- naccept_accepted(env, descP, accSock, caller, remote, &res);
+ esock_accept_accepted(env, descP, accSock, caller, remote, &res);
return res;
}
@@ -5845,7 +5855,7 @@ ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
-/* *** naccept_accepting ***
+/* *** esock_accept_accepting ***
*
* We have an active acceptor and possibly acceptors waiting in queue.
* If the pid of the calling process is not the pid of the "current process",
@@ -5853,20 +5863,20 @@ ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM ref)
+ERL_NIF_TERM esock_accept_accepting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM ref)
{
ErlNifPid caller;
ERL_NIF_TERM res;
- SSDBG( descP, ("SOCKET", "naccept_accepting -> get caller\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_accept_accepting -> get caller\r\n") );
if (enif_self(env, &caller) == NULL)
return esock_make_error(env, atom_exself);
- SSDBG( descP, ("SOCKET", "naccept_accepting -> check: "
+ SSDBG( descP, ("SOCKET", "esock_accept_accepting -> check: "
"are caller current acceptor:"
"\r\n Caller: %T"
"\r\n Current: %T"
@@ -5875,18 +5885,19 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
if (COMPARE_PIDS(&descP->currentAcceptor.pid, &caller) == 0) {
SSDBG( descP,
- ("SOCKET", "naccept_accepting -> current acceptor\r\n") );
+ ("SOCKET", "esock_accept_accepting -> current acceptor\r\n") );
- res = naccept_accepting_current(env, descP, sockRef, ref);
+ res = esock_accept_accepting_current(env, descP, sockRef, ref);
} else {
/* Not the "current acceptor", so (maybe) push onto queue */
SSDBG( descP,
- ("SOCKET", "naccept_accepting -> *not* current acceptor\r\n") );
+ ("SOCKET",
+ "esock_accept_accepting -> *not* current acceptor\r\n") );
- res = naccept_accepting_other(env, descP, ref, caller);
+ res = esock_accept_accepting_other(env, descP, ref, caller);
}
@@ -5896,14 +5907,14 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env,
-/* *** naccept_accepting_current ***
+/* *** esock_accept_accepting_current ***
* Handles when the current acceptor makes another attempt.
*/
static
-ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM accRef)
+ERL_NIF_TERM esock_accept_accepting_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef)
{
ESockAddress remote;
unsigned int n;
@@ -5911,7 +5922,8 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
int save_errno;
ERL_NIF_TERM res;
- SSDBG( descP, ("SOCKET", "naccept_accepting_current -> try accept\r\n") );
+ SSDBG( descP, ("SOCKET",
+ "esock_accept_accepting_current -> try accept\r\n") );
n = sizeof(descP->remote);
sys_memzero((char *) &remote, n);
accSock = sock_accept(descP->sock, (struct sockaddr*) &remote, &n);
@@ -5921,18 +5933,19 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
SSDBG( descP,
("SOCKET",
- "naccept_accepting_current -> accept failed: %d\r\n",
+ "esock_accept_accepting_current -> accept failed: %d\r\n",
save_errno) );
- res = naccept_accepting_current_error(env, descP, sockRef,
- accRef, save_errno);
+ res = esock_accept_accepting_current_error(env, descP, sockRef,
+ accRef, save_errno);
} else {
- SSDBG( descP, ("SOCKET", "naccept_accepting_current -> accepted\r\n") );
+ SSDBG( descP, ("SOCKET",
+ "esock_accept_accepting_current -> accepted\r\n") );
- res = naccept_accepting_current_accept(env, descP, sockRef,
- accSock, &remote);
+ res = esock_accept_accepting_current_accept(env, descP, sockRef,
+ accSock, &remote);
}
@@ -5940,27 +5953,27 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env,
}
-/* *** naccept_accepting_current_accept ***
+/* *** esock_accept_accepting_current_accept ***
* Handles when the current acceptor succeeded in its accept call -
* handle the new connection.
*/
static
-ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- SOCKET accSock,
- ESockAddress* remote)
+ERL_NIF_TERM esock_accept_accepting_current_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ SOCKET accSock,
+ ESockAddress* remote)
{
ERL_NIF_TERM res;
- if (naccept_accepted(env, descP, accSock,
- descP->currentAcceptor.pid, remote, &res)) {
+ if (esock_accept_accepted(env, descP, accSock,
+ descP->currentAcceptor.pid, remote, &res)) {
/* Clean out the old cobweb's before trying to invite a new spider */
descP->currentAcceptor.ref = esock_atom_undefined;
enif_set_pid_undefined(&descP->currentAcceptor.pid);
- esock_free_env("naccept_accepting_current_accept - "
+ esock_free_env("esock_accept_accepting_current_accept - "
"current-accept-env",
descP->currentAcceptor.env);
descP->currentAcceptor.env = NULL;
@@ -5969,10 +5982,10 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
SSDBG( descP,
("SOCKET",
- "naccept_accepting_current_accept -> "
+ "esock_accept_accepting_current_accept -> "
"no more writers\r\n") );
- descP->state = SOCKET_STATE_LISTENING;
+ descP->state = ESOCK_STATE_LISTENING;
descP->currentAcceptorP = NULL;
ESOCK_ASSERT(!descP->currentAcceptor.env);
@@ -5986,18 +5999,18 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env,
}
-/* *** naccept_accepting_current_error ***
+/* *** esock_accept_accepting_current_error ***
* The accept call of current acceptor resultet in an error - handle it.
* There are only two cases:
* 1) BLOCK => Attempt a "retry"
* 2) Other => Return the value (converted to an atom)
*/
static
-ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef,
- int save_errno)
+ERL_NIF_TERM esock_accept_accepting_current_error(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef,
+ int save_errno)
{
ESockRequestor req;
ERL_NIF_TERM res, reason;
@@ -6011,13 +6024,13 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
SSDBG( descP,
("SOCKET",
- "naccept_accepting_current_error -> "
+ "esock_accept_accepting_current_error -> "
"would block: try again\r\n") );
- res = naccept_busy_retry(env, descP, sockRef, opRef,
- &descP->currentAcceptor.pid,
- /* No state change */
- descP->state);
+ res = esock_accept_busy_retry(env, descP, sockRef, opRef,
+ &descP->currentAcceptor.pid,
+ /* No state change */
+ descP->state);
} else {
@@ -6026,12 +6039,13 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
while (acceptor_pop(env, descP, &req)) {
SSDBG( descP,
- ("SOCKET", "naccept_accepting_current_error -> abort %T\r\n",
+ ("SOCKET",
+ "esock_accept_accepting_current_error -> abort %T\r\n",
req.pid) );
esock_send_abort_msg(env, sockRef, req.ref, req.env,
reason, &req.pid);
req.env = NULL;
- DEMONP("naccept_accepting_current_error -> pop'ed writer",
+ DEMONP("esock_accept_accepting_current_error -> pop'ed writer",
env, descP, &req.mon);
}
@@ -6041,16 +6055,16 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env,
}
-/* *** naccept_accepting_other ***
+/* *** esock_accept_accepting_other ***
* Handles when the another acceptor makes an attempt, which
* results (maybe) in the request beeing pushed onto the
* acceptor queue.
*/
static
-ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM ref,
- ErlNifPid caller)
+ERL_NIF_TERM esock_accept_accepting_other(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM ref,
+ ErlNifPid caller)
{
ERL_NIF_TERM result;
@@ -6065,18 +6079,18 @@ ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env,
-/* *** naccept_busy_retry ***
+/* *** esock_accept_busy_retry ***
*
* Perform a retry select. If successful, set nextState.
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM accRef,
- ErlNifPid* pid,
- unsigned int nextState)
+ERL_NIF_TERM esock_accept_busy_retry(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM accRef,
+ ErlNifPid* pid,
+ unsigned int nextState)
{
int sres;
ERL_NIF_TERM res, reason;
@@ -6095,17 +6109,17 @@ ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env,
-/* *** naccept_accepted ***
+/* *** esock_accept_accepted ***
*
* Generic function handling a successful accept.
*/
static
-BOOLEAN_T naccept_accepted(ErlNifEnv* env,
- ESockDescriptor* descP,
- SOCKET accSock,
- ErlNifPid pid,
- ESockAddress* remote,
- ERL_NIF_TERM* result)
+BOOLEAN_T esock_accept_accepted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ SOCKET accSock,
+ ErlNifPid pid,
+ ESockAddress* remote,
+ ERL_NIF_TERM* result)
{
ESockDescriptor* accDescP;
HANDLE accEvent;
@@ -6143,7 +6157,7 @@ BOOLEAN_T naccept_accepted(ErlNifEnv* env,
enif_release_resource(accDescP);
accDescP->ctrlPid = pid;
- if (MONP("naccept_accepted -> ctrl",
+ if (MONP("esock_accept_accepted -> ctrl",
env, accDescP,
&accDescP->ctrlPid,
&accDescP->ctrlMon) != 0) {
@@ -6156,7 +6170,7 @@ BOOLEAN_T naccept_accepted(ErlNifEnv* env,
accDescP->remote = *remote;
SET_NONBLOCKING(accDescP->sock);
- accDescP->state = SOCKET_STATE_CONNECTED;
+ accDescP->state = ESOCK_STATE_CONNECTED;
accDescP->isReadable = TRUE;
accDescP->isWritable = TRUE;
@@ -6209,7 +6223,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
sockRef = argv[0]; // We need this in case we send in case we send abort
sendRef = argv[1];
- if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -6234,7 +6248,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
* is done!
*/
- res = nsend(env, descP, sockRef, sendRef, &sndData, flags);
+ res = esock_send(env, descP, sockRef, sendRef, &sndData, flags);
MUNLOCK(descP->writeMtx);
@@ -6245,7 +6259,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
-/* *** nsend ***
+/* *** esock_send ***
*
* Do the actual send.
* Do some initial writer checks, do the actual send and then
@@ -6254,12 +6268,12 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsend(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* sndDataP,
- int flags)
+ERL_NIF_TERM esock_send(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* sndDataP,
+ int flags)
{
int save_errno;
ssize_t written;
@@ -6331,16 +6345,15 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 5) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP) ||
!GET_BIN(env, argv[2], &sndData) ||
!GET_UINT(env, argv[4], &eflags)) {
return enif_make_badarg(env);
}
- sockRef = argv[0]; // We need this in case we send in case we send abort
+ sockRef = argv[0]; // We need this in case we send abort (to the caller)
sendRef = argv[1];
eSockAddr = argv[3];
- if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -6369,8 +6382,8 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
MLOCK(descP->writeMtx);
- res = nsendto(env, descP, sockRef, sendRef, &sndData, flags,
- &remoteAddr, remoteAddrLen);
+ res = esock_sendto(env, descP, sockRef, sendRef, &sndData, flags,
+ &remoteAddr, remoteAddrLen);
MUNLOCK(descP->writeMtx);
@@ -6386,14 +6399,14 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsendto(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ErlNifBinary* dataP,
- int flags,
- ESockAddress* toAddrP,
- unsigned int toAddrLen)
+ERL_NIF_TERM esock_sendto(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ErlNifBinary* dataP,
+ int flags,
+ ESockAddress* toAddrP,
+ unsigned int toAddrLen)
{
int save_errno;
ssize_t written;
@@ -6468,11 +6481,11 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
!GET_UINT(env, argv[3], &eflags)) {
return enif_make_badarg(env);
}
- sockRef = argv[0]; // We need this in case we send in case we send abort
+ sockRef = argv[0]; // We need this in case we send abort (to the caller)
sendRef = argv[1];
eMsgHdr = argv[2];
- if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -6489,7 +6502,7 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
MLOCK(descP->writeMtx);
- res = nsendmsg(env, descP, sockRef, sendRef, eMsgHdr, flags);
+ res = esock_sendmsg(env, descP, sockRef, sendRef, eMsgHdr, flags);
MUNLOCK(descP->writeMtx);
@@ -6506,12 +6519,12 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM sendRef,
- ERL_NIF_TERM eMsgHdr,
- int flags)
+ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM sendRef,
+ ERL_NIF_TERM eMsgHdr,
+ int flags)
{
ERL_NIF_TERM res, eAddr, eIOV, eCtrl;
ESockAddress addr;
@@ -6540,7 +6553,8 @@ ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
/* We don't need the address */
- SSDBG( descP, ("SOCKET", "nsendmsg -> connected: no address\r\n") );
+ SSDBG( descP, ("SOCKET",
+ "esock_sendmsg -> connected: no address\r\n") );
msgHdr.msg_name = NULL;
msgHdr.msg_namelen = 0;
@@ -6555,7 +6569,7 @@ ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
if (!GET_MAP_VAL(env, eMsgHdr, esock_atom_addr, &eAddr))
return esock_make_error(env, esock_atom_einval);
- SSDBG( descP, ("SOCKET", "nsendmsg -> not connected: "
+ SSDBG( descP, ("SOCKET", "esock_sendmsg -> not connected: "
"\r\n address: %T"
"\r\n", eAddr) );
@@ -6575,7 +6589,7 @@ ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
if (!GET_LIST_LEN(env, eIOV, &iovLen) && (iovLen > 0))
return esock_make_error(env, esock_atom_einval);
- SSDBG( descP, ("SOCKET", "nsendmsg -> iov length: %d\r\n", iovLen) );
+ SSDBG( descP, ("SOCKET", "esock_sendmsg -> iov length: %d\r\n", iovLen) );
iovBins = MALLOC(iovLen * sizeof(ErlNifBinary));
ESOCK_ASSERT( (iovBins != NULL) );
@@ -6593,7 +6607,7 @@ ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
ctrlBufLen = 0;
ctrlBuf = NULL;
}
- SSDBG( descP, ("SOCKET", "nsendmsg -> optional ctrl: "
+ SSDBG( descP, ("SOCKET", "esock_sendmsg -> optional ctrl: "
"\r\n ctrlBuf: 0x%lX"
"\r\n ctrlBufLen: %d"
"\r\n eCtrl: %T\r\n", ctrlBuf, ctrlBufLen, eCtrl) );
@@ -6611,7 +6625,8 @@ ERL_NIF_TERM nsendmsg(ErlNifEnv* env,
SSDBG( descP, ("SOCKET",
- "nsendmsg -> total (iov) data size: %d\r\n", dataSize) );
+ "esock_sendmsg -> "
+ "total (iov) data size: %d\r\n", dataSize) );
/* Decode the ctrl and initiate that part of the msghdr.
@@ -6769,10 +6784,10 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env,
!GET_UINT(env, argv[3], &eflags)) {
return enif_make_badarg(env);
}
- sockRef = argv[0]; // We need this in case we case we send abort
+ sockRef = argv[0]; // We need this in case we send abort (to the caller)
recvRef = argv[1];
- if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -6789,7 +6804,7 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env,
* is done!
*/
- res = nrecv(env, descP, sockRef, recvRef, len, flags);
+ res = esock_recv(env, descP, sockRef, recvRef, len, flags);
MUNLOCK(descP->readMtx);
@@ -6806,12 +6821,12 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nrecv(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- int len,
- int flags)
+ERL_NIF_TERM esock_recv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ int len,
+ int flags)
{
ssize_t read;
ErlNifBinary buf;
@@ -6819,7 +6834,7 @@ ERL_NIF_TERM nrecv(ErlNifEnv* env,
int save_errno;
int bufSz = (len ? len : descP->rBufSz);
- SSDBG( descP, ("SOCKET", "nrecv -> entry with"
+ SSDBG( descP, ("SOCKET", "esock_recv -> entry with"
"\r\n len: %d (%d:%d)"
"\r\n flags: %d"
"\r\n", len, descP->rNumCnt, bufSz, flags) );
@@ -6842,7 +6857,7 @@ ERL_NIF_TERM nrecv(ErlNifEnv* env,
SOCK_CNT_INC(env, descP, sockRef, atom_read_tries, &descP->readTries, 1);
// If it fails (read = -1), we need errno...
- SSDBG( descP, ("SOCKET", "nrecv -> try read (%d)\r\n", buf.size) );
+ SSDBG( descP, ("SOCKET", "esock_recv -> try read (%d)\r\n", buf.size) );
read = sock_recv(descP->sock, buf.data, buf.size, flags);
if (IS_SOCKET_ERROR(read)) {
save_errno = sock_errno();
@@ -6850,7 +6865,8 @@ ERL_NIF_TERM nrecv(ErlNifEnv* env,
save_errno = -1; // The value does not actually matter in this case
}
- SSDBG( descP, ("SOCKET", "nrecv -> read: %d (%d)\r\n", read, save_errno) );
+ SSDBG( descP, ("SOCKET",
+ "esock_recv -> read: %d (%d)\r\n", read, save_errno) );
return recv_check_result(env, descP,
read, len,
@@ -6911,10 +6927,10 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env,
!GET_UINT(env, argv[3], &eflags)) {
return enif_make_badarg(env);
}
- sockRef = argv[0]; // We need this in case we send in case we send abort
+ sockRef = argv[0]; // We need this in case we send abort (to the caller)
recvRef = argv[1];
- if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -6951,7 +6967,7 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env,
* </KOLLA>
*/
- res = nrecvfrom(env, descP, sockRef, recvRef, bufSz, flags);
+ res = esock_recvfrom(env, descP, sockRef, recvRef, bufSz, flags);
MUNLOCK(descP->readMtx);
@@ -6967,12 +6983,12 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nrecvfrom(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 len,
- int flags)
+ERL_NIF_TERM esock_recvfrom(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 len,
+ int flags)
{
ESockAddress fromAddr;
unsigned int addrLen;
@@ -6982,7 +6998,7 @@ ERL_NIF_TERM nrecvfrom(ErlNifEnv* env,
ERL_NIF_TERM readerCheck;
int bufSz = (len ? len : descP->rBufSz);
- SSDBG( descP, ("SOCKET", "nrecvfrom -> entry with"
+ SSDBG( descP, ("SOCKET", "esock_recvfrom -> entry with"
"\r\n len: %d (%d)"
"\r\n flags: %d"
"\r\n", len, bufSz, flags) );
@@ -7080,10 +7096,10 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
!GET_UINT(env, argv[4], &eflags)) {
return enif_make_badarg(env);
}
- sockRef = argv[0]; // We need this in case we send in case we send abort
+ sockRef = argv[0]; // We need this in case we send abort (to the caller)
recvRef = argv[1];
- if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -7121,7 +7137,7 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
* </KOLLA>
*/
- res = nrecvmsg(env, descP, sockRef, recvRef, bufSz, ctrlSz, flags);
+ res = esock_recvmsg(env, descP, sockRef, recvRef, bufSz, ctrlSz, flags);
MUNLOCK(descP->readMtx);
@@ -7137,13 +7153,13 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env,
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM recvRef,
- Uint16 bufLen,
- Uint16 ctrlLen,
- int flags)
+ERL_NIF_TERM esock_recvmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM recvRef,
+ Uint16 bufLen,
+ Uint16 ctrlLen,
+ int flags)
{
unsigned int addrLen;
ssize_t read;
@@ -7157,7 +7173,7 @@ ERL_NIF_TERM nrecvmsg(ErlNifEnv* env,
ERL_NIF_TERM readerCheck;
ESockAddress addr;
- SSDBG( descP, ("SOCKET", "nrecvmsg -> entry with"
+ SSDBG( descP, ("SOCKET", "esock_recvmsg -> entry with"
"\r\n bufSz: %d (%d)"
"\r\n ctrlSz: %d (%d)"
"\r\n flags: %d"
@@ -7246,28 +7262,28 @@ ERL_NIF_TERM nif_close(ErlNifEnv* env,
ESockDescriptor* descP;
if ((argc != 1) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) {
return enif_make_badarg(env);
}
if (IS_CLOSED(descP) || IS_CLOSING(descP))
return esock_make_error(env, atom_closed);
- return nclose(env, descP);
+ return esock_close(env, descP);
#endif // if defined(__WIN32__)
}
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nclose(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_close(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM reply, reason;
BOOLEAN_T doClose;
SSDBG( descP, ("SOCKET",
- "nclose -> [%d] entry (0x%lX, 0x%lX, 0x%lX, 0x%lX)\r\n",
+ "esock_close -> [%d] entry (0x%lX, 0x%lX, 0x%lX, 0x%lX)\r\n",
descP->sock,
descP->state,
descP->currentWriterP,
@@ -7276,10 +7292,10 @@ ERL_NIF_TERM nclose(ErlNifEnv* env,
MLOCK(descP->closeMtx);
- doClose = nclose_check(env, descP, &reason);
+ doClose = esock_close_check(env, descP, &reason);
if (doClose) {
- reply = nclose_do(env, descP);
+ reply = esock_close_do(env, descP);
} else {
reply = esock_make_error(env, reason);
}
@@ -7287,7 +7303,7 @@ ERL_NIF_TERM nclose(ErlNifEnv* env,
MUNLOCK(descP->closeMtx);
SSDBG( descP,
- ("SOCKET", "nclose -> [%d] done when: "
+ ("SOCKET", "esock_close -> [%d] done when: "
"\r\n state: 0x%lX"
"\r\n reply: %T"
"\r\n", descP->sock, descP->state, reply) );
@@ -7297,23 +7313,23 @@ ERL_NIF_TERM nclose(ErlNifEnv* env,
-/* *** nclose_check ***
+/* *** esock_close_check ***
*
* Check if we should try to perform the first stage close.
*/
static
-BOOLEAN_T nclose_check(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM* reason)
+BOOLEAN_T esock_close_check(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM* reason)
{
BOOLEAN_T doClose;
- if (descP->state == SOCKET_STATE_CLOSED) {
+ if (descP->state == ESOCK_STATE_CLOSED) {
doClose = FALSE;
*reason = atom_closed;
- } else if (descP->state == SOCKET_STATE_CLOSING) {
+ } else if (descP->state == ESOCK_STATE_CLOSING) {
doClose = FALSE;
*reason = atom_closing;
@@ -7343,7 +7359,7 @@ BOOLEAN_T nclose_check(ErlNifEnv* env,
* </KOLLA>
*/
- if (MONP("nclose_check -> closer",
+ if (MONP("esock_close_check -> closer",
env, descP,
&descP->closerPid,
&descP->closerMon) != 0) {
@@ -7354,7 +7370,7 @@ BOOLEAN_T nclose_check(ErlNifEnv* env,
} else {
descP->closeLocal = TRUE;
- descP->state = SOCKET_STATE_CLOSING;
+ descP->state = ESOCK_STATE_CLOSING;
descP->isReadable = FALSE;
descP->isWritable = FALSE;
doClose = TRUE;
@@ -7370,13 +7386,13 @@ BOOLEAN_T nclose_check(ErlNifEnv* env,
-/* *** nclose_do ***
+/* *** esock_close_do ***
*
* Perform (do) the first stage close.
*/
static
-ERL_NIF_TERM nclose_do(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_close_do(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
int domain = descP->domain;
int type = descP->type;
@@ -7384,7 +7400,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env,
int sres;
ERL_NIF_TERM reply, reason;
- descP->closeEnv = esock_alloc_env("nclose-do - close-env");
+ descP->closeEnv = esock_alloc_env("esock_close_do - close-env");
descP->closeRef = MKREF(descP->closeEnv);
sres = esock_select_stop(env, descP->sock, descP);
@@ -7393,7 +7409,8 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env,
/* Prep done - inform the caller it can finalize (close) directly */
SSDBG( descP,
- ("SOCKET", "nclose -> [%d] stop was called\r\n", descP->sock) );
+ ("SOCKET",
+ "esock_close -> [%d] stop was called\r\n", descP->sock) );
dec_socket(domain, type, protocol);
reply = esock_atom_ok;
@@ -7403,7 +7420,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env,
/* The stop callback function has been *scheduled* which means that we
* have to wait for it to complete. */
SSDBG( descP,
- ("SOCKET", "nclose -> [%d] stop was scheduled\r\n",
+ ("SOCKET", "esock_close -> [%d] stop was scheduled\r\n",
descP->sock) );
dec_socket(domain, type, protocol); // SHALL WE DO THIS AT finalize?
@@ -7412,7 +7429,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env,
} else {
SSDBG( descP,
- ("SOCKET", "nclose -> [%d] stop failed: %d\r\n",
+ ("SOCKET", "esock_close -> [%d] stop failed: %d\r\n",
descP->sock, sres) );
/* <KOLLA>
@@ -7426,7 +7443,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env,
*/
// Do we need this?
- DEMONP("nclose_do -> closer", env, descP, &descP->closerMon);
+ DEMONP("esock_close_do -> closer", env, descP, &descP->closerMon);
reason = MKT2(env, esock_atom_select_failed, MKI(env, sres));
reply = esock_make_error(env, reason);
@@ -7464,22 +7481,22 @@ ERL_NIF_TERM nif_finalize_close(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 1) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) {
return enif_make_badarg(env);
}
- return nfinalize_close(env, descP);
+ return esock_finalize_close(env, descP);
#endif // if defined(__WIN32__)
}
-/* *** nfinalize_close ***
+/* *** esock_finalize_close ***
* Perform the final step in the socket close.
*/
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_finalize_close(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM reply;
@@ -7516,7 +7533,7 @@ ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
descP->sock = INVALID_SOCKET;
descP->event = INVALID_EVENT;
- descP->state = SOCKET_STATE_CLOSED;
+ descP->state = ESOCK_STATE_CLOSED;
return reply;
}
@@ -7548,7 +7565,7 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env,
int how;
if ((argc != 2) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP) ||
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) ||
!GET_UINT(env, argv[1], &ehow)) {
return enif_make_badarg(env);
}
@@ -7559,7 +7576,7 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env,
if (!ehow2how(ehow, &how))
return enif_make_badarg(env);
- return nshutdown(env, descP, how);
+ return esock_shutdown(env, descP, how);
#endif // if defined(__WIN32__)
}
@@ -7567,9 +7584,9 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nshutdown(ErlNifEnv* env,
- ESockDescriptor* descP,
- int how)
+ERL_NIF_TERM esock_shutdown(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int how)
{
ERL_NIF_TERM reply;
@@ -7637,7 +7654,7 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 5) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP) ||
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) ||
!GET_INT(env, argv[2], &eLevel) ||
!GET_INT(env, argv[3], &eOpt)) {
SGDBG( ("SOCKET", "nif_setopt -> failed initial arg check\r\n") );
@@ -7674,7 +7691,7 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
MLOCK(descP->cfgMtx);
- result = nsetopt(env, descP, isEncoded, isOTP, level, eOpt, eVal);
+ result = esock_setopt(env, descP, isEncoded, isOTP, level, eOpt, eVal);
MUNLOCK(descP->cfgMtx);
@@ -7691,13 +7708,13 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsetopt(ErlNifEnv* env,
- ESockDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
@@ -7705,11 +7722,11 @@ ERL_NIF_TERM nsetopt(ErlNifEnv* env,
/* These are not actual socket options,
* but options for our implementation.
*/
- result = nsetopt_otp(env, descP, eOpt, eVal);
+ result = esock_setopt_otp(env, descP, eOpt, eVal);
} else if (!isEncoded) {
- result = nsetopt_native(env, descP, level, eOpt, eVal);
+ result = esock_setopt_native(env, descP, level, eOpt, eVal);
} else {
- result = nsetopt_level(env, descP, level, eOpt, eVal);
+ result = esock_setopt_level(env, descP, level, eOpt, eVal);
}
return result;
@@ -7717,45 +7734,45 @@ ERL_NIF_TERM nsetopt(ErlNifEnv* env,
-/* nsetopt_otp - Handle OTP (level) options
+/* esock_setopt_otp - Handle OTP (level) options
*/
static
-ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_otp -> entry with"
+ ("SOCKET", "esock_setopt_otp -> entry with"
"\r\n eOpt: %d"
"\r\n eVal: %T"
"\r\n", eOpt, eVal) );
switch (eOpt) {
- case SOCKET_OPT_OTP_DEBUG:
- result = nsetopt_otp_debug(env, descP, eVal);
+ case ESOCK_OPT_OTP_DEBUG:
+ result = esock_setopt_otp_debug(env, descP, eVal);
break;
- case SOCKET_OPT_OTP_IOW:
- result = nsetopt_otp_iow(env, descP, eVal);
+ case ESOCK_OPT_OTP_IOW:
+ result = esock_setopt_otp_iow(env, descP, eVal);
break;
- case SOCKET_OPT_OTP_CTRL_PROC:
- result = nsetopt_otp_ctrl_proc(env, descP, eVal);
+ case ESOCK_OPT_OTP_CTRL_PROC:
+ result = esock_setopt_otp_ctrl_proc(env, descP, eVal);
break;
- case SOCKET_OPT_OTP_RCVBUF:
- result = nsetopt_otp_rcvbuf(env, descP, eVal);
+ case ESOCK_OPT_OTP_RCVBUF:
+ result = esock_setopt_otp_rcvbuf(env, descP, eVal);
break;
- case SOCKET_OPT_OTP_RCVCTRLBUF:
- result = nsetopt_otp_rcvctrlbuf(env, descP, eVal);
+ case ESOCK_OPT_OTP_RCVCTRLBUF:
+ result = esock_setopt_otp_rcvctrlbuf(env, descP, eVal);
break;
- case SOCKET_OPT_OTP_SNDCTRLBUF:
- result = nsetopt_otp_sndctrlbuf(env, descP, eVal);
+ case ESOCK_OPT_OTP_SNDCTRLBUF:
+ result = esock_setopt_otp_sndctrlbuf(env, descP, eVal);
break;
default:
@@ -7767,12 +7784,12 @@ ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env,
}
-/* nsetopt_otp_debug - Handle the OTP (level) debug options
+/* esock_setopt_otp_debug - Handle the OTP (level) debug options
*/
static
-ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_otp_debug(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
descP->dbg = esock_decode_bool(eVal);
@@ -7780,12 +7797,12 @@ ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env,
}
-/* nsetopt_otp_iow - Handle the OTP (level) iow options
+/* esock_setopt_otp_iow - Handle the OTP (level) iow options
*/
static
-ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_otp_iow(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
descP->iow = esock_decode_bool(eVal);
@@ -7794,19 +7811,20 @@ ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env,
-/* nsetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process options
+/* esock_setopt_otp_ctrl_proc - Handle the OTP (level)
+ * controlling_process options
*/
static
-ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_otp_ctrl_proc(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ErlNifPid caller, newCtrlPid;
ESockMonitor newCtrlMon;
int xres;
SSDBG( descP,
- ("SOCKET", "nsetopt_otp_ctrl_proc -> entry with"
+ ("SOCKET", "esock_setopt_otp_ctrl_proc -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
@@ -7815,7 +7833,8 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
return esock_make_error(env, atom_exself);
if (COMPARE_PIDS(&descP->ctrlPid, &caller) != 0) {
- SSDBG( descP, ("SOCKET", "nsetopt_otp_ctrl_proc -> not owner (%T)\r\n",
+ SSDBG( descP, ("SOCKET",
+ "esock_setopt_otp_ctrl_proc -> not owner (%T)\r\n",
descP->ctrlPid) );
return esock_make_error(env, esock_atom_not_owner);
}
@@ -7825,13 +7844,14 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
}
- if ((xres = MONP("nsetopt_otp_ctrl_proc -> (new) ctrl",
+ if ((xres = MONP("esock_setopt_otp_ctrl_proc -> (new) ctrl",
env, descP, &newCtrlPid, &newCtrlMon)) != 0) {
- esock_warning_msg("Failed monitor %d) (new) controlling process\r\n", xres);
+ esock_warning_msg("Failed monitor (%d) (new) controlling process\r\n",
+ xres);
return esock_make_error(env, esock_atom_einval);
}
- if ((xres = DEMONP("nsetopt_otp_ctrl_proc -> (old) ctrl",
+ if ((xres = DEMONP("esock_setopt_otp_ctrl_proc -> (old) ctrl",
env, descP, &descP->ctrlMon)) != 0) {
esock_warning_msg("Failed demonitor (%d) "
"old controlling process %T (%T)\r\n",
@@ -7841,14 +7861,14 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
descP->ctrlPid = newCtrlPid;
descP->ctrlMon = newCtrlMon;
- SSDBG( descP, ("SOCKET", "nsetopt_otp_ctrl_proc -> done\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_setopt_otp_ctrl_proc -> done\r\n") );
return esock_atom_ok;
}
-/* nsetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option
+/* esock_setopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option
* The (otp) rcvbuf option is provided as:
*
* BufSz :: integer() | {N :: pos_integer(), BufSz :: pod_integer()}
@@ -7856,9 +7876,9 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env,
* Where N is the max number of reads.
*/
static
-ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_otp_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
const ERL_NIF_TERM* t; // The array of the elements of the tuple
int tsz; // The size of the tuple - should be 2
@@ -7875,7 +7895,7 @@ ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
if ((xres = esock_decode_bufsz(env,
eVal,
- SOCKET_RECV_BUFFER_SIZE_DEFAULT,
+ ESOCK_RECV_BUFFER_SIZE_DEFAULT,
&bufSz)) != NULL)
return esock_make_error_str(env, xres);
@@ -7892,7 +7912,7 @@ ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
if ((xres = esock_decode_bufsz(env,
t[1],
- SOCKET_RECV_BUFFER_SIZE_DEFAULT,
+ ESOCK_RECV_BUFFER_SIZE_DEFAULT,
&bufSz)) != NULL)
return esock_make_error_str(env, xres);
@@ -7908,19 +7928,19 @@ ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env,
-/* nsetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option
+/* esock_setopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option
*/
static
-ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_otp_rcvctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
size_t val;
char* xres;
if ((xres = esock_decode_bufsz(env,
eVal,
- SOCKET_RECV_CTRL_BUFFER_SIZE_DEFAULT,
+ ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT,
&val)) != NULL)
return esock_make_error_str(env, xres);
@@ -7931,19 +7951,19 @@ ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env,
-/* nsetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option
+/* esock_setopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option
*/
static
-ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_otp_sndctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
size_t val;
char* xres;
if ((xres = esock_decode_bufsz(env,
eVal,
- SOCKET_SEND_CTRL_BUFFER_SIZE_DEFAULT,
+ ESOCK_SEND_CTRL_BUFFER_SIZE_DEFAULT,
&val)) != NULL)
return esock_make_error_str(env, xres);
@@ -7958,17 +7978,17 @@ ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env,
* in "native mode" (option is provided as is and value as a binary).
*/
static
-ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ErlNifBinary val;
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_native -> entry with"
+ ("SOCKET", "esock_setopt_native -> entry with"
"\r\n level: %d"
"\r\n opt: %d"
"\r\n eVal: %T"
@@ -7986,7 +8006,7 @@ ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "nsetopt_native -> done when"
+ ("SOCKET", "esock_setopt_native -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -7995,25 +8015,25 @@ ERL_NIF_TERM nsetopt_native(ErlNifEnv* env,
-/* nsetopt_level - A "proper" level (option) has been specified
+/* esock_setopt_level - A "proper" level (option) has been specified
*/
static
-ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_level(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_level -> entry with"
+ ("SOCKET", "esock_setopt_level -> entry with"
"\r\n level: %d"
"\r\n", level) );
switch (level) {
case SOL_SOCKET:
- result = nsetopt_lvl_socket(env, descP, eOpt, eVal);
+ result = esock_setopt_lvl_socket(env, descP, eOpt, eVal);
break;
#if defined(SOL_IP)
@@ -8021,7 +8041,7 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
#else
case IPPROTO_IP:
#endif
- result = nsetopt_lvl_ip(env, descP, eOpt, eVal);
+ result = esock_setopt_lvl_ip(env, descP, eOpt, eVal);
break;
#if defined(HAVE_IPV6)
@@ -8030,33 +8050,34 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
#else
case IPPROTO_IPV6:
#endif
- result = nsetopt_lvl_ipv6(env, descP, eOpt, eVal);
+ result = esock_setopt_lvl_ipv6(env, descP, eOpt, eVal);
break;
#endif
case IPPROTO_TCP:
- result = nsetopt_lvl_tcp(env, descP, eOpt, eVal);
+ result = esock_setopt_lvl_tcp(env, descP, eOpt, eVal);
break;
case IPPROTO_UDP:
- result = nsetopt_lvl_udp(env, descP, eOpt, eVal);
+ result = esock_setopt_lvl_udp(env, descP, eOpt, eVal);
break;
#if defined(HAVE_SCTP)
case IPPROTO_SCTP:
- result = nsetopt_lvl_sctp(env, descP, eOpt, eVal);
+ result = esock_setopt_lvl_sctp(env, descP, eOpt, eVal);
break;
#endif
default:
SSDBG( descP,
- ("SOCKET", "nsetopt_level -> unknown level (%d)\r\n", level) );
+ ("SOCKET",
+ "esock_setopt_level -> unknown level (%d)\r\n", level) );
result = esock_make_error(env, esock_atom_einval);
break;
}
SSDBG( descP,
- ("SOCKET", "nsetopt_level -> done when"
+ ("SOCKET", "esock_setopt_level -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -8065,139 +8086,140 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env,
-/* nsetopt_lvl_socket - Level *SOCKET* option
+/* esock_setopt_lvl_socket - Level *SOCKET* option
*/
static
-ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_socket -> entry with"
+ ("SOCKET", "esock_setopt_lvl_socket -> entry with"
"\r\n opt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(SO_BINDTODEVICE)
- case SOCKET_OPT_SOCK_BINDTODEVICE:
- result = nsetopt_lvl_sock_bindtodevice(env, descP, eVal);
+ case ESOCK_OPT_SOCK_BINDTODEVICE:
+ result = esock_setopt_lvl_sock_bindtodevice(env, descP, eVal);
break;
#endif
#if defined(SO_BROADCAST)
- case SOCKET_OPT_SOCK_BROADCAST:
- result = nsetopt_lvl_sock_broadcast(env, descP, eVal);
+ case ESOCK_OPT_SOCK_BROADCAST:
+ result = esock_setopt_lvl_sock_broadcast(env, descP, eVal);
break;
#endif
#if defined(SO_DEBUG)
- case SOCKET_OPT_SOCK_DEBUG:
- result = nsetopt_lvl_sock_debug(env, descP, eVal);
+ case ESOCK_OPT_SOCK_DEBUG:
+ result = esock_setopt_lvl_sock_debug(env, descP, eVal);
break;
#endif
#if defined(SO_DONTROUTE)
- case SOCKET_OPT_SOCK_DONTROUTE:
- result = nsetopt_lvl_sock_dontroute(env, descP, eVal);
+ case ESOCK_OPT_SOCK_DONTROUTE:
+ result = esock_setopt_lvl_sock_dontroute(env, descP, eVal);
break;
#endif
#if defined(SO_KEEPALIVE)
- case SOCKET_OPT_SOCK_KEEPALIVE:
- result = nsetopt_lvl_sock_keepalive(env, descP, eVal);
+ case ESOCK_OPT_SOCK_KEEPALIVE:
+ result = esock_setopt_lvl_sock_keepalive(env, descP, eVal);
break;
#endif
#if defined(SO_LINGER)
- case SOCKET_OPT_SOCK_LINGER:
- result = nsetopt_lvl_sock_linger(env, descP, eVal);
+ case ESOCK_OPT_SOCK_LINGER:
+ result = esock_setopt_lvl_sock_linger(env, descP, eVal);
break;
#endif
#if defined(SO_PEEK_OFF)
- case SOCKET_OPT_SOCK_PEEK_OFF:
- result = nsetopt_lvl_sock_peek_off(env, descP, eVal);
+ case ESOCK_OPT_SOCK_PEEK_OFF:
+ result = esock_setopt_lvl_sock_peek_off(env, descP, eVal);
break;
#endif
#if defined(SO_OOBINLINE)
- case SOCKET_OPT_SOCK_OOBINLINE:
- result = nsetopt_lvl_sock_oobinline(env, descP, eVal);
+ case ESOCK_OPT_SOCK_OOBINLINE:
+ result = esock_setopt_lvl_sock_oobinline(env, descP, eVal);
break;
#endif
#if defined(SO_PRIORITY)
- case SOCKET_OPT_SOCK_PRIORITY:
- result = nsetopt_lvl_sock_priority(env, descP, eVal);
+ case ESOCK_OPT_SOCK_PRIORITY:
+ result = esock_setopt_lvl_sock_priority(env, descP, eVal);
break;
#endif
#if defined(SO_RCVBUF)
- case SOCKET_OPT_SOCK_RCVBUF:
- result = nsetopt_lvl_sock_rcvbuf(env, descP, eVal);
+ case ESOCK_OPT_SOCK_RCVBUF:
+ result = esock_setopt_lvl_sock_rcvbuf(env, descP, eVal);
break;
#endif
#if defined(SO_RCVLOWAT)
- case SOCKET_OPT_SOCK_RCVLOWAT:
- result = nsetopt_lvl_sock_rcvlowat(env, descP, eVal);
+ case ESOCK_OPT_SOCK_RCVLOWAT:
+ result = esock_setopt_lvl_sock_rcvlowat(env, descP, eVal);
break;
#endif
#if defined(SO_RCVTIMEO)
- case SOCKET_OPT_SOCK_RCVTIMEO:
- result = nsetopt_lvl_sock_rcvtimeo(env, descP, eVal);
+ case ESOCK_OPT_SOCK_RCVTIMEO:
+ result = esock_setopt_lvl_sock_rcvtimeo(env, descP, eVal);
break;
#endif
#if defined(SO_REUSEADDR)
- case SOCKET_OPT_SOCK_REUSEADDR:
- result = nsetopt_lvl_sock_reuseaddr(env, descP, eVal);
+ case ESOCK_OPT_SOCK_REUSEADDR:
+ result = esock_setopt_lvl_sock_reuseaddr(env, descP, eVal);
break;
#endif
#if defined(SO_REUSEPORT)
- case SOCKET_OPT_SOCK_REUSEPORT:
- result = nsetopt_lvl_sock_reuseport(env, descP, eVal);
+ case ESOCK_OPT_SOCK_REUSEPORT:
+ result = esock_setopt_lvl_sock_reuseport(env, descP, eVal);
break;
#endif
#if defined(SO_SNDBUF)
- case SOCKET_OPT_SOCK_SNDBUF:
- result = nsetopt_lvl_sock_sndbuf(env, descP, eVal);
+ case ESOCK_OPT_SOCK_SNDBUF:
+ result = esock_setopt_lvl_sock_sndbuf(env, descP, eVal);
break;
#endif
#if defined(SO_SNDLOWAT)
- case SOCKET_OPT_SOCK_SNDLOWAT:
- result = nsetopt_lvl_sock_sndlowat(env, descP, eVal);
+ case ESOCK_OPT_SOCK_SNDLOWAT:
+ result = esock_setopt_lvl_sock_sndlowat(env, descP, eVal);
break;
#endif
#if defined(SO_SNDTIMEO)
- case SOCKET_OPT_SOCK_SNDTIMEO:
- result = nsetopt_lvl_sock_sndtimeo(env, descP, eVal);
+ case ESOCK_OPT_SOCK_SNDTIMEO:
+ result = esock_setopt_lvl_sock_sndtimeo(env, descP, eVal);
break;
#endif
#if defined(SO_TIMESTAMP)
- case SOCKET_OPT_SOCK_TIMESTAMP:
- result = nsetopt_lvl_sock_timestamp(env, descP, eVal);
+ case ESOCK_OPT_SOCK_TIMESTAMP:
+ result = esock_setopt_lvl_sock_timestamp(env, descP, eVal);
break;
#endif
default:
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_socket -> unknown opt (%d)\r\n", eOpt) );
+ ("SOCKET",
+ "esock_setopt_lvl_socket -> unknown opt (%d)\r\n", eOpt) );
result = esock_make_error(env, esock_atom_einval);
break;
}
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_socket -> done when"
+ ("SOCKET", "esock_setopt_lvl_socket -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -8207,66 +8229,66 @@ ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env,
#if defined(SO_BINDTODEVICE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_str_opt(env, descP,
- SOL_SOCKET, SO_BROADCAST,
- IFNAMSIZ, eVal);
+ return esock_setopt_str_opt(env, descP,
+ SOL_SOCKET, SO_BINDTODEVICE,
+ IFNAMSIZ, eVal);
}
#endif
#if defined(SO_BROADCAST)
static
-ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST, eVal);
}
#endif
#if defined(SO_DEBUG)
static
-ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG, eVal);
+ return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG, eVal);
}
#endif
#if defined(SO_DONTROUTE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE, eVal);
}
#endif
#if defined(SO_KEEPALIVE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE, eVal);
}
#endif
#if defined(SO_LINGER)
static
-ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
struct linger val;
@@ -8290,346 +8312,347 @@ ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env,
#if defined(SO_OOBINLINE)
static
-ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE, eVal);
}
#endif
#if defined(SO_PEEK_OFF)
static
-ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF, eVal);
+ return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF, eVal);
}
#endif
#if defined(SO_PRIORITY)
static
-ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY, eVal);
+ return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY, eVal);
}
#endif
#if defined(SO_RCVBUF)
static
-ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF, eVal);
+ return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF, eVal);
}
#endif
#if defined(SO_RCVLOWAT)
static
-ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT, eVal);
+ return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT, eVal);
}
#endif
#if defined(SO_RCVTIMEO)
static
-ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO, eVal);
+ return esock_setopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO, eVal);
}
#endif
#if defined(SO_REUSEADDR)
static
-ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR, eVal);
}
#endif
#if defined(SO_REUSEPORT)
static
-ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT, eVal);
}
#endif
#if defined(SO_SNDBUF)
static
-ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF, eVal);
+ return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF, eVal);
}
#endif
#if defined(SO_SNDLOWAT)
static
-ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT, eVal);
+ return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT, eVal);
}
#endif
#if defined(SO_SNDTIMEO)
static
-ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sock_sndtimeo -> entry with"
+ ("SOCKET", "esock_setopt_lvl_sock_sndtimeo -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
- return nsetopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO, eVal);
+ return esock_setopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO, eVal);
}
#endif
#if defined(SO_TIMESTAMP)
static
-ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP, eVal);
}
#endif
-/* nsetopt_lvl_ip - Level *IP* option(s)
+/* esock_setopt_lvl_ip - Level *IP* option(s)
*/
static
-ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip -> entry with"
+ ("SOCKET", "esock_setopt_lvl_ip -> entry with"
"\r\n opt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(IP_ADD_MEMBERSHIP)
- case SOCKET_OPT_IP_ADD_MEMBERSHIP:
- result = nsetopt_lvl_ip_add_membership(env, descP, eVal);
+ case ESOCK_OPT_IP_ADD_MEMBERSHIP:
+ result = esock_setopt_lvl_ip_add_membership(env, descP, eVal);
break;
#endif
#if defined(IP_ADD_SOURCE_MEMBERSHIP)
- case SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP:
- result = nsetopt_lvl_ip_add_source_membership(env, descP, eVal);
+ case ESOCK_OPT_IP_ADD_SOURCE_MEMBERSHIP:
+ result = esock_setopt_lvl_ip_add_source_membership(env, descP, eVal);
break;
#endif
#if defined(IP_BLOCK_SOURCE)
- case SOCKET_OPT_IP_BLOCK_SOURCE:
- result = nsetopt_lvl_ip_block_source(env, descP, eVal);
+ case ESOCK_OPT_IP_BLOCK_SOURCE:
+ result = esock_setopt_lvl_ip_block_source(env, descP, eVal);
break;
#endif
#if defined(IP_DROP_MEMBERSHIP)
- case SOCKET_OPT_IP_DROP_MEMBERSHIP:
- result = nsetopt_lvl_ip_drop_membership(env, descP, eVal);
+ case ESOCK_OPT_IP_DROP_MEMBERSHIP:
+ result = esock_setopt_lvl_ip_drop_membership(env, descP, eVal);
break;
#endif
#if defined(IP_DROP_SOURCE_MEMBERSHIP)
- case SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP:
- result = nsetopt_lvl_ip_drop_source_membership(env, descP, eVal);
+ case ESOCK_OPT_IP_DROP_SOURCE_MEMBERSHIP:
+ result = esock_setopt_lvl_ip_drop_source_membership(env, descP, eVal);
break;
#endif
#if defined(IP_FREEBIND)
- case SOCKET_OPT_IP_FREEBIND:
- result = nsetopt_lvl_ip_freebind(env, descP, eVal);
+ case ESOCK_OPT_IP_FREEBIND:
+ result = esock_setopt_lvl_ip_freebind(env, descP, eVal);
break;
#endif
#if defined(IP_HDRINCL)
- case SOCKET_OPT_IP_HDRINCL:
- result = nsetopt_lvl_ip_hdrincl(env, descP, eVal);
+ case ESOCK_OPT_IP_HDRINCL:
+ result = esock_setopt_lvl_ip_hdrincl(env, descP, eVal);
break;
#endif
#if defined(IP_MINTTL)
- case SOCKET_OPT_IP_MINTTL:
- result = nsetopt_lvl_ip_minttl(env, descP, eVal);
+ case ESOCK_OPT_IP_MINTTL:
+ result = esock_setopt_lvl_ip_minttl(env, descP, eVal);
break;
#endif
#if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE)
- case SOCKET_OPT_IP_MSFILTER:
- result = nsetopt_lvl_ip_msfilter(env, descP, eVal);
+ case ESOCK_OPT_IP_MSFILTER:
+ result = esock_setopt_lvl_ip_msfilter(env, descP, eVal);
break;
#endif
#if defined(IP_MTU_DISCOVER)
- case SOCKET_OPT_IP_MTU_DISCOVER:
- result = nsetopt_lvl_ip_mtu_discover(env, descP, eVal);
+ case ESOCK_OPT_IP_MTU_DISCOVER:
+ result = esock_setopt_lvl_ip_mtu_discover(env, descP, eVal);
break;
#endif
#if defined(IP_MULTICAST_ALL)
- case SOCKET_OPT_IP_MULTICAST_ALL:
- result = nsetopt_lvl_ip_multicast_all(env, descP, eVal);
+ case ESOCK_OPT_IP_MULTICAST_ALL:
+ result = esock_setopt_lvl_ip_multicast_all(env, descP, eVal);
break;
#endif
#if defined(IP_MULTICAST_IF)
- case SOCKET_OPT_IP_MULTICAST_IF:
- result = nsetopt_lvl_ip_multicast_if(env, descP, eVal);
+ case ESOCK_OPT_IP_MULTICAST_IF:
+ result = esock_setopt_lvl_ip_multicast_if(env, descP, eVal);
break;
#endif
#if defined(IP_MULTICAST_LOOP)
- case SOCKET_OPT_IP_MULTICAST_LOOP:
- result = nsetopt_lvl_ip_multicast_loop(env, descP, eVal);
+ case ESOCK_OPT_IP_MULTICAST_LOOP:
+ result = esock_setopt_lvl_ip_multicast_loop(env, descP, eVal);
break;
#endif
#if defined(IP_MULTICAST_TTL)
- case SOCKET_OPT_IP_MULTICAST_TTL:
- result = nsetopt_lvl_ip_multicast_ttl(env, descP, eVal);
+ case ESOCK_OPT_IP_MULTICAST_TTL:
+ result = esock_setopt_lvl_ip_multicast_ttl(env, descP, eVal);
break;
#endif
#if defined(IP_NODEFRAG)
- case SOCKET_OPT_IP_NODEFRAG:
- result = nsetopt_lvl_ip_nodefrag(env, descP, eVal);
+ case ESOCK_OPT_IP_NODEFRAG:
+ result = esock_setopt_lvl_ip_nodefrag(env, descP, eVal);
break;
#endif
#if defined(IP_PKTINFO)
- case SOCKET_OPT_IP_PKTINFO:
- result = nsetopt_lvl_ip_pktinfo(env, descP, eVal);
+ case ESOCK_OPT_IP_PKTINFO:
+ result = esock_setopt_lvl_ip_pktinfo(env, descP, eVal);
break;
#endif
#if defined(IP_RECVDSTADDR)
- case SOCKET_OPT_IP_RECVDSTADDR:
- result = nsetopt_lvl_ip_recvdstaddr(env, descP, eVal);
+ case ESOCK_OPT_IP_RECVDSTADDR:
+ result = esock_setopt_lvl_ip_recvdstaddr(env, descP, eVal);
break;
#endif
#if defined(IP_RECVERR)
- case SOCKET_OPT_IP_RECVERR:
- result = nsetopt_lvl_ip_recverr(env, descP, eVal);
+ case ESOCK_OPT_IP_RECVERR:
+ result = esock_setopt_lvl_ip_recverr(env, descP, eVal);
break;
#endif
#if defined(IP_RECVIF)
- case SOCKET_OPT_IP_RECVIF:
- result = nsetopt_lvl_ip_recvif(env, descP, eVal);
+ case ESOCK_OPT_IP_RECVIF:
+ result = esock_setopt_lvl_ip_recvif(env, descP, eVal);
break;
#endif
#if defined(IP_RECVOPTS)
- case SOCKET_OPT_IP_RECVOPTS:
- result = nsetopt_lvl_ip_recvopts(env, descP, eVal);
+ case ESOCK_OPT_IP_RECVOPTS:
+ result = esock_setopt_lvl_ip_recvopts(env, descP, eVal);
break;
#endif
#if defined(IP_RECVORIGDSTADDR)
- case SOCKET_OPT_IP_RECVORIGDSTADDR:
- result = nsetopt_lvl_ip_recvorigdstaddr(env, descP, eVal);
+ case ESOCK_OPT_IP_RECVORIGDSTADDR:
+ result = esock_setopt_lvl_ip_recvorigdstaddr(env, descP, eVal);
break;
#endif
#if defined(IP_RECVTOS)
- case SOCKET_OPT_IP_RECVTOS:
- result = nsetopt_lvl_ip_recvtos(env, descP, eVal);
+ case ESOCK_OPT_IP_RECVTOS:
+ result = esock_setopt_lvl_ip_recvtos(env, descP, eVal);
break;
#endif
#if defined(IP_RECVTTL)
- case SOCKET_OPT_IP_RECVTTL:
- result = nsetopt_lvl_ip_recvttl(env, descP, eVal);
+ case ESOCK_OPT_IP_RECVTTL:
+ result = esock_setopt_lvl_ip_recvttl(env, descP, eVal);
break;
#endif
#if defined(IP_RETOPTS)
- case SOCKET_OPT_IP_RETOPTS:
- result = nsetopt_lvl_ip_retopts(env, descP, eVal);
+ case ESOCK_OPT_IP_RETOPTS:
+ result = esock_setopt_lvl_ip_retopts(env, descP, eVal);
break;
#endif
#if defined(IP_ROUTER_ALERT)
- case SOCKET_OPT_IP_ROUTER_ALERT:
- result = nsetopt_lvl_ip_router_alert(env, descP, eVal);
+ case ESOCK_OPT_IP_ROUTER_ALERT:
+ result = esock_setopt_lvl_ip_router_alert(env, descP, eVal);
break;
#endif
#if defined(IP_SENDSRCADDR)
- case SOCKET_OPT_IP_SENDSRCADDR:
- result = nsetopt_lvl_ip_sendsrcaddr(env, descP, eVal);
+ case ESOCK_OPT_IP_SENDSRCADDR:
+ result = esock_setopt_lvl_ip_sendsrcaddr(env, descP, eVal);
break;
#endif
#if defined(IP_TOS)
- case SOCKET_OPT_IP_TOS:
- result = nsetopt_lvl_ip_tos(env, descP, eVal);
+ case ESOCK_OPT_IP_TOS:
+ result = esock_setopt_lvl_ip_tos(env, descP, eVal);
break;
#endif
#if defined(IP_TRANSPARENT)
- case SOCKET_OPT_IP_TRANSPARENT:
- result = nsetopt_lvl_ip_transparent(env, descP, eVal);
+ case ESOCK_OPT_IP_TRANSPARENT:
+ result = esock_setopt_lvl_ip_transparent(env, descP, eVal);
break;
#endif
#if defined(IP_TTL)
- case SOCKET_OPT_IP_TTL:
- result = nsetopt_lvl_ip_ttl(env, descP, eVal);
+ case ESOCK_OPT_IP_TTL:
+ result = esock_setopt_lvl_ip_ttl(env, descP, eVal);
break;
#endif
#if defined(IP_UNBLOCK_SOURCE)
- case SOCKET_OPT_IP_UNBLOCK_SOURCE:
- result = nsetopt_lvl_ip_unblock_source(env, descP, eVal);
+ case ESOCK_OPT_IP_UNBLOCK_SOURCE:
+ result = esock_setopt_lvl_ip_unblock_source(env, descP, eVal);
break;
#endif
default:
- SSDBG( descP, ("SOCKET", "nsetopt_lvl_ip -> unknown opt (%d)\r\n", eOpt) );
+ SSDBG( descP, ("SOCKET",
+ "esock_setopt_lvl_ip -> unknown opt (%d)\r\n", eOpt) );
result = esock_make_error(env, esock_atom_einval);
break;
}
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip -> done when"
+ ("SOCKET", "esock_setopt_lvl_ip -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -8637,7 +8660,7 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
}
-/* nsetopt_lvl_ip_add_membership - Level IP ADD_MEMBERSHIP option
+/* esock_setopt_lvl_ip_add_membership - Level IP ADD_MEMBERSHIP option
*
* The value is a map with two attributes: multiaddr and interface.
* The attribute 'multiaddr' is always a 4-tuple (IPv4 address).
@@ -8646,16 +8669,18 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env,
*/
#if defined(IP_ADD_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ip_update_membership(env, descP, eVal, IP_ADD_MEMBERSHIP);
+ return esock_setopt_lvl_ip_update_membership(env, descP, eVal,
+ IP_ADD_MEMBERSHIP);
}
#endif
-/* nsetopt_lvl_ip_add_source_membership - Level IP ADD_SOURCE_MEMBERSHIP option
+/* esock_setopt_lvl_ip_add_source_membership -
+ * Level IP ADD_SOURCE_MEMBERSHIP option
*
* The value is a map with three attributes: multiaddr, interface and
* sourceaddr.
@@ -8666,17 +8691,17 @@ ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env,
*/
#if defined(IP_ADD_SOURCE_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_add_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ip_update_source(env, descP, eVal,
- IP_ADD_SOURCE_MEMBERSHIP);
+ return esock_setopt_lvl_ip_update_source(env, descP, eVal,
+ IP_ADD_SOURCE_MEMBERSHIP);
}
#endif
-/* nsetopt_lvl_ip_block_source - Level IP BLOCK_SOURCE option
+/* esock_setopt_lvl_ip_block_source - Level IP BLOCK_SOURCE option
*
* The value is a map with three attributes: multiaddr, interface and
* sourceaddr.
@@ -8687,16 +8712,16 @@ ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env,
*/
#if defined(IP_BLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_block_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ip_update_source(env, descP, eVal, IP_BLOCK_SOURCE);
+ return esock_setopt_lvl_ip_update_source(env, descP, eVal, IP_BLOCK_SOURCE);
}
#endif
-/* nsetopt_lvl_ip_drop_membership - Level IP DROP_MEMBERSHIP option
+/* esock_setopt_lvl_ip_drop_membership - Level IP DROP_MEMBERSHIP option
*
* The value is a map with two attributes: multiaddr and interface.
* The attribute 'multiaddr' is always a 4-tuple (IPv4 address).
@@ -8709,18 +8734,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env,
*/
#if defined(IP_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ip_update_membership(env, descP, eVal,
- IP_DROP_MEMBERSHIP);
+ return esock_setopt_lvl_ip_update_membership(env, descP, eVal,
+ IP_DROP_MEMBERSHIP);
}
#endif
-/* nsetopt_lvl_ip_drop_source_membership - Level IP DROP_SOURCE_MEMBERSHIP option
+/* esock_setopt_lvl_ip_drop_source_membership -
+ * Level IP DROP_SOURCE_MEMBERSHIP option
*
* The value is a map with three attributes: multiaddr, interface and
* sourceaddr.
@@ -8731,24 +8757,24 @@ ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env,
*/
#if defined(IP_DROP_SOURCE_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_drop_source_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ip_update_source(env, descP, eVal,
- IP_DROP_SOURCE_MEMBERSHIP);
+ return esock_setopt_lvl_ip_update_source(env, descP, eVal,
+ IP_DROP_SOURCE_MEMBERSHIP);
}
#endif
-/* nsetopt_lvl_ip_freebind - Level IP FREEBIND option
+/* esock_setopt_lvl_ip_freebind - Level IP FREEBIND option
*/
#if defined(IP_FREEBIND)
static
-ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8756,19 +8782,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_FREEBIND, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_FREEBIND, eVal);
}
#endif
-/* nsetopt_lvl_ip_hdrincl - Level IP HDRINCL option
+/* esock_setopt_lvl_ip_hdrincl - Level IP HDRINCL option
*/
#if defined(IP_HDRINCL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8776,19 +8802,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_HDRINCL, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_HDRINCL, eVal);
}
#endif
-/* nsetopt_lvl_ip_minttl - Level IP MINTTL option
+/* esock_setopt_lvl_ip_minttl - Level IP MINTTL option
*/
#if defined(IP_MINTTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8796,26 +8822,26 @@ ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_int_opt(env, descP, level, IP_MINTTL, eVal);
+ return esock_setopt_int_opt(env, descP, level, IP_MINTTL, eVal);
}
#endif
-/* nsetopt_lvl_ip_msfilter - Level IP MSFILTER option
+/* esock_setopt_lvl_ip_msfilter - Level IP MSFILTER option
*
* The value can be *either* the atom 'null' or a map of type ip_msfilter().
*/
#if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_msfilter(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
if (COMPARE(eVal, atom_null) == 0) {
- return nsetopt_lvl_ip_msfilter_set(env, descP->sock, NULL, 0);
+ return esock_setopt_lvl_ip_msfilter_set(env, descP->sock, NULL, 0);
} else {
struct ip_msfilter* msfP;
Uint32 msfSz;
@@ -8880,7 +8906,8 @@ ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env,
}
/* And now, finally, set the option */
- result = nsetopt_lvl_ip_msfilter_set(env, descP->sock, msfP, msfSz);
+ result = esock_setopt_lvl_ip_msfilter_set(env, descP->sock,
+ msfP, msfSz);
FREE(msfP);
return result;
}
@@ -8910,10 +8937,10 @@ BOOLEAN_T decode_ip_msfilter_mode(ErlNifEnv* env,
static
-ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env,
- SOCKET sock,
- struct ip_msfilter* msfP,
- SOCKLEN_T optLen)
+ERL_NIF_TERM esock_setopt_lvl_ip_msfilter_set(ErlNifEnv* env,
+ SOCKET sock,
+ struct ip_msfilter* msfP,
+ SOCKLEN_T optLen)
{
ERL_NIF_TERM result;
int res;
@@ -8935,15 +8962,15 @@ ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env,
-/* nsetopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option
+/* esock_setopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option
*
* The value is an atom of the type ip_pmtudisc().
*/
#if defined(IP_MTU_DISCOVER)
static
-ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int val;
@@ -8976,13 +9003,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
#endif
-/* nsetopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option
+/* esock_setopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option
*/
#if defined(IP_MULTICAST_ALL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -8990,20 +9017,20 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_MULTICAST_ALL, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_MULTICAST_ALL, eVal);
}
#endif
-/* nsetopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option
+/* esock_setopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option
*
* The value is either the atom 'any' or a 4-tuple.
*/
#if defined(IP_MULTICAST_IF)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
struct in_addr ifAddr;
@@ -9034,13 +9061,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env,
#endif
-/* nsetopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option
+/* esock_setopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option
*/
#if defined(IP_MULTICAST_LOOP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9048,18 +9075,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP, eVal);
}
#endif
-/* nsetopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option
+/* esock_setopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option
*/
#if defined(IP_MULTICAST_TTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9067,18 +9094,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_int_opt(env, descP, level, IP_MULTICAST_TTL, eVal);
+ return esock_setopt_int_opt(env, descP, level, IP_MULTICAST_TTL, eVal);
}
#endif
-/* nsetopt_lvl_ip_nodefrag - Level IP NODEFRAG option
+/* esock_setopt_lvl_ip_nodefrag - Level IP NODEFRAG option
*/
#if defined(IP_NODEFRAG)
static
-ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9086,18 +9113,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_NODEFRAG, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_NODEFRAG, eVal);
}
#endif
-/* nsetopt_lvl_ip_pktinfo - Level IP PKTINFO option
+/* esock_setopt_lvl_ip_pktinfo - Level IP PKTINFO option
*/
#if defined(IP_PKTINFO)
static
-ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9105,18 +9132,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_PKTINFO, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_PKTINFO, eVal);
}
#endif
-/* nsetopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option
+/* esock_setopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option
*/
#if defined(IP_RECVDSTADDR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9124,18 +9151,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RECVDSTADDR, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RECVDSTADDR, eVal);
}
#endif
-/* nsetopt_lvl_ip_recverr - Level IP RECVERR option
+/* esock_setopt_lvl_ip_recverr - Level IP RECVERR option
*/
#if defined(IP_RECVERR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9143,18 +9170,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RECVERR, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RECVERR, eVal);
}
#endif
-/* nsetopt_lvl_ip_recvif - Level IP RECVIF option
+/* esock_setopt_lvl_ip_recvif - Level IP RECVIF option
*/
#if defined(IP_RECVIF)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9162,18 +9189,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RECVIF, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RECVIF, eVal);
}
#endif
-/* nsetopt_lvl_ip_recvopts - Level IP RECVOPTS option
+/* esock_setopt_lvl_ip_recvopts - Level IP RECVOPTS option
*/
#if defined(IP_RECVOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9181,18 +9208,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RECVOPTS, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RECVOPTS, eVal);
}
#endif
-/* nsetopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option
+/* esock_setopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option
*/
#if defined(IP_RECVORIGDSTADDR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9200,18 +9227,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR, eVal);
}
#endif
-/* nsetopt_lvl_ip_recvtos - Level IP RECVTOS option
+/* esock_setopt_lvl_ip_recvtos - Level IP RECVTOS option
*/
#if defined(IP_RECVTOS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9219,18 +9246,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RECVTOS, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RECVTOS, eVal);
}
#endif
-/* nsetopt_lvl_ip_recvttl - Level IP RECVTTL option
+/* esock_setopt_lvl_ip_recvttl - Level IP RECVTTL option
*/
#if defined(IP_RECVTTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9238,18 +9265,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RECVTTL, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RECVTTL, eVal);
}
#endif
-/* nsetopt_lvl_ip_retopts - Level IP RETOPTS option
+/* esock_setopt_lvl_ip_retopts - Level IP RETOPTS option
*/
#if defined(IP_RETOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_retopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9257,18 +9284,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_RETOPTS, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_RETOPTS, eVal);
}
#endif
-/* nsetopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option
+/* esock_setopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option
*/
#if defined(IP_ROUTER_ALERT)
static
-ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9276,18 +9303,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_int_opt(env, descP, level, IP_ROUTER_ALERT, eVal);
+ return esock_setopt_int_opt(env, descP, level, IP_ROUTER_ALERT, eVal);
}
#endif
-/* nsetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option
+/* esock_setopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option
*/
#if defined(IP_SENDSRCADDR)
static
-ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9295,18 +9322,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_SENDSRCADDR, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_SENDSRCADDR, eVal);
}
#endif
-/* nsetopt_lvl_ip_tos - Level IP TOS option
+/* esock_setopt_lvl_ip_tos - Level IP TOS option
*/
#if defined(IP_TOS)
static
-ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9333,13 +9360,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env,
#endif
-/* nsetopt_lvl_ip_transparent - Level IP TRANSPARENT option
+/* esock_setopt_lvl_ip_transparent - Level IP TRANSPARENT option
*/
#if defined(IP_TRANSPARENT)
static
-ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9347,19 +9374,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_bool_opt(env, descP, level, IP_TRANSPARENT, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IP_TRANSPARENT, eVal);
}
#endif
-/* nsetopt_lvl_ip_ttl - Level IP TTL option
+/* esock_setopt_lvl_ip_ttl - Level IP TTL option
*/
#if defined(IP_TTL)
static
-ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -9367,13 +9394,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return nsetopt_int_opt(env, descP, level, IP_TTL, eVal);
+ return esock_setopt_int_opt(env, descP, level, IP_TTL, eVal);
}
#endif
-/* nsetopt_lvl_ip_unblock_source - Level IP UNBLOCK_SOURCE option
+/* esock_setopt_lvl_ip_unblock_source - Level IP UNBLOCK_SOURCE option
*
* The value is a map with three attributes: multiaddr, interface and
* sourceaddr.
@@ -9384,11 +9411,12 @@ ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env,
*/
#if defined(IP_UNBLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ip_unblock_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ip_update_source(env, descP, eVal, IP_UNBLOCK_SOURCE);
+ return esock_setopt_lvl_ip_update_source(env, descP, eVal,
+ IP_UNBLOCK_SOURCE);
}
#endif
@@ -9396,10 +9424,10 @@ ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env,
#if defined(IP_ADD_MEMBERSHIP) || defined(IP_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt)
+ERL_NIF_TERM esock_setopt_lvl_ip_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt)
{
ERL_NIF_TERM result, eMultiAddr, eInterface;
struct ip_mreq mreq;
@@ -9415,7 +9443,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
// It must be a map
if (!IS_MAP(env, eVal)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"value *not* a map\r\n") );
return enif_make_badarg(env);
}
@@ -9423,21 +9451,21 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
// It must have atleast two attributes
if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"invalid map value: %T\r\n", eVal) );
return enif_make_badarg(env);
}
if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"failed get multiaddr (map) attribute\r\n") );
return enif_make_badarg(env);
}
if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"failed get interface (map) attribute\r\n") );
return enif_make_badarg(env);
}
@@ -9446,7 +9474,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
eMultiAddr,
&mreq.imr_multiaddr)) != NULL) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) );
return esock_make_error_str(env, xres);
}
@@ -9455,7 +9483,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
eInterface,
&mreq.imr_interface)) != NULL) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"failed decode interface %T: %s\r\n", eInterface, xres) );
return esock_make_error_str(env, xres);
}
@@ -9468,7 +9496,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
result = esock_make_error_errno(env, save_errno);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"failed setopt: %T (%d)\r\n", result, save_errno) );
} else {
@@ -9482,10 +9510,10 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env,
#if defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(IP_DROP_SOURCE_MEMBERSHIP) || defined(IP_BLOCK_SOURCE) || defined(IP_UNBLOCK_SOURCE)
static
-ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt)
+ERL_NIF_TERM esock_setopt_lvl_ip_update_source(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt)
{
ERL_NIF_TERM result, eMultiAddr, eInterface, eSourceAddr;
struct ip_mreq_source mreq;
@@ -9545,146 +9573,147 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env,
/* *** Handling set of socket options for level = ipv6 *** */
-/* nsetopt_lvl_ipv6 - Level *IPv6* option(s)
+/* esock_setopt_lvl_ipv6 - Level *IPv6* option(s)
*/
#if defined(HAVE_IPV6)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6 -> entry with"
+ ("SOCKET", "esock_setopt_lvl_ipv6 -> entry with"
"\r\n opt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(IPV6_ADDRFORM)
- case SOCKET_OPT_IPV6_ADDRFORM:
- result = nsetopt_lvl_ipv6_addrform(env, descP, eVal);
+ case ESOCK_OPT_IPV6_ADDRFORM:
+ result = esock_setopt_lvl_ipv6_addrform(env, descP, eVal);
break;
#endif
#if defined(IPV6_ADD_MEMBERSHIP)
- case SOCKET_OPT_IPV6_ADD_MEMBERSHIP:
- result = nsetopt_lvl_ipv6_add_membership(env, descP, eVal);
+ case ESOCK_OPT_IPV6_ADD_MEMBERSHIP:
+ result = esock_setopt_lvl_ipv6_add_membership(env, descP, eVal);
break;
#endif
#if defined(IPV6_AUTHHDR)
- case SOCKET_OPT_IPV6_AUTHHDR:
- result = nsetopt_lvl_ipv6_authhdr(env, descP, eVal);
+ case ESOCK_OPT_IPV6_AUTHHDR:
+ result = esock_setopt_lvl_ipv6_authhdr(env, descP, eVal);
break;
#endif
#if defined(IPV6_DROP_MEMBERSHIP)
- case SOCKET_OPT_IPV6_DROP_MEMBERSHIP:
- result = nsetopt_lvl_ipv6_drop_membership(env, descP, eVal);
+ case ESOCK_OPT_IPV6_DROP_MEMBERSHIP:
+ result = esock_setopt_lvl_ipv6_drop_membership(env, descP, eVal);
break;
#endif
#if defined(IPV6_DSTOPTS)
- case SOCKET_OPT_IPV6_DSTOPTS:
- result = nsetopt_lvl_ipv6_dstopts(env, descP, eVal);
+ case ESOCK_OPT_IPV6_DSTOPTS:
+ result = esock_setopt_lvl_ipv6_dstopts(env, descP, eVal);
break;
#endif
#if defined(IPV6_FLOWINFO)
- case SOCKET_OPT_IPV6_FLOWINFO:
- result = nsetopt_lvl_ipv6_flowinfo(env, descP, eVal);
+ case ESOCK_OPT_IPV6_FLOWINFO:
+ result = esock_setopt_lvl_ipv6_flowinfo(env, descP, eVal);
break;
#endif
#if defined(IPV6_HOPLIMIT)
- case SOCKET_OPT_IPV6_HOPLIMIT:
- result = nsetopt_lvl_ipv6_hoplimit(env, descP, eVal);
+ case ESOCK_OPT_IPV6_HOPLIMIT:
+ result = esock_setopt_lvl_ipv6_hoplimit(env, descP, eVal);
break;
#endif
#if defined(IPV6_HOPOPTS)
- case SOCKET_OPT_IPV6_HOPOPTS:
- result = nsetopt_lvl_ipv6_hopopts(env, descP, eVal);
+ case ESOCK_OPT_IPV6_HOPOPTS:
+ result = esock_setopt_lvl_ipv6_hopopts(env, descP, eVal);
break;
#endif
#if defined(IPV6_MTU)
- case SOCKET_OPT_IPV6_MTU:
- result = nsetopt_lvl_ipv6_mtu(env, descP, eVal);
+ case ESOCK_OPT_IPV6_MTU:
+ result = esock_setopt_lvl_ipv6_mtu(env, descP, eVal);
break;
#endif
#if defined(IPV6_MTU_DISCOVER)
- case SOCKET_OPT_IPV6_MTU_DISCOVER:
- result = nsetopt_lvl_ipv6_mtu_discover(env, descP, eVal);
+ case ESOCK_OPT_IPV6_MTU_DISCOVER:
+ result = esock_setopt_lvl_ipv6_mtu_discover(env, descP, eVal);
break;
#endif
#if defined(IPV6_MULTICAST_HOPS)
- case SOCKET_OPT_IPV6_MULTICAST_HOPS:
- result = nsetopt_lvl_ipv6_multicast_hops(env, descP, eVal);
+ case ESOCK_OPT_IPV6_MULTICAST_HOPS:
+ result = esock_setopt_lvl_ipv6_multicast_hops(env, descP, eVal);
break;
#endif
#if defined(IPV6_MULTICAST_IF)
- case SOCKET_OPT_IPV6_MULTICAST_IF:
- result = nsetopt_lvl_ipv6_multicast_if(env, descP, eVal);
+ case ESOCK_OPT_IPV6_MULTICAST_IF:
+ result = esock_setopt_lvl_ipv6_multicast_if(env, descP, eVal);
break;
#endif
#if defined(IPV6_MULTICAST_LOOP)
- case SOCKET_OPT_IPV6_MULTICAST_LOOP:
- result = nsetopt_lvl_ipv6_multicast_loop(env, descP, eVal);
+ case ESOCK_OPT_IPV6_MULTICAST_LOOP:
+ result = esock_setopt_lvl_ipv6_multicast_loop(env, descP, eVal);
break;
#endif
#if defined(IPV6_RECVERR)
- case SOCKET_OPT_IPV6_RECVERR:
- result = nsetopt_lvl_ipv6_recverr(env, descP, eVal);
+ case ESOCK_OPT_IPV6_RECVERR:
+ result = esock_setopt_lvl_ipv6_recverr(env, descP, eVal);
break;
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
- case SOCKET_OPT_IPV6_RECVPKTINFO:
- result = nsetopt_lvl_ipv6_recvpktinfo(env, descP, eVal);
+ case ESOCK_OPT_IPV6_RECVPKTINFO:
+ result = esock_setopt_lvl_ipv6_recvpktinfo(env, descP, eVal);
break;
#endif
#if defined(IPV6_ROUTER_ALERT)
- case SOCKET_OPT_IPV6_ROUTER_ALERT:
- result = nsetopt_lvl_ipv6_router_alert(env, descP, eVal);
+ case ESOCK_OPT_IPV6_ROUTER_ALERT:
+ result = esock_setopt_lvl_ipv6_router_alert(env, descP, eVal);
break;
#endif
#if defined(IPV6_RTHDR)
- case SOCKET_OPT_IPV6_RTHDR:
- result = nsetopt_lvl_ipv6_rthdr(env, descP, eVal);
+ case ESOCK_OPT_IPV6_RTHDR:
+ result = esock_setopt_lvl_ipv6_rthdr(env, descP, eVal);
break;
#endif
#if defined(IPV6_UNICAST_HOPS)
- case SOCKET_OPT_IPV6_UNICAST_HOPS:
- result = nsetopt_lvl_ipv6_unicast_hops(env, descP, eVal);
+ case ESOCK_OPT_IPV6_UNICAST_HOPS:
+ result = esock_setopt_lvl_ipv6_unicast_hops(env, descP, eVal);
break;
#endif
#if defined(IPV6_V6ONLY)
- case SOCKET_OPT_IPV6_V6ONLY:
- result = nsetopt_lvl_ipv6_v6only(env, descP, eVal);
+ case ESOCK_OPT_IPV6_V6ONLY:
+ result = esock_setopt_lvl_ipv6_v6only(env, descP, eVal);
break;
#endif
default:
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6 -> unknown opt (%d)\r\n", eOpt) );
+ ("SOCKET",
+ "esock_setopt_lvl_ipv6 -> unknown opt (%d)\r\n", eOpt) );
result = esock_make_error(env, esock_atom_einval);
break;
}
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6 -> done when"
+ ("SOCKET", "esock_setopt_lvl_ipv6 -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -9694,15 +9723,15 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env,
#if defined(IPV6_ADDRFORM)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_addrform(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int res, edomain, domain;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_addrform -> entry with"
+ ("SOCKET", "esock_setopt_lvl_ipv6_addrform -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
@@ -9710,14 +9739,15 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_addrform -> decode"
+ ("SOCKET", "esock_setopt_lvl_ipv6_addrform -> decode"
"\r\n edomain: %d"
"\r\n", edomain) );
if (!edomain2domain(edomain, &domain))
return esock_make_error(env, esock_atom_einval);
- SSDBG( descP, ("SOCKET", "nsetopt_lvl_ipv6_addrform -> try set opt to %d\r\n",
+ SSDBG( descP, ("SOCKET",
+ "esock_setopt_lvl_ipv6_addrform -> try set opt to %d\r\n",
domain) );
res = socket_setopt(descP->sock,
@@ -9736,11 +9766,11 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env,
#if defined(IPV6_ADD_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_add_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ipv6_update_membership(env, descP, eVal,
+ return esock_setopt_lvl_ipv6_update_membership(env, descP, eVal,
IPV6_ADD_MEMBERSHIP);
}
#endif
@@ -9748,22 +9778,22 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env,
#if defined(IPV6_AUTHHDR)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR, eVal);
+ return esock_setopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR, eVal);
}
#endif
#if defined(IPV6_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_lvl_ipv6_update_membership(env, descP, eVal,
+ return esock_setopt_lvl_ipv6_update_membership(env, descP, eVal,
IPV6_DROP_MEMBERSHIP);
}
#endif
@@ -9771,9 +9801,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env,
#if defined(IPV6_DSTOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9781,16 +9811,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_DSTOPTS, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_DSTOPTS, eVal);
}
#endif
#if defined(IPV6_FLOWINFO)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9798,16 +9828,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_FLOWINFO, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_FLOWINFO, eVal);
}
#endif
#if defined(IPV6_HOPLIMIT)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9815,16 +9845,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_HOPLIMIT, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_HOPLIMIT, eVal);
}
#endif
#if defined(IPV6_HOPOPTS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9832,14 +9862,14 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_HOPOPTS, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_HOPOPTS, eVal);
}
#endif
#if defined(IPV6_MTU)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM eVal)
{
@@ -9849,20 +9879,20 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_int_opt(env, descP, level, IPV6_MTU, eVal);
+ return esock_setopt_int_opt(env, descP, level, IPV6_MTU, eVal);
}
#endif
-/* nsetopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option
+/* esock_setopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option
*
* The value is an atom of the type ipv6_pmtudisc().
*/
#if defined(IPV6_MTU_DISCOVER)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int val;
@@ -9898,9 +9928,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_HOPS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9908,7 +9938,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS, eVal);
+ return esock_setopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS, eVal);
}
#endif
@@ -9916,9 +9946,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_IF)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9926,7 +9956,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_int_opt(env, descP, level, IPV6_MULTICAST_IF, eVal);
+ return esock_setopt_int_opt(env, descP, level, IPV6_MULTICAST_IF, eVal);
}
#endif
@@ -9934,9 +9964,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_LOOP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9944,16 +9974,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP, eVal);
}
#endif
#if defined(IPV6_RECVERR)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9961,16 +9991,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_RECVERR, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_RECVERR, eVal);
}
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -9983,16 +10013,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
int opt = IPV6_PKTINFO;
#endif
- return nsetopt_bool_opt(env, descP, level, opt, eVal);
+ return esock_setopt_bool_opt(env, descP, level, opt, eVal);
}
#endif
#if defined(IPV6_ROUTER_ALERT)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -10000,7 +10030,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT, eVal);
+ return esock_setopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT, eVal);
}
#endif
@@ -10008,9 +10038,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
#if defined(IPV6_RTHDR)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -10018,16 +10048,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_RTHDR, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_RTHDR, eVal);
}
#endif
#if defined(IPV6_UNICAST_HOPS)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -10035,7 +10065,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS, eVal);
+ return esock_setopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS, eVal);
}
#endif
@@ -10043,9 +10073,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
#if defined(IPV6_V6ONLY)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -10053,17 +10083,17 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return nsetopt_bool_opt(env, descP, level, IPV6_V6ONLY, eVal);
+ return esock_setopt_bool_opt(env, descP, level, IPV6_V6ONLY, eVal);
}
#endif
#if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP)
static
-ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal,
- int opt)
+ERL_NIF_TERM esock_setopt_lvl_ipv6_update_membership(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal,
+ int opt)
{
ERL_NIF_TERM result, eMultiAddr, eInterface;
struct ipv6_mreq mreq;
@@ -10079,7 +10109,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
// It must be a map
if (!IS_MAP(env, eVal)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> "
"value *not* a map\r\n") );
return enif_make_badarg(env);
}
@@ -10087,21 +10117,21 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
// It must have atleast two attributes
if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> "
"invalid map value: %T\r\n", eVal) );
return enif_make_badarg(env);
}
if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> "
"failed get multiaddr (map) attribute\r\n") );
return enif_make_badarg(env);
}
if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> "
"failed get interface (map) attribute\r\n") );
return enif_make_badarg(env);
}
@@ -10110,14 +10140,14 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
eMultiAddr,
&mreq.ipv6mr_multiaddr)) != NULL) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> "
"failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) );
return esock_make_error_str(env, xres);
}
if (!GET_UINT(env, eInterface, &mreq.ipv6mr_interface)) {
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ip_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ip_update_membership -> "
"failed decode interface %T: %s\r\n", eInterface, xres) );
return esock_make_error(env, esock_atom_einval);
}
@@ -10130,7 +10160,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
result = esock_make_error_errno(env, save_errno);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> "
+ ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> "
"failed setopt: %T (%d)\r\n", result, save_errno) );
} else {
@@ -10147,37 +10177,37 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env,
-/* nsetopt_lvl_tcp - Level *TCP* option(s)
+/* esock_setopt_lvl_tcp - Level *TCP* option(s)
*/
static
-ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_tcp -> entry with"
+ ("SOCKET", "esock_setopt_lvl_tcp -> entry with"
"\r\n opt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(TCP_CONGESTION)
- case SOCKET_OPT_TCP_CONGESTION:
- result = nsetopt_lvl_tcp_congestion(env, descP, eVal);
+ case ESOCK_OPT_TCP_CONGESTION:
+ result = esock_setopt_lvl_tcp_congestion(env, descP, eVal);
break;
#endif
#if defined(TCP_MAXSEG)
- case SOCKET_OPT_TCP_MAXSEG:
- result = nsetopt_lvl_tcp_maxseg(env, descP, eVal);
+ case ESOCK_OPT_TCP_MAXSEG:
+ result = esock_setopt_lvl_tcp_maxseg(env, descP, eVal);
break;
#endif
#if defined(TCP_NODELAY)
- case SOCKET_OPT_TCP_NODELAY:
- result = nsetopt_lvl_tcp_nodelay(env, descP, eVal);
+ case ESOCK_OPT_TCP_NODELAY:
+ result = esock_setopt_lvl_tcp_nodelay(env, descP, eVal);
break;
#endif
@@ -10190,67 +10220,68 @@ ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env,
}
-/* nsetopt_lvl_tcp_congestion - Level TCP CONGESTION option
+/* esock_setopt_lvl_tcp_congestion - Level TCP CONGESTION option
*/
#if defined(TCP_CONGESTION)
static
-ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- int max = SOCKET_OPT_TCP_CONGESTION_NAME_MAX+1;
+ int max = ESOCK_OPT_TCP_CONGESTION_NAME_MAX+1;
- return nsetopt_str_opt(env, descP, IPPROTO_TCP, TCP_CONGESTION, max, eVal);
+ return esock_setopt_str_opt(env, descP,
+ IPPROTO_TCP, TCP_CONGESTION, max, eVal);
}
#endif
-/* nsetopt_lvl_tcp_maxseg - Level TCP MAXSEG option
+/* esock_setopt_lvl_tcp_maxseg - Level TCP MAXSEG option
*/
#if defined(TCP_MAXSEG)
static
-ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG, eVal);
+ return esock_setopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG, eVal);
}
#endif
-/* nsetopt_lvl_tcp_nodelay - Level TCP NODELAY option
+/* esock_setopt_lvl_tcp_nodelay - Level TCP NODELAY option
*/
#if defined(TCP_NODELAY)
static
-ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY, eVal);
+ return esock_setopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY, eVal);
}
#endif
-/* nsetopt_lvl_udp - Level *UDP* option(s)
+/* esock_setopt_lvl_udp - Level *UDP* option(s)
*/
static
-ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_udp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_udp -> entry with"
+ ("SOCKET", "esock_setopt_lvl_udp -> entry with"
"\r\n opt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(UDP_CORK)
- case SOCKET_OPT_UDP_CORK:
- result = nsetopt_lvl_udp_cork(env, descP, eVal);
+ case ESOCK_OPT_UDP_CORK:
+ result = esock_setopt_lvl_udp_cork(env, descP, eVal);
break;
#endif
@@ -10263,83 +10294,83 @@ ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env,
}
-/* nsetopt_lvl_udp_cork - Level UDP CORK option
+/* esock_setopt_lvl_udp_cork - Level UDP CORK option
*/
#if defined(UDP_CORK)
static
-ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK, eVal);
+ return esock_setopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK, eVal);
}
#endif
-/* nsetopt_lvl_sctp - Level *SCTP* option(s)
+/* esock_setopt_lvl_sctp - Level *SCTP* option(s)
*/
#if defined(HAVE_SCTP)
static
-ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp -> entry with"
+ ("SOCKET", "esock_setopt_lvl_sctp -> entry with"
"\r\n opt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(SCTP_ASSOCINFO)
- case SOCKET_OPT_SCTP_ASSOCINFO:
- result = nsetopt_lvl_sctp_associnfo(env, descP, eVal);
+ case ESOCK_OPT_SCTP_ASSOCINFO:
+ result = esock_setopt_lvl_sctp_associnfo(env, descP, eVal);
break;
#endif
#if defined(SCTP_AUTOCLOSE)
- case SOCKET_OPT_SCTP_AUTOCLOSE:
- result = nsetopt_lvl_sctp_autoclose(env, descP, eVal);
+ case ESOCK_OPT_SCTP_AUTOCLOSE:
+ result = esock_setopt_lvl_sctp_autoclose(env, descP, eVal);
break;
#endif
#if defined(SCTP_DISABLE_FRAGMENTS)
- case SOCKET_OPT_SCTP_DISABLE_FRAGMENTS:
- result = nsetopt_lvl_sctp_disable_fragments(env, descP, eVal);
+ case ESOCK_OPT_SCTP_DISABLE_FRAGMENTS:
+ result = esock_setopt_lvl_sctp_disable_fragments(env, descP, eVal);
break;
#endif
#if defined(SCTP_EVENTS)
- case SOCKET_OPT_SCTP_EVENTS:
- result = nsetopt_lvl_sctp_events(env, descP, eVal);
+ case ESOCK_OPT_SCTP_EVENTS:
+ result = esock_setopt_lvl_sctp_events(env, descP, eVal);
break;
#endif
#if defined(SCTP_INITMSG)
- case SOCKET_OPT_SCTP_INITMSG:
- result = nsetopt_lvl_sctp_initmsg(env, descP, eVal);
+ case ESOCK_OPT_SCTP_INITMSG:
+ result = esock_setopt_lvl_sctp_initmsg(env, descP, eVal);
break;
#endif
#if defined(SCTP_MAXSEG)
- case SOCKET_OPT_SCTP_MAXSEG:
- result = nsetopt_lvl_sctp_maxseg(env, descP, eVal);
+ case ESOCK_OPT_SCTP_MAXSEG:
+ result = esock_setopt_lvl_sctp_maxseg(env, descP, eVal);
break;
#endif
#if defined(SCTP_NODELAY)
- case SOCKET_OPT_SCTP_NODELAY:
- result = nsetopt_lvl_sctp_nodelay(env, descP, eVal);
+ case ESOCK_OPT_SCTP_NODELAY:
+ result = esock_setopt_lvl_sctp_nodelay(env, descP, eVal);
break;
#endif
#if defined(SCTP_RTOINFO)
- case SOCKET_OPT_SCTP_RTOINFO:
- result = nsetopt_lvl_sctp_rtoinfo(env, descP, eVal);
+ case ESOCK_OPT_SCTP_RTOINFO:
+ result = esock_setopt_lvl_sctp_rtoinfo(env, descP, eVal);
break;
#endif
@@ -10352,13 +10383,13 @@ ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env,
}
-/* nsetopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option
+/* esock_setopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option
*/
#if defined(SCTP_ASSOCINFO)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eAssocId, eMaxRxt, eNumPeerDests;
@@ -10369,7 +10400,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
unsigned int tmp;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_associnfo -> entry with"
+ ("SOCKET", "esock_setopt_lvl_sctp_associnfo -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
@@ -10382,7 +10413,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_associnfo -> extract attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_associnfo -> extract attributes\r\n") );
if (!GET_MAP_VAL(env, eVal, atom_assoc_id, &eAssocId))
return esock_make_error(env, esock_atom_einval);
@@ -10403,7 +10435,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_associnfo -> decode attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_associnfo -> decode attributes\r\n") );
/* On some platforms the assoc id is typed as an unsigned integer (uint32)
* So, to avoid warnings there, we always make an explicit cast...
@@ -10456,7 +10489,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_associnfo -> set associnfo option\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_associnfo -> set associnfo option\r\n") );
res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_ASSOCINFO,
&assocParams, sizeof(assocParams));
@@ -10467,7 +10501,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
result = esock_atom_ok;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_associnfo -> done with"
+ ("SOCKET", "esock_setopt_lvl_sctp_associnfo -> done with"
"\r\n result: %T"
"\r\n", result) );
@@ -10477,39 +10511,42 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env,
#endif
-/* nsetopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option
+/* esock_setopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option
*/
#if defined(SCTP_AUTOCLOSE)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE, eVal);
+ return esock_setopt_int_opt(env, descP,
+ IPPROTO_SCTP, SCTP_AUTOCLOSE, eVal);
}
#endif
-/* nsetopt_lvl_sctp_disable_fragments - Level SCTP DISABLE_FRAGMENTS option
+/* esock_setopt_lvl_sctp_disable_fragments -
+ * Level SCTP DISABLE_FRAGMENTS option
*/
#if defined(SCTP_DISABLE_FRAGMENTS)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, eVal);
+ return esock_setopt_bool_opt(env, descP,
+ IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, eVal);
}
#endif
-/* nsetopt_lvl_sctp_events - Level SCTP EVENTS option
+/* esock_setopt_lvl_sctp_events - Level SCTP EVENTS option
*/
#if defined(SCTP_EVENTS)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_events(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eDataIn, eAssoc, eAddr, eSndFailure;
@@ -10526,7 +10563,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
size_t sz;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_events -> entry with"
+ ("SOCKET", "esock_setopt_lvl_sctp_events -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
@@ -10539,7 +10576,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_events -> extract attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_events -> extract attributes\r\n") );
if (!GET_MAP_VAL(env, eVal, atom_data_in, &eDataIn))
return esock_make_error(env, esock_atom_einval);
@@ -10576,7 +10614,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
#endif
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_events -> decode attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_events -> decode attributes\r\n") );
events.sctp_data_io_event = esock_decode_bool(eDataIn);
events.sctp_association_event = esock_decode_bool(eAssoc);
@@ -10594,7 +10633,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
#endif
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_events -> set events option\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_events -> set events option\r\n") );
res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_EVENTS,
&events, sizeof(events));
@@ -10605,7 +10645,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
result = esock_atom_ok;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_events -> done with"
+ ("SOCKET", "esock_setopt_lvl_sctp_events -> done with"
"\r\n result: %T"
"\r\n", result) );
@@ -10615,13 +10655,13 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env,
#endif
-/* nsetopt_lvl_sctp_initmsg - Level SCTP INITMSG option
+/* esock_setopt_lvl_sctp_initmsg - Level SCTP INITMSG option
*/
#if defined(SCTP_INITMSG)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eNumOut, eMaxIn, eMaxAttempts, eMaxInitTO;
@@ -10631,7 +10671,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
unsigned int tmp;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_initmsg -> entry with"
+ ("SOCKET", "esock_setopt_lvl_sctp_initmsg -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
@@ -10644,7 +10684,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_initmsg -> extract attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_initmsg -> extract attributes\r\n") );
if (!GET_MAP_VAL(env, eVal, atom_num_outstreams, &eNumOut))
return esock_make_error(env, esock_atom_einval);
@@ -10659,7 +10700,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_initmsg -> decode attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_initmsg -> decode attributes\r\n") );
if (!GET_UINT(env, eNumOut, &tmp))
return esock_make_error(env, esock_atom_einval);
@@ -10678,7 +10720,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
initMsg.sinit_max_init_timeo = (Uint16) tmp;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_initmsg -> set initmsg option\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_initmsg -> set initmsg option\r\n") );
res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_INITMSG,
&initMsg, sizeof(initMsg));
@@ -10689,7 +10732,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
result = esock_atom_ok;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_initmsg -> done with"
+ ("SOCKET", "esock_setopt_lvl_sctp_initmsg -> done with"
"\r\n result: %T"
"\r\n", result) );
@@ -10699,39 +10742,39 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env,
#endif
-/* nsetopt_lvl_sctp_maxseg - Level SCTP MAXSEG option
+/* esock_setopt_lvl_sctp_maxseg - Level SCTP MAXSEG option
*/
#if defined(SCTP_MAXSEG)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG, eVal);
+ return esock_setopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG, eVal);
}
#endif
-/* nsetopt_lvl_sctp_nodelay - Level SCTP NODELAY option
+/* esock_setopt_lvl_sctp_nodelay - Level SCTP NODELAY option
*/
#if defined(SCTP_NODELAY)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
- return nsetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY, eVal);
+ return esock_setopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY, eVal);
}
#endif
-/* nsetopt_lvl_sctp_rtoinfo - Level SCTP RTOINFO option
+/* esock_setopt_lvl_sctp_rtoinfo - Level SCTP RTOINFO option
*/
#if defined(SCTP_RTOINFO)
static
-ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eAssocId, eInitial, eMax, eMin;
@@ -10740,7 +10783,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
size_t sz;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> entry with"
+ ("SOCKET", "esock_setopt_lvl_sctp_rtoinfo -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
@@ -10753,7 +10796,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> extract attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_rtoinfo -> extract attributes\r\n") );
if (!GET_MAP_VAL(env, eVal, atom_assoc_id, &eAssocId))
return esock_make_error(env, esock_atom_einval);
@@ -10768,7 +10812,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> decode attributes\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_rtoinfo -> decode attributes\r\n") );
/* On some platforms the assoc id is typed as an unsigned integer (uint32)
* So, to avoid warnings there, we always make an explicit cast...
@@ -10803,7 +10848,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
return esock_make_error(env, esock_atom_einval);
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> set associnfo option\r\n") );
+ ("SOCKET",
+ "esock_setopt_lvl_sctp_rtoinfo -> set associnfo option\r\n") );
res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_RTOINFO,
&rtoInfo, sizeof(rtoInfo));
@@ -10814,7 +10860,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
result = esock_atom_ok;
SSDBG( descP,
- ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> done with"
+ ("SOCKET", "esock_setopt_lvl_sctp_rtoinfo -> done with"
"\r\n result: %T"
"\r\n", result) );
@@ -10830,14 +10876,14 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
-/* nsetopt_bool_opt - set an option that has an (integer) bool value
+/* esock_setopt_bool_opt - set an option that has an (integer) bool value
*/
static
-ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
BOOLEAN_T val;
@@ -10857,14 +10903,14 @@ ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env,
}
-/* nsetopt_int_opt - set an option that has an integer value
+/* esock_setopt_int_opt - set an option that has an integer value
*/
static
-ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
int val;
@@ -10874,7 +10920,7 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
/*
SSDBG( descP,
- ("SOCKET", "nsetopt_int_opt -> set option"
+ ("SOCKET", "esock_setopt_int_opt -> set option"
"\r\n opt: %d"
"\r\n val: %d"
"\r\n", opt, val) );
@@ -10895,16 +10941,16 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env,
}
-/* nsetopt_str_opt - set an option that has an string value
+/* esock_setopt_str_opt - set an option that has an string value
*/
#if defined(USE_SETOPT_STR_OPT)
static
-ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- int max,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
char* val = MALLOC(max);
@@ -10929,14 +10975,14 @@ ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env,
#endif
-/* nsetopt_timeval_opt - set an option that has an (timeval) bool value
+/* esock_setopt_timeval_opt - set an option that has an (timeval) bool value
*/
static
-ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- ERL_NIF_TERM eVal)
+ERL_NIF_TERM esock_setopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ ERL_NIF_TERM eVal)
{
ERL_NIF_TERM result;
struct timeval timeVal;
@@ -10944,7 +10990,7 @@ ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
char* xres;
SSDBG( descP,
- ("SOCKET", "nsetopt_timeval_opt -> entry with"
+ ("SOCKET", "esock_setopt_timeval_opt -> entry with"
"\r\n eVal: %T"
"\r\n", eVal) );
@@ -10952,7 +10998,7 @@ ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
return esock_make_error_str(env, xres);
SSDBG( descP,
- ("SOCKET", "nsetopt_timeval_opt -> set timeval option\r\n") );
+ ("SOCKET", "esock_setopt_timeval_opt -> set timeval option\r\n") );
res = socket_setopt(descP->sock, level, opt, &timeVal, sizeof(timeVal));
@@ -10962,7 +11008,7 @@ ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env,
result = esock_atom_ok;
SSDBG( descP,
- ("SOCKET", "nsetopt_timeval_opt -> done with"
+ ("SOCKET", "esock_setopt_timeval_opt -> done with"
"\r\n result: %T"
"\r\n", result) );
@@ -10982,19 +11028,19 @@ BOOLEAN_T elevel2level(BOOLEAN_T isEncoded,
if (isEncoded) {
switch (eLevel) {
- case SOCKET_OPT_LEVEL_OTP:
+ case ESOCK_OPT_LEVEL_OTP:
*isOTP = TRUE;
*level = -1;
result = TRUE;
break;
- case SOCKET_OPT_LEVEL_SOCKET:
+ case ESOCK_OPT_LEVEL_SOCKET:
*isOTP = FALSE;
*level = SOL_SOCKET;
result = TRUE;
break;
- case SOCKET_OPT_LEVEL_IP:
+ case ESOCK_OPT_LEVEL_IP:
*isOTP = FALSE;
#if defined(SOL_IP)
*level = SOL_IP;
@@ -11005,7 +11051,7 @@ BOOLEAN_T elevel2level(BOOLEAN_T isEncoded,
break;
#if defined(HAVE_IPV6)
- case SOCKET_OPT_LEVEL_IPV6:
+ case ESOCK_OPT_LEVEL_IPV6:
*isOTP = FALSE;
#if defined(SOL_IPV6)
*level = SOL_IPV6;
@@ -11016,20 +11062,20 @@ BOOLEAN_T elevel2level(BOOLEAN_T isEncoded,
break;
#endif
- case SOCKET_OPT_LEVEL_TCP:
+ case ESOCK_OPT_LEVEL_TCP:
*isOTP = FALSE;
*level = IPPROTO_TCP;
result = TRUE;
break;
- case SOCKET_OPT_LEVEL_UDP:
+ case ESOCK_OPT_LEVEL_UDP:
*isOTP = FALSE;
*level = IPPROTO_UDP;
result = TRUE;
break;
#ifdef HAVE_SCTP
- case SOCKET_OPT_LEVEL_SCTP:
+ case ESOCK_OPT_LEVEL_SCTP:
*isOTP = FALSE;
*level = IPPROTO_SCTP;
result = TRUE;
@@ -11174,7 +11220,7 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
SGDBG( ("SOCKET", "nif_getopt -> entry with argc: %d\r\n", argc) );
if ((argc != 4) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP) ||
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) ||
!GET_INT(env, argv[2], &eLevel)) {
SGDBG( ("SOCKET", "nif_getopt -> failed processing args\r\n") );
return enif_make_badarg(env);
@@ -11200,7 +11246,7 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
MLOCK(descP->cfgMtx);
- result = ngetopt(env, descP, isEncoded, isOTP, level, eOpt);
+ result = esock_getopt(env, descP, isEncoded, isOTP, level, eOpt);
MUNLOCK(descP->cfgMtx);
@@ -11213,18 +11259,18 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM ngetopt(ErlNifEnv* env,
- ESockDescriptor* descP,
- BOOLEAN_T isEncoded,
- BOOLEAN_T isOTP,
- int level,
- ERL_NIF_TERM eOpt)
+ERL_NIF_TERM esock_getopt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ BOOLEAN_T isEncoded,
+ BOOLEAN_T isOTP,
+ int level,
+ ERL_NIF_TERM eOpt)
{
ERL_NIF_TERM result;
int opt;
SSDBG( descP,
- ("SOCKET", "ngetopt -> entry with"
+ ("SOCKET", "esock_getopt -> entry with"
"\r\n isEncoded: %s"
"\r\n isOTP: %s"
"\r\n level: %d"
@@ -11236,20 +11282,20 @@ ERL_NIF_TERM ngetopt(ErlNifEnv* env,
* but options for our implementation.
*/
if (GET_INT(env, eOpt, &opt))
- result = ngetopt_otp(env, descP, opt);
+ result = esock_getopt_otp(env, descP, opt);
else
result = esock_make_error(env, esock_atom_einval);
} else if (!isEncoded) {
- result = ngetopt_native(env, descP, level, eOpt);
+ result = esock_getopt_native(env, descP, level, eOpt);
} else {
if (GET_INT(env, eOpt, &opt))
- result = ngetopt_level(env, descP, level, opt);
+ result = esock_getopt_level(env, descP, level, opt);
else
result = esock_make_error(env, esock_atom_einval);
}
SSDBG( descP,
- ("SOCKET", "ngetopt -> done when"
+ ("SOCKET", "esock_getopt -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -11258,60 +11304,60 @@ ERL_NIF_TERM ngetopt(ErlNifEnv* env,
-/* ngetopt_otp - Handle OTP (level) options
+/* esock_getopt_otp - Handle OTP (level) options
*/
static
-ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM esock_getopt_otp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "ngetopt_otp -> entry with"
+ ("SOCKET", "esock_getopt_otp -> entry with"
"\r\n eOpt: %d"
"\r\n", eOpt) );
switch (eOpt) {
- case SOCKET_OPT_OTP_DEBUG:
- result = ngetopt_otp_debug(env, descP);
+ case ESOCK_OPT_OTP_DEBUG:
+ result = esock_getopt_otp_debug(env, descP);
break;
- case SOCKET_OPT_OTP_IOW:
- result = ngetopt_otp_iow(env, descP);
+ case ESOCK_OPT_OTP_IOW:
+ result = esock_getopt_otp_iow(env, descP);
break;
- case SOCKET_OPT_OTP_CTRL_PROC:
- result = ngetopt_otp_ctrl_proc(env, descP);
+ case ESOCK_OPT_OTP_CTRL_PROC:
+ result = esock_getopt_otp_ctrl_proc(env, descP);
break;
- case SOCKET_OPT_OTP_RCVBUF:
- result = ngetopt_otp_rcvbuf(env, descP);
+ case ESOCK_OPT_OTP_RCVBUF:
+ result = esock_getopt_otp_rcvbuf(env, descP);
break;
- case SOCKET_OPT_OTP_RCVCTRLBUF:
- result = ngetopt_otp_rcvctrlbuf(env, descP);
+ case ESOCK_OPT_OTP_RCVCTRLBUF:
+ result = esock_getopt_otp_rcvctrlbuf(env, descP);
break;
- case SOCKET_OPT_OTP_SNDCTRLBUF:
- result = ngetopt_otp_sndctrlbuf(env, descP);
+ case ESOCK_OPT_OTP_SNDCTRLBUF:
+ result = esock_getopt_otp_sndctrlbuf(env, descP);
break;
- case SOCKET_OPT_OTP_FD:
- result = ngetopt_otp_fd(env, descP);
+ case ESOCK_OPT_OTP_FD:
+ result = esock_getopt_otp_fd(env, descP);
break;
/* *** INTERNAL *** */
- case SOCKET_OPT_OTP_DOMAIN:
- result = ngetopt_otp_domain(env, descP);
+ case ESOCK_OPT_OTP_DOMAIN:
+ result = esock_getopt_otp_domain(env, descP);
break;
- case SOCKET_OPT_OTP_TYPE:
- result = ngetopt_otp_type(env, descP);
+ case ESOCK_OPT_OTP_TYPE:
+ result = esock_getopt_otp_type(env, descP);
break;
- case SOCKET_OPT_OTP_PROTOCOL:
- result = ngetopt_otp_protocol(env, descP);
+ case ESOCK_OPT_OTP_PROTOCOL:
+ result = esock_getopt_otp_protocol(env, descP);
break;
default:
@@ -11320,7 +11366,7 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_otp -> done when"
+ ("SOCKET", "esock_getopt_otp -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -11328,11 +11374,11 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env,
}
-/* ngetopt_otp_debug - Handle the OTP (level) debug option
+/* esock_getopt_otp_debug - Handle the OTP (level) debug option
*/
static
-ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_debug(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = esock_encode_bool(descP->dbg);
@@ -11340,11 +11386,11 @@ ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env,
}
-/* ngetopt_otp_iow - Handle the OTP (level) iow option
+/* esock_getopt_otp_iow - Handle the OTP (level) iow option
*/
static
-ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_iow(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = esock_encode_bool(descP->iow);
@@ -11352,11 +11398,11 @@ ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env,
}
-/* ngetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process option
+/* esock_getopt_otp_ctrl_proc - Handle the OTP (level) controlling_process option
*/
static
-ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_ctrl_proc(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKPID(env, &descP->ctrlPid);
@@ -11365,11 +11411,11 @@ ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env,
-/* ngetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option
+/* esock_getopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option
*/
static
-ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal;
@@ -11383,11 +11429,11 @@ ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env,
}
-/* ngetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option
+/* esock_getopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option
*/
static
-ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_rcvctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKI(env, descP->rCtrlSz);
@@ -11395,11 +11441,11 @@ ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env,
}
-/* ngetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option
+/* esock_getopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option
*/
static
-ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_sndctrlbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKI(env, descP->wCtrlSz);
@@ -11407,11 +11453,11 @@ ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env,
}
-/* ngetopt_otp_fd - Handle the OTP (level) fd option
+/* esock_getopt_otp_fd - Handle the OTP (level) fd option
*/
static
-ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_fd(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM eVal = MKI(env, descP->sock);
@@ -11419,11 +11465,11 @@ ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env,
}
-/* ngetopt_otp_domain - Handle the OTP (level) domain option
+/* esock_getopt_otp_domain - Handle the OTP (level) domain option
*/
static
-ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_domain(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val = descP->domain;
@@ -11455,11 +11501,11 @@ ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env,
}
-/* ngetopt_otp_type - Handle the OTP (level) type options.
+/* esock_getopt_otp_type - Handle the OTP (level) type options.
*/
static
-ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_type(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val = descP->type;
@@ -11496,11 +11542,11 @@ ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env,
}
-/* ngetopt_otp_protocol - Handle the OTP (level) protocol options.
+/* esock_getopt_otp_protocol - Handle the OTP (level) protocol options.
*/
static
-ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_otp_protocol(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val = descP->protocol;
@@ -11548,10 +11594,10 @@ ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env,
* format: {NativeOpt :: integer(), ValueSize :: non_neg_integer()}
*/
static
-ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- ERL_NIF_TERM eOpt)
+ERL_NIF_TERM esock_getopt_native(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ ERL_NIF_TERM eOpt)
{
ERL_NIF_TERM result = enif_make_badarg(env);
int opt;
@@ -11559,7 +11605,7 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
SOCKOPTLEN_T valueSz;
SSDBG( descP,
- ("SOCKET", "ngetopt_native -> entry with"
+ ("SOCKET", "esock_getopt_native -> entry with"
"\r\n level: %d"
"\r\n eOpt: %T"
"\r\n", level, eOpt) );
@@ -11573,20 +11619,21 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
if (decode_native_get_opt(env, eOpt, &opt, &valueType, (int*) &valueSz)) {
SSDBG( descP,
- ("SOCKET", "ngetopt_native -> decoded opt"
+ ("SOCKET", "esock_getopt_native -> decoded opt"
"\r\n valueType: %d (%s)"
"\r\n ValueSize: %d"
"\r\n", valueType, VT2S(valueType), valueSz) );
switch (valueType) {
- case SOCKET_OPT_VALUE_TYPE_UNSPEC:
- result = ngetopt_native_unspec(env, descP, level, opt, valueSz);
+ case ESOCK_OPT_VALUE_TYPE_UNSPEC:
+ result = esock_getopt_native_unspec(env, descP,
+ level, opt, valueSz);
break;
- case SOCKET_OPT_VALUE_TYPE_INT:
- result = ngetopt_int_opt(env, descP, level, opt);
+ case ESOCK_OPT_VALUE_TYPE_INT:
+ result = esock_getopt_int_opt(env, descP, level, opt);
break;
- case SOCKET_OPT_VALUE_TYPE_BOOL:
- result = ngetopt_bool_opt(env, descP, level, opt);
+ case ESOCK_OPT_VALUE_TYPE_BOOL:
+ result = esock_getopt_bool_opt(env, descP, level, opt);
break;
default:
result = esock_make_error(env, esock_atom_einval);
@@ -11597,7 +11644,7 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_native -> done when"
+ ("SOCKET", "esock_getopt_native -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -11606,17 +11653,17 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env,
static
-ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- SOCKOPTLEN_T valueSz)
+ERL_NIF_TERM esock_getopt_native_unspec(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ SOCKOPTLEN_T valueSz)
{
ERL_NIF_TERM result = esock_make_error(env, esock_atom_einval);
int res;
SSDBG( descP,
- ("SOCKET", "ngetopt_native_unspec -> entry with"
+ ("SOCKET", "esock_getopt_native_unspec -> entry with"
"\r\n level: %d"
"\r\n opt: %d"
"\r\n valueSz: %d"
@@ -11632,7 +11679,8 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
SOCKOPTLEN_T vsz = valueSz;
ErlNifBinary val;
- SSDBG( descP, ("SOCKET", "ngetopt_native_unspec -> try alloc buffer\r\n") );
+ SSDBG( descP, ("SOCKET",
+ "esock_getopt_native_unspec -> try alloc buffer\r\n") );
if (ALLOC_BIN(vsz, &val)) {
int saveErrno;
@@ -11664,7 +11712,7 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_native_unspec -> done when"
+ ("SOCKET", "esock_getopt_native_unspec -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -11673,25 +11721,25 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env,
-/* ngetopt_level - A "proper" level (option) has been specified
+/* esock_getopt_level - A "proper" level (option) has been specified
*/
static
-ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int eOpt)
+ERL_NIF_TERM esock_getopt_level(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int eOpt)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "ngetopt_level -> entry with"
+ ("SOCKET", "esock_getopt_level -> entry with"
"\r\n level: %d"
"\r\n eOpt: %d"
"\r\n", level, eOpt) );
switch (level) {
case SOL_SOCKET:
- result = ngetopt_lvl_socket(env, descP, eOpt);
+ result = esock_getopt_lvl_socket(env, descP, eOpt);
break;
#if defined(SOL_IP)
@@ -11699,7 +11747,7 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
#else
case IPPROTO_IP:
#endif
- result = ngetopt_lvl_ip(env, descP, eOpt);
+ result = esock_getopt_lvl_ip(env, descP, eOpt);
break;
#if defined(HAVE_IPV6)
@@ -11708,21 +11756,21 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
#else
case IPPROTO_IPV6:
#endif
- result = ngetopt_lvl_ipv6(env, descP, eOpt);
+ result = esock_getopt_lvl_ipv6(env, descP, eOpt);
break;
#endif
case IPPROTO_TCP:
- result = ngetopt_lvl_tcp(env, descP, eOpt);
+ result = esock_getopt_lvl_tcp(env, descP, eOpt);
break;
case IPPROTO_UDP:
- result = ngetopt_lvl_udp(env, descP, eOpt);
+ result = esock_getopt_lvl_udp(env, descP, eOpt);
break;
#if defined(HAVE_SCTP)
case IPPROTO_SCTP:
- result = ngetopt_lvl_sctp(env, descP, eOpt);
+ result = esock_getopt_lvl_sctp(env, descP, eOpt);
break;
#endif
@@ -11732,7 +11780,7 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_level -> done when"
+ ("SOCKET", "esock_getopt_level -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -11740,150 +11788,150 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env,
}
-/* ngetopt_lvl_socket - Level *SOCKET* option
+/* esock_getopt_lvl_socket - Level *SOCKET* option
*/
static
-ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM esock_getopt_lvl_socket(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_socket -> entry with"
+ ("SOCKET", "esock_getopt_lvl_socket -> entry with"
"\r\n eOpt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(SO_ACCEPTCONN)
- case SOCKET_OPT_SOCK_ACCEPTCONN:
- result = ngetopt_lvl_sock_acceptconn(env, descP);
+ case ESOCK_OPT_SOCK_ACCEPTCONN:
+ result = esock_getopt_lvl_sock_acceptconn(env, descP);
break;
#endif
#if defined(SO_BINDTODEVICE)
- case SOCKET_OPT_SOCK_BINDTODEVICE:
- result = ngetopt_lvl_sock_bindtodevice(env, descP);
+ case ESOCK_OPT_SOCK_BINDTODEVICE:
+ result = esock_getopt_lvl_sock_bindtodevice(env, descP);
break;
#endif
#if defined(SO_BROADCAST)
- case SOCKET_OPT_SOCK_BROADCAST:
- result = ngetopt_lvl_sock_broadcast(env, descP);
+ case ESOCK_OPT_SOCK_BROADCAST:
+ result = esock_getopt_lvl_sock_broadcast(env, descP);
break;
#endif
#if defined(SO_DEBUG)
- case SOCKET_OPT_SOCK_DEBUG:
- result = ngetopt_lvl_sock_debug(env, descP);
+ case ESOCK_OPT_SOCK_DEBUG:
+ result = esock_getopt_lvl_sock_debug(env, descP);
break;
#endif
#if defined(SO_DOMAIN)
- case SOCKET_OPT_SOCK_DOMAIN:
- result = ngetopt_lvl_sock_domain(env, descP);
+ case ESOCK_OPT_SOCK_DOMAIN:
+ result = esock_getopt_lvl_sock_domain(env, descP);
break;
#endif
#if defined(SO_DONTROUTE)
- case SOCKET_OPT_SOCK_DONTROUTE:
- result = ngetopt_lvl_sock_dontroute(env, descP);
+ case ESOCK_OPT_SOCK_DONTROUTE:
+ result = esock_getopt_lvl_sock_dontroute(env, descP);
break;
#endif
#if defined(SO_KEEPALIVE)
- case SOCKET_OPT_SOCK_KEEPALIVE:
- result = ngetopt_lvl_sock_keepalive(env, descP);
+ case ESOCK_OPT_SOCK_KEEPALIVE:
+ result = esock_getopt_lvl_sock_keepalive(env, descP);
break;
#endif
#if defined(SO_LINGER)
- case SOCKET_OPT_SOCK_LINGER:
- result = ngetopt_lvl_sock_linger(env, descP);
+ case ESOCK_OPT_SOCK_LINGER:
+ result = esock_getopt_lvl_sock_linger(env, descP);
break;
#endif
#if defined(SO_OOBINLINE)
- case SOCKET_OPT_SOCK_OOBINLINE:
- result = ngetopt_lvl_sock_oobinline(env, descP);
+ case ESOCK_OPT_SOCK_OOBINLINE:
+ result = esock_getopt_lvl_sock_oobinline(env, descP);
break;
#endif
#if defined(SO_PEEK_OFF)
- case SOCKET_OPT_SOCK_PEEK_OFF:
- result = ngetopt_lvl_sock_peek_off(env, descP);
+ case ESOCK_OPT_SOCK_PEEK_OFF:
+ result = esock_getopt_lvl_sock_peek_off(env, descP);
break;
#endif
#if defined(SO_PRIORITY)
- case SOCKET_OPT_SOCK_PRIORITY:
- result = ngetopt_lvl_sock_priority(env, descP);
+ case ESOCK_OPT_SOCK_PRIORITY:
+ result = esock_getopt_lvl_sock_priority(env, descP);
break;
#endif
#if defined(SO_PROTOCOL)
- case SOCKET_OPT_SOCK_PROTOCOL:
- result = ngetopt_lvl_sock_protocol(env, descP);
+ case ESOCK_OPT_SOCK_PROTOCOL:
+ result = esock_getopt_lvl_sock_protocol(env, descP);
break;
#endif
#if defined(SO_RCVBUF)
- case SOCKET_OPT_SOCK_RCVBUF:
- result = ngetopt_lvl_sock_rcvbuf(env, descP);
+ case ESOCK_OPT_SOCK_RCVBUF:
+ result = esock_getopt_lvl_sock_rcvbuf(env, descP);
break;
#endif
#if defined(SO_RCVLOWAT)
- case SOCKET_OPT_SOCK_RCVLOWAT:
- result = ngetopt_lvl_sock_rcvlowat(env, descP);
+ case ESOCK_OPT_SOCK_RCVLOWAT:
+ result = esock_getopt_lvl_sock_rcvlowat(env, descP);
break;
#endif
#if defined(SO_RCVTIMEO)
- case SOCKET_OPT_SOCK_RCVTIMEO:
- result = ngetopt_lvl_sock_rcvtimeo(env, descP);
+ case ESOCK_OPT_SOCK_RCVTIMEO:
+ result = esock_getopt_lvl_sock_rcvtimeo(env, descP);
break;
#endif
#if defined(SO_REUSEADDR)
- case SOCKET_OPT_SOCK_REUSEADDR:
- result = ngetopt_lvl_sock_reuseaddr(env, descP);
+ case ESOCK_OPT_SOCK_REUSEADDR:
+ result = esock_getopt_lvl_sock_reuseaddr(env, descP);
break;
#endif
#if defined(SO_REUSEPORT)
- case SOCKET_OPT_SOCK_REUSEPORT:
- result = ngetopt_lvl_sock_reuseport(env, descP);
+ case ESOCK_OPT_SOCK_REUSEPORT:
+ result = esock_getopt_lvl_sock_reuseport(env, descP);
break;
#endif
#if defined(SO_SNDBUF)
- case SOCKET_OPT_SOCK_SNDBUF:
- result = ngetopt_lvl_sock_sndbuf(env, descP);
+ case ESOCK_OPT_SOCK_SNDBUF:
+ result = esock_getopt_lvl_sock_sndbuf(env, descP);
break;
#endif
#if defined(SO_SNDLOWAT)
- case SOCKET_OPT_SOCK_SNDLOWAT:
- result = ngetopt_lvl_sock_sndlowat(env, descP);
+ case ESOCK_OPT_SOCK_SNDLOWAT:
+ result = esock_getopt_lvl_sock_sndlowat(env, descP);
break;
#endif
#if defined(SO_SNDTIMEO)
- case SOCKET_OPT_SOCK_SNDTIMEO:
- result = ngetopt_lvl_sock_sndtimeo(env, descP);
+ case ESOCK_OPT_SOCK_SNDTIMEO:
+ result = esock_getopt_lvl_sock_sndtimeo(env, descP);
break;
#endif
#if defined(SO_TIMESTAMP)
- case SOCKET_OPT_SOCK_TIMESTAMP:
- result = ngetopt_lvl_sock_timestamp(env, descP);
+ case ESOCK_OPT_SOCK_TIMESTAMP:
+ result = esock_getopt_lvl_sock_timestamp(env, descP);
break;
#endif
#if defined(SO_TYPE)
- case SOCKET_OPT_SOCK_TYPE:
- result = ngetopt_lvl_sock_type(env, descP);
+ case ESOCK_OPT_SOCK_TYPE:
+ result = esock_getopt_lvl_sock_type(env, descP);
break;
#endif
@@ -11893,7 +11941,7 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_socket -> done when"
+ ("SOCKET", "esock_getopt_lvl_socket -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -11903,51 +11951,52 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env,
#if defined(SO_ACCEPTCONN)
static
-ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_acceptconn(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_ACCEPTCONN);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_ACCEPTCONN);
}
#endif
#if defined(SO_BINDTODEVICE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_bindtodevice(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_sock_bindtodevice -> entry with\r\n") );
+ ("SOCKET", "esock_getopt_lvl_sock_bindtodevice -> entry with\r\n") );
- return ngetopt_str_opt(env, descP, SOL_SOCKET, SO_BROADCAST, IFNAMSIZ+1);
+ return esock_getopt_str_opt(env, descP,
+ SOL_SOCKET, SO_BINDTODEVICE, IFNAMSIZ+1);
}
#endif
#if defined(SO_BROADCAST)
static
-ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_broadcast(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST);
}
#endif
#if defined(SO_DEBUG)
static
-ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_debug(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG);
+ return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG);
}
#endif
#if defined(SO_DOMAIN)
static
-ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_domain(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val;
@@ -11991,28 +12040,28 @@ ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env,
#if defined(SO_DONTROUTE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_dontroute(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE);
}
#endif
#if defined(SO_KEEPALIVE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_keepalive(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE);
}
#endif
#if defined(SO_LINGER)
static
-ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_linger(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct linger val;
@@ -12041,38 +12090,38 @@ ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env,
#if defined(SO_OOBINLINE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_oobinline(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE);
}
#endif
#if defined(SO_PEEK_OFF)
static
-ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_peek_off(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF);
+ return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF);
}
#endif
#if defined(SO_PRIORITY)
static
-ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_priority(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY);
+ return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY);
}
#endif
#if defined(SO_PROTOCOL)
static
-ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_protocol(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val;
@@ -12125,98 +12174,98 @@ ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env,
#if defined(SO_RCVBUF)
static
-ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_rcvbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF);
+ return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF);
}
#endif
#if defined(SO_RCVLOWAT)
static
-ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_rcvlowat(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT);
+ return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT);
}
#endif
#if defined(SO_RCVTIMEO)
static
-ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_rcvtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO);
+ return esock_getopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO);
}
#endif
#if defined(SO_REUSEADDR)
static
-ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_reuseaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR);
}
#endif
#if defined(SO_REUSEPORT)
static
-ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_reuseport(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT);
}
#endif
#if defined(SO_SNDBUF)
static
-ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_sndbuf(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF);
+ return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF);
}
#endif
#if defined(SO_SNDLOWAT)
static
-ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_sndlowat(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT);
+ return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT);
}
#endif
#if defined(SO_SNDTIMEO)
static
-ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_sndtimeo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO);
+ return esock_getopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO);
}
#endif
#if defined(SO_TIMESTAMP)
static
-ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_timestamp(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP);
+ return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP);
}
#endif
#if defined(SO_TYPE)
static
-ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sock_type(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result, reason;
int val;
@@ -12258,174 +12307,174 @@ ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env,
#endif
-/* ngetopt_lvl_ip - Level *IP* option(s)
+/* esock_getopt_lvl_ip - Level *IP* option(s)
*/
static
-ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM esock_getopt_lvl_ip(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_ip -> entry with"
+ ("SOCKET", "esock_getopt_lvl_ip -> entry with"
"\r\n eOpt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(IP_FREEBIND)
- case SOCKET_OPT_IP_FREEBIND:
- result = ngetopt_lvl_ip_freebind(env, descP);
+ case ESOCK_OPT_IP_FREEBIND:
+ result = esock_getopt_lvl_ip_freebind(env, descP);
break;
#endif
#if defined(IP_HDRINCL)
- case SOCKET_OPT_IP_HDRINCL:
- result = ngetopt_lvl_ip_hdrincl(env, descP);
+ case ESOCK_OPT_IP_HDRINCL:
+ result = esock_getopt_lvl_ip_hdrincl(env, descP);
break;
#endif
#if defined(IP_MINTTL)
- case SOCKET_OPT_IP_MINTTL:
- result = ngetopt_lvl_ip_minttl(env, descP);
+ case ESOCK_OPT_IP_MINTTL:
+ result = esock_getopt_lvl_ip_minttl(env, descP);
break;
#endif
#if defined(IP_MTU)
- case SOCKET_OPT_IP_MTU:
- result = ngetopt_lvl_ip_mtu(env, descP);
+ case ESOCK_OPT_IP_MTU:
+ result = esock_getopt_lvl_ip_mtu(env, descP);
break;
#endif
#if defined(IP_MTU_DISCOVER)
- case SOCKET_OPT_IP_MTU_DISCOVER:
- result = ngetopt_lvl_ip_mtu_discover(env, descP);
+ case ESOCK_OPT_IP_MTU_DISCOVER:
+ result = esock_getopt_lvl_ip_mtu_discover(env, descP);
break;
#endif
#if defined(IP_MULTICAST_ALL)
- case SOCKET_OPT_IP_MULTICAST_ALL:
- result = ngetopt_lvl_ip_multicast_all(env, descP);
+ case ESOCK_OPT_IP_MULTICAST_ALL:
+ result = esock_getopt_lvl_ip_multicast_all(env, descP);
break;
#endif
#if defined(IP_MULTICAST_IF)
- case SOCKET_OPT_IP_MULTICAST_IF:
- result = ngetopt_lvl_ip_multicast_if(env, descP);
+ case ESOCK_OPT_IP_MULTICAST_IF:
+ result = esock_getopt_lvl_ip_multicast_if(env, descP);
break;
#endif
#if defined(IP_MULTICAST_LOOP)
- case SOCKET_OPT_IP_MULTICAST_LOOP:
- result = ngetopt_lvl_ip_multicast_loop(env, descP);
+ case ESOCK_OPT_IP_MULTICAST_LOOP:
+ result = esock_getopt_lvl_ip_multicast_loop(env, descP);
break;
#endif
#if defined(IP_MULTICAST_TTL)
- case SOCKET_OPT_IP_MULTICAST_TTL:
- result = ngetopt_lvl_ip_multicast_ttl(env, descP);
+ case ESOCK_OPT_IP_MULTICAST_TTL:
+ result = esock_getopt_lvl_ip_multicast_ttl(env, descP);
break;
#endif
#if defined(IP_NODEFRAG)
- case SOCKET_OPT_IP_NODEFRAG:
- result = ngetopt_lvl_ip_nodefrag(env, descP);
+ case ESOCK_OPT_IP_NODEFRAG:
+ result = esock_getopt_lvl_ip_nodefrag(env, descP);
break;
#endif
#if defined(IP_PKTINFO)
- case SOCKET_OPT_IP_PKTINFO:
- result = ngetopt_lvl_ip_pktinfo(env, descP);
+ case ESOCK_OPT_IP_PKTINFO:
+ result = esock_getopt_lvl_ip_pktinfo(env, descP);
break;
#endif
#if defined(IP_RECVDSTADDR)
- case SOCKET_OPT_IP_RECVDSTADDR:
- result = ngetopt_lvl_ip_recvdstaddr(env, descP);
+ case ESOCK_OPT_IP_RECVDSTADDR:
+ result = esock_getopt_lvl_ip_recvdstaddr(env, descP);
break;
#endif
#if defined(IP_RECVERR)
- case SOCKET_OPT_IP_RECVERR:
- result = ngetopt_lvl_ip_recverr(env, descP);
+ case ESOCK_OPT_IP_RECVERR:
+ result = esock_getopt_lvl_ip_recverr(env, descP);
break;
#endif
#if defined(IP_RECVIF)
- case SOCKET_OPT_IP_RECVIF:
- result = ngetopt_lvl_ip_recvif(env, descP);
+ case ESOCK_OPT_IP_RECVIF:
+ result = esock_getopt_lvl_ip_recvif(env, descP);
break;
#endif
#if defined(IP_RECVOPTS)
- case SOCKET_OPT_IP_RECVOPTS:
- result = ngetopt_lvl_ip_recvopts(env, descP);
+ case ESOCK_OPT_IP_RECVOPTS:
+ result = esock_getopt_lvl_ip_recvopts(env, descP);
break;
#endif
#if defined(IP_RECVORIGDSTADDR)
- case SOCKET_OPT_IP_RECVORIGDSTADDR:
- result = ngetopt_lvl_ip_recvorigdstaddr(env, descP);
+ case ESOCK_OPT_IP_RECVORIGDSTADDR:
+ result = esock_getopt_lvl_ip_recvorigdstaddr(env, descP);
break;
#endif
#if defined(IP_RECVTOS)
- case SOCKET_OPT_IP_RECVTOS:
- result = ngetopt_lvl_ip_recvtos(env, descP);
+ case ESOCK_OPT_IP_RECVTOS:
+ result = esock_getopt_lvl_ip_recvtos(env, descP);
break;
#endif
#if defined(IP_RECVTTL)
- case SOCKET_OPT_IP_RECVTTL:
- result = ngetopt_lvl_ip_recvttl(env, descP);
+ case ESOCK_OPT_IP_RECVTTL:
+ result = esock_getopt_lvl_ip_recvttl(env, descP);
break;
#endif
#if defined(IP_RETOPTS)
- case SOCKET_OPT_IP_RETOPTS:
- result = ngetopt_lvl_ip_retopts(env, descP);
+ case ESOCK_OPT_IP_RETOPTS:
+ result = esock_getopt_lvl_ip_retopts(env, descP);
break;
#endif
#if defined(IP_ROUTER_ALERT)
- case SOCKET_OPT_IP_ROUTER_ALERT:
- result = ngetopt_lvl_ip_router_alert(env, descP);
+ case ESOCK_OPT_IP_ROUTER_ALERT:
+ result = esock_getopt_lvl_ip_router_alert(env, descP);
break;
#endif
#if defined(IP_SENDSRCADDR)
- case SOCKET_OPT_IP_SENDSRCADDR:
- result = ngetopt_lvl_ip_sendsrcaddr(env, descP);
+ case ESOCK_OPT_IP_SENDSRCADDR:
+ result = esock_getopt_lvl_ip_sendsrcaddr(env, descP);
break;
#endif
#if defined(IP_TOS)
- case SOCKET_OPT_IP_TOS:
- result = ngetopt_lvl_ip_tos(env, descP);
+ case ESOCK_OPT_IP_TOS:
+ result = esock_getopt_lvl_ip_tos(env, descP);
break;
#endif
#if defined(IP_TRANSPARENT)
- case SOCKET_OPT_IP_TRANSPARENT:
- result = ngetopt_lvl_ip_transparent(env, descP);
+ case ESOCK_OPT_IP_TRANSPARENT:
+ result = esock_getopt_lvl_ip_transparent(env, descP);
break;
#endif
#if defined(IP_TTL)
- case SOCKET_OPT_IP_TTL:
- result = ngetopt_lvl_ip_ttl(env, descP);
+ case ESOCK_OPT_IP_TTL:
+ result = esock_getopt_lvl_ip_ttl(env, descP);
break;
#endif
default:
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_ip -> unknown opt %d\r\n", eOpt) );
+ ("SOCKET", "esock_getopt_lvl_ip -> unknown opt %d\r\n", eOpt) );
result = esock_make_error(env, esock_atom_einval);
break;
}
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_ip -> done when"
+ ("SOCKET", "esock_getopt_lvl_ip -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -12433,12 +12482,12 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env,
}
-/* ngetopt_lvl_ip_minttl - Level IP MINTTL option
+/* esock_getopt_lvl_ip_minttl - Level IP MINTTL option
*/
#if defined(IP_MINTTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_minttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12446,17 +12495,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_int_opt(env, descP, level, IP_MINTTL);
+ return esock_getopt_int_opt(env, descP, level, IP_MINTTL);
}
#endif
-/* ngetopt_lvl_ip_freebind - Level IP FREEBIND option
+/* esock_getopt_lvl_ip_freebind - Level IP FREEBIND option
*/
#if defined(IP_FREEBIND)
static
-ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_freebind(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12464,17 +12513,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_FREEBIND);
+ return esock_getopt_bool_opt(env, descP, level, IP_FREEBIND);
}
#endif
-/* ngetopt_lvl_ip_hdrincl - Level IP HDRINCL option
+/* esock_getopt_lvl_ip_hdrincl - Level IP HDRINCL option
*/
#if defined(IP_HDRINCL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_hdrincl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12482,17 +12531,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_HDRINCL);
+ return esock_getopt_bool_opt(env, descP, level, IP_HDRINCL);
}
#endif
-/* ngetopt_lvl_ip_mtu - Level IP MTU option
+/* esock_getopt_lvl_ip_mtu - Level IP MTU option
*/
#if defined(IP_MTU)
static
-ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12500,17 +12549,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_int_opt(env, descP, level, IP_MTU);
+ return esock_getopt_int_opt(env, descP, level, IP_MTU);
}
#endif
-/* ngetopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option
+/* esock_getopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option
*/
#if defined(IP_MTU_DISCOVER)
static
-ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eMtuDisc;
@@ -12539,12 +12588,12 @@ ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env,
#endif
-/* ngetopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option
+/* esock_getopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option
*/
#if defined(IP_MULTICAST_ALL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_multicast_all(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12552,17 +12601,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_MULTICAST_ALL);
+ return esock_getopt_bool_opt(env, descP, level, IP_MULTICAST_ALL);
}
#endif
-/* ngetopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option
+/* esock_getopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option
*/
#if defined(IP_MULTICAST_IF)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eAddr;
@@ -12594,12 +12643,12 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env,
#endif
-/* ngetopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option
+/* esock_getopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option
*/
#if defined(IP_MULTICAST_LOOP)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12607,17 +12656,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP);
+ return esock_getopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP);
}
#endif
-/* ngetopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option
+/* esock_getopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option
*/
#if defined(IP_MULTICAST_TTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12625,17 +12674,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_int_opt(env, descP, level, IP_MULTICAST_TTL);
+ return esock_getopt_int_opt(env, descP, level, IP_MULTICAST_TTL);
}
#endif
-/* ngetopt_lvl_ip_nodefrag - Level IP NODEFRAG option
+/* esock_getopt_lvl_ip_nodefrag - Level IP NODEFRAG option
*/
#if defined(IP_NODEFRAG)
static
-ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_nodefrag(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12643,17 +12692,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_NODEFRAG);
+ return esock_getopt_bool_opt(env, descP, level, IP_NODEFRAG);
}
#endif
-/* ngetopt_lvl_ip_pktinfo - Level IP PKTINFO option
+/* esock_getopt_lvl_ip_pktinfo - Level IP PKTINFO option
*/
#if defined(IP_PKTINFO)
static
-ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_pktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12661,17 +12710,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_PKTINFO);
+ return esock_getopt_bool_opt(env, descP, level, IP_PKTINFO);
}
#endif
-/* ngetopt_lvl_ip_recvtos - Level IP RECVTOS option
+/* esock_getopt_lvl_ip_recvtos - Level IP RECVTOS option
*/
#if defined(IP_RECVTOS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_recvtos(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12679,17 +12728,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RECVTOS);
+ return esock_getopt_bool_opt(env, descP, level, IP_RECVTOS);
}
#endif
-/* ngetopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option
+/* esock_getopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option
*/
#if defined(IP_RECVDSTADDR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12697,17 +12746,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RECVDSTADDR);
+ return esock_getopt_bool_opt(env, descP, level, IP_RECVDSTADDR);
}
#endif
-/* ngetopt_lvl_ip_recverr - Level IP RECVERR option
+/* esock_getopt_lvl_ip_recverr - Level IP RECVERR option
*/
#if defined(IP_RECVERR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12715,17 +12764,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RECVERR);
+ return esock_getopt_bool_opt(env, descP, level, IP_RECVERR);
}
#endif
-/* ngetopt_lvl_ip_recvif - Level IP RECVIF option
+/* esock_getopt_lvl_ip_recvif - Level IP RECVIF option
*/
#if defined(IP_RECVIF)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_recvif(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12733,17 +12782,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RECVIF);
+ return esock_getopt_bool_opt(env, descP, level, IP_RECVIF);
}
#endif
-/* ngetopt_lvl_ip_recvopt - Level IP RECVOPTS option
+/* esock_getopt_lvl_ip_recvopt - Level IP RECVOPTS option
*/
#if defined(IP_RECVOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_recvopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12751,17 +12800,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RECVOPTS);
+ return esock_getopt_bool_opt(env, descP, level, IP_RECVOPTS);
}
#endif
-/* ngetopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option
+/* esock_getopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option
*/
#if defined(IP_RECVORIGDSTADDR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12769,17 +12818,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR);
+ return esock_getopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR);
}
#endif
-/* ngetopt_lvl_ip_recvttl - Level IP RECVTTL option
+/* esock_getopt_lvl_ip_recvttl - Level IP RECVTTL option
*/
#if defined(IP_RECVTTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_recvttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12787,17 +12836,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RECVTTL);
+ return esock_getopt_bool_opt(env, descP, level, IP_RECVTTL);
}
#endif
-/* ngetopt_lvl_ip_retopts - Level IP RETOPTS option
+/* esock_getopt_lvl_ip_retopts - Level IP RETOPTS option
*/
#if defined(IP_RETOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_retopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12805,17 +12854,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_RETOPTS);
+ return esock_getopt_bool_opt(env, descP, level, IP_RETOPTS);
}
#endif
-/* ngetopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option
+/* esock_getopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option
*/
#if defined(IP_ROUTER_ALERT)
static
-ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12823,17 +12872,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_int_opt(env, descP, level, IP_ROUTER_ALERT);
+ return esock_getopt_int_opt(env, descP, level, IP_ROUTER_ALERT);
}
#endif
-/* ngetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option
+/* esock_getopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option
*/
#if defined(IP_SENDSRCADDR)
static
-ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12841,17 +12890,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_SENDSRCADDR);
+ return esock_getopt_bool_opt(env, descP, level, IP_SENDSRCADDR);
}
#endif
-/* ngetopt_lvl_ip_tos - Level IP TOS option
+/* esock_getopt_lvl_ip_tos - Level IP TOS option
*/
#if defined(IP_TOS)
static
-ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_tos(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12876,12 +12925,12 @@ ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env,
#endif
-/* ngetopt_lvl_ip_transparent - Level IP TRANSPARENT option
+/* esock_getopt_lvl_ip_transparent - Level IP TRANSPARENT option
*/
#if defined(IP_TRANSPARENT)
static
-ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_transparent(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12889,18 +12938,18 @@ ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_bool_opt(env, descP, level, IP_TRANSPARENT);
+ return esock_getopt_bool_opt(env, descP, level, IP_TRANSPARENT);
}
#endif
-/* ngetopt_lvl_ip_ttl - Level IP TTL option
+/* esock_getopt_lvl_ip_ttl - Level IP TTL option
*/
#if defined(IP_TTL)
static
-ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ip_ttl(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IP)
int level = SOL_IP;
@@ -12908,121 +12957,121 @@ ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env,
int level = IPPROTO_IP;
#endif
- return ngetopt_int_opt(env, descP, level, IP_TTL);
+ return esock_getopt_int_opt(env, descP, level, IP_TTL);
}
#endif
-/* ngetopt_lvl_ipv6 - Level *IPv6* option(s)
+/* esock_getopt_lvl_ipv6 - Level *IPv6* option(s)
*/
#if defined(HAVE_IPV6)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM esock_getopt_lvl_ipv6(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_ipv6 -> entry with"
+ ("SOCKET", "esock_getopt_lvl_ipv6 -> entry with"
"\r\n eOpt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(IPV6_AUTHHDR)
- case SOCKET_OPT_IPV6_AUTHHDR:
- result = ngetopt_lvl_ipv6_authhdr(env, descP);
+ case ESOCK_OPT_IPV6_AUTHHDR:
+ result = esock_getopt_lvl_ipv6_authhdr(env, descP);
break;
#endif
#if defined(IPV6_DSTOPTS)
- case SOCKET_OPT_IPV6_DSTOPTS:
- result = ngetopt_lvl_ipv6_dstopts(env, descP);
+ case ESOCK_OPT_IPV6_DSTOPTS:
+ result = esock_getopt_lvl_ipv6_dstopts(env, descP);
break;
#endif
#if defined(IPV6_FLOWINFO)
- case SOCKET_OPT_IPV6_FLOWINFO:
- result = ngetopt_lvl_ipv6_flowinfo(env, descP);
+ case ESOCK_OPT_IPV6_FLOWINFO:
+ result = esock_getopt_lvl_ipv6_flowinfo(env, descP);
break;
#endif
#if defined(IPV6_HOPLIMIT)
- case SOCKET_OPT_IPV6_HOPLIMIT:
- result = ngetopt_lvl_ipv6_hoplimit(env, descP);
+ case ESOCK_OPT_IPV6_HOPLIMIT:
+ result = esock_getopt_lvl_ipv6_hoplimit(env, descP);
break;
#endif
#if defined(IPV6_HOPOPTS)
- case SOCKET_OPT_IPV6_HOPOPTS:
- result = ngetopt_lvl_ipv6_hopopts(env, descP);
+ case ESOCK_OPT_IPV6_HOPOPTS:
+ result = esock_getopt_lvl_ipv6_hopopts(env, descP);
break;
#endif
#if defined(IPV6_MTU)
- case SOCKET_OPT_IPV6_MTU:
- result = ngetopt_lvl_ipv6_mtu(env, descP);
+ case ESOCK_OPT_IPV6_MTU:
+ result = esock_getopt_lvl_ipv6_mtu(env, descP);
break;
#endif
#if defined(IPV6_MTU_DISCOVER)
- case SOCKET_OPT_IPV6_MTU_DISCOVER:
- result = ngetopt_lvl_ipv6_mtu_discover(env, descP);
+ case ESOCK_OPT_IPV6_MTU_DISCOVER:
+ result = esock_getopt_lvl_ipv6_mtu_discover(env, descP);
break;
#endif
#if defined(IPV6_MULTICAST_HOPS)
- case SOCKET_OPT_IPV6_MULTICAST_HOPS:
- result = ngetopt_lvl_ipv6_multicast_hops(env, descP);
+ case ESOCK_OPT_IPV6_MULTICAST_HOPS:
+ result = esock_getopt_lvl_ipv6_multicast_hops(env, descP);
break;
#endif
#if defined(IPV6_MULTICAST_IF)
- case SOCKET_OPT_IPV6_MULTICAST_IF:
- result = ngetopt_lvl_ipv6_multicast_if(env, descP);
+ case ESOCK_OPT_IPV6_MULTICAST_IF:
+ result = esock_getopt_lvl_ipv6_multicast_if(env, descP);
break;
#endif
#if defined(IPV6_MULTICAST_LOOP)
- case SOCKET_OPT_IPV6_MULTICAST_LOOP:
- result = ngetopt_lvl_ipv6_multicast_loop(env, descP);
+ case ESOCK_OPT_IPV6_MULTICAST_LOOP:
+ result = esock_getopt_lvl_ipv6_multicast_loop(env, descP);
break;
#endif
#if defined(IPV6_RECVERR)
- case SOCKET_OPT_IPV6_RECVERR:
- result = ngetopt_lvl_ipv6_recverr(env, descP);
+ case ESOCK_OPT_IPV6_RECVERR:
+ result = esock_getopt_lvl_ipv6_recverr(env, descP);
break;
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
- case SOCKET_OPT_IPV6_RECVPKTINFO:
- result = ngetopt_lvl_ipv6_recvpktinfo(env, descP);
+ case ESOCK_OPT_IPV6_RECVPKTINFO:
+ result = esock_getopt_lvl_ipv6_recvpktinfo(env, descP);
break;
#endif
#if defined(IPV6_ROUTER_ALERT)
- case SOCKET_OPT_IPV6_ROUTER_ALERT:
- result = ngetopt_lvl_ipv6_router_alert(env, descP);
+ case ESOCK_OPT_IPV6_ROUTER_ALERT:
+ result = esock_getopt_lvl_ipv6_router_alert(env, descP);
break;
#endif
#if defined(IPV6_RTHDR)
- case SOCKET_OPT_IPV6_RTHDR:
- result = ngetopt_lvl_ipv6_rthdr(env, descP);
+ case ESOCK_OPT_IPV6_RTHDR:
+ result = esock_getopt_lvl_ipv6_rthdr(env, descP);
break;
#endif
#if defined(IPV6_UNICAST_HOPS)
- case SOCKET_OPT_IPV6_UNICAST_HOPS:
- result = ngetopt_lvl_ipv6_unicast_hops(env, descP);
+ case ESOCK_OPT_IPV6_UNICAST_HOPS:
+ result = esock_getopt_lvl_ipv6_unicast_hops(env, descP);
break;
#endif
#if defined(IPV6_V6ONLY)
- case SOCKET_OPT_IPV6_V6ONLY:
- result = ngetopt_lvl_ipv6_v6only(env, descP);
+ case ESOCK_OPT_IPV6_V6ONLY:
+ result = esock_getopt_lvl_ipv6_v6only(env, descP);
break;
#endif
@@ -13032,7 +13081,7 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_ipv6 -> done when"
+ ("SOCKET", "esock_getopt_lvl_ipv6 -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -13042,33 +13091,33 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env,
#if defined(IPV6_AUTHHDR)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_authhdr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR);
+ return esock_getopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR);
}
#endif
#if defined(IPV6_DSTOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_dstopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
#else
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_DSTOPTS);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_DSTOPTS);
}
#endif
#if defined(IPV6_FLOWINFO)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13076,15 +13125,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_FLOWINFO);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_FLOWINFO);
}
#endif
#if defined(IPV6_HOPLIMIT)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13092,15 +13141,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_HOPLIMIT);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_HOPLIMIT);
}
#endif
#if defined(IPV6_HOPOPTS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_hopopts(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13108,15 +13157,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_HOPOPTS);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_HOPOPTS);
}
#endif
#if defined(IPV6_MTU)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13124,17 +13173,17 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_int_opt(env, descP, level, IPV6_MTU);
+ return esock_getopt_int_opt(env, descP, level, IPV6_MTU);
}
#endif
-/* ngetopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option
+/* esock_getopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option
*/
#if defined(IPV6_MTU_DISCOVER)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
ERL_NIF_TERM eMtuDisc;
@@ -13165,8 +13214,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env,
#if defined(IPV6_MULTICAST_HOPS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13174,15 +13223,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS);
+ return esock_getopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS);
}
#endif
#if defined(IPV6_MULTICAST_IF)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13190,15 +13239,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_int_opt(env, descP, level, IPV6_MULTICAST_IF);
+ return esock_getopt_int_opt(env, descP, level, IPV6_MULTICAST_IF);
}
#endif
#if defined(IPV6_MULTICAST_LOOP)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13206,15 +13255,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP);
}
#endif
#if defined(IPV6_RECVERR)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_recverr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13222,15 +13271,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_RECVERR);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_RECVERR);
}
#endif
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13243,15 +13292,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env,
int opt = IPV6_PKTINFO;
#endif
- return ngetopt_bool_opt(env, descP, level, opt);
+ return esock_getopt_bool_opt(env, descP, level, opt);
}
#endif
#if defined(IPV6_ROUTER_ALERT)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_router_alert(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13259,15 +13308,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT);
+ return esock_getopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT);
}
#endif
#if defined(IPV6_RTHDR)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_rthdr(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13275,15 +13324,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_RTHDR);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_RTHDR);
}
#endif
#if defined(IPV6_UNICAST_HOPS)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13291,15 +13340,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS);
+ return esock_getopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS);
}
#endif
#if defined(IPV6_V6ONLY)
static
-ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_ipv6_v6only(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
#if defined(SOL_IPV6)
int level = SOL_IPV6;
@@ -13307,7 +13356,7 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
int level = IPPROTO_IPV6;
#endif
- return ngetopt_bool_opt(env, descP, level, IPV6_V6ONLY);
+ return esock_getopt_bool_opt(env, descP, level, IPV6_V6ONLY);
}
#endif
@@ -13316,31 +13365,31 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env,
-/* ngetopt_lvl_tcp - Level *TCP* option(s)
+/* esock_getopt_lvl_tcp - Level *TCP* option(s)
*/
static
-ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM esock_getopt_lvl_tcp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
switch (eOpt) {
#if defined(TCP_CONGESTION)
- case SOCKET_OPT_TCP_CONGESTION:
- result = ngetopt_lvl_tcp_congestion(env, descP);
+ case ESOCK_OPT_TCP_CONGESTION:
+ result = esock_getopt_lvl_tcp_congestion(env, descP);
break;
#endif
#if defined(TCP_MAXSEG)
- case SOCKET_OPT_TCP_MAXSEG:
- result = ngetopt_lvl_tcp_maxseg(env, descP);
+ case ESOCK_OPT_TCP_MAXSEG:
+ result = esock_getopt_lvl_tcp_maxseg(env, descP);
break;
#endif
#if defined(TCP_NODELAY)
- case SOCKET_OPT_TCP_NODELAY:
- result = ngetopt_lvl_tcp_nodelay(env, descP);
+ case ESOCK_OPT_TCP_NODELAY:
+ result = esock_getopt_lvl_tcp_nodelay(env, descP);
break;
#endif
@@ -13353,58 +13402,58 @@ ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env,
}
-/* ngetopt_lvl_tcp_congestion - Level TCP CONGESTION option
+/* esock_getopt_lvl_tcp_congestion - Level TCP CONGESTION option
*/
#if defined(TCP_CONGESTION)
static
-ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_tcp_congestion(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- int max = SOCKET_OPT_TCP_CONGESTION_NAME_MAX+1;
+ int max = ESOCK_OPT_TCP_CONGESTION_NAME_MAX+1;
- return ngetopt_str_opt(env, descP, IPPROTO_TCP, TCP_CONGESTION, max);
+ return esock_getopt_str_opt(env, descP, IPPROTO_TCP, TCP_CONGESTION, max);
}
#endif
-/* ngetopt_lvl_tcp_maxseg - Level TCP MAXSEG option
+/* esock_getopt_lvl_tcp_maxseg - Level TCP MAXSEG option
*/
#if defined(TCP_MAXSEG)
static
-ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_tcp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG);
+ return esock_getopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG);
}
#endif
-/* ngetopt_lvl_tcp_nodelay - Level TCP NODELAY option
+/* esock_getopt_lvl_tcp_nodelay - Level TCP NODELAY option
*/
#if defined(TCP_NODELAY)
static
-ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_tcp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY);
+ return esock_getopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY);
}
#endif
-/* ngetopt_lvl_udp - Level *UDP* option(s)
+/* esock_getopt_lvl_udp - Level *UDP* option(s)
*/
static
-ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM esock_getopt_lvl_udp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
switch (eOpt) {
#if defined(UDP_CORK)
- case SOCKET_OPT_UDP_CORK:
- result = ngetopt_lvl_udp_cork(env, descP);
+ case ESOCK_OPT_UDP_CORK:
+ result = esock_getopt_lvl_udp_cork(env, descP);
break;
#endif
@@ -13417,74 +13466,74 @@ ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env,
}
-/* ngetopt_lvl_udp_cork - Level UDP CORK option
+/* esock_getopt_lvl_udp_cork - Level UDP CORK option
*/
#if defined(UDP_CORK)
static
-ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_udp_cork(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK);
+ return esock_getopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK);
}
#endif
-/* ngetopt_lvl_sctp - Level *SCTP* option(s)
+/* esock_getopt_lvl_sctp - Level *SCTP* option(s)
*/
#if defined(HAVE_SCTP)
static
-ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
- ESockDescriptor* descP,
- int eOpt)
+ERL_NIF_TERM esock_getopt_lvl_sctp(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int eOpt)
{
ERL_NIF_TERM result;
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_sctp -> entry with"
+ ("SOCKET", "esock_getopt_lvl_sctp -> entry with"
"\r\n opt: %d"
"\r\n", eOpt) );
switch (eOpt) {
#if defined(SCTP_ASSOCINFO)
- case SOCKET_OPT_SCTP_ASSOCINFO:
- result = ngetopt_lvl_sctp_associnfo(env, descP);
+ case ESOCK_OPT_SCTP_ASSOCINFO:
+ result = esock_getopt_lvl_sctp_associnfo(env, descP);
break;
#endif
#if defined(SCTP_AUTOCLOSE)
- case SOCKET_OPT_SCTP_AUTOCLOSE:
- result = ngetopt_lvl_sctp_autoclose(env, descP);
+ case ESOCK_OPT_SCTP_AUTOCLOSE:
+ result = esock_getopt_lvl_sctp_autoclose(env, descP);
break;
#endif
#if defined(SCTP_DISABLE_FRAGMENTS)
- case SOCKET_OPT_SCTP_DISABLE_FRAGMENTS:
- result = ngetopt_lvl_sctp_disable_fragments(env, descP);
+ case ESOCK_OPT_SCTP_DISABLE_FRAGMENTS:
+ result = esock_getopt_lvl_sctp_disable_fragments(env, descP);
break;
#endif
#if defined(SCTP_INITMSG)
- case SOCKET_OPT_SCTP_INITMSG:
- result = ngetopt_lvl_sctp_initmsg(env, descP);
+ case ESOCK_OPT_SCTP_INITMSG:
+ result = esock_getopt_lvl_sctp_initmsg(env, descP);
break;
#endif
#if defined(SCTP_MAXSEG)
- case SOCKET_OPT_SCTP_MAXSEG:
- result = ngetopt_lvl_sctp_maxseg(env, descP);
+ case ESOCK_OPT_SCTP_MAXSEG:
+ result = esock_getopt_lvl_sctp_maxseg(env, descP);
break;
#endif
#if defined(SCTP_NODELAY)
- case SOCKET_OPT_SCTP_NODELAY:
- result = ngetopt_lvl_sctp_nodelay(env, descP);
+ case ESOCK_OPT_SCTP_NODELAY:
+ result = esock_getopt_lvl_sctp_nodelay(env, descP);
break;
#endif
#if defined(SCTP_RTOINFO)
- case SOCKET_OPT_SCTP_RTOINFO:
- result = ngetopt_lvl_sctp_rtoinfo(env, descP);
+ case ESOCK_OPT_SCTP_RTOINFO:
+ result = esock_getopt_lvl_sctp_rtoinfo(env, descP);
break;
#endif
@@ -13494,7 +13543,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_sctp -> done when"
+ ("SOCKET", "esock_getopt_lvl_sctp -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -13502,7 +13551,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
}
-/* ngetopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option
+/* esock_getopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option
*
* <KOLLA>
*
@@ -13517,15 +13566,15 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env,
*/
#if defined(SCTP_ASSOCINFO)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sctp_associnfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct sctp_assocparams val;
SOCKOPTLEN_T valSz = sizeof(val);
int res;
- SSDBG( descP, ("SOCKET", "ngetopt_lvl_sctp_associnfo -> entry\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_getopt_lvl_sctp_associnfo -> entry\r\n") );
sys_memzero((char*) &val, valSz);
res = sock_getopt(descP->sock, IPPROTO_SCTP, SCTP_ASSOCINFO, &val, &valSz);
@@ -13554,7 +13603,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_sctp_associnfo -> done with"
+ ("SOCKET", "esock_getopt_lvl_sctp_associnfo -> done with"
"\r\n res: %d"
"\r\n result: %T"
"\r\n", res, result) );
@@ -13564,44 +13613,45 @@ ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env,
#endif
-/* ngetopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option
+/* esock_getopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option
*/
#if defined(SCTP_AUTOCLOSE)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sctp_autoclose(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE);
+ return esock_getopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE);
}
#endif
-/* ngetopt_lvl_sctp_disable_fragments - Level SCTP DISABLE:FRAGMENTS option
+/* esock_getopt_lvl_sctp_disable_fragments - Level SCTP DISABLE:FRAGMENTS option
*/
#if defined(SCTP_DISABLE_FRAGMENTS)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sctp_disable_fragments(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS);
+ return esock_getopt_bool_opt(env, descP,
+ IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS);
}
#endif
-/* ngetopt_lvl_sctp_initmsg - Level SCTP INITMSG option
+/* esock_getopt_lvl_sctp_initmsg - Level SCTP INITMSG option
*
*/
#if defined(SCTP_INITMSG)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sctp_initmsg(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct sctp_initmsg val;
SOCKOPTLEN_T valSz = sizeof(val);
int res;
- SSDBG( descP, ("SOCKET", "ngetopt_lvl_sctp_initmsg -> entry\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_getopt_lvl_sctp_initmsg -> entry\r\n") );
sys_memzero((char*) &val, valSz);
res = sock_getopt(descP->sock, IPPROTO_SCTP, SCTP_INITMSG, &val, &valSz);
@@ -13628,7 +13678,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_sctp_initmsg -> done with"
+ ("SOCKET", "esock_getopt_lvl_sctp_initmsg -> done with"
"\r\n res: %d"
"\r\n result: %T"
"\r\n", res, result) );
@@ -13638,31 +13688,31 @@ ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env,
#endif
-/* ngetopt_lvl_sctp_maxseg - Level SCTP MAXSEG option
+/* esock_getopt_lvl_sctp_maxseg - Level SCTP MAXSEG option
*/
#if defined(SCTP_MAXSEG)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sctp_maxseg(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG);
+ return esock_getopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG);
}
#endif
-/* ngetopt_lvl_sctp_nodelay - Level SCTP NODELAY option
+/* esock_getopt_lvl_sctp_nodelay - Level SCTP NODELAY option
*/
#if defined(SCTP_NODELAY)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sctp_nodelay(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
- return ngetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY);
+ return esock_getopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY);
}
#endif
-/* ngetopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option
+/* esock_getopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option
*
* <KOLLA>
*
@@ -13677,15 +13727,15 @@ ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env,
*/
#if defined(SCTP_RTOINFO)
static
-ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_getopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ERL_NIF_TERM result;
struct sctp_rtoinfo val;
SOCKOPTLEN_T valSz = sizeof(val);
int res;
- SSDBG( descP, ("SOCKET", "ngetopt_lvl_sctp_rtoinfo -> entry\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_getopt_lvl_sctp_rtoinfo -> entry\r\n") );
sys_memzero((char*) &val, valSz);
res = sock_getopt(descP->sock, IPPROTO_SCTP, SCTP_RTOINFO, &val, &valSz);
@@ -13711,7 +13761,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_lvl_sctp_rtoinfo -> done with"
+ ("SOCKET", "esock_getopt_lvl_sctp_rtoinfo -> done with"
"\r\n res: %d"
"\r\n result: %T"
"\r\n", res, result) );
@@ -13726,13 +13776,13 @@ ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env,
-/* ngetopt_bool_opt - get an (integer) bool option
+/* esock_getopt_bool_opt - get an (integer) bool option
*/
static
-ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt)
+ERL_NIF_TERM esock_getopt_bool_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt)
{
ERL_NIF_TERM result;
int val;
@@ -13740,7 +13790,7 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
int res;
/*
- SSDBG( descP, ("SOCKET", "ngetopt_bool_opt -> entry with"
+ SSDBG( descP, ("SOCKET", "esock_getopt_bool_opt -> entry with"
"\r\n: level: %d"
"\r\n: opt: %d"
"\r\n", level, opt) );
@@ -13757,7 +13807,7 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
}
/*
- SSDBG( descP, ("SOCKET", "ngetopt_bool_opt -> done when"
+ SSDBG( descP, ("SOCKET", "esock_getopt_bool_opt -> done when"
"\r\n: res: %d"
"\r\n: result: %T"
"\r\n", res, result) );
@@ -13767,13 +13817,13 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env,
}
-/* ngetopt_int_opt - get an integer option
+/* esock_getopt_int_opt - get an integer option
*/
static
-ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt)
+ERL_NIF_TERM esock_getopt_int_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt)
{
ERL_NIF_TERM result;
int val;
@@ -13793,13 +13843,13 @@ ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env,
-/* ngetopt_timeval_opt - get an timeval option
+/* esock_getopt_timeval_opt - get an timeval option
*/
static
-ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt)
+ERL_NIF_TERM esock_getopt_timeval_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt)
{
ERL_NIF_TERM result;
struct timeval val;
@@ -13807,7 +13857,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
int res;
SSDBG( descP,
- ("SOCKET", "ngetopt_timeval_opt -> entry with"
+ ("SOCKET", "esock_getopt_timeval_opt -> entry with"
"\r\n level: %d"
"\r\n opt: %d"
"\r\n", level, opt) );
@@ -13828,7 +13878,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_timeval_opt -> done when"
+ ("SOCKET", "esock_getopt_timeval_opt -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -13837,7 +13887,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
-/* ngetopt_str_opt - get an string option
+/* esock_getopt_str_opt - get an string option
*
* We provide the max size of the string. This is the
* size of the buffer we allocate for the value.
@@ -13846,11 +13896,11 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env,
*/
#if defined(USE_GETOPT_STR_OPT)
static
-ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
- ESockDescriptor* descP,
- int level,
- int opt,
- int max)
+ERL_NIF_TERM esock_getopt_str_opt(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ int level,
+ int opt,
+ int max)
{
ERL_NIF_TERM result;
char* val = MALLOC(max);
@@ -13858,7 +13908,7 @@ ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
int res;
SSDBG( descP,
- ("SOCKET", "ngetopt_str_opt -> entry with"
+ ("SOCKET", "esock_getopt_str_opt -> entry with"
"\r\n level: %d"
"\r\n opt: %d"
"\r\n max: %d"
@@ -13875,7 +13925,7 @@ ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env,
}
SSDBG( descP,
- ("SOCKET", "ngetopt_str_opt -> done when"
+ ("SOCKET", "esock_getopt_str_opt -> done when"
"\r\n result: %T"
"\r\n", result) );
@@ -13914,7 +13964,7 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 1) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -13926,7 +13976,7 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env,
"\r\n Socket: %T"
"\r\n", descP->sock, argv[0]) );
- res = nsockname(env, descP);
+ res = esock_sockname(env, descP);
SSDBG( descP, ("SOCKET", "nif_sockname -> done with res = %T\r\n", res) );
@@ -13938,8 +13988,8 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM nsockname(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_sockname(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ESockAddress sa;
ESockAddress* saP = &sa;
@@ -13988,7 +14038,7 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env,
/* Extract arguments and perform preliminary validation */
if ((argc != 1) ||
- !enif_get_resource(env, argv[0], sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) {
return enif_make_badarg(env);
}
@@ -14000,7 +14050,7 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env,
"\r\n Socket: %T"
"\r\n", descP->sock, argv[0]) );
- res = npeername(env, descP);
+ res = esock_peername(env, descP);
SSDBG( descP, ("SOCKET", "nif_peername -> done with res = %T\r\n", res) );
@@ -14012,8 +14062,8 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM npeername(ErlNifEnv* env,
- ESockDescriptor* descP)
+ERL_NIF_TERM esock_peername(ErlNifEnv* env,
+ ESockDescriptor* descP)
{
ESockAddress sa;
ESockAddress* saP = &sa;
@@ -14064,7 +14114,7 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
sockRef = argv[0];
if ((argc != 3) ||
- !enif_get_resource(env, sockRef, sockets, (void**) &descP)) {
+ !ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) {
return enif_make_badarg(env);
}
op = argv[1];
@@ -14079,7 +14129,7 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
"\r\n opRef: %T"
"\r\n", descP->sock, op, opRef) );
- result = ncancel(env, descP, op, sockRef, opRef);
+ result = esock_cancel(env, descP, op, sockRef, opRef);
SSDBG( descP,
("SOCKET", "nif_cancel -> done with result: "
@@ -14093,11 +14143,11 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env,
#if !defined(__WIN32__)
static
-ERL_NIF_TERM ncancel(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM op,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM op,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
/* <KOLLA>
*
@@ -14108,21 +14158,21 @@ ERL_NIF_TERM ncancel(ErlNifEnv* env,
* </KOLLA>
*/
if (COMPARE(op, esock_atom_connect) == 0) {
- return ncancel_connect(env, descP, opRef);
+ return esock_cancel_connect(env, descP, opRef);
} else if (COMPARE(op, esock_atom_accept) == 0) {
- return ncancel_accept(env, descP, sockRef, opRef);
+ return esock_cancel_accept(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_send) == 0) {
- return ncancel_send(env, descP, sockRef, opRef);
+ return esock_cancel_send(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_sendto) == 0) {
- return ncancel_send(env, descP, sockRef, opRef);
+ return esock_cancel_send(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_sendmsg) == 0) {
- return ncancel_send(env, descP, sockRef, opRef);
+ return esock_cancel_send(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_recv) == 0) {
- return ncancel_recv(env, descP, sockRef, opRef);
+ return esock_cancel_recv(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_recvfrom) == 0) {
- return ncancel_recv(env, descP, sockRef, opRef);
+ return esock_cancel_recv(env, descP, sockRef, opRef);
} else if (COMPARE(op, esock_atom_recvmsg) == 0) {
- return ncancel_recv(env, descP, sockRef, opRef);
+ return esock_cancel_recv(env, descP, sockRef, opRef);
} else {
return esock_make_error(env, esock_atom_einval);
}
@@ -14130,20 +14180,20 @@ ERL_NIF_TERM ncancel(ErlNifEnv* env,
-/* *** ncancel_connect ***
+/* *** esock_cancel_connect ***
*
*
*/
static
-ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_connect(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
- return ncancel_write_select(env, descP, opRef);
+ return esock_cancel_write_select(env, descP, opRef);
}
-/* *** ncancel_accept ***
+/* *** esock_cancel_accept ***
*
* We have two different cases:
* *) Its the current acceptor
@@ -14154,15 +14204,15 @@ ERL_NIF_TERM ncancel_connect(ErlNifEnv* env,
*
*/
static
-ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_accept(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
SSDBG( descP,
- ("SOCKET", "ncancel_accept -> entry with"
+ ("SOCKET", "esock_cancel_accept -> entry with"
"\r\n opRef: %T"
"\r\n %s"
"\r\n", opRef,
@@ -14172,9 +14222,9 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
if (descP->currentAcceptorP != NULL) {
if (COMPARE(opRef, descP->currentAcceptor.ref) == 0) {
- res = ncancel_accept_current(env, descP, sockRef);
+ res = esock_cancel_accept_current(env, descP, sockRef);
} else {
- res = ncancel_accept_waiting(env, descP, opRef);
+ res = esock_cancel_accept_waiting(env, descP, opRef);
}
} else {
/* Or badarg? */
@@ -14184,7 +14234,7 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
MUNLOCK(descP->accMtx);
SSDBG( descP,
- ("SOCKET", "ncancel_accept -> done with result:"
+ ("SOCKET", "esock_cancel_accept -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -14197,27 +14247,27 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env,
* in the acceptor queue).
*/
static
-ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM esock_cancel_accept_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res;
- SSDBG( descP, ("SOCKET", "ncancel_accept_current -> entry\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_cancel_accept_current -> entry\r\n") );
- DEMONP("ncancel_accept_current -> current acceptor",
+ DEMONP("esock_cancel_accept_current -> current acceptor",
env, descP, &descP->currentAcceptor.mon);
- res = ncancel_read_select(env, descP, descP->currentAcceptor.ref);
+ res = esock_cancel_read_select(env, descP, descP->currentAcceptor.ref);
SSDBG( descP, ("SOCKET",
- "ncancel_accept_current -> cancel res: %T\r\n", res) );
+ "esock_cancel_accept_current -> cancel res: %T\r\n", res) );
if (!activate_next_acceptor(env, descP, sockRef)) {
SSDBG( descP,
- ("SOCKET", "ncancel_accept_current -> no more writers\r\n") );
+ ("SOCKET", "esock_cancel_accept_current -> no more writers\r\n") );
- descP->state = SOCKET_STATE_LISTENING;
+ descP->state = ESOCK_STATE_LISTENING;
descP->currentAcceptorP = NULL;
descP->currentAcceptor.ref = esock_atom_undefined;
@@ -14225,7 +14275,7 @@ ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
esock_monitor_init(&descP->currentAcceptor.mon);
}
- SSDBG( descP, ("SOCKET", "ncancel_accept_current -> done with result:"
+ SSDBG( descP, ("SOCKET", "esock_cancel_accept_current -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -14237,9 +14287,9 @@ ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env,
* remove them from the acceptor queue.
*/
static
-ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_accept_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
ErlNifPid caller;
@@ -14258,23 +14308,23 @@ ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env,
-/* *** ncancel_send ***
+/* *** esock_cancel_send ***
*
* Cancel a send operation.
* Its either the current writer or one of the waiting writers.
*/
static
-ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_send(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
MLOCK(descP->writeMtx);
SSDBG( descP,
- ("SOCKET", "ncancel_send -> entry with"
+ ("SOCKET", "esock_cancel_send -> entry with"
"\r\n opRef: %T"
"\r\n %s"
"\r\n", opRef,
@@ -14282,9 +14332,9 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
if (descP->currentWriterP != NULL) {
if (COMPARE(opRef, descP->currentWriter.ref) == 0) {
- res = ncancel_send_current(env, descP, sockRef);
+ res = esock_cancel_send_current(env, descP, sockRef);
} else {
- res = ncancel_send_waiting(env, descP, opRef);
+ res = esock_cancel_send_waiting(env, descP, opRef);
}
} else {
/* Or badarg? */
@@ -14294,7 +14344,7 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
MUNLOCK(descP->writeMtx);
SSDBG( descP,
- ("SOCKET", "ncancel_send -> done with result:"
+ ("SOCKET", "esock_cancel_send -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -14308,31 +14358,31 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env,
* in the writer queue).
*/
static
-ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM esock_cancel_send_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res;
- SSDBG( descP, ("SOCKET", "ncancel_send_current -> entry\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_cancel_send_current -> entry\r\n") );
- DEMONP("ncancel_send_current -> current writer",
+ DEMONP("esock_cancel_send_current -> current writer",
env, descP, &descP->currentWriter.mon);
- res = ncancel_write_select(env, descP, descP->currentWriter.ref);
+ res = esock_cancel_write_select(env, descP, descP->currentWriter.ref);
SSDBG( descP,
- ("SOCKET", "ncancel_send_current -> cancel res: %T\r\n", res) );
+ ("SOCKET", "esock_cancel_send_current -> cancel res: %T\r\n", res) );
if (!activate_next_writer(env, descP, sockRef)) {
SSDBG( descP,
- ("SOCKET", "ncancel_send_current -> no more writers\r\n") );
+ ("SOCKET", "esock_cancel_send_current -> no more writers\r\n") );
descP->currentWriterP = NULL;
descP->currentWriter.ref = esock_atom_undefined;
enif_set_pid_undefined(&descP->currentWriter.pid);
esock_monitor_init(&descP->currentWriter.mon);
}
- SSDBG( descP, ("SOCKET", "ncancel_send_current -> done with result:"
+ SSDBG( descP, ("SOCKET", "esock_cancel_send_current -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -14344,9 +14394,9 @@ ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env,
* remove them from the writer queue.
*/
static
-ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_send_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
ErlNifPid caller;
@@ -14365,23 +14415,23 @@ ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env,
-/* *** ncancel_recv ***
+/* *** esock_cancel_recv ***
*
* Cancel a read operation.
* Its either the current reader or one of the waiting readers.
*/
static
-ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_recv(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ERL_NIF_TERM opRef)
{
ERL_NIF_TERM res;
MLOCK(descP->readMtx);
SSDBG( descP,
- ("SOCKET", "ncancel_recv -> entry with"
+ ("SOCKET", "esock_cancel_recv -> entry with"
"\r\n opRef: %T"
"\r\n %s"
"\r\n", opRef,
@@ -14389,9 +14439,9 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
if (descP->currentReaderP != NULL) {
if (COMPARE(opRef, descP->currentReader.ref) == 0) {
- res = ncancel_recv_current(env, descP, sockRef);
+ res = esock_cancel_recv_current(env, descP, sockRef);
} else {
- res = ncancel_recv_waiting(env, descP, opRef);
+ res = esock_cancel_recv_waiting(env, descP, opRef);
}
} else {
/* Or badarg? */
@@ -14401,7 +14451,7 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
MUNLOCK(descP->readMtx);
SSDBG( descP,
- ("SOCKET", "ncancel_recv -> done with result:"
+ ("SOCKET", "esock_cancel_recv -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -14414,31 +14464,31 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env,
* in the reader queue).
*/
static
-ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef)
+ERL_NIF_TERM esock_cancel_recv_current(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef)
{
ERL_NIF_TERM res;
- SSDBG( descP, ("SOCKET", "ncancel_recv_current -> entry\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_cancel_recv_current -> entry\r\n") );
- DEMONP("ncancel_recv_current -> current reader",
+ DEMONP("esock_cancel_recv_current -> current reader",
env, descP, &descP->currentReader.mon);
- res = ncancel_read_select(env, descP, descP->currentReader.ref);
+ res = esock_cancel_read_select(env, descP, descP->currentReader.ref);
SSDBG( descP,
- ("SOCKET", "ncancel_recv_current -> cancel res: %T\r\n", res) );
+ ("SOCKET", "esock_cancel_recv_current -> cancel res: %T\r\n", res) );
if (!activate_next_reader(env, descP, sockRef)) {
SSDBG( descP,
- ("SOCKET", "ncancel_recv_current -> no more readers\r\n") );
+ ("SOCKET", "esock_cancel_recv_current -> no more readers\r\n") );
descP->currentReaderP = NULL;
descP->currentReader.ref = esock_atom_undefined;
enif_set_pid_undefined(&descP->currentReader.pid);
esock_monitor_init(&descP->currentReader.mon);
}
- SSDBG( descP, ("SOCKET", "ncancel_recv_current -> done with result:"
+ SSDBG( descP, ("SOCKET", "esock_cancel_recv_current -> done with result:"
"\r\n %T"
"\r\n", res) );
@@ -14450,9 +14500,9 @@ ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env,
* remove them from the reader queue.
*/
static
-ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_recv_waiting(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
ErlNifPid caller;
@@ -14472,33 +14522,33 @@ ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env,
static
-ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef)
+ERL_NIF_TERM esock_cancel_read_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef)
{
- return ncancel_mode_select(env, descP, opRef,
- ERL_NIF_SELECT_READ,
- ERL_NIF_SELECT_READ_CANCELLED);
+ return esock_cancel_mode_select(env, descP, opRef,
+ ERL_NIF_SELECT_READ,
+ ERL_NIF_SELECT_READ_CANCELLED);
}
static
-ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env,
+ERL_NIF_TERM esock_cancel_write_select(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM opRef)
{
- return ncancel_mode_select(env, descP, opRef,
- ERL_NIF_SELECT_WRITE,
- ERL_NIF_SELECT_WRITE_CANCELLED);
+ return esock_cancel_mode_select(env, descP, opRef,
+ ERL_NIF_SELECT_WRITE,
+ ERL_NIF_SELECT_WRITE_CANCELLED);
}
static
-ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
- ESockDescriptor* descP,
- ERL_NIF_TERM opRef,
- int smode,
- int rmode)
+ERL_NIF_TERM esock_cancel_mode_select(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM opRef,
+ int smode,
+ int rmode)
{
int selectRes = esock_select_cancel(env, descP->sock, smode, descP);
@@ -14510,7 +14560,8 @@ ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env,
return esock_make_error(env, esock_atom_select_sent);
} else {
/* Stopped? */
- SSDBG( descP, ("SOCKET", "ncancel_mode_select -> failed: %d (0x%lX)"
+ SSDBG( descP, ("SOCKET",
+ "esock_cancel_mode_select -> failed: %d (0x%lX)"
"\r\n", selectRes, selectRes) );
return esock_make_error(env, esock_atom_einval);
}
@@ -15348,7 +15399,7 @@ ERL_NIF_TERM recv_check_fail_closed(ErlNifEnv* env,
*/
descP->closeLocal = FALSE;
- descP->state = SOCKET_STATE_CLOSING;
+ descP->state = ESOCK_STATE_CLOSING;
recv_error_current_reader(env, descP, sockRef, res);
@@ -17368,11 +17419,11 @@ BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal,
if (COMPARE(nativeOptT[1], atom_int) == 0) {
SGDBG( ("SOCKET", "decode_native_get_opt -> int\r\n") );
- *valueType = SOCKET_OPT_VALUE_TYPE_INT;
+ *valueType = ESOCK_OPT_VALUE_TYPE_INT;
*valueSz = sizeof(int); // Just to be sure
} else if (COMPARE(nativeOptT[1], atom_bool) == 0) {
SGDBG( ("SOCKET", "decode_native_get_opt -> bool\r\n") );
- *valueType = SOCKET_OPT_VALUE_TYPE_BOOL;
+ *valueType = ESOCK_OPT_VALUE_TYPE_BOOL;
*valueSz = sizeof(int); // Just to be sure
} else {
return FALSE;
@@ -17380,7 +17431,7 @@ BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal,
} else if (IS_NUM(env, nativeOptT[1])) {
if (GET_INT(env, nativeOptT[1], valueSz)) {
SGDBG( ("SOCKET", "decode_native_get_opt -> unspec\r\n") );
- *valueType = SOCKET_OPT_VALUE_TYPE_UNSPEC;
+ *valueType = ESOCK_OPT_VALUE_TYPE_UNSPEC;
} else {
return FALSE;
}
@@ -17447,7 +17498,7 @@ ESockDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
{
ESockDescriptor* descP;
- if ((descP = enif_alloc_resource(sockets, sizeof(ESockDescriptor))) != NULL) {
+ if ((descP = enif_alloc_resource(esocks, sizeof(ESockDescriptor))) != NULL) {
char buf[64]; /* Buffer used for building the mutex name */
descP->pattern = ESOCK_DESC_PATTERN_CREATED;
@@ -17506,13 +17557,13 @@ ESockDescriptor* alloc_descriptor(SOCKET sock, HANDLE event)
sprintf(buf, "esock[cfg,%d]", sock);
descP->cfgMtx = MCREATE(buf);
- descP->rBufSz = SOCKET_RECV_BUFFER_SIZE_DEFAULT;
+ descP->rBufSz = ESOCK_RECV_BUFFER_SIZE_DEFAULT;
descP->rNum = 0;
descP->rNumCnt = 0;
- descP->rCtrlSz = SOCKET_RECV_CTRL_BUFFER_SIZE_DEFAULT;
- descP->wCtrlSz = SOCKET_SEND_CTRL_BUFFER_SIZE_DEFAULT;
+ descP->rCtrlSz = ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT;
+ descP->wCtrlSz = ESOCK_SEND_CTRL_BUFFER_SIZE_DEFAULT;
descP->iow = FALSE;
- descP->dbg = SOCKET_DEBUG_DEFAULT;
+ descP->dbg = ESOCK_DEBUG_DEFAULT;
descP->sock = sock;
descP->event = event;
@@ -17639,17 +17690,17 @@ static
BOOLEAN_T edomain2domain(int edomain, int* domain)
{
switch (edomain) {
- case SOCKET_DOMAIN_INET:
+ case ESOCK_DOMAIN_INET:
*domain = AF_INET;
break;
#if defined(HAVE_IN6) && defined(AF_INET6)
- case SOCKET_DOMAIN_INET6:
+ case ESOCK_DOMAIN_INET6:
*domain = AF_INET6;
break;
#endif
#ifdef HAVE_SYS_UN_H
- case SOCKET_DOMAIN_LOCAL:
+ case ESOCK_DOMAIN_LOCAL:
*domain = AF_UNIX;
break;
#endif
@@ -17671,20 +17722,20 @@ static
BOOLEAN_T etype2type(int etype, int* type)
{
switch (etype) {
- case SOCKET_TYPE_STREAM:
+ case ESOCK_TYPE_STREAM:
*type = SOCK_STREAM;
break;
- case SOCKET_TYPE_DGRAM:
+ case ESOCK_TYPE_DGRAM:
*type = SOCK_DGRAM;
break;
- case SOCKET_TYPE_RAW:
+ case ESOCK_TYPE_RAW:
*type = SOCK_RAW;
break;
#ifdef HAVE_SCTP
- case SOCKET_TYPE_SEQPACKET:
+ case ESOCK_TYPE_SEQPACKET:
*type = SOCK_SEQPACKET;
break;
#endif
@@ -17716,33 +17767,33 @@ BOOLEAN_T eproto2proto(ErlNifEnv* env,
}
switch (ep) {
- case SOCKET_PROTOCOL_DEFAULT:
+ case ESOCK_PROTOCOL_DEFAULT:
*proto = 0; // default - note that _IP also has the value 0...
break;
- case SOCKET_PROTOCOL_IP:
+ case ESOCK_PROTOCOL_IP:
*proto = IPPROTO_IP;
break;
- case SOCKET_PROTOCOL_TCP:
+ case ESOCK_PROTOCOL_TCP:
*proto = IPPROTO_TCP;
break;
- case SOCKET_PROTOCOL_UDP:
+ case ESOCK_PROTOCOL_UDP:
*proto = IPPROTO_UDP;
break;
#if defined(HAVE_SCTP)
- case SOCKET_PROTOCOL_SCTP:
+ case ESOCK_PROTOCOL_SCTP:
*proto = IPPROTO_SCTP;
break;
#endif
- case SOCKET_PROTOCOL_ICMP:
+ case ESOCK_PROTOCOL_ICMP:
*proto = IPPROTO_ICMP;
break;
- case SOCKET_PROTOCOL_IGMP:
+ case ESOCK_PROTOCOL_IGMP:
*proto = IPPROTO_IGMP;
break;
@@ -17851,47 +17902,47 @@ BOOLEAN_T esendflags2sendflags(unsigned int eflags, int* flags)
return TRUE;
}
- for (ef = SOCKET_SEND_FLAG_LOW; ef <= SOCKET_SEND_FLAG_HIGH; ef++) {
+ for (ef = ESOCK_SEND_FLAG_LOW; ef <= ESOCK_SEND_FLAG_HIGH; ef++) {
switch (ef) {
#if defined(MSG_CONFIRM)
- case SOCKET_SEND_FLAG_CONFIRM:
- if ((1 << SOCKET_SEND_FLAG_CONFIRM) & eflags)
+ case ESOCK_SEND_FLAG_CONFIRM:
+ if ((1 << ESOCK_SEND_FLAG_CONFIRM) & eflags)
tmp |= MSG_CONFIRM;
break;
#endif
#if defined(MSG_DONTROUTE)
- case SOCKET_SEND_FLAG_DONTROUTE:
- if ((1 << SOCKET_SEND_FLAG_DONTROUTE) & eflags)
+ case ESOCK_SEND_FLAG_DONTROUTE:
+ if ((1 << ESOCK_SEND_FLAG_DONTROUTE) & eflags)
tmp |= MSG_DONTROUTE;
break;
#endif
#if defined(MSG_EOR)
- case SOCKET_SEND_FLAG_EOR:
- if ((1 << SOCKET_SEND_FLAG_EOR) & eflags)
+ case ESOCK_SEND_FLAG_EOR:
+ if ((1 << ESOCK_SEND_FLAG_EOR) & eflags)
tmp |= MSG_EOR;
break;
#endif
#if defined(MSG_MORE)
- case SOCKET_SEND_FLAG_MORE:
- if ((1 << SOCKET_SEND_FLAG_MORE) & eflags)
+ case ESOCK_SEND_FLAG_MORE:
+ if ((1 << ESOCK_SEND_FLAG_MORE) & eflags)
tmp |= MSG_MORE;
break;
#endif
#if defined(MSG_NOSIGNAL)
- case SOCKET_SEND_FLAG_NOSIGNAL:
- if ((1 << SOCKET_SEND_FLAG_NOSIGNAL) & eflags)
+ case ESOCK_SEND_FLAG_NOSIGNAL:
+ if ((1 << ESOCK_SEND_FLAG_NOSIGNAL) & eflags)
tmp |= MSG_NOSIGNAL;
break;
#endif
#if defined(MSG_OOB)
- case SOCKET_SEND_FLAG_OOB:
- if ((1 << SOCKET_SEND_FLAG_OOB) & eflags)
+ case ESOCK_SEND_FLAG_OOB:
+ if ((1 << ESOCK_SEND_FLAG_OOB) & eflags)
tmp |= MSG_OOB;
break;
#endif
@@ -17927,7 +17978,7 @@ BOOLEAN_T erecvflags2recvflags(unsigned int eflags, int* flags)
return TRUE;
}
- for (ef = SOCKET_RECV_FLAG_LOW; ef <= SOCKET_RECV_FLAG_HIGH; ef++) {
+ for (ef = ESOCK_RECV_FLAG_LOW; ef <= ESOCK_RECV_FLAG_HIGH; ef++) {
SGDBG( ("SOCKET", "erecvflags2recvflags -> iteration"
"\r\n ef: %d"
@@ -17936,22 +17987,22 @@ BOOLEAN_T erecvflags2recvflags(unsigned int eflags, int* flags)
switch (ef) {
#if defined(MSG_CMSG_CLOEXEC)
- case SOCKET_RECV_FLAG_CMSG_CLOEXEC:
- if ((1 << SOCKET_RECV_FLAG_CMSG_CLOEXEC) & eflags)
+ case ESOCK_RECV_FLAG_CMSG_CLOEXEC:
+ if ((1 << ESOCK_RECV_FLAG_CMSG_CLOEXEC) & eflags)
tmp |= MSG_CMSG_CLOEXEC;
break;
#endif
#if defined(MSG_ERRQUEUE)
- case SOCKET_RECV_FLAG_ERRQUEUE:
- if ((1 << SOCKET_RECV_FLAG_ERRQUEUE) & eflags)
+ case ESOCK_RECV_FLAG_ERRQUEUE:
+ if ((1 << ESOCK_RECV_FLAG_ERRQUEUE) & eflags)
tmp |= MSG_ERRQUEUE;
break;
#endif
#if defined(MSG_OOB)
- case SOCKET_RECV_FLAG_OOB:
- if ((1 << SOCKET_RECV_FLAG_OOB) & eflags)
+ case ESOCK_RECV_FLAG_OOB:
+ if ((1 << ESOCK_RECV_FLAG_OOB) & eflags)
tmp |= MSG_OOB;
break;
#endif
@@ -17964,15 +18015,15 @@ BOOLEAN_T erecvflags2recvflags(unsigned int eflags, int* flags)
* </KOLLA>
*/
#if defined(MSG_PEEK)
- case SOCKET_RECV_FLAG_PEEK:
- if ((1 << SOCKET_RECV_FLAG_PEEK) & eflags)
+ case ESOCK_RECV_FLAG_PEEK:
+ if ((1 << ESOCK_RECV_FLAG_PEEK) & eflags)
tmp |= MSG_PEEK;
break;
#endif
#if defined(MSG_TRUNC)
- case SOCKET_RECV_FLAG_TRUNC:
- if ((1 << SOCKET_RECV_FLAG_TRUNC) & eflags)
+ case ESOCK_RECV_FLAG_TRUNC:
+ if ((1 << ESOCK_RECV_FLAG_TRUNC) & eflags)
tmp |= MSG_TRUNC;
break;
#endif
@@ -17998,15 +18049,15 @@ static
BOOLEAN_T ehow2how(unsigned int ehow, int* how)
{
switch (ehow) {
- case SOCKET_SHUTDOWN_HOW_RD:
+ case ESOCK_SHUTDOWN_HOW_RD:
*how = SHUT_RD;
break;
- case SOCKET_SHUTDOWN_HOW_WR:
+ case ESOCK_SHUTDOWN_HOW_WR:
*how = SHUT_WR;
break;
- case SOCKET_SHUTDOWN_HOW_RDWR:
+ case ESOCK_SHUTDOWN_HOW_RDWR:
*how = SHUT_RDWR;
break;
@@ -18052,7 +18103,7 @@ BOOLEAN_T ecommand2command(ErlNifEnv* env,
return FALSE;
}
if (COMPARE(ecmd, esock_atom_debug) == 0) {
- *command = SOCKET_CMD_DEBUG;
+ *command = ESOCK_CMD_DEBUG;
} else {
SGDBG( ("SOCKET", "ecommand2command -> unknown command %T\r\n", ecmd) );
return FALSE;
@@ -18874,11 +18925,11 @@ static void free_request_queue(ESockRequestQueue* q)
}
/* =========================================================================
- * socket_dtor - Callback function for resource destructor
+ * esock_dtor - Callback function for resource destructor
*
*/
static
-void socket_dtor(ErlNifEnv* env, void* obj)
+void esock_dtor(ErlNifEnv* env, void* obj)
{
#if !defined(__WIN32__)
ESockDescriptor* descP = (ESockDescriptor*) obj;
@@ -18905,14 +18956,14 @@ void socket_dtor(ErlNifEnv* env, void* obj)
free_request_queue(&descP->writersQ);
free_request_queue(&descP->acceptorsQ);
- descP->state = SOCKET_STATE_DTOR;
+ descP->state = ESOCK_STATE_DTOR;
descP->pattern = ESOCK_DESC_PATTERN_DTOR;
#endif
}
/* =========================================================================
- * socket_stop - Callback function for resource stop
+ * esock_stop - Callback function for resource stop
*
* When the socket is stopped, we need to inform:
*
@@ -18927,14 +18978,14 @@ void socket_dtor(ErlNifEnv* env, void* obj)
*
*/
static
-void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
+void esock_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
{
#if !defined(__WIN32__)
ESockDescriptor* descP = (ESockDescriptor*) obj;
ERL_NIF_TERM sockRef;
SSDBG( descP,
- ("SOCKET", "socket_stop -> entry when %s"
+ ("SOCKET", "esock_stop -> entry when %s"
"\r\n sock: %d (%d)"
"\r\n",
((is_direct_call) ? "called" : "scheduled"), descP->sock, fd) );
@@ -18947,7 +18998,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
MLOCK(descP->cfgMtx);
if (!is_direct_call) MLOCK(descP->closeMtx);
- SSDBG( descP, ("SOCKET", "socket_stop -> "
+ SSDBG( descP, ("SOCKET", "esock_stop -> "
"[%d, %T] all mutex(s) locked when counters:"
"\r\n writePkgCnt: %u"
"\r\n writeByteCnt: %u"
@@ -18971,7 +19022,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
descP->readWaits) );
sockRef = enif_make_resource(env, descP);
- descP->state = SOCKET_STATE_CLOSING; // Just in case...???
+ descP->state = ESOCK_STATE_CLOSING; // Just in case...???
descP->isReadable = FALSE;
descP->isWritable = FALSE;
@@ -18982,7 +19033,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
* there is no point to demonitor. Also, we do not actually
* have a monitor in that case...
*/
- DEMONP("socket_stop -> ctrl", env, descP, &descP->ctrlMon);
+ DEMONP("esock_stop -> ctrl", env, descP, &descP->ctrlMon);
@@ -18999,12 +19050,12 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
* writers waiting.
*/
- socket_stop_handle_current(env,
- "writer",
- descP, sockRef, &descP->currentWriter);
+ esock_stop_handle_current(env,
+ "writer",
+ descP, sockRef, &descP->currentWriter);
/* And also deal with the waiting writers (in the same way) */
- SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting writer(s)\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_stop -> handle waiting writer(s)\r\n") );
inform_waiting_procs(env, "writer",
descP, sockRef, &descP->writersQ, TRUE, atom_closed);
}
@@ -19023,12 +19074,12 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
* readers waiting.
*/
- socket_stop_handle_current(env,
- "reader",
- descP, sockRef, &descP->currentReader);
+ esock_stop_handle_current(env,
+ "reader",
+ descP, sockRef, &descP->currentReader);
/* And also deal with the waiting readers (in the same way) */
- SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting reader(s)\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_stop -> handle waiting reader(s)\r\n") );
inform_waiting_procs(env, "reader",
descP, sockRef, &descP->readersQ, TRUE, atom_closed);
}
@@ -19048,12 +19099,12 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
* acceptors waiting.
*/
- socket_stop_handle_current(env,
- "acceptor",
- descP, sockRef, &descP->currentAcceptor);
-
+ esock_stop_handle_current(env,
+ "acceptor",
+ descP, sockRef, &descP->currentAcceptor);
+
/* And also deal with the waiting acceptors (in the same way) */
- SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting acceptor(s)\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_stop -> handle waiting acceptor(s)\r\n") );
inform_waiting_procs(env, "acceptor",
descP, sockRef, &descP->acceptorsQ, TRUE, atom_closed);
}
@@ -19077,7 +19128,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
esock_send_close_msg(env, descP, &descP->closerPid);
- DEMONP("socket_stop -> closer", env, descP, &descP->closerMon);
+ DEMONP("esock_stop -> closer", env, descP, &descP->closerMon);
} else {
@@ -19086,14 +19137,14 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
*/
if (descP->closeEnv != NULL)
- esock_free_env("socket_stop - close-env", descP->closeEnv);
+ esock_free_env("esock_stop - close-env", descP->closeEnv);
}
}
}
- SSDBG( descP, ("SOCKET", "socket_stop -> unlock all mutex(s)\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_stop -> unlock all mutex(s)\r\n") );
if (!is_direct_call) MUNLOCK(descP->closeMtx);
MUNLOCK(descP->cfgMtx);
@@ -19102,33 +19153,33 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call)
MUNLOCK(descP->writeMtx);
SSDBG( descP,
- ("SOCKET", "socket_stop -> done (%d, %d)\r\n", descP->sock, fd) );
+ ("SOCKET", "esock_stop -> done (%d, %d)\r\n", descP->sock, fd) );
#endif // if !defined(__WIN32__)
}
-/* *** socket_stop_handle_current ***
+/* *** esock_stop_handle_current ***
*
* Handle current requestor (reader, writer or acceptor) during
* socket stop.
*/
#if !defined(__WIN32__)
static
-void socket_stop_handle_current(ErlNifEnv* env,
- const char* role,
- ESockDescriptor* descP,
- ERL_NIF_TERM sockRef,
- ESockRequestor* reqP)
+void esock_stop_handle_current(ErlNifEnv* env,
+ const char* role,
+ ESockDescriptor* descP,
+ ERL_NIF_TERM sockRef,
+ ESockRequestor* reqP)
{
- SSDBG( descP, ("SOCKET", "socket_stop -> handle current %s\r\n", role) );
+ SSDBG( descP, ("SOCKET", "esock_stop -> handle current %s\r\n", role) );
- DEMONP("socket_stop_handle_current", env, descP, &reqP->mon);
+ DEMONP("esock_stop_handle_current", env, descP, &reqP->mon);
if (COMPARE_PIDS(&descP->closerPid, &reqP->pid) != 0) {
- SSDBG( descP, ("SOCKET", "socket_stop_handle_current -> "
+ SSDBG( descP, ("SOCKET", "esock_stop_handle_current -> "
"send abort message to current %s %T\r\n",
role, reqP->pid) );
@@ -19213,21 +19264,21 @@ void inform_waiting_procs(ErlNifEnv* env,
/* =========================================================================
- * socket_down - Callback function for resource down (monitored processes)
+ * esock_down - Callback function for resource down (monitored processes)
*
*/
static
-void socket_down(ErlNifEnv* env,
- void* obj,
- const ErlNifPid* pid,
- const ErlNifMonitor* mon)
+void esock_down(ErlNifEnv* env,
+ void* obj,
+ const ErlNifPid* pid,
+ const ErlNifMonitor* mon)
{
#if !defined(__WIN32__)
ESockDescriptor* descP = (ESockDescriptor*) obj;
int sres;
ERL_NIF_TERM sockRef;
- SSDBG( descP, ("SOCKET", "socket_down -> entry with"
+ SSDBG( descP, ("SOCKET", "esock_down -> entry with"
"\r\n sock: %d"
"\r\n pid: %T"
"\r\n Close: %s (%s)"
@@ -19245,9 +19296,9 @@ void socket_down(ErlNifEnv* env,
*/
SSDBG( descP,
- ("SOCKET", "socket_down -> controlling process exit\r\n") );
+ ("SOCKET", "esock_down -> controlling process exit\r\n") );
- descP->state = SOCKET_STATE_CLOSING;
+ descP->state = ESOCK_STATE_CLOSING;
descP->closeLocal = TRUE;
descP->closerPid = *pid;
MON_INIT(&descP->closerMon);
@@ -19259,10 +19310,10 @@ void socket_down(ErlNifEnv* env,
/* We are done - we can finalize (socket close) directly */
SSDBG( descP,
("SOCKET",
- "socket_down -> [%d] stop called\r\n", descP->sock) );
+ "esock_down -> [%d] stop called\r\n", descP->sock) );
dec_socket(descP->domain, descP->type, descP->protocol);
- descP->state = SOCKET_STATE_CLOSED;
+ descP->state = ESOCK_STATE_CLOSED;
/* And finally close the socket.
* Since we close the socket because of an exiting owner,
@@ -19285,7 +19336,7 @@ void socket_down(ErlNifEnv* env,
descP->sock = INVALID_SOCKET;
descP->event = INVALID_EVENT;
- descP->state = SOCKET_STATE_CLOSED;
+ descP->state = ESOCK_STATE_CLOSED;
} else if (sres & ERL_NIF_SELECT_STOP_SCHEDULED) {
@@ -19296,7 +19347,7 @@ void socket_down(ErlNifEnv* env,
*/
SSDBG( descP,
("SOCKET",
- "socket_down -> [%d] stop scheduled\r\n",
+ "esock_down -> [%d] stop scheduled\r\n",
descP->sock) );
dec_socket(descP->domain, descP->type, descP->protocol);
@@ -19336,9 +19387,9 @@ void socket_down(ErlNifEnv* env,
* The same goes for the monitor (connMon).
*/
- descP->state = SOCKET_STATE_OPEN; /* restore state */
+ descP->state = ESOCK_STATE_OPEN; /* restore state */
enif_set_pid_undefined(&descP->connPid);
- DEMONP("socket_down -> connector",
+ DEMONP("esock_down -> connector",
env, descP, &descP->connMon);
} else {
@@ -19349,43 +19400,43 @@ void socket_down(ErlNifEnv* env,
*
*/
- SSDBG( descP, ("SOCKET", "socket_down -> other process term\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_down -> other process term\r\n") );
sockRef = enif_make_resource(env, descP);
MLOCK(descP->accMtx);
if (descP->currentAcceptorP != NULL)
- socket_down_acceptor(env, descP, sockRef, pid);
+ esock_down_acceptor(env, descP, sockRef, pid);
MUNLOCK(descP->accMtx);
MLOCK(descP->writeMtx);
if (descP->currentWriterP != NULL)
- socket_down_writer(env, descP, sockRef, pid);
+ esock_down_writer(env, descP, sockRef, pid);
MUNLOCK(descP->writeMtx);
MLOCK(descP->readMtx);
if (descP->currentReaderP != NULL)
- socket_down_reader(env, descP, sockRef, pid);
+ esock_down_reader(env, descP, sockRef, pid);
MUNLOCK(descP->readMtx);
}
}
- SSDBG( descP, ("SOCKET", "socket_down -> done\r\n") );
+ SSDBG( descP, ("SOCKET", "esock_down -> done\r\n") );
#endif // if !defined(__WIN32__)
}
-/* *** socket_down_acceptor ***
+/* *** esock_down_acceptor ***
*
* Check and then handle a downed acceptor process.
*
*/
#if !defined(__WIN32__)
static
-void socket_down_acceptor(ErlNifEnv* env,
+void esock_down_acceptor(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM sockRef,
const ErlNifPid* pid)
@@ -19393,15 +19444,15 @@ void socket_down_acceptor(ErlNifEnv* env,
if (COMPARE_PIDS(&descP->currentAcceptor.pid, pid) == 0) {
SSDBG( descP, ("SOCKET",
- "socket_down_acceptor -> "
+ "esock_down_acceptor -> "
"current acceptor - try activate next\r\n") );
if (!activate_next_acceptor(env, descP, sockRef)) {
SSDBG( descP,
- ("SOCKET", "socket_down_acceptor -> no more writers\r\n") );
+ ("SOCKET", "esock_down_acceptor -> no more writers\r\n") );
- descP->state = SOCKET_STATE_LISTENING;
+ descP->state = ESOCK_STATE_LISTENING;
descP->currentAcceptorP = NULL;
descP->currentAcceptor.ref = esock_atom_undefined;
@@ -19414,7 +19465,7 @@ void socket_down_acceptor(ErlNifEnv* env,
/* Maybe unqueue one of the waiting acceptors */
SSDBG( descP, ("SOCKET",
- "socket_down_acceptor -> "
+ "esock_down_acceptor -> "
"not current acceptor - maybe a waiting acceptor\r\n") );
acceptor_unqueue(env, descP, pid);
@@ -19424,13 +19475,13 @@ void socket_down_acceptor(ErlNifEnv* env,
-/* *** socket_down_writer ***
+/* *** esock_down_writer ***
*
* Check and then handle a downed writer process.
*
*/
static
-void socket_down_writer(ErlNifEnv* env,
+void esock_down_writer(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM sockRef,
const ErlNifPid* pid)
@@ -19438,12 +19489,12 @@ void socket_down_writer(ErlNifEnv* env,
if (COMPARE_PIDS(&descP->currentWriter.pid, pid) == 0) {
SSDBG( descP, ("SOCKET",
- "socket_down_writer -> "
+ "esock_down_writer -> "
"current writer - try activate next\r\n") );
if (!activate_next_writer(env, descP, sockRef)) {
SSDBG( descP, ("SOCKET",
- "socket_down_writer -> no active writer\r\n") );
+ "esock_down_writer -> no active writer\r\n") );
descP->currentWriterP = NULL;
descP->currentWriter.ref = esock_atom_undefined;
enif_set_pid_undefined(&descP->currentWriter.pid);
@@ -19455,7 +19506,7 @@ void socket_down_writer(ErlNifEnv* env,
/* Maybe unqueue one of the waiting writer(s) */
SSDBG( descP, ("SOCKET",
- "socket_down_writer -> "
+ "esock_down_writer -> "
"not current writer - maybe a waiting writer\r\n") );
writer_unqueue(env, descP, pid);
@@ -19465,13 +19516,13 @@ void socket_down_writer(ErlNifEnv* env,
-/* *** socket_down_reader ***
+/* *** esock_down_reader ***
*
* Check and then handle a downed reader process.
*
*/
static
-void socket_down_reader(ErlNifEnv* env,
+void esock_down_reader(ErlNifEnv* env,
ESockDescriptor* descP,
ERL_NIF_TERM sockRef,
const ErlNifPid* pid)
@@ -19479,12 +19530,13 @@ void socket_down_reader(ErlNifEnv* env,
if (COMPARE_PIDS(&descP->currentReader.pid, pid) == 0) {
SSDBG( descP, ("SOCKET",
- "socket_down_reader -> "
+ "esock_down_reader -> "
"current reader - try activate next\r\n") );
if (!activate_next_reader(env, descP, sockRef)) {
SSDBG( descP,
- ("SOCKET", "ncancel_recv_current -> no more readers\r\n") );
+ ("SOCKET",
+ "esock_down_reader -> no more readers\r\n") );
descP->currentReaderP = NULL;
descP->currentReader.ref = esock_atom_undefined;
enif_set_pid_undefined(&descP->currentReader.pid);
@@ -19496,7 +19548,7 @@ void socket_down_reader(ErlNifEnv* env,
/* Maybe unqueue one of the waiting reader(s) */
SSDBG( descP, ("SOCKET",
- "socket_down_reader -> "
+ "esock_down_reader -> "
"not current reader - maybe a waiting reader\r\n") );
reader_unqueue(env, descP, pid);
@@ -19512,7 +19564,7 @@ void socket_down_reader(ErlNifEnv* env,
*/
static
-ErlNifFunc socket_funcs[] =
+ErlNifFunc esock_funcs[] =
{
// Some utility and support functions
{"nif_info", 0, nif_info, 0},
@@ -19564,7 +19616,7 @@ BOOLEAN_T extract_debug(ErlNifEnv* env,
*/
ERL_NIF_TERM debug = MKA(env, "debug");
- return esock_extract_bool_from_map(env, map, debug, SOCKET_GLOBAL_DEBUG_DEFAULT);
+ return esock_extract_bool_from_map(env, map, debug, ESOCK_GLOBAL_DEBUG_DEFAULT);
}
static
@@ -19577,7 +19629,7 @@ BOOLEAN_T extract_iow(ErlNifEnv* env,
*/
ERL_NIF_TERM iow = MKA(env, "iow");
- return esock_extract_bool_from_map(env, map, iow, SOCKET_NIF_IOW_DEFAULT);
+ return esock_extract_bool_from_map(env, map, iow, ESOCK_NIF_IOW_DEFAULT);
}
#endif // if !defined(__WIN32__)
@@ -19598,7 +19650,7 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
data.iow = extract_iow(env, load_info);
/* +++ Global Counters +++ */
- data.cntMtx = MCREATE("socket[gcnt]");
+ data.cntMtx = MCREATE("esock[gcnt]");
data.numSockets = 0;
data.numTypeDGrams = 0;
data.numTypeStreams = 0;
@@ -19625,13 +19677,21 @@ GLOBAL_ERROR_REASON_ATOMS
#undef GLOBAL_ATOM_DECL
esock_atom_socket_tag = MKA(env, "$socket");
- sockets = enif_open_resource_type_x(env,
- "sockets",
- &socketInit,
- ERL_NIF_RT_CREATE,
- NULL);
+ esocks = enif_open_resource_type_x(env,
+ "sockets",
+ &esockInit,
+ ERL_NIF_RT_CREATE,
+ NULL);
- return !sockets;
+ return !esocks;
}
-ERL_NIF_INIT(socket, socket_funcs, on_load, NULL, NULL, NULL)
+/*
+ * MODULE: socket (the erlang API/interface module)
+ * funcs: esock_funcs (defines the API of this nif)
+ * load: on_load (load this nif)
+ * upgrade: NULL (not used)
+ * NULL: THIS IS NOT USED
+ * unload: NULL (not used)
+ */
+ERL_NIF_INIT(socket, esock_funcs, on_load, NULL, NULL, NULL)
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 2740cb51ef..54c310ecc7 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -741,16 +741,24 @@ char* esock_decode_ip4_address(ErlNifEnv* env,
"\r\n", eAddr) );
if (IS_ATOM(env, eAddr)) {
- /* This is either 'any' or 'loopback' */
+
+ /* This is either 'any' | 'broadcast' | 'loopback' */
if (COMPARE(esock_atom_loopback, eAddr) == 0) {
- UDBG( ("SUTIL", "esock_decode_ip4_address -> address: lookback\r\n") );
+ UDBG( ("SUTIL",
+ "esock_decode_ip4_address -> address: lookback\r\n") );
addr.s_addr = htonl(INADDR_LOOPBACK);
} else if (COMPARE(esock_atom_any, eAddr) == 0) {
- UDBG( ("SUTIL", "esock_decode_ip4_address -> address: any\r\n") );
- addr.s_addr = htonl(INADDR_ANY);
+ UDBG( ("SUTIL",
+ "esock_decode_ip4_address -> address: any\r\n") );
+ addr.s_addr = htonl(INADDR_ANY);
+ } else if (COMPARE(esock_atom_broadcast, eAddr) == 0) {
+ UDBG( ("SUTIL",
+ "esock_decode_ip4_address -> address: broadcast\r\n") );
+ addr.s_addr = htonl(INADDR_BROADCAST);
} else {
- UDBG( ("SUTIL", "esock_decode_ip4_address -> address: unknown\r\n") );
+ UDBG( ("SUTIL",
+ "esock_decode_ip4_address -> address: unknown\r\n") );
return ESOCK_STR_EINVAL;
}
diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c
index 664d677ebd..92020c6f35 100644
--- a/erts/emulator/sys/unix/sys_drivers.c
+++ b/erts/emulator/sys/unix/sys_drivers.c
@@ -785,15 +785,15 @@ static ErlDrvSSizeT spawn_control(ErlDrvData e, unsigned int cmd, char *buf,
static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height)
{
-#ifdef TIOCGWINSZ
+#ifdef TIOCGWINSZ
struct winsize ws;
if (ioctl(fd,TIOCGWINSZ,&ws) == 0) {
*width = (Uint32) ws.ws_col;
*height = (Uint32) ws.ws_row;
- return 0;
+ return 1;
}
#endif
- return -1;
+ return 0;
}
static ErlDrvSSizeT fd_control(ErlDrvData drv_data,
@@ -801,16 +801,28 @@ static ErlDrvSSizeT fd_control(ErlDrvData drv_data,
char *buf, ErlDrvSizeT len,
char **rbuf, ErlDrvSizeT rlen)
{
- int fd = (int)(long)drv_data;
char resbuff[2*sizeof(Uint32)];
-
+ ErtsSysDriverData* dd = (ErtsSysDriverData*)drv_data;
command -= ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER;
switch (command) {
case FD_CTRL_OP_GET_WINSIZE:
{
Uint32 w,h;
- if (fd_get_window_size(fd,&w,&h))
- return 0;
+ int success = 0;
+ if (dd->ofd != NULL) {
+ /* Try with output file descriptor */
+ int out_fd = dd->ofd->fd;
+ success = fd_get_window_size(out_fd,&w,&h);
+ }
+ if (!success && dd->ifd != NULL) {
+ /* Try with input file descriptor */
+ int in_fd = dd->ifd->fd;
+ success = fd_get_window_size(in_fd,&w,&h);
+ }
+ if (!success) {
+ return -1;
+ }
+ /* Succeeded */
memcpy(resbuff,&w,sizeof(Uint32));
memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32));
}
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 4fb339926e..fbd1325c3a 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -1438,7 +1438,8 @@ sleeper() ->
gc_test(Config) when is_list(Config) ->
%% Note: This test is only relevant for REFC binaries.
%% Therefore, we take care that all binaries are REFC binaries.
- B = list_to_binary(lists:seq(0, ?heap_binary_size)),
+ true = 192 > ?heap_binary_size,
+ B = list_to_binary(lists:seq(1, 192)),
Self = self(),
F1 = fun() ->
gc(),
@@ -1447,22 +1448,22 @@ gc_test(Config) when is_list(Config) ->
end,
F = fun() ->
receive go -> ok end,
- {binary,[{_,65,1}]} = process_info(self(), binary),
+ {binary,[{_,192,1}]} = process_info(self(), binary),
gc(),
- {B1,B2} = my_split_binary(B, 4),
+ {B1,B2} = my_split_binary(B, 68),
gc(),
gc(),
{binary,L1} = process_info(self(), binary),
[Binfo1,Binfo2,Binfo3] = L1,
- {_,65,3} = Binfo1 = Binfo2 = Binfo3,
- 65 = size(B),
- 4 = size(B1),
- 61 = size(B2),
+ {_,192,3} = Binfo1 = Binfo2 = Binfo3,
+ 192 = size(B),
+ 68 = size(B1),
+ 124 = size(B2),
F1()
end,
gc(),
gc(),
- 65 = size(B),
+ 192 = size(B),
gc_test1(spawn_opt(erlang, apply, [F,[]], [link,{fullsweep_after,0}])).
gc_test1(Pid) ->
diff --git a/erts/emulator/test/esock_ttest/esock-ttest b/erts/emulator/test/esock_ttest/esock-ttest
index 9adc51fc8b..2ded557484 100755
--- a/erts/emulator/test/esock_ttest/esock-ttest
+++ b/erts/emulator/test/esock_ttest/esock-ttest
@@ -203,7 +203,7 @@ process_client_args(["--max-outstanding", Max|Args], State) ->
end;
process_client_args(["--scon", Server|Args], State) ->
- case string:tokens(Server, [$:]) of
+ case string:split(Server, ":", trailing) of
[AddrStr,PortStr] ->
Addr = case inet:parse_address(AddrStr) of
{ok, A} ->
@@ -343,9 +343,9 @@ exec(#{role := client,
runtime := RunTime}) ->
case socket_test_ttest_tcp_client_socket:start(true,
Async,
+ Active,
Method,
ServerInfo,
- Active,
MsgID, MaxOutstanding,
RunTime) of
{ok, Pid} ->
diff --git a/erts/emulator/test/esock_ttest/esock-ttest-client b/erts/emulator/test/esock_ttest/esock-ttest-client
index 7c90ae6391..5ae05d03b8 100755
--- a/erts/emulator/test/esock_ttest/esock-ttest-client
+++ b/erts/emulator/test/esock_ttest/esock-ttest-client
@@ -20,23 +20,30 @@
# %CopyrightEnd%
#
+#
+# This is just a simple convenience wrapper to the esock-ttest.
+# That means that there are some options not available here.
+#
+
EMU=$ERL_TOP/erts/emulator
EMU_TEST=$EMU/test
ESOCK_TTEST=$EMU_TEST/esock_ttest
RUNTIME=30
+# RUNTIME=60
+# RUNTIME=600
if [ $# = 3 ]; then
MSGID=$1
SERVER_INFO=$2:$3
ITERATIONS="\
- gen false $MSGID
- gen true $MSGID
- gen once $MSGID
- sock false $MSGID
- sock true $MSGID
- sock once $MSGID"
+ gen false $MSGID
+ gen true $MSGID
+ gen once $MSGID
+ sock false $MSGID --async
+ sock true $MSGID --async
+ sock once $MSGID --async"
else
if [ $# = 2 ]; then
@@ -44,9 +51,9 @@ else
SERVER_INFO=$2
ITERATIONS="\
- sock false $MSGID
- sock true $MSGID
- sock once $MSGID"
+ sock false $MSGID --async
+ sock true $MSGID --async
+ sock once $MSGID --async"
else
echo "Invalid number of args"
@@ -70,14 +77,14 @@ fi
# ---------------------------------------------------------------------------
echo "$ITERATIONS" |
- while read TRANSPORT ACTIVE MSG_ID; do
+ while read TRANSPORT ACTIVE MSG_ID ASYNC; do
echo ""
echo "=========== transport = $TRANSPORT, active = $ACTIVE, msg-id = $MSG_ID ==========="
# The /dev/null at the end is necessary because erlang "does things" with stdin
# and this case would cause the 'while read' to "fail" so that we only would
# loop one time
- $ESOCK_TTEST/esock-ttest --client --transport $TRANSPORT --active $ACTIVE --msg-id $MSG_ID --scon $SERVER_INFO --runtime $RUNTIME </dev/null
+ $ESOCK_TTEST/esock-ttest --client --transport $TRANSPORT $ASYNC --active $ACTIVE --msg-id $MSG_ID --scon $SERVER_INFO --runtime $RUNTIME </dev/null
echo ""
done
diff --git a/erts/emulator/test/esock_ttest/esock-ttest-server-sock b/erts/emulator/test/esock_ttest/esock-ttest-server-sock
index fc87499f09..c443d42e64 100755
--- a/erts/emulator/test/esock_ttest/esock-ttest-server-sock
+++ b/erts/emulator/test/esock_ttest/esock-ttest-server-sock
@@ -24,9 +24,10 @@ EMU=$ERL_TOP/erts/emulator
EMU_TEST=$EMU/test
ESOCK_TTEST=$EMU_TEST/esock_ttest
-# $1 - async - boolean()
-# $2 - active - once | boolean()
-if [ $# = 2 ]; then
+# $1 - async - boolean()
+# $2 - active - once | boolean()
+# [$3 - domain - inet (default) | inet6 | local]
+if [ $# -ge 2 ]; then
async=$1
active=$2
@@ -39,6 +40,11 @@ if [ $# = 2 ]; then
ACTIVE="--active $active"
+ if [ $# = 3 ]; then
+ DOMAIN="--domain $3"
+ fi
+
+
else
echo "<ERROR> Missing args: async and active"
echo ""
@@ -46,5 +52,5 @@ else
fi
-$ESOCK_TTEST/esock-ttest --server $ASYNC --transport sock $ACTIVE
+$ESOCK_TTEST/esock-ttest --server $DOMAIN $ASYNC --transport sock $ACTIVE
diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl
index 2cbde621ce..ad8ef0feff 100644
--- a/erts/emulator/test/fun_SUITE.erl
+++ b/erts/emulator/test/fun_SUITE.erl
@@ -27,7 +27,7 @@
fun_to_port/1,t_phash/1,t_phash2/1,md5/1,
refc/1,refc_ets/1,refc_dist/1,
const_propagation/1,t_arity/1,t_is_function2/1,
- t_fun_info/1,t_fun_info_mfa/1]).
+ t_fun_info/1,t_fun_info_mfa/1,t_fun_to_list/1]).
-export([nothing/0]).
@@ -44,7 +44,7 @@ all() ->
equality, ordering, fun_to_port, t_phash,
t_phash2, md5, refc, refc_ets, refc_dist,
const_propagation, t_arity, t_is_function2, t_fun_info,
- t_fun_info_mfa].
+ t_fun_info_mfa,t_fun_to_list].
%% Test that the correct EXIT code is returned for all types of bad funs.
bad_apply(Config) when is_list(Config) ->
@@ -802,6 +802,12 @@ t_fun_info_mfa(Config) when is_list(Config) ->
{'EXIT',_} = (catch erlang:fun_info_mfa(id(d))),
ok.
+t_fun_to_list(Config) when is_list(Config) ->
+ "fun a:b/1" = erlang:fun_to_list(fun a:b/1),
+ "fun 'a-esc':'b-esc'/1" = erlang:fun_to_list(fun 'a-esc':'b-esc'/1),
+ "fun 'a-esc':b/1" = erlang:fun_to_list(fun 'a-esc':b/1),
+ "fun a:'b-esc'/1" = erlang:fun_to_list(fun a:'b-esc'/1),
+ ok.
bad_info(Term) ->
try erlang:fun_info(Term, module) of
diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl
index 7d2db5257c..c44693f8d9 100644
--- a/erts/emulator/test/node_container_SUITE.erl
+++ b/erts/emulator/test/node_container_SUITE.erl
@@ -51,7 +51,8 @@
unique_pid/1,
iter_max_procs/1,
magic_ref/1,
- dist_entry_gc/1]).
+ dist_entry_gc/1,
+ persistent_term/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -63,7 +64,8 @@ all() ->
node_table_gc, dist_link_refc, dist_monitor_refc,
node_controller_refc, ets_refc, match_spec_refc,
timer_refc, pid_wrap, port_wrap, bad_nc,
- unique_pid, iter_max_procs, magic_ref].
+ unique_pid, iter_max_procs,
+ magic_ref, persistent_term].
init_per_suite(Config) ->
Config.
@@ -906,6 +908,44 @@ magic_ref(Config) when is_list(Config) ->
true = erts_debug:get_internal_state({magic_ref,MRef2}),
ok.
+persistent_term(Config) when is_list(Config) ->
+ {ok, Node} = start_node(get_nodefirstname()),
+ Self = self(),
+ NcData = make_ref(),
+ RPid = spawn_link(Node,
+ fun () ->
+ Self ! {NcData, self(), hd(erlang:ports()), erlang:make_ref()}
+ end),
+ Data = receive
+ {NcData, RPid, RPort, RRef} ->
+ {RPid, RPort, RRef}
+ end,
+ unlink(RPid),
+ stop_node(Node),
+ Stuff = lists:foldl(fun (N, Acc) ->
+ persistent_term:put({?MODULE, N}, Data),
+ persistent_term:erase({?MODULE, N-1}),
+ node_container_refc_check(node()),
+ Data = persistent_term:get({?MODULE, N}),
+ try
+ persistent_term:get({?MODULE, N-1})
+ catch
+ error:badarg ->
+ ok
+ end,
+ case N rem 4 of
+ 0 -> [persistent_term:get({?MODULE, N})|Acc];
+ _ -> Acc
+ end
+ end,
+ [],
+ lists:seq(1, 100)),
+ persistent_term:erase({?MODULE, 100}),
+ receive after 2000 -> ok end, %% give literal gc some time to run...
+ node_container_refc_check(node()),
+ id(Stuff),
+ ok.
+
lost_pending_connection(Node) ->
_ = (catch erts_internal:new_connection(Node)),
diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl
index b80cc794e7..4980ea2a82 100644
--- a/erts/emulator/test/socket_SUITE.erl
+++ b/erts/emulator/test/socket_SUITE.erl
@@ -58,6 +58,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
+-include("socket_test_evaluator.hrl").
%% Suite exports
-export([suite/0, all/0, groups/0]).
@@ -86,26 +87,52 @@
%% *** API async ***
api_a_connect_tcp4/1,
+ api_a_connect_tcp6/1,
api_a_sendto_and_recvfrom_udp4/1,
+ api_a_sendto_and_recvfrom_udp6/1,
api_a_sendmsg_and_recvmsg_udp4/1,
+ api_a_sendmsg_and_recvmsg_udp6/1,
api_a_send_and_recv_tcp4/1,
+ api_a_send_and_recv_tcp6/1,
api_a_sendmsg_and_recvmsg_tcp4/1,
+ api_a_sendmsg_and_recvmsg_tcp6/1,
api_a_recvfrom_cancel_udp4/1,
+ api_a_recvfrom_cancel_udp6/1,
api_a_recvmsg_cancel_udp4/1,
+ api_a_recvmsg_cancel_udp6/1,
api_a_accept_cancel_tcp4/1,
+ api_a_accept_cancel_tcp6/1,
api_a_recv_cancel_tcp4/1,
+ api_a_recv_cancel_tcp6/1,
api_a_recvmsg_cancel_tcp4/1,
+ api_a_recvmsg_cancel_tcp6/1,
api_a_mrecvfrom_cancel_udp4/1,
+ api_a_mrecvfrom_cancel_udp6/1,
api_a_mrecvmsg_cancel_udp4/1,
+ api_a_mrecvmsg_cancel_udp6/1,
api_a_maccept_cancel_tcp4/1,
+ api_a_maccept_cancel_tcp6/1,
api_a_mrecv_cancel_tcp4/1,
+ api_a_mrecv_cancel_tcp6/1,
api_a_mrecvmsg_cancel_tcp4/1,
+ api_a_mrecvmsg_cancel_tcp6/1,
%% *** API Options ***
api_opt_simple_otp_options/1,
api_opt_simple_otp_rcvbuf_option/1,
api_opt_simple_otp_controlling_process/1,
+ api_opt_sock_acceptconn_udp/1,
+ api_opt_sock_acceptconn_tcp/1,
+ api_opt_sock_acceptfilter/1,
+ api_opt_sock_bindtodevice/1,
+ api_opt_sock_broadcast/1,
+ api_opt_sock_debug/1,
+ api_opt_sock_domain/1,
+ api_opt_sock_dontroute/1,
+ api_opt_sock_error/1,
+ api_opt_sock_keepalive/1,
+ api_opt_sock_linger/1,
api_opt_ip_add_drop_membership/1,
%% *** API Operation Timeout ***
@@ -172,12 +199,16 @@
%% *** Traffic ***
traffic_send_and_recv_counters_tcp4/1,
+ traffic_send_and_recv_counters_tcp6/1,
traffic_send_and_recv_counters_tcpL/1,
traffic_sendmsg_and_recvmsg_counters_tcp4/1,
+ traffic_sendmsg_and_recvmsg_counters_tcp6/1,
traffic_sendmsg_and_recvmsg_counters_tcpL/1,
traffic_sendto_and_recvfrom_counters_udp4/1,
+ traffic_sendto_and_recvfrom_counters_udp6/1,
traffic_sendto_and_recvfrom_counters_udpL/1,
traffic_sendmsg_and_recvmsg_counters_udp4/1,
+ traffic_sendmsg_and_recvmsg_counters_udp6/1,
traffic_sendmsg_and_recvmsg_counters_udpL/1,
traffic_send_and_recv_chunks_tcp4/1,
@@ -526,30 +557,31 @@
]).
--include("socket_test_evaluator.hrl").
-
%% Internal exports
%% -export([]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--define(BASIC_REQ, <<"hejsan">>).
--define(BASIC_REP, <<"hoppsan">>).
+-define(LIB, socket_test_lib).
+-define(TTEST_LIB, socket_test_ttest_lib).
+-define(LOGGER, socket_test_logger).
--define(DATA, <<"HOPPSAN">>). % Temporary
--define(FAIL(R), exit(R)).
+-define(BASIC_REQ, <<"hejsan">>).
+-define(BASIC_REP, <<"hoppsan">>).
--define(SLEEP(T), receive after T -> ok end).
+-define(DATA, <<"HOPPSAN">>). % Temporary
+-define(FAIL(R), exit(R)).
--define(MINS(M), timer:minutes(M)).
--define(SECS(S), timer:seconds(S)).
+-define(SLEEP(T), receive after T -> ok end).
--define(TT(T), ct:timetrap(T)).
+-define(MINS(M), timer:minutes(M)).
+-define(SECS(S), timer:seconds(S)).
+
+-define(TT(T), ct:timetrap(T)).
+
+-define(F(F, A), ?LIB:f(F, A)).
--define(LIB, socket_test_lib).
--define(TTEST_LIB, socket_test_ttest_lib).
--define(LOGGER, socket_test_logger).
-define(TPP_SMALL, lists:seq(1, 8)).
-define(TPP_MEDIUM, lists:flatten(lists:duplicate(1024, ?TPP_SMALL))).
@@ -594,80 +626,86 @@ use_group(Group, Env, Default) ->
groups() ->
- [{api, [], api_cases()},
- {api_misc, [], api_misc_cases()},
- {api_basic, [], api_basic_cases()},
- {api_async, [], api_async_cases()},
- {api_options, [], api_options_cases()},
- {api_options_otp, [], api_options_otp_cases()},
- {api_options_ip, [], api_options_ip_cases()},
- {api_op_with_timeout, [], api_op_with_timeout_cases()},
- {socket_close, [], socket_close_cases()},
- {sc_ctrl_proc_exit, [], sc_cp_exit_cases()},
- {sc_local_close, [], sc_lc_cases()},
- {sc_remote_close, [], sc_rc_cases()},
- {sc_remote_shutdown, [], sc_rs_cases()},
- {traffic, [], traffic_cases()},
- {traffic_counters, [], traffic_counters_cases()},
- {traffic_chunks, [], traffic_chunks_cases()},
- {traffic_pp_send_recv, [], traffic_pp_send_recv_cases()},
- {traffic_pp_sendto_recvfrom, [], traffic_pp_sendto_recvfrom_cases()},
- {traffic_pp_sendmsg_recvmsg, [], traffic_pp_sendmsg_recvmsg_cases()},
- {ttest, [], ttest_cases()},
- {ttest_sgenf, [], ttest_sgenf_cases()},
- {ttest_sgenf_cgen, [], ttest_sgenf_cgen_cases()},
- {ttest_sgenf_cgenf, [], ttest_sgenf_cgenf_cases()},
- {ttest_sgenf_cgeno, [], ttest_sgenf_cgeno_cases()},
- {ttest_sgenf_cgent, [], ttest_sgenf_cgent_cases()},
- {ttest_sgenf_csock, [], ttest_sgenf_csock_cases()},
- {ttest_sgenf_csockf, [], ttest_sgenf_csockf_cases()},
- {ttest_sgenf_csocko, [], ttest_sgenf_csocko_cases()},
- {ttest_sgenf_csockt, [], ttest_sgenf_csockt_cases()},
- {ttest_sgeno, [], ttest_sgeno_cases()},
- {ttest_sgeno_cgen, [], ttest_sgeno_cgen_cases()},
- {ttest_sgeno_cgenf, [], ttest_sgeno_cgenf_cases()},
- {ttest_sgeno_cgeno, [], ttest_sgeno_cgeno_cases()},
- {ttest_sgeno_cgent, [], ttest_sgeno_cgent_cases()},
- {ttest_sgeno_csock, [], ttest_sgeno_csock_cases()},
- {ttest_sgeno_csockf, [], ttest_sgeno_csockf_cases()},
- {ttest_sgeno_csocko, [], ttest_sgeno_csocko_cases()},
- {ttest_sgeno_csockt, [], ttest_sgeno_csockt_cases()},
- {ttest_sgent, [], ttest_sgent_cases()},
- {ttest_sgent_cgen, [], ttest_sgent_cgen_cases()},
- {ttest_sgent_cgenf, [], ttest_sgent_cgenf_cases()},
- {ttest_sgent_cgeno, [], ttest_sgent_cgeno_cases()},
- {ttest_sgent_cgent, [], ttest_sgent_cgent_cases()},
- {ttest_sgent_csock, [], ttest_sgent_csock_cases()},
- {ttest_sgent_csockf, [], ttest_sgent_csockf_cases()},
- {ttest_sgent_csocko, [], ttest_sgent_csocko_cases()},
- {ttest_sgent_csockt, [], ttest_sgent_csockt_cases()},
- {ttest_ssockf, [], ttest_ssockf_cases()},
- {ttest_ssockf_cgen, [], ttest_ssockf_cgen_cases()},
- {ttest_ssockf_cgenf, [], ttest_ssockf_cgenf_cases()},
- {ttest_ssockf_cgeno, [], ttest_ssockf_cgeno_cases()},
- {ttest_ssockf_cgent, [], ttest_ssockf_cgent_cases()},
- {ttest_ssockf_csock, [], ttest_ssockf_csock_cases()},
- {ttest_ssockf_csockf, [], ttest_ssockf_csockf_cases()},
- {ttest_ssockf_csocko, [], ttest_ssockf_csocko_cases()},
- {ttest_ssockf_csockt, [], ttest_ssockf_csockt_cases()},
- {ttest_ssocko, [], ttest_ssocko_cases()},
- {ttest_ssocko_cgen, [], ttest_ssocko_cgen_cases()},
- {ttest_ssocko_cgenf, [], ttest_ssocko_cgenf_cases()},
- {ttest_ssocko_cgeno, [], ttest_ssocko_cgeno_cases()},
- {ttest_ssocko_cgent, [], ttest_ssocko_cgent_cases()},
- {ttest_ssocko_csock, [], ttest_ssocko_csock_cases()},
- {ttest_ssocko_csockf, [], ttest_ssocko_csockf_cases()},
- {ttest_ssocko_csocko, [], ttest_ssocko_csocko_cases()},
- {ttest_ssocko_csockt, [], ttest_ssocko_csockt_cases()},
- {ttest_ssockt, [], ttest_ssockt_cases()},
- {ttest_ssockt_cgen, [], ttest_ssockt_cgen_cases()},
- {ttest_ssockt_cgenf, [], ttest_ssockt_cgenf_cases()},
- {ttest_ssockt_cgeno, [], ttest_ssockt_cgeno_cases()},
- {ttest_ssockt_cgent, [], ttest_ssockt_cgent_cases()},
- {ttest_ssockt_csock, [], ttest_ssockt_csock_cases()},
- {ttest_ssockt_csockf, [], ttest_ssockt_csockf_cases()},
- {ttest_ssockt_csocko, [], ttest_ssockt_csocko_cases()},
- {ttest_ssockt_csockt, [], ttest_ssockt_csockt_cases()}
+ [{api, [], api_cases()},
+ {api_misc, [], api_misc_cases()},
+ {api_basic, [], api_basic_cases()},
+ {api_async, [], api_async_cases()},
+ {api_options, [], api_options_cases()},
+ {api_options_otp, [], api_options_otp_cases()},
+ {api_options_socket, [], api_options_socket_cases()},
+ {api_option_sock_acceptconn, [], api_option_sock_acceptconn_cases()},
+ {api_options_ip, [], api_options_ip_cases()},
+ %% {api_options_ipv6, [], api_options_ipv6_cases()},
+ %% {api_options_tcp, [], api_options_tcp_cases()},
+ %% {api_options_udp, [], api_options_udp_cases()},
+ %% {api_options_sctp, [], api_options_sctp_cases()},
+ {api_op_with_timeout, [], api_op_with_timeout_cases()},
+ {socket_close, [], socket_close_cases()},
+ {sc_ctrl_proc_exit, [], sc_cp_exit_cases()},
+ {sc_local_close, [], sc_lc_cases()},
+ {sc_remote_close, [], sc_rc_cases()},
+ {sc_remote_shutdown, [], sc_rs_cases()},
+ {traffic, [], traffic_cases()},
+ {traffic_counters, [], traffic_counters_cases()},
+ {traffic_chunks, [], traffic_chunks_cases()},
+ {traffic_pp_send_recv, [], traffic_pp_send_recv_cases()},
+ {traffic_pp_sendto_recvfrom, [], traffic_pp_sendto_recvfrom_cases()},
+ {traffic_pp_sendmsg_recvmsg, [], traffic_pp_sendmsg_recvmsg_cases()},
+ {ttest, [], ttest_cases()},
+ {ttest_sgenf, [], ttest_sgenf_cases()},
+ {ttest_sgenf_cgen, [], ttest_sgenf_cgen_cases()},
+ {ttest_sgenf_cgenf, [], ttest_sgenf_cgenf_cases()},
+ {ttest_sgenf_cgeno, [], ttest_sgenf_cgeno_cases()},
+ {ttest_sgenf_cgent, [], ttest_sgenf_cgent_cases()},
+ {ttest_sgenf_csock, [], ttest_sgenf_csock_cases()},
+ {ttest_sgenf_csockf, [], ttest_sgenf_csockf_cases()},
+ {ttest_sgenf_csocko, [], ttest_sgenf_csocko_cases()},
+ {ttest_sgenf_csockt, [], ttest_sgenf_csockt_cases()},
+ {ttest_sgeno, [], ttest_sgeno_cases()},
+ {ttest_sgeno_cgen, [], ttest_sgeno_cgen_cases()},
+ {ttest_sgeno_cgenf, [], ttest_sgeno_cgenf_cases()},
+ {ttest_sgeno_cgeno, [], ttest_sgeno_cgeno_cases()},
+ {ttest_sgeno_cgent, [], ttest_sgeno_cgent_cases()},
+ {ttest_sgeno_csock, [], ttest_sgeno_csock_cases()},
+ {ttest_sgeno_csockf, [], ttest_sgeno_csockf_cases()},
+ {ttest_sgeno_csocko, [], ttest_sgeno_csocko_cases()},
+ {ttest_sgeno_csockt, [], ttest_sgeno_csockt_cases()},
+ {ttest_sgent, [], ttest_sgent_cases()},
+ {ttest_sgent_cgen, [], ttest_sgent_cgen_cases()},
+ {ttest_sgent_cgenf, [], ttest_sgent_cgenf_cases()},
+ {ttest_sgent_cgeno, [], ttest_sgent_cgeno_cases()},
+ {ttest_sgent_cgent, [], ttest_sgent_cgent_cases()},
+ {ttest_sgent_csock, [], ttest_sgent_csock_cases()},
+ {ttest_sgent_csockf, [], ttest_sgent_csockf_cases()},
+ {ttest_sgent_csocko, [], ttest_sgent_csocko_cases()},
+ {ttest_sgent_csockt, [], ttest_sgent_csockt_cases()},
+ {ttest_ssockf, [], ttest_ssockf_cases()},
+ {ttest_ssockf_cgen, [], ttest_ssockf_cgen_cases()},
+ {ttest_ssockf_cgenf, [], ttest_ssockf_cgenf_cases()},
+ {ttest_ssockf_cgeno, [], ttest_ssockf_cgeno_cases()},
+ {ttest_ssockf_cgent, [], ttest_ssockf_cgent_cases()},
+ {ttest_ssockf_csock, [], ttest_ssockf_csock_cases()},
+ {ttest_ssockf_csockf, [], ttest_ssockf_csockf_cases()},
+ {ttest_ssockf_csocko, [], ttest_ssockf_csocko_cases()},
+ {ttest_ssockf_csockt, [], ttest_ssockf_csockt_cases()},
+ {ttest_ssocko, [], ttest_ssocko_cases()},
+ {ttest_ssocko_cgen, [], ttest_ssocko_cgen_cases()},
+ {ttest_ssocko_cgenf, [], ttest_ssocko_cgenf_cases()},
+ {ttest_ssocko_cgeno, [], ttest_ssocko_cgeno_cases()},
+ {ttest_ssocko_cgent, [], ttest_ssocko_cgent_cases()},
+ {ttest_ssocko_csock, [], ttest_ssocko_csock_cases()},
+ {ttest_ssocko_csockf, [], ttest_ssocko_csockf_cases()},
+ {ttest_ssocko_csocko, [], ttest_ssocko_csocko_cases()},
+ {ttest_ssocko_csockt, [], ttest_ssocko_csockt_cases()},
+ {ttest_ssockt, [], ttest_ssockt_cases()},
+ {ttest_ssockt_cgen, [], ttest_ssockt_cgen_cases()},
+ {ttest_ssockt_cgenf, [], ttest_ssockt_cgenf_cases()},
+ {ttest_ssockt_cgeno, [], ttest_ssockt_cgeno_cases()},
+ {ttest_ssockt_cgent, [], ttest_ssockt_cgent_cases()},
+ {ttest_ssockt_csock, [], ttest_ssockt_csock_cases()},
+ {ttest_ssockt_csockf, [], ttest_ssockt_csockf_cases()},
+ {ttest_ssockt_csocko, [], ttest_ssockt_csocko_cases()},
+ {ttest_ssockt_csockt, [], ttest_ssockt_csockt_cases()}
%% {tickets, [], ticket_cases()}
].
@@ -705,26 +743,46 @@ api_basic_cases() ->
api_async_cases() ->
[
api_a_connect_tcp4,
+ api_a_connect_tcp6,
api_a_sendto_and_recvfrom_udp4,
+ api_a_sendto_and_recvfrom_udp6,
api_a_sendmsg_and_recvmsg_udp4,
+ api_a_sendmsg_and_recvmsg_udp6,
api_a_send_and_recv_tcp4,
+ api_a_send_and_recv_tcp6,
api_a_sendmsg_and_recvmsg_tcp4,
+ api_a_sendmsg_and_recvmsg_tcp6,
api_a_recvfrom_cancel_udp4,
+ api_a_recvfrom_cancel_udp6,
api_a_recvmsg_cancel_udp4,
+ api_a_recvmsg_cancel_udp6,
api_a_accept_cancel_tcp4,
+ api_a_accept_cancel_tcp6,
api_a_recv_cancel_tcp4,
+ api_a_recv_cancel_tcp6,
api_a_recvmsg_cancel_tcp4,
+ api_a_recvmsg_cancel_tcp6,
api_a_mrecvfrom_cancel_udp4,
+ api_a_mrecvfrom_cancel_udp6,
api_a_mrecvmsg_cancel_udp4,
+ api_a_mrecvmsg_cancel_udp6,
api_a_maccept_cancel_tcp4,
+ api_a_maccept_cancel_tcp6,
api_a_mrecv_cancel_tcp4,
- api_a_mrecvmsg_cancel_tcp4
+ api_a_mrecv_cancel_tcp6,
+ api_a_mrecvmsg_cancel_tcp4,
+ api_a_mrecvmsg_cancel_tcp6
].
api_options_cases() ->
[
{group, api_options_otp},
- {group, api_options_ip}
+ {group, api_options_socket},
+ {group, api_options_ip}% ,
+ %% {group, api_options_ipv6},
+ %% {group, api_options_tcp},
+ %% {group, api_options_udp},
+ %% {group, api_options_sctp}
].
api_options_otp_cases() ->
@@ -734,11 +792,35 @@ api_options_otp_cases() ->
api_opt_simple_otp_controlling_process
].
+api_options_socket_cases() ->
+ [
+ {group, api_option_sock_acceptconn},
+ api_opt_sock_acceptfilter,
+ api_opt_sock_bindtodevice,
+ api_opt_sock_broadcast,
+ api_opt_sock_debug,
+ api_opt_sock_domain,
+ api_opt_sock_dontroute,
+ api_opt_sock_error,
+ api_opt_sock_keepalive,
+ api_opt_sock_linger
+ ].
+
+api_option_sock_acceptconn_cases() ->
+ [
+ api_opt_sock_acceptconn_udp,
+ api_opt_sock_acceptconn_tcp
+ ].
+
api_options_ip_cases() ->
[
api_opt_ip_add_drop_membership
].
+%% api_options_ipv6_cases() ->
+%% [
+%% ].
+
api_op_with_timeout_cases() ->
[
api_to_connect_tcp4,
@@ -848,12 +930,16 @@ traffic_cases() ->
traffic_counters_cases() ->
[
traffic_send_and_recv_counters_tcp4,
+ traffic_send_and_recv_counters_tcp6,
traffic_send_and_recv_counters_tcpL,
traffic_sendmsg_and_recvmsg_counters_tcp4,
+ traffic_sendmsg_and_recvmsg_counters_tcp6,
traffic_sendmsg_and_recvmsg_counters_tcpL,
traffic_sendto_and_recvfrom_counters_udp4,
+ traffic_sendto_and_recvfrom_counters_udp6,
traffic_sendto_and_recvfrom_counters_udpL,
traffic_sendmsg_and_recvmsg_counters_udp4,
+ traffic_sendmsg_and_recvmsg_counters_udp6,
traffic_sendmsg_and_recvmsg_counters_udpL
].
@@ -1714,13 +1800,15 @@ has_bugfree_gcc() ->
%% Make sure we are on linux
has_bugfree_gcc({unix, linux}) ->
- has_bugfree_gcc2(os:cmd("cat /etc/issue"));
+ has_bugfree_gcc2(string:trim(os:cmd("cat /etc/issue")));
has_bugfree_gcc(_) ->
ok.
%% Make sure we are on Fedora 16
has_bugfree_gcc2("Fedora release 16 " ++ _) ->
has_bugfree_gcc3(os:cmd("gcc --version"));
+has_bugfree_gcc2("Welcome to SUSE Linux " ++ _) ->
+ has_bugfree_gcc4(os:cmd("gcc --version"));
has_bugfree_gcc2(_) ->
ok.
@@ -1729,6 +1817,11 @@ has_bugfree_gcc3("gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2" ++ _) ->
has_bugfree_gcc3(_) ->
ok.
+has_bugfree_gcc4("gcc (SUSE Linux) 4.3.2" ++ _) ->
+ skip("Buggy GCC");
+has_bugfree_gcc4(_) ->
+ ok.
+
api_m_debug() ->
i("get initial info"),
#{debug := D0} = socket:info(),
@@ -1746,6 +1839,7 @@ api_m_debug() ->
ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
@@ -2768,7 +2862,7 @@ api_b_send_and_recv_tcp(InitState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Basically establish a TCP connection via an async connect.
+%% Basically establish a TCP connection via an async connect. IPv4.
api_a_connect_tcp4(suite) ->
[];
@@ -2778,25 +2872,48 @@ api_a_connect_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_a_connect_tcp4,
fun() ->
- Connect = fun(Sock, SockAddr) ->
- socket:connect(Sock, SockAddr, nowait)
- end,
- Send = fun(Sock, Data) ->
- socket:send(Sock, Data)
- end,
- Recv = fun(Sock) ->
- socket:recv(Sock)
- end,
- InitState = #{domain => inet,
- connect => Connect,
- send => Send,
- recv => Recv},
- ok = api_a_connect_tcp(InitState)
+ ok = api_a_connect_tcpD(inet)
end).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically establish a TCP connection via an async connect. IPv6.
+
+api_a_connect_tcp6(suite) ->
+ [];
+api_a_connect_tcp6(doc) ->
+ [];
+api_a_connect_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_connect_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ ok = api_a_connect_tcpD(inet6)
+ end).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+api_a_connect_tcpD(Domain) ->
+ Connect = fun(Sock, SockAddr) ->
+ socket:connect(Sock, SockAddr, nowait)
+ end,
+ Send = fun(Sock, Data) ->
+ socket:send(Sock, Data)
+ end,
+ Recv = fun(Sock) ->
+ socket:recv(Sock)
+ end,
+ InitState = #{domain => Domain,
+ connect => Connect,
+ send => Send,
+ recv => Recv},
+ api_a_connect_tcp(InitState).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_connect_tcp(InitState) ->
process_flag(trap_exit, true),
ServerSeq =
@@ -3296,6 +3413,37 @@ api_a_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically send and receive on an IPv6 UDP (dgram) socket using
+%% sendto and recvfrom. But we try to be async. That is, we use
+%% the 'nowait' value for the Timeout argument (and await the eventual
+%% select message). Note that we only do this for the recvfrom,
+%% since its much more difficult to "arrange" for sendto.
+%%
+api_a_sendto_and_recvfrom_udp6(suite) ->
+ [];
+api_a_sendto_and_recvfrom_udp6(doc) ->
+ [];
+api_a_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(5)),
+ tc_try(api_a_sendto_and_recvfrom_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Send = fun(Sock, Data, Dest) ->
+ socket:sendto(Sock, Data, Dest)
+ end,
+ Recv = fun(Sock) ->
+ socket:recvfrom(Sock, 0, nowait)
+ end,
+ InitState = #{domain => inet6,
+ send => Send,
+ recv => Recv},
+ ok = api_a_send_and_recv_udp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Basically send and receive on an IPv4 UDP (dgram) socket using
%% sendto and recvfrom. But we try to be async. That is, we use
%% the 'nowait' value for the Timeout argument (and await the eventual
@@ -3339,6 +3487,50 @@ api_a_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically send and receive on an IPv6 UDP (dgram) socket using
+%% sendto and recvfrom. But we try to be async. That is, we use
+%% the 'nowait' value for the Timeout argument (and await the eventual
+%% select message). Note that we only do this for the recvmsg,
+%% since its much more difficult to "arrange" for sendmsg.
+%%
+api_a_sendmsg_and_recvmsg_udp6(suite) ->
+ [];
+api_a_sendmsg_and_recvmsg_udp6(doc) ->
+ [];
+api_a_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(5)),
+ tc_try(api_a_sendmsg_and_recvmsg_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Send = fun(Sock, Data, Dest) ->
+ MsgHdr = #{addr => Dest,
+ %% ctrl => CMsgHdrs,
+ iov => [Data]},
+ socket:sendmsg(Sock, MsgHdr)
+ end,
+ Recv = fun(Sock) ->
+ case socket:recvmsg(Sock, nowait) of
+ {ok, #{addr := Source,
+ iov := [Data]}} ->
+ {ok, {Source, Data}};
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ send => Send,
+ recv => Recv},
+ ok = api_a_send_and_recv_udp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_send_and_recv_udp(InitState) ->
ServerSeq =
[
@@ -3788,6 +3980,37 @@ api_a_send_and_recv_tcp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically send and receive using the "common" functions (send and recv)
+%% on an IPv6 TCP (stream) socket. But we try to be async. That is, we use
+%% the 'nowait' value for the Timeout argument (and await the eventual
+%% select message). Note that we only do this for the recv,
+%% since its much more difficult to "arrange" for send.
+%% We *also* test async for accept.
+api_a_send_and_recv_tcp6(suite) ->
+ [];
+api_a_send_and_recv_tcp6(doc) ->
+ [];
+api_a_send_and_recv_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_send_and_recv_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Send = fun(Sock, Data) ->
+ socket:send(Sock, Data)
+ end,
+ Recv = fun(Sock) ->
+ socket:recv(Sock, 0, nowait)
+ end,
+ InitState = #{domain => inet6,
+ send => Send,
+ recv => Recv},
+ ok = api_a_send_and_recv_tcp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an IPv4 TCP (stream) socket. But we try to be async. That is, we use
%% the 'nowait' value for the Timeout argument (and await the eventual
@@ -3815,7 +4038,7 @@ api_a_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
OK;
{select, _} = SELECT ->
SELECT;
- {error, _} = ERROR ->
+ {error, _} = ERROR ->
ERROR
end
end,
@@ -3826,6 +4049,49 @@ api_a_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
end).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Basically send and receive using the msg functions (sendmsg and recvmsg)
+%% on an IPv6 TCP (stream) socket. But we try to be async. That is, we use
+%% the 'nowait' value for the Timeout argument (and await the eventual
+%% select message). Note that we only do this for the recvmsg,
+%% since its much more difficult to "arrange" for sendmsg.
+%% We *also* test async for accept.
+api_a_sendmsg_and_recvmsg_tcp6(suite) ->
+ [];
+api_a_sendmsg_and_recvmsg_tcp6(doc) ->
+ [];
+api_a_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_sendmsg_and_recvmsg_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Send = fun(Sock, Data) ->
+ MsgHdr = #{iov => [Data]},
+ socket:sendmsg(Sock, MsgHdr)
+ end,
+ Recv = fun(Sock) ->
+ case socket:recvmsg(Sock, nowait) of
+ {ok, #{addr := undefined,
+ iov := [Data]}} ->
+ {ok, Data};
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ send => Send,
+ recv => Recv},
+ ok = api_a_send_and_recv_tcp(InitState)
+ end).
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
api_a_send_and_recv_tcp(InitState) ->
@@ -4326,7 +4592,7 @@ api_a_send_and_recv_tcp(InitState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Basically we make an async (Timeout = nowait) call to recvfrom,
-%% wait some time and then cancel.
+%% wait some time and then cancel. IPv4
%%
api_a_recvfrom_cancel_udp4(suite) ->
[];
@@ -4355,8 +4621,39 @@ api_a_recvfrom_cancel_udp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make an async (Timeout = nowait) call to recvfrom,
+%% wait some time and then cancel. IPv6
+%%
+api_a_recvfrom_cancel_udp6(suite) ->
+ [];
+api_a_recvfrom_cancel_udp6(doc) ->
+ [];
+api_a_recvfrom_cancel_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_recvfrom_cancel_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ case socket:recvfrom(Sock, 0, nowait) of
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_recv_cancel_udp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Basically we make an async (Timeout = nowait) call to recvmsg,
-%% wait some time and then cancel.
+%% wait some time and then cancel. IPv4
%%
api_a_recvmsg_cancel_udp4(suite) ->
[];
@@ -4385,6 +4682,37 @@ api_a_recvmsg_cancel_udp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make an async (Timeout = nowait) call to recvmsg,
+%% wait some time and then cancel. IPv6
+%%
+api_a_recvmsg_cancel_udp6(suite) ->
+ [];
+api_a_recvmsg_cancel_udp6(doc) ->
+ [];
+api_a_recvmsg_cancel_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_recvmsg_cancel_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ case socket:recvmsg(Sock, nowait) of
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_recv_cancel_udp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_recv_cancel_udp(InitState) ->
ServerSeq =
[
@@ -4590,7 +4918,7 @@ api_a_recv_cancel_udp(InitState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Basically we make an async (Timeout = nowait) call to accept,
-%% wait some time and then cancel.
+%% wait some time and then cancel. IPv4
%%
api_a_accept_cancel_tcp4(suite) ->
[];
@@ -4620,6 +4948,38 @@ api_a_accept_cancel_tcp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make an async (Timeout = nowait) call to accept,
+%% wait some time and then cancel. IPv6
+%%
+api_a_accept_cancel_tcp6(suite) ->
+ [];
+api_a_accept_cancel_tcp6(doc) ->
+ [];
+api_a_accept_cancel_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_accept_cancel_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Accept = fun(Sock) ->
+ case socket:accept(Sock, nowait) of
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ accept => Accept},
+ ok = api_a_accept_cancel_tcp(InitState)
+ end).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_accept_cancel_tcp(InitState) ->
process_flag(trap_exit, true),
ServerSeq =
@@ -4820,7 +5180,7 @@ api_a_accept_cancel_tcp(InitState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Basically we make an async (Timeout = nowait) call to recv,
-%% wait some time and then cancel.
+%% wait some time and then cancel. IPv4
%%
api_a_recv_cancel_tcp4(suite) ->
[];
@@ -4842,8 +5202,32 @@ api_a_recv_cancel_tcp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make an async (Timeout = nowait) call to recv,
+%% wait some time and then cancel. IPv6
+%%
+api_a_recv_cancel_tcp6(suite) ->
+ [];
+api_a_recv_cancel_tcp6(doc) ->
+ [];
+api_a_recv_cancel_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_recv_cancel_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ socket:recv(Sock, 0, nowait)
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_recv_cancel_tcp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Basically we make an async (Timeout = nowait) call to recvmsg,
-%% wait some time and then cancel.
+%% wait some time and then cancel. IPv4
%%
api_a_recvmsg_cancel_tcp4(suite) ->
[];
@@ -4865,6 +5249,30 @@ api_a_recvmsg_cancel_tcp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make an async (Timeout = nowait) call to recvmsg,
+%% wait some time and then cancel. IPv6
+%%
+api_a_recvmsg_cancel_tcp6(suite) ->
+ [];
+api_a_recvmsg_cancel_tcp6(doc) ->
+ [];
+api_a_recvmsg_cancel_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_a_recvmsg_cancel_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ socket:recvmsg(Sock, nowait)
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_recv_cancel_tcp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_recv_cancel_tcp(InitState) ->
process_flag(trap_exit, true),
ServerSeq =
@@ -5218,7 +5626,7 @@ api_a_recv_cancel_tcp(InitState) ->
%% Basically we make multiple async (Timeout = nowait) call(s) to recvfrom
%% (from *several* processes), wait some time and then cancel.
-%% This should result in abort messages to the 'other' processes.
+%% This should result in abort messages to the 'other' processes. IPv4
%%
api_a_mrecvfrom_cancel_udp4(suite) ->
[];
@@ -5247,9 +5655,41 @@ api_a_mrecvfrom_cancel_udp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make multiple async (Timeout = nowait) call(s) to recvfrom
+%% (from *several* processes), wait some time and then cancel.
+%% This should result in abort messages to the 'other' processes. IPv6
+%%
+api_a_mrecvfrom_cancel_udp6(suite) ->
+ [];
+api_a_mrecvfrom_cancel_udp6(doc) ->
+ [];
+api_a_mrecvfrom_cancel_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(20)),
+ tc_try(api_a_mrecvfrom_cancel_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ case socket:recvfrom(Sock, 0, nowait) of
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_mrecv_cancel_udp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg
%% (from *several* processes), wait some time and then cancel.
-%% This should result in abort messages to the 'other' processes.
+%% This should result in abort messages to the 'other' processes. IPv4
%%
api_a_mrecvmsg_cancel_udp4(suite) ->
[];
@@ -5278,6 +5718,38 @@ api_a_mrecvmsg_cancel_udp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg
+%% (from *several* processes), wait some time and then cancel.
+%% This should result in abort messages to the 'other' processes. IPv6
+%%
+api_a_mrecvmsg_cancel_udp6(suite) ->
+ [];
+api_a_mrecvmsg_cancel_udp6(doc) ->
+ [];
+api_a_mrecvmsg_cancel_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(20)),
+ tc_try(api_a_mrecvmsg_cancel_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ case socket:recvmsg(Sock, nowait) of
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_mrecv_cancel_udp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_mrecv_cancel_udp(InitState) ->
ServerSeq =
[
@@ -5649,7 +6121,7 @@ api_a_mrecv_cancel_udp(InitState) ->
%% Basically we make multiple async (Timeout = nowait) call(s) to accept
%% (from *several* processes), wait some time and then cancel,
-%% This should result in abort messages to the 'other' processes.
+%% This should result in abort messages to the 'other' processes. IPv4
%%
api_a_maccept_cancel_tcp4(suite) ->
[];
@@ -5679,6 +6151,39 @@ api_a_maccept_cancel_tcp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make multiple async (Timeout = nowait) call(s) to accept
+%% (from *several* processes), wait some time and then cancel,
+%% This should result in abort messages to the 'other' processes. IPv6
+%%
+api_a_maccept_cancel_tcp6(suite) ->
+ [];
+api_a_maccept_cancel_tcp6(doc) ->
+ [];
+api_a_maccept_cancel_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(20)),
+ tc_try(api_a_maccept_cancel_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Accept = fun(Sock) ->
+ case socket:accept(Sock, nowait) of
+ {ok, _} = OK ->
+ OK;
+ {select, _} = SELECT ->
+ SELECT;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ InitState = #{domain => inet6,
+ accept => Accept},
+ ok = api_a_maccept_cancel_tcp(InitState)
+ end).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_maccept_cancel_tcp(InitState) ->
process_flag(trap_exit, true),
ServerSeq =
@@ -6047,7 +6552,7 @@ api_a_maccept_cancel_tcp(InitState) ->
%% Basically we make multiple async (Timeout = nowait) call(s) to recv
%% (from *several* processes), wait some time and then cancel,
-%% This should result in abort messages to the 'other' processes.
+%% This should result in abort messages to the 'other' processes. IPv4
%%
api_a_mrecv_cancel_tcp4(suite) ->
[];
@@ -6069,9 +6574,34 @@ api_a_mrecv_cancel_tcp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make multiple async (Timeout = nowait) call(s) to recv
+%% (from *several* processes), wait some time and then cancel,
+%% This should result in abort messages to the 'other' processes. IPv6
+%%
+api_a_mrecv_cancel_tcp6(suite) ->
+ [];
+api_a_mrecv_cancel_tcp6(doc) ->
+ [];
+api_a_mrecv_cancel_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(20)),
+ tc_try(api_a_mrecv_cancel_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ socket:recv(Sock, 0, nowait)
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_mrecv_cancel_tcp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg
%% (from *several* processes), wait some time and then cancel,
-%% This should result in abort messages to the 'other' processes.
+%% This should result in abort messages to the 'other' processes. IPv4
%%
api_a_mrecvmsg_cancel_tcp4(suite) ->
[];
@@ -6093,6 +6623,31 @@ api_a_mrecvmsg_cancel_tcp4(_Config) when is_list(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg
+%% (from *several* processes), wait some time and then cancel,
+%% This should result in abort messages to the 'other' processes. IPv6
+%%
+api_a_mrecvmsg_cancel_tcp6(suite) ->
+ [];
+api_a_mrecvmsg_cancel_tcp6(doc) ->
+ [];
+api_a_mrecvmsg_cancel_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(20)),
+ tc_try(api_a_mrecvmsg_cancel_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ Recv = fun(Sock) ->
+ socket:recvmsg(Sock, nowait)
+ end,
+ InitState = #{domain => inet6,
+ recv => Recv},
+ ok = api_a_mrecv_cancel_tcp(InitState)
+ end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
api_a_mrecv_cancel_tcp(InitState) ->
process_flag(trap_exit, true),
ServerSeq =
@@ -7834,6 +8389,1695 @@ api_opt_simple_otp_controlling_process() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Tests the socket option acceptconn for UDP.
+%% This should be possible to get but not set.
+
+api_opt_sock_acceptconn_udp(suite) ->
+ [];
+api_opt_sock_acceptconn_udp(doc) ->
+ [];
+api_opt_sock_acceptconn_udp(_Config) when is_list(_Config) ->
+ ?TT(?SECS(30)),
+ tc_try(api_opt_sock_acceptconn_udp,
+ fun() ->
+ has_support_sock_acceptconn()
+ end,
+ fun() -> api_opt_sock_acceptconn_udp() end).
+
+
+
+api_opt_sock_acceptconn_udp() ->
+ Opt = acceptconn,
+ Set = fun(S, Val) ->
+ socket:setopt(S, socket, Opt, Val)
+ end,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ LSA = which_local_socket_addr(Domain),
+ {ok, State#{local_sa => LSA}}
+ end},
+ #{desc => "create socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{sock => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "[get] verify socket (before bind)",
+ cmd => fun(#{sock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Not accepting connections"),
+ ok;
+ {ok, true} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Accepting connections"),
+ {error, {unexpected_success, {Opt, true}}};
+ {error, enoprotoopt = Reason} ->
+ %% On some platforms this is not accepted
+ %% for UDP, so skip this part (UDP).
+ ?SEV_EPRINT("Expected Failure: "
+ "~p => SKIP", [Reason]),
+ (catch socket:close(Sock)),
+ {skip, Reason};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify socket (before bind)",
+ cmd => fun(#{sock := Sock} = _State) ->
+ case Set(Sock, true) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p",
+ [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=true)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ #{desc => "bind socket to local address",
+ cmd => fun(#{sock := Sock, local_sa := LSA} = _State) ->
+ case socket:bind(Sock, LSA) of
+ {ok, _} ->
+ ok;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "[get] verify socket (after bind)",
+ cmd => fun(#{sock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Not accepting connections"),
+ ok;
+ {ok, true} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Accepting connections"),
+ {error, {unexpected_success, {Opt, true}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify socket (after bind)",
+ cmd => fun(#{sock := Sock} = _State) ->
+ case Set(Sock, true) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p",
+ [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=true)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ %% *** Termination ***
+ #{desc => "close socket",
+ cmd => fun(#{sock := Sock} = State) ->
+ socket:close(Sock),
+ {ok, maps:remove(sock, State)}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option acceptconn for TCP.
+%% This should be possible to get but not set.
+
+api_opt_sock_acceptconn_tcp(suite) ->
+ [];
+api_opt_sock_acceptconn_tcp(doc) ->
+ [];
+api_opt_sock_acceptconn_tcp(_Config) when is_list(_Config) ->
+ ?TT(?SECS(30)),
+ tc_try(api_opt_sock_acceptconn_tcp,
+ fun() ->
+ has_support_sock_acceptconn()
+ end,
+ fun() -> api_opt_sock_acceptconn_tcp() end).
+
+
+
+api_opt_sock_acceptconn_tcp() ->
+ Opt = acceptconn,
+ Set = fun(S, Val) ->
+ socket:setopt(S, socket, Opt, Val)
+ end,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ LSA = which_local_socket_addr(Domain),
+ {ok, State#{local_sa => LSA}}
+ end},
+
+ #{desc => "create listen socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, stream, tcp) of
+ {ok, Sock} ->
+ {ok, State#{lsock => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "[get] verify listen socket (before bind)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Not accepting connections"),
+ ok;
+ {ok, true} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Accepting connections"),
+ {error, {unexpected_success, {Opt, true}}};
+ {error, enoprotoopt = Reason} ->
+ ?SEV_EPRINT("Expected Failure: "
+ "~p => SKIP", [Reason]),
+ (catch socket:close(Sock)),
+ {skip, Reason};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify listen socket (before bind)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Set(Sock, true) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=true)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "bind listen socket to local address",
+ cmd => fun(#{lsock := Sock, local_sa := LSA} = State) ->
+ case socket:bind(Sock, LSA) of
+ {ok, Port} ->
+ {ok, State#{server_sa => LSA#{port => Port}}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "[get] verify listen socket (after bind)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Not accepting connections"),
+ ok;
+ {ok, true} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Accepting connections"),
+ {error, {unexpected_success, {Opt, true}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify listen socket (after bind)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Set(Sock, true) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=true)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "make listen socket accept connections",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case socket:listen(Sock) of
+ ok ->
+ ok;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "[get] verify listen socket (after listen)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, true} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Accepting connections"),
+ ok;
+ {ok, false} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Not accepting connections"),
+ {error, {unexpected_success, {Opt, false}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify listen socket (after listen)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Set(Sock, false) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=false)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "create (connecting) socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, stream, tcp) of
+ {ok, Sock} ->
+ {ok, State#{csockc => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "bind connecting socket to local address",
+ cmd => fun(#{csockc := Sock, local_sa := LSA} = _State) ->
+ case socket:bind(Sock, LSA) of
+ {ok, _Port} ->
+ ok;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "[get] verify connecting socket (before connect)",
+ cmd => fun(#{csockc := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Not accepting connections"),
+ ok;
+ {ok, true} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Accepting connections"),
+ {error, {unexpected_success, {Opt, true}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify connecting socket (before connect)",
+ cmd => fun(#{csockc := Sock} = _State) ->
+ case Set(Sock, true) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=true)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "connect to server",
+ cmd => fun(#{csockc := Sock, server_sa := SSA} = _State) ->
+ case socket:connect(Sock, SSA) of
+ ok ->
+ ok;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "accept connection",
+ cmd => fun(#{lsock := Sock} = State) ->
+ case socket:accept(Sock) of
+ {ok, CSock} ->
+ {ok, State#{csocks => CSock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "[get] verify connecting socket (after connect)",
+ cmd => fun(#{csockc := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Not accepting connections"),
+ ok;
+ {ok, true} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Accepting connections"),
+ {error, {unexpected_success, {Opt, true}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify connecting socket (after connect)",
+ cmd => fun(#{csockc := Sock} = _State) ->
+ case Set(Sock, true) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=true)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ #{desc => "[get] verify connected socket",
+ cmd => fun(#{csocks := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Not accepting connections"),
+ ok;
+ {ok, true} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Accepting connections"),
+ {error, {unexpected_success, {Opt, true}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify connected socket",
+ cmd => fun(#{csocks := Sock} = _State) ->
+ case Set(Sock, true) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=true)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ #{desc => "[get] verify listen socket (after connect)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, true} ->
+ ?SEV_IPRINT("Expected Success: "
+ "Accepting connections"),
+ ok;
+ {ok, false} ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Not accepting connections"),
+ {error, {unexpected_success, {Opt, false}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[set] verify listen socket (after connect)",
+ cmd => fun(#{lsock := Sock} = _State) ->
+ case Set(Sock, false) of
+ {error, Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ ok;
+ ok ->
+ ?SEV_EPRINT("Unexpected Success: "
+ "Set acceptconn (=false)"),
+ {error, unexpected_success}
+ end
+ end},
+
+ %% *** Termination ***
+ #{desc => "close connecting socket(s)",
+ cmd => fun(#{csockc := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(csockc, State0),
+ State2 = maps:remove(csocks, State1), %% Auto-close
+ {ok, maps:remove(csockc, State2)}
+ end},
+ #{desc => "close listen socket",
+ cmd => fun(#{lsock := Sock} = State) ->
+ socket:close(Sock),
+ {ok, maps:remove(lsock, State)}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option acceptfilter. PLACEHOLDER!
+
+api_opt_sock_acceptfilter(suite) ->
+ [];
+api_opt_sock_acceptfilter(doc) ->
+ [];
+api_opt_sock_acceptfilter(_Config) when is_list(_Config) ->
+ ?TT(?SECS(30)),
+ tc_try(api_opt_sock_acceptfilter,
+ fun() -> not_yet_implemented() end,
+ fun() -> ok end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option bindtodevice.
+%% It has not always been possible to 'get' this option
+%% (atleast on linux).
+
+api_opt_sock_bindtodevice(suite) ->
+ [];
+api_opt_sock_bindtodevice(doc) ->
+ [];
+api_opt_sock_bindtodevice(_Config) when is_list(_Config) ->
+ ?TT(?SECS(30)),
+ tc_try(api_opt_sock_bindtodevice,
+ fun() -> has_support_sock_bindtodevice() end,
+ fun() -> api_opt_sock_bindtodevice() end).
+
+
+api_opt_sock_bindtodevice() ->
+ Opt = bindtodevice,
+ Set = fun(S, Val) ->
+ socket:setopt(S, socket, Opt, Val)
+ end,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{name := Name, addr := Addr}} ->
+ ?SEV_IPRINT("local host info (~p): "
+ "~n Name: ~p"
+ "~n Addr: ~p",
+ [Domain, Name, Addr]),
+ LSA = #{family => Domain,
+ addr => Addr},
+ {ok, State#{dev => Name,
+ local_sa => LSA}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "create UDP socket 1",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{usock1 => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "create UDP socket 2",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{usock2 => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "create TCP socket 1",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, stream, tcp) of
+ {ok, Sock} ->
+ {ok, State#{tsock1 => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "create TCP socket 2",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, stream, tcp) of
+ {ok, Sock} ->
+ {ok, State#{tsock2 => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "[get] verify UDP socket 1 (before bindtodevice)",
+ cmd => fun(#{usock1 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, enoprotoopt = Reason} ->
+ ?SEV_EPRINT("Unexpected Failure: ~p => SKIP",
+ [Reason]),
+ {skip, Reason};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[get] verify UDP socket 2 (before bind)",
+ cmd => fun(#{usock2 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[get] verify TCP socket 1 (before bindtodevice)",
+ cmd => fun(#{tsock1 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[get] verify TCP socket 2 (before bind)",
+ cmd => fun(#{tsock2 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "Bind UDP socket 1 to device",
+ cmd => fun(#{usock1 := Sock, dev := Dev} = State) ->
+ case Set(Sock, Dev) of
+ ok ->
+ ?SEV_IPRINT("Expected Success"),
+ ok;
+ {error, eperm = Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ (catch socket:close(Sock)),
+ {ok, State#{usock1 => skip}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Bind UDP socket 2 to local address",
+ cmd => fun(#{usock2 := Sock, local_sa := LSA} = _State) ->
+ case socket:bind(Sock, LSA) of
+ {ok, _Port} ->
+ ?SEV_IPRINT("Expected Success"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Bind TCP socket 1 to device",
+ cmd => fun(#{usock1 := USock1,
+ tsock1 := Sock, dev := Dev} = State) ->
+ case Set(Sock, Dev) of
+ ok ->
+ ?SEV_IPRINT("Expected Success"),
+ ok;
+ {error, eperm = Reason} when (USock1 =:= skip) ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ {skip, Reason};
+ {error, eperm = Reason} ->
+ ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
+ (catch socket:close(Sock)),
+ {ok, State#{tsock1 => skip}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Bind TCP socket 2 to local address",
+ cmd => fun(#{tsock2 := Sock, local_sa := LSA} = _State) ->
+ case socket:bind(Sock, LSA) of
+ {ok, _Port} ->
+ ?SEV_IPRINT("Expected Success"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "[get] verify UDP socket 1 (after bindtodevice)",
+ cmd => fun(#{usock1 := skip} = _State) ->
+ ?SEV_IPRINT("SKIP'ed (previous eperm)"),
+ ok;
+ (#{usock1 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[get] verify UDP socket 2 (after bind)",
+ cmd => fun(#{usock2 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[get] verify TCP socket 1 (after bindtodevice)",
+ cmd => fun(#{tsock1 := skip} = _State) ->
+ ?SEV_IPRINT("SKIP'ed (previous eperm)"),
+ ok;
+ (#{tsock1 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[get] verify TCP socket 2 (after bind)",
+ cmd => fun(#{tsock2 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Dev} ->
+ ?SEV_IPRINT("Expected Success: ~p", [Dev]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ %% *** Termination ***
+ #{desc => "close UDP socket 1",
+ cmd => fun(#{usock1 := skip} = State) ->
+ ?SEV_IPRINT("SKIP'ed (already closed)"),
+ {ok, maps:remove(usock1, State)};
+ (#{usock1 := Sock} = State) ->
+ socket:close(Sock),
+ {ok, maps:remove(usock1, State)}
+ end},
+ #{desc => "close UDP socket 2",
+ cmd => fun(#{usock2 := Sock} = State) ->
+ socket:close(Sock),
+ {ok, maps:remove(usock2, State)}
+ end},
+ #{desc => "close TCP socket 1",
+ cmd => fun(#{tsock1 := skip} = State) ->
+ ?SEV_IPRINT("SKIP'ed (already closed)"),
+ {ok, maps:remove(tsock1, State)};
+ (#{tsock1 := Sock} = State) ->
+ socket:close(Sock),
+ {ok, maps:remove(tsock1, State)}
+ end},
+ #{desc => "close TCP socket 2",
+ cmd => fun(#{tsock2 := Sock} = State) ->
+ socket:close(Sock),
+ {ok, maps:remove(tsock2, State)}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option broadcast.
+%% Make it possible for datagram sockets to send packets to a broadcast
+%% address (IPv4 only).
+
+api_opt_sock_broadcast(suite) ->
+ [];
+api_opt_sock_broadcast(doc) ->
+ [];
+api_opt_sock_broadcast(_Config) when is_list(_Config) ->
+ ?TT(?SECS(30)),
+ tc_try(api_opt_sock_broadcast,
+ fun() -> has_support_sock_broadcast() end,
+ fun() -> api_opt_sock_broadcast() end).
+
+
+api_opt_sock_broadcast() ->
+ Opt = broadcast,
+ Set = fun(S, Val) when is_boolean(Val) ->
+ socket:setopt(S, socket, Opt, Val)
+ end,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{name := Name,
+ addr := Addr,
+ broadaddr := BAddr}} ->
+ ?SEV_IPRINT("local host info: "
+ "~n Name: ~p"
+ "~n Addr: ~p"
+ "~n Broadcast Addr: ~p",
+ [Name, Addr, BAddr]),
+ LSA = #{family => Domain,
+ addr => Addr},
+ BSA = #{family => Domain,
+ addr => BAddr},
+ {ok, State#{lsa => LSA,
+ bsa => BSA}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "[socket 1] create UDP socket (listening 1)",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{sock1 => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "[socket 1] Bind UDP socket (to limited broadcast address)",
+ cmd => fun(#{sock1 := Sock} = State) ->
+ BSA = #{family => inet,
+ addr => broadcast},
+ ?SEV_IPRINT("Try bind (socket 1) to: "
+ "~n ~p", [BSA]),
+ case socket:bind(Sock, BSA) of
+ {ok, Port} ->
+ ?SEV_IPRINT("Expected Success (bound): ~p",
+ [Port]),
+ {ok, State#{sa1 => BSA#{port => Port}}};
+ {error, eaddrnotavail = Reason} ->
+ ?SEV_IPRINT("~p => "
+ "SKIP limited broadcast test",
+ [Reason]),
+ {ok, State#{sa1 => skip}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 1] UDP socket sockname",
+ cmd => fun(#{sa1 := skip} = _State) ->
+ ?SEV_IPRINT("SKIP limited broadcast test"),
+ ok;
+ (#{sock1 := Sock} = _State) ->
+ case socket:sockname(Sock) of
+ {ok, SA} ->
+ ?SEV_IPRINT("SA: ~p", [SA]),
+ ok;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "[socket 2] create UDP socket (listening 2)",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{sock2 => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "[socket 2] Bind UDP socket (to subnet-directed broadcast address)",
+ cmd => fun(#{sock2 := Sock,
+ bsa := BSA} = State) ->
+ ?SEV_IPRINT("Try bind (socket 1) to: "
+ "~n ~p", [BSA]),
+ case socket:bind(Sock, BSA) of
+ {ok, Port} ->
+ ?SEV_IPRINT("Expected Success (bound): ~p",
+ [Port]),
+ {ok, State#{sa2 => BSA#{port => Port}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 2] UDP socket sockname",
+ cmd => fun(#{sock2 := Sock} = _State) ->
+ case socket:sockname(Sock) of
+ {ok, SA} ->
+ ?SEV_IPRINT("SA: ~p", [SA]),
+ ok;
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "[socket 3] create UDP socket (sender)",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{sock3 => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "[socket 3][get] verify UDP socket (before bind and set)",
+ cmd => fun(#{sock3 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, false} ->
+ ?SEV_IPRINT("Expected Success: "
+ "broadcast not allowed"),
+ ok;
+ {ok, true} ->
+ ?SEV_IPRINT("Unexpected Success result: "
+ "broadcast already allowed"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 3] Try make broadcast allowed",
+ cmd => fun(#{sock3 := Sock} = _State) ->
+ case Set(Sock, true) of
+ ok ->
+ ?SEV_IPRINT("Expected Success: "
+ "broadcast now allowed"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 3] verify UDP socket broadcast allowed",
+ cmd => fun(#{sock3 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, true} ->
+ ?SEV_IPRINT("Expected Success: "
+ "broadcast allowed"),
+ ok;
+ {ok, false} ->
+ ?SEV_IPRINT("Unexpected Success result: "
+ "broadcast *not* allowed"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 3] Bind UDP socket (to local address)",
+ cmd => fun(#{sock3 := Sock, lsa := LSA} = State) ->
+ ?SEV_IPRINT("Try bind (socket 2) to: "
+ "~n ~p", [LSA]),
+ case socket:bind(Sock, LSA) of
+ {ok, Port} ->
+ ?SEV_IPRINT("Expected Success (bound): ~p",
+ [Port]),
+ {ok, State#{sa3 => LSA#{port => Port}}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 3] verify UDP socket (after set)",
+ cmd => fun(#{sock3 := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, true} ->
+ ?SEV_IPRINT("Expected Success: "
+ "broadcast allowed"),
+ ok;
+ {ok, false} ->
+ ?SEV_IPRINT("Unexpected Success result: "
+ "broadcast not allowed"),
+ {error, not_allowed};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "[socket 3] try send to limited broadcast address",
+ cmd => fun(#{sa1 := skip} = _State) ->
+ ?SEV_IPRINT("SKIP limited broadcast test"),
+ ok;
+ (#{sock3 := Sock,
+ sa1 := Dest} = _State) ->
+ Data = list_to_binary("hejsan"),
+ ?SEV_IPRINT("try send to bradcast address: "
+ "~n ~p", [Dest]),
+ case socket:sendto(Sock, Data, Dest) of
+ ok ->
+ ?SEV_IPRINT("Expected Success: "
+ "broadcast message sent"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 1] try recv",
+ cmd => fun(#{sa1 := skip} = _State) ->
+ ?SEV_IPRINT("SKIP limited broadcast test"),
+ ok;
+ (#{sock1 := Sock} = State) ->
+ case socket:recvfrom(Sock, 0, 5000) of
+ {ok, _} ->
+ ?SEV_IPRINT("Expected Success: "
+ "received message"),
+ ok;
+ {error, timeout = Reason} ->
+ %% Some platforms seem to balk at this.
+ %% It spossible to bind to this, and
+ %% send to it, but no data is received.
+ %% At some point we should investigate...
+ %% For now, we just skip this part of
+ %% the test...
+ ?SEV_IPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ {ok, State#{sa1 => skip}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+
+ ?SEV_SLEEP(?SECS(1)),
+
+ #{desc => "[socket 3] try send to subnet-directed broadcast address",
+ cmd => fun(#{sock3 := Sock,
+ sa2 := Dest} = _State) ->
+ Data = list_to_binary("hejsan"),
+ ?SEV_IPRINT("try send to bradcast address: "
+ "~n ~p", [Dest]),
+ case socket:sendto(Sock, Data, Dest) of
+ ok ->
+ ?SEV_IPRINT("Expected Success: "
+ "broadcast message sent"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "[socket 2] try recv",
+ cmd => fun(#{sock2 := Sock, sa1 := SA1} = _State) ->
+ case socket:recvfrom(Sock, 0, 5000) of
+ {ok, _} ->
+ ?SEV_IPRINT("Expected Success: "
+ "received message"),
+ ok;
+ {error, timeout = Reason} when (SA1 =:= skip) ->
+ ?SEV_IPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ {skip, "receive timeout"};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+
+ %% *** Termination ***
+ #{desc => "[socket 3] close UDP socket (sender)",
+ cmd => fun(#{sock3 := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(sock3, State0),
+ State2 = maps:remove(sa3, State1),
+ {ok, State2}
+ end},
+ #{desc => "[socket 2] close UDP socket (listener 2)",
+ cmd => fun(#{sock2 := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(sock2, State0),
+ State2 = maps:remove(sa2, State1),
+ {ok, State2}
+ end},
+ #{desc => "[socket 1] close UDP socket (listener 1)",
+ cmd => fun(#{sock1 := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(sock1, State0),
+ State2 = maps:remove(sa1, State1),
+ {ok, State2}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option debug.
+%% On linux, this test requires that the user running the test to have
+%% CAP_NET_ADMIN capabilities or be root (effective user ID of 0),
+%% therefor we explicitly test for the result eacces when attempting to
+%% set, and skip if we get it.
+
+api_opt_sock_debug(suite) ->
+ [];
+api_opt_sock_debug(doc) ->
+ [];
+api_opt_sock_debug(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_opt_sock_debug,
+ fun() -> has_support_sock_debug() end,
+ fun() -> api_opt_sock_debug() end).
+
+
+api_opt_sock_debug() ->
+ Opt = debug,
+ Set = fun(S, Val) when is_integer(Val) ->
+ socket:setopt(S, socket, Opt, Val)
+ end,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{name := Name,
+ addr := Addr,
+ broadaddr := BAddr}} ->
+ ?SEV_IPRINT("local host info: "
+ "~n Name: ~p"
+ "~n Addr: ~p"
+ "~n Broadcast Addr: ~p",
+ [Name, Addr, BAddr]),
+ LSA = #{family => Domain,
+ addr => Addr},
+ BSA = #{family => Domain,
+ addr => BAddr},
+ {ok, State#{lsa => LSA,
+ bsa => BSA}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "create UDP socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{sock => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "Get current debug value",
+ cmd => fun(#{sock := Sock} = State) ->
+ case Get(Sock) of
+ {ok, Debug} when is_integer(Debug) ->
+ ?SEV_IPRINT("Success: ~p", [Debug]),
+ {ok, State#{debug => Debug}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Try enable socket debug",
+ cmd => fun(#{sock := Sock, debug := Debug} = State) ->
+ NewDebug = Debug + 1,
+ case Set(Sock, NewDebug) of
+ ok ->
+ ?SEV_IPRINT("Expected Success"),
+ {ok, State#{debug => NewDebug}};
+ {error, eacces = Reason} ->
+ ?SEV_EPRINT("NO ACCESS => SKIP"),
+ {skip, Reason};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Get current (new) debug value",
+ cmd => fun(#{sock := Sock, debug := Debug} = _State) ->
+ case Get(Sock) of
+ {ok, Debug} when is_integer(Debug) ->
+ ?SEV_IPRINT("Success: ~p", [Debug]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+
+ %% *** Termination ***
+ #{desc => "close UDP socket",
+ cmd => fun(#{sock := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(sock, State0),
+ {ok, State1}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option domain.
+%% This is a read only option. Also not available on all platforms.
+
+api_opt_sock_domain(suite) ->
+ [];
+api_opt_sock_domain(doc) ->
+ [];
+api_opt_sock_domain(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_opt_sock_domain,
+ fun() -> has_support_sock_domain() end,
+ fun() -> api_opt_sock_domain() end).
+
+
+api_opt_sock_domain() ->
+ Opt = domain,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{name := Name,
+ addr := Addr,
+ broadaddr := BAddr}} ->
+ ?SEV_IPRINT("local host info: "
+ "~n Name: ~p"
+ "~n Addr: ~p"
+ "~n Broadcast Addr: ~p",
+ [Name, Addr, BAddr]),
+ LSA = #{family => Domain,
+ addr => Addr},
+ BSA = #{family => Domain,
+ addr => BAddr},
+ {ok, State#{lsa => LSA,
+ bsa => BSA}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "create IPv4 UDP socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{usock => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "Get domain for the UDP socket",
+ cmd => fun(#{domain := Domain, usock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Domain} ->
+ ?SEV_IPRINT("Success: ~p", [Domain]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "create TCP socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, stream, tcp) of
+ {ok, Sock} ->
+ {ok, State#{tsock => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "Get domain for the TCP socket",
+ cmd => fun(#{domain := Domain, tsock := Sock} = _State) ->
+ case Get(Sock) of
+ {ok, Domain} ->
+ ?SEV_IPRINT("Success: ~p", [Domain]),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+
+ %% *** Termination ***
+ #{desc => "close UDP socket",
+ cmd => fun(#{usock := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(usock, State0),
+ {ok, State1}
+ end},
+ #{desc => "close TCP socket",
+ cmd => fun(#{tsock := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(tsock, State0),
+ {ok, State1}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option dontroute.
+%% The man page has the following to say:
+%% "Don't send via a gateway, send only to directly connected hosts.
+%% The same effect can be achieved by setting the MSG_DONTROUTE
+%% flag on a socket send(2) operation."
+%% Since its "kind of" difficult to check if it actually takes an
+%% effect (you would need a gateway for that and a machine "on the
+%% other side"), we only test if we can set and get the value.
+%% Better then nothing.
+
+api_opt_sock_dontroute(suite) ->
+ [];
+api_opt_sock_dontroute(doc) ->
+ [];
+api_opt_sock_dontroute(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_opt_sock_dontroute,
+ fun() -> has_support_sock_dontroute() end,
+ fun() -> api_opt_sock_dontroute() end).
+
+
+api_opt_sock_dontroute() ->
+ Opt = dontroute,
+ Set = fun(S, Val) when is_boolean(Val) ->
+ socket:setopt(S, socket, Opt, Val)
+ end,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{name := Name,
+ addr := Addr,
+ broadaddr := BAddr}} ->
+ ?SEV_IPRINT("local host info: "
+ "~n Name: ~p"
+ "~n Addr: ~p"
+ "~n Broadcast Addr: ~p",
+ [Name, Addr, BAddr]),
+ LSA = #{family => Domain,
+ addr => Addr},
+ BSA = #{family => Domain,
+ addr => BAddr},
+ {ok, State#{lsa => LSA,
+ bsa => BSA}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "create UDP socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, dgram, udp) of
+ {ok, Sock} ->
+ {ok, State#{sock => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "Get current value",
+ cmd => fun(#{sock := Sock} = State) ->
+ case Get(Sock) of
+ {ok, Val} when is_boolean(Val) ->
+ ?SEV_IPRINT("Success: ~p", [Val]),
+ {ok, State#{dontroute => Val}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Try change value",
+ cmd => fun(#{sock := Sock, dontroute := Current} = State) ->
+ New = not Current,
+ ?SEV_IPRINT("Change from ~p to ~p", [Current, New]),
+ case Set(Sock, New) of
+ ok ->
+ ?SEV_IPRINT("Expected Success"),
+ {ok, State#{dontroute => New}};
+ {error, eopnotsupp = Reason} ->
+ ?SEV_EPRINT("Expected Failure: ~p",
+ [Reason]),
+ {skip, Reason};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Verify changed value",
+ cmd => fun(#{sock := Sock, dontroute := Val} = _State) ->
+ case Get(Sock) of
+ {ok, Val} ->
+ ?SEV_IPRINT("Expected Success"),
+ ok;
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+
+ %% *** Termination ***
+ #{desc => "close UDP socket",
+ cmd => fun(#{sock := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(sock, State0),
+ {ok, State1}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option error. PLACEHOLDER!
+
+api_opt_sock_error(suite) ->
+ [];
+api_opt_sock_error(doc) ->
+ [];
+api_opt_sock_error(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_opt_sock_error,
+ fun() -> not_yet_implemented() end,
+ fun() -> ok end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option keepalive.
+%% This is bit tricky to test, partly because we have no control over
+%% the underlying TCP timeouts. So, for now, we just test that we can
+%% change the value.
+
+api_opt_sock_keepalive(suite) ->
+ [];
+api_opt_sock_keepalive(doc) ->
+ [];
+api_opt_sock_keepalive(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_opt_sock_keepalive,
+ fun() -> has_support_sock_keepalive() end,
+ fun() -> api_opt_sock_keepalive() end).
+
+
+api_opt_sock_keepalive() ->
+ Opt = keepalive,
+ Set = fun(S, Val) when is_boolean(Val) ->
+ socket:setopt(S, socket, Opt, Val)
+ end,
+ Get = fun(S) ->
+ socket:getopt(S, socket, Opt)
+ end,
+
+ TesterSeq =
+ [
+ #{desc => "which local address",
+ cmd => fun(#{domain := Domain} = State) ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{name := Name,
+ addr := Addr,
+ broadaddr := BAddr}} ->
+ ?SEV_IPRINT("local host info: "
+ "~n Name: ~p"
+ "~n Addr: ~p"
+ "~n Broadcast Addr: ~p",
+ [Name, Addr, BAddr]),
+ LSA = #{family => Domain,
+ addr => Addr},
+ BSA = #{family => Domain,
+ addr => BAddr},
+ {ok, State#{lsa => LSA,
+ bsa => BSA}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+
+ #{desc => "create TCP socket",
+ cmd => fun(#{domain := Domain} = State) ->
+ case socket:open(Domain, stream, tcp) of
+ {ok, Sock} ->
+ {ok, State#{sock => Sock}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end},
+ #{desc => "Get current value",
+ cmd => fun(#{sock := Sock} = State) ->
+ case Get(Sock) of
+ {ok, Val} when is_boolean(Val) ->
+ ?SEV_IPRINT("Success: ~p", [Val]),
+ {ok, State#{keepalive => Val}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Try change the value",
+ cmd => fun(#{sock := Sock, keepalive := Current} = State) ->
+ New = not Current,
+ ?SEV_IPRINT("Try change value from ~p to ~p",
+ [Current, New]),
+ case Set(Sock, New) of
+ ok ->
+ ?SEV_IPRINT("Expected Success"),
+ {ok, State#{keepalive => New}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected Failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+ #{desc => "Verify (new) current value",
+ cmd => fun(#{sock := Sock, keepalive := Val} = _State) ->
+ case Get(Sock) of
+ {ok, Val} ->
+ ?SEV_IPRINT("Expected Success (~p)", [Val]),
+ ok;
+ {ok, OtherVal} ->
+ ?SEV_IPRINT("Unexpected Success: ~p",
+ [OtherVal]),
+ {error, {unexpected_success_value,
+ Val, OtherVal}};
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("Unexpected failure: ~p",
+ [Reason]),
+ ERROR
+ end
+ end},
+
+ %% *** Termination ***
+ #{desc => "close UDP socket",
+ cmd => fun(#{sock := Sock} = State0) ->
+ socket:close(Sock),
+ State1 = maps:remove(sock, State0),
+ {ok, State1}
+ end},
+
+ %% *** We are done ***
+ ?SEV_FINISH_NORMAL
+ ],
+
+ Domain = inet,
+
+ i("start tester evaluator"),
+ InitState = #{domain => Domain},
+ Tester = ?SEV_START("tester", TesterSeq, InitState),
+
+ i("await evaluator(s)"),
+ ok = ?SEV_AWAIT_FINISH([Tester]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Tests the socket option linger. PLACEHOLDER!
+
+api_opt_sock_linger(suite) ->
+ [];
+api_opt_sock_linger(doc) ->
+ [];
+api_opt_sock_linger(_Config) when is_list(_Config) ->
+ ?TT(?SECS(10)),
+ tc_try(api_opt_sock_linger,
+ fun() -> not_yet_implemented() end,
+ fun() -> ok end).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Tests that the add_mambership and drop_membership ip options work.
%% We create one server and two clients. The server only send messages,
%% the clients only receives messages.
@@ -7853,9 +10097,9 @@ api_opt_ip_add_drop_membership(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_ip_add_drop_membership,
fun() ->
- has_ip_add_membership_support(),
- has_ip_drop_membership_support(),
- has_ip_multicast_support()
+ has_support_ip_add_membership(),
+ has_support_ip_drop_membership(),
+ has_support_ip_multicast()
end,
fun() -> api_opt_ip_add_drop_membership() end).
@@ -8072,8 +10316,8 @@ api_opt_ip_add_drop_membership() ->
],
- i("get multicast address"),
Domain = inet,
+ i("get multicast address"),
MAddr = which_ip_multicast_address(),
MSA = #{family => Domain, addr => MAddr},
@@ -8106,6 +10350,7 @@ which_multicast_address(Domain) ->
which_multicast_address2(Domain, WhichMAddr);
Type ->
+ %% Actually, what is "not supported". is netstat!
not_supported({multicast, Type})
end.
@@ -8115,20 +10360,28 @@ which_multicast_address(Domain) ->
which_multicast_address2(Domain, WhichMAddr) ->
IfName = which_local_host_ifname(Domain),
- try
- begin
- %% On some platforms the netstat barfs out some crap on stderr
- %% before the actual info...
- NetstatGroupsStr = os:cmd("netstat -g 2>/dev/null | grep " ++ IfName),
- NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]),
- NetstatGroups = [string:tokens(G, [$ ]) || G <- NetstatGroups0],
- MAddrs = [WhichMAddr(NetstatGroup) || NetstatGroup <-
- NetstatGroups],
- which_multicast_address3(Domain, MAddrs)
- end
- catch
- C:E:S ->
- not_supported({multicast, {C,E,S}})
+ %% On some platforms the netstat barfs out some crap on stderr
+ %% before the actual info...
+ case os:cmd("netstat -g 2>/dev/null | grep " ++ IfName) of
+ [] ->
+ %% Can't figure out if we support multicast or not...
+ not_supported(no_netstat);
+ NetstatGroupsStr ->
+ try
+ begin
+ NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]),
+ NetstatGroups = [string:tokens(G, [$ ]) ||
+ G <- NetstatGroups0],
+ MAddrs = [WhichMAddr(NetstatGroup) ||
+ NetstatGroup <- NetstatGroups],
+ which_multicast_address3(Domain, MAddrs)
+ end
+ catch
+ throw:E:_ ->
+ throw(E);
+ C:E:S ->
+ not_supported({multicast, {C,E,S}})
+ end
end.
which_multicast_address3(_Domain, []) ->
@@ -8146,8 +10399,8 @@ which_multicast_address3(Domain, [MAddrStr|MAddrs]) ->
end.
which_local_host_ifname(Domain) ->
- case which_local_host_info(Domain) of
- {ok, {Name, _Addr, _Flags}} ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{name := Name}} ->
Name;
{error, Reason} ->
not_supported({multicast, Reason})
@@ -9222,6 +11475,7 @@ api_to_send_tcp6(doc) ->
[];
api_to_send_tcp6(_Config) when is_list(_Config) ->
tc_try(api_to_send_tcp6,
+ fun() -> has_support_ipv6() end,
fun() ->
not_yet_implemented()%% ,
%% ok = api_to_send_tcp(inet6)
@@ -9254,6 +11508,7 @@ api_to_sendto_udp6(doc) ->
[];
api_to_sendto_udp6(_Config) when is_list(_Config) ->
tc_try(api_to_sendto_udp6,
+ fun() -> has_support_ipv6() end,
fun() ->
not_yet_implemented()%% ,
%% ok = api_to_sendto_to_udp(inet6)
@@ -9286,6 +11541,7 @@ api_to_sendmsg_tcp6(doc) ->
[];
api_to_sendmsg_tcp6(_Config) when is_list(_Config) ->
tc_try(api_to_sendmsg_tcp6,
+ fun() -> has_support_ipv6() end,
fun() ->
not_yet_implemented()%% ,
%% ok = api_to_sendmsg_tcp(inet6)
@@ -9320,6 +11576,7 @@ api_to_recv_udp6(doc) ->
[];
api_to_recv_udp6(_Config) when is_list(_Config) ->
tc_try(api_to_recv_udp6,
+ fun() -> has_support_ipv6() end,
fun() ->
not_yet_implemented()%% ,
%% ok = api_to_recv_udp(inet6)
@@ -9899,7 +12156,7 @@ sc_cpe_socket_cleanup_tcp4(suite) ->
sc_cpe_socket_cleanup_tcp4(doc) ->
[];
sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) ->
- ?TT(?SECS(5)),
+ ?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_tcp4,
fun() ->
InitState = #{domain => inet,
@@ -9919,7 +12176,7 @@ sc_cpe_socket_cleanup_tcp6(suite) ->
sc_cpe_socket_cleanup_tcp6(doc) ->
[];
sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) ->
- ?TT(?SECS(5)),
+ ?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_tcp6,
fun() -> has_support_ipv6() end,
fun() ->
@@ -9940,7 +12197,7 @@ sc_cpe_socket_cleanup_tcpL(suite) ->
sc_cpe_socket_cleanup_tcpL(doc) ->
[];
sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) ->
- ?TT(?SECS(5)),
+ ?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_tcpL,
fun() -> has_support_unix_domain_socket() end,
fun() ->
@@ -9961,7 +12218,7 @@ sc_cpe_socket_cleanup_udp4(suite) ->
sc_cpe_socket_cleanup_udp4(doc) ->
[];
sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) ->
- ?TT(?SECS(5)),
+ ?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_udp4,
fun() ->
InitState = #{domain => inet,
@@ -9982,7 +12239,7 @@ sc_cpe_socket_cleanup_udp6(suite) ->
sc_cpe_socket_cleanup_udp6(doc) ->
[];
sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) ->
- ?TT(?SECS(5)),
+ ?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_udp6,
fun() -> has_support_ipv6() end,
fun() ->
@@ -10003,7 +12260,7 @@ sc_cpe_socket_cleanup_udpL(suite) ->
sc_cpe_socket_cleanup_udpL(doc) ->
[];
sc_cpe_socket_cleanup_udpL(_Config) when is_list(_Config) ->
- ?TT(?SECS(5)),
+ ?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_udpL,
fun() -> has_support_unix_domain_socket() end,
fun() ->
@@ -10109,8 +12366,15 @@ sc_cpe_socket_cleanup(InitState) ->
ERROR
end
end},
+
+ ?SEV_SLEEP(?SECS(5)),
+
%% The reason we get closed, is that as long as there is a ref to
%% the resource (socket), then it will not be garbage collected.
+ %% Note that its still a race that the nif has processed that the
+ %% "controlling process" has terminated. There really is no
+ %% proper timeout for this, but the 5 seconds "should" be enough...
+ %% We should really have some way to subscribe to socket events...
#{desc => "verify no socket (closed)",
cmd => fun(#{owner := Pid, sock := Sock} = _State) ->
case socket:getopt(Sock, otp, controlling_process) of
@@ -13952,6 +16216,29 @@ traffic_send_and_recv_counters_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
+%% We use TCP on IPv6.
+
+traffic_send_and_recv_counters_tcp6(suite) ->
+ [];
+traffic_send_and_recv_counters_tcp6(doc) ->
+ [];
+traffic_send_and_recv_counters_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(15)),
+ tc_try(traffic_send_and_recv_counters_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ InitState = #{domain => inet6,
+ proto => tcp,
+ recv => fun(S) -> socket:recv(S) end,
+ send => fun(S, D) -> socket:send(S, D) end},
+ ok = traffic_send_and_recv_tcp(InitState)
+ end).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This test case is intended to (simply) test that the counters
+%% for both read and write.
+%% So that its easy to extend, we use fun's for read and write.
%% We use default (TCP) on local.
traffic_send_and_recv_counters_tcpL(suite) ->
@@ -13961,6 +16248,7 @@ traffic_send_and_recv_counters_tcpL(doc) ->
traffic_send_and_recv_counters_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_send_and_recv_counters_tcpL,
+ fun() -> has_support_unix_domain_socket() end,
fun() ->
InitState = #{domain => local,
proto => default,
@@ -14007,6 +16295,40 @@ traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
+%% We use TCP on IPv6.
+
+traffic_sendmsg_and_recvmsg_counters_tcp6(suite) ->
+ [];
+traffic_sendmsg_and_recvmsg_counters_tcp6(doc) ->
+ [];
+traffic_sendmsg_and_recvmsg_counters_tcp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(15)),
+ tc_try(traffic_sendmsg_and_recvmsg_counters_tcp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ InitState = #{domain => inet6,
+ proto => tcp,
+ recv => fun(S) ->
+ case socket:recvmsg(S) of
+ {ok, #{addr := _Source,
+ iov := [Data]}} ->
+ {ok, Data};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ send => fun(S, Data) ->
+ MsgHdr = #{iov => [Data]},
+ socket:sendmsg(S, MsgHdr)
+ end},
+ ok = traffic_send_and_recv_tcp(InitState)
+ end).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This test case is intended to (simply) test that the counters
+%% for both read and write.
+%% So that its easy to extend, we use fun's for read and write.
%% We use default (TCP) on local.
traffic_sendmsg_and_recvmsg_counters_tcpL(suite) ->
@@ -14016,6 +16338,7 @@ traffic_sendmsg_and_recvmsg_counters_tcpL(doc) ->
traffic_sendmsg_and_recvmsg_counters_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_tcpL,
+ fun() -> has_support_unix_domain_socket() end,
fun() ->
InitState = #{domain => local,
proto => default,
@@ -14064,6 +16387,8 @@ traffic_send_and_recv_tcp(InitState) ->
case socket:open(Domain, stream, Proto) of
{ok, Sock} ->
{ok, State#{lsock => Sock}};
+ {error, eafnosupport = Reason} ->
+ {skip, Reason};
{error, _} = ERROR ->
ERROR
end
@@ -14408,6 +16733,8 @@ traffic_send_and_recv_tcp(InitState) ->
case socket:open(Domain, stream, Proto) of
{ok, Sock} ->
{ok, State#{sock => Sock}};
+ {error, eafnosupport = Reason} ->
+ {skip, Reason};
{error, _} = ERROR ->
ERROR
end
@@ -14928,6 +17255,33 @@ traffic_sendto_and_recvfrom_counters_udp4(_Config) when is_list(_Config) ->
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
+%% We use UDP on IPv6.
+
+traffic_sendto_and_recvfrom_counters_udp6(suite) ->
+ [];
+traffic_sendto_and_recvfrom_counters_udp6(doc) ->
+ [];
+traffic_sendto_and_recvfrom_counters_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(15)),
+ tc_try(traffic_sendto_and_recvfrom_counters_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ InitState = #{domain => inet6,
+ proto => udp,
+ recv => fun(S) ->
+ socket:recvfrom(S)
+ end,
+ send => fun(S, Data, Dest) ->
+ socket:sendto(S, Data, Dest)
+ end},
+ ok = traffic_send_and_recv_udp(InitState)
+ end).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This test case is intended to (simply) test that the counters
+%% for both read and write.
+%% So that its easy to extend, we use fun's for read and write.
%% We use default (UDP) on local.
traffic_sendto_and_recvfrom_counters_udpL(suite) ->
@@ -14937,6 +17291,7 @@ traffic_sendto_and_recvfrom_counters_udpL(doc) ->
traffic_sendto_and_recvfrom_counters_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendto_and_recvfrom_counters_udp4,
+ fun() -> has_support_unix_domain_socket() end,
fun() ->
InitState = #{domain => local,
proto => default,
@@ -14988,6 +17343,41 @@ traffic_sendmsg_and_recvmsg_counters_udp4(_Config) when is_list(_Config) ->
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
+%% We use UDP on IPv6.
+
+traffic_sendmsg_and_recvmsg_counters_udp6(suite) ->
+ [];
+traffic_sendmsg_and_recvmsg_counters_udp6(doc) ->
+ [];
+traffic_sendmsg_and_recvmsg_counters_udp6(_Config) when is_list(_Config) ->
+ ?TT(?SECS(15)),
+ tc_try(traffic_sendmsg_and_recvmsg_counters_udp6,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ InitState = #{domain => inet6,
+ proto => udp,
+ recv => fun(S) ->
+ case socket:recvmsg(S) of
+ {ok, #{addr := Source,
+ iov := [Data]}} ->
+ {ok, {Source, Data}};
+ {error, _} = ERROR ->
+ ERROR
+ end
+ end,
+ send => fun(S, Data, Dest) ->
+ MsgHdr = #{addr => Dest,
+ iov => [Data]},
+ socket:sendmsg(S, MsgHdr)
+ end},
+ ok = traffic_send_and_recv_udp(InitState)
+ end).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This test case is intended to (simply) test that the counters
+%% for both read and write.
+%% So that its easy to extend, we use fun's for read and write.
%% We use default (UDP) on local.
traffic_sendmsg_and_recvmsg_counters_udpL(suite) ->
@@ -14997,6 +17387,7 @@ traffic_sendmsg_and_recvmsg_counters_udpL(doc) ->
traffic_sendmsg_and_recvmsg_counters_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_udpL,
+ fun() -> has_support_unix_domain_socket() end,
fun() ->
InitState = #{domain => local,
proto => default,
@@ -15455,7 +17846,7 @@ traffic_send_and_recv_udp(InitState) ->
#{desc => "recv (1)",
cmd => fun(#{sock := Sock,
recv := Recv,
- server_sa := ServerSA} = State) ->
+ server_sa := #{family := local} = ServerSA} = State) ->
case Recv(Sock) of
{ok, {ServerSA, Data}} ->
?SEV_IPRINT("recv ~p bytes", [size(Data)]),
@@ -15463,6 +17854,17 @@ traffic_send_and_recv_udp(InitState) ->
read_byte => size(Data)}};
{error, _} = ERROR ->
ERROR
+ end;
+ (#{sock := Sock,
+ recv := Recv,
+ server_sa := #{addr := Addr, port := Port}} = State) ->
+ case Recv(Sock) of
+ {ok, {#{addr := Addr, port := Port}, Data}} ->
+ ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
+ {ok, State#{read_pkg => 1,
+ read_byte => size(Data)}};
+ {error, _} = ERROR ->
+ ERROR
end
end},
#{desc => "validate (recv 1)",
@@ -15557,7 +17959,7 @@ traffic_send_and_recv_udp(InitState) ->
end},
#{desc => "recv (2)",
cmd => fun(#{sock := Sock,
- server_sa := ServerSA,
+ server_sa := #{family := local} = ServerSA,
recv := Recv,
read_pkg := RPkg,
read_byte := RByte} = State) ->
@@ -15568,6 +17970,19 @@ traffic_send_and_recv_udp(InitState) ->
read_byte => RByte + size(Data)}};
{error, _} = ERROR ->
ERROR
+ end;
+ (#{sock := Sock,
+ server_sa := #{addr := Addr, port := Port},
+ recv := Recv,
+ read_pkg := RPkg,
+ read_byte := RByte} = State) ->
+ case Recv(Sock) of
+ {ok, {#{addr := Addr, port := Port}, Data}} ->
+ ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
+ {ok, State#{read_pkg => RPkg + 1,
+ read_byte => RByte + size(Data)}};
+ {error, _} = ERROR ->
+ ERROR
end
end},
#{desc => "validate (recv 2)",
@@ -17175,12 +19590,12 @@ traffic_ping_pong_small_sendto_and_recvfrom_udp6(suite) ->
traffic_ping_pong_small_sendto_and_recvfrom_udp6(doc) ->
[];
traffic_ping_pong_small_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) ->
- ?TT(?SECS(45)),
Msg = l2b(?TPP_SMALL),
Num = ?TPP_SMALL_NUM,
tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp6,
fun() -> has_support_ipv6() end,
fun() ->
+ ?TT(?SECS(45)),
InitState = #{domain => inet6,
proto => udp,
msg => Msg,
@@ -17204,12 +19619,12 @@ traffic_ping_pong_small_sendto_and_recvfrom_udpL(suite) ->
traffic_ping_pong_small_sendto_and_recvfrom_udpL(doc) ->
[];
traffic_ping_pong_small_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) ->
- ?TT(?SECS(45)),
Msg = l2b(?TPP_SMALL),
Num = ?TPP_SMALL_NUM,
tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udpL,
fun() -> has_support_unix_domain_socket() end,
fun() ->
+ ?TT(?SECS(45)),
InitState = #{domain => local,
proto => default,
msg => Msg,
@@ -17433,7 +19848,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6,
fun() -> has_support_ipv6() end,
fun() ->
- ?TT(?SECS(20)),
+ ?TT(?SECS(30)),
InitState = #{domain => inet6,
proto => tcp,
msg => Msg,
@@ -17461,7 +19876,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL,
fun() -> has_support_unix_domain_socket() end,
fun() ->
- ?TT(?SECS(20)),
+ ?TT(?SECS(30)),
InitState = #{domain => local,
proto => default,
msg => Msg,
@@ -17489,7 +19904,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4,
fun() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end,
fun() ->
- ?TT(?SECS(30)),
+ ?TT(?SECS(60)),
InitState = #{domain => inet,
proto => tcp,
msg => Msg,
@@ -17530,7 +19945,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config)
traffic_ping_pong_large_sendmsg_and_recvmsg_cond()
end,
fun() ->
- ?TT(?SECS(30)),
+ ?TT(?SECS(60)),
InitState = #{domain => inet6,
proto => tcp,
msg => Msg,
@@ -17559,7 +19974,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL,
fun() -> has_support_unix_domain_socket() end,
fun() ->
- ?TT(?SECS(30)),
+ ?TT(?SECS(60)),
InitState = #{domain => local,
proto => default,
msg => Msg,
@@ -17615,7 +20030,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp6,
fun() -> has_support_ipv6() end,
fun() ->
- ?TT(?SECS(30)),
+ ?TT(?SECS(60)),
InitState = #{domain => inet6,
proto => udp,
msg => Msg,
@@ -17643,7 +20058,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udpL,
fun() -> has_support_unix_domain_socket() end,
fun() ->
- ?TT(?SECS(30)),
+ ?TT(?SECS(60)),
InitState = #{domain => local,
proto => default,
msg => Msg,
@@ -17670,7 +20085,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config)
Num = ?TPP_MEDIUM_NUM,
tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4,
fun() ->
- ?TT(?SECS(30)),
+ ?TT(?SECS(60)),
InitState = #{domain => inet,
proto => udp,
msg => Msg,
@@ -17698,7 +20113,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6,
fun() -> has_support_ipv6() end,
fun() ->
- ?TT(?SECS(20)),
+ ?TT(?SECS(60)),
InitState = #{domain => inet6,
proto => udp,
msg => Msg,
@@ -17727,7 +20142,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config)
tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL,
fun() -> has_support_unix_domain_socket() end,
fun() ->
- ?TT(?SECS(20)),
+ ?TT(?SECS(60)),
InitState = #{domain => local,
proto => default,
msg => Msg,
@@ -17799,12 +20214,14 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) ->
?SEV_IPRINT("RcvBuf is ~p (needs atleast ~p)",
[RcvSz, 16+size(Msg)]),
if (RcvSz < size(Msg)) ->
- case socket:setopt(Sock,
- socket, rcvbuf, 1024+size(Msg)) of
+ NewRcvSz = 1024+size(Msg),
+ case socket:setopt(Sock, socket, rcvbuf, NewRcvSz) of
ok ->
ok;
{error, enobufs} ->
- skip({failed_change, rcvbuf});
+ skip(?F("Change ~w buffer size (to ~w) "
+ "not allowed",
+ [rcvbuf, NewRcvSz]));
{error, Reason1} ->
?FAIL({rcvbuf, Reason1})
end;
@@ -17815,12 +20232,14 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) ->
?SEV_IPRINT("SndBuf is ~p (needs atleast ~p)",
[SndSz, 16+size(Msg)]),
if (SndSz < size(Msg)) ->
- case socket:setopt(Sock,
- socket, sndbuf, 1024+size(Msg)) of
+ NewSndSz = 1024+size(Msg),
+ case socket:setopt(Sock, socket, sndbuf, NewSndSz) of
ok ->
ok;
{error, enobufs} ->
- skip({failed_change, sndbuf});
+ skip(?F("Change ~w buffer size (to ~w) "
+ "not allowed",
+ [sndbuf, NewSndSz]));
{error, Reason2} ->
?FAIL({sndbuf, Reason2})
end;
@@ -19408,7 +21827,9 @@ tpp_udp_client_handler_msg_exchange_loop(_Sock, _Dest, _Send, _Recv, _Msg,
Start) ->
Stop = ?LIB:timestamp(),
{Sent, Received, Start, Stop};
-tpp_udp_client_handler_msg_exchange_loop(Sock, Dest, Send, Recv, Data,
+tpp_udp_client_handler_msg_exchange_loop(Sock,
+ #{family := local} = Dest,
+ Send, Recv, Data,
Num, N, Sent, Received, Start) ->
case tpp_udp_send_req(Sock, Send, Data, Dest) of
{ok, SendSz} ->
@@ -19427,6 +21848,28 @@ tpp_udp_client_handler_msg_exchange_loop(Sock, Dest, Send, Recv, Data,
{error, SReason} ->
?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]),
exit({send, SReason, N})
+ end;
+tpp_udp_client_handler_msg_exchange_loop(Sock,
+ #{addr := Addr, port := Port} = Dest0,
+ Send, Recv, Data,
+ Num, N, Sent, Received, Start) ->
+ case tpp_udp_send_req(Sock, Send, Data, Dest0) of
+ {ok, SendSz} ->
+ case tpp_udp_recv_rep(Sock, Recv) of
+ {ok, NewData, RecvSz, #{addr := Addr, port := Port} = Dest1} ->
+ tpp_udp_client_handler_msg_exchange_loop(Sock, Dest1,
+ Send, Recv,
+ NewData, Num, N+1,
+ Sent+SendSz,
+ Received+RecvSz,
+ Start);
+ {error, RReason} ->
+ ?SEV_EPRINT("recv (~w of ~w): ~p", [N, Num, RReason]),
+ exit({recv, RReason, N})
+ end;
+ {error, SReason} ->
+ ?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]),
+ exit({send, SReason, N})
end.
@@ -25450,7 +27893,7 @@ ttest_tcp(TC,
fun() ->
if
(Domain =:= local) -> has_support_unix_domain_socket();
- (Domain =:= inet6) -> has_support_ipv6();
+ (Domain =:= inet6) -> has_support_ipv6();
true -> ok
end
end,
@@ -25913,16 +28356,22 @@ ttest_tcp(InitState) ->
?SEV_FINISH_NORMAL
],
+ Domain = maps:get(domain, InitState),
+ LHost = local_host(),
+ LAddr = which_local_addr(Domain),
+
i("start server evaluator"),
- ServerInitState = #{host => local_host(),
- domain => maps:get(domain, InitState),
+ ServerInitState = #{host => LHost,
+ addr => LAddr,
+ domain => Domain,
mod => maps:get(server_mod, InitState),
active => maps:get(server_active, InitState)},
Server = ?SEV_START("server", ServerSeq, ServerInitState),
i("start client evaluator"),
- ClientInitState = #{host => local_host(),
- domain => maps:get(domain, InitState),
+ ClientInitState = #{host => LHost,
+ addr => LAddr,
+ domain => Domain,
mod => maps:get(client_mod, InitState),
active => maps:get(client_active, InitState),
msg_id => maps:get(msg_id, InitState),
@@ -25931,9 +28380,14 @@ ttest_tcp(InitState) ->
Client = ?SEV_START("client", ClientSeq, ClientInitState),
i("start 'tester' evaluator"),
- TesterInitState = #{domain => maps:get(domain, InitState),
- server => Server#ev.pid,
- client => Client#ev.pid},
+ TesterInitState = #{domain => Domain,
+ msg_id => maps:get(msg_id, InitState),
+ client => Client#ev.pid,
+ client_mod => maps:get(client_mod, InitState),
+ client_active => maps:get(client_active, InitState),
+ server => Server#ev.pid,
+ server_mod => maps:get(server_mod, InitState),
+ server_active => maps:get(server_active, InitState)},
Tester = ?SEV_START("tester", TesterSeq, TesterInitState),
i("await evaluator(s)"),
@@ -25941,8 +28395,9 @@ ttest_tcp(InitState) ->
-ttest_tcp_server_start(Node, _Domain, gen, Active) ->
- Transport = socket_test_ttest_tcp_gen,
+ttest_tcp_server_start(Node, Domain, gen, Active) ->
+ TransportMod = socket_test_ttest_tcp_gen,
+ Transport = {TransportMod, #{domain => Domain}},
socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active);
ttest_tcp_server_start(Node, Domain, sock, Active) ->
TransportMod = socket_test_ttest_tcp_socket,
@@ -25956,9 +28411,10 @@ ttest_tcp_server_stop(Pid) ->
ttest_tcp_client_start(Node,
Notify,
- _Domain, gen,
+ Domain, gen,
ServerInfo, Active, MsgID, MaxOutstanding, RunTime) ->
- Transport = socket_test_ttest_tcp_gen,
+ TransportMod = socket_test_ttest_tcp_gen,
+ Transport = {TransportMod, #{domain => Domain}},
socket_test_ttest_tcp_client:start_monitor(Node,
Notify,
Transport,
@@ -26253,39 +28709,6 @@ sock_sockname(Sock) ->
?FAIL({sockname, C, E, S})
end.
-
-%% sock_listen(Sock) ->
-%% sock_listen2(fun() -> socket:listen(Sock) end).
-
-%% sock_listen(Sock, BackLog) ->
-%% sock_listen2(fun() -> socket:listen(Sock, BackLog) end).
-
-%% sock_listen2(Listen) ->
-%% try Listen() of
-%% ok ->
-%% ok;
-%% {error, Reason} ->
-%% ?FAIL({listen, Reason})
-%% catch
-%% C:E:S ->
-%% ?FAIL({listen, C, E, S})
-%% end.
-
-
-%% sock_accept(LSock) ->
-%% try socket:accept(LSock) of
-%% {ok, Sock} ->
-%% Sock;
-%% {error, Reason} ->
-%% i("sock_accept -> error: ~p", [Reason]),
-%% ?FAIL({accept, Reason})
-%% catch
-%% C:E:S ->
-%% i("sock_accept -> failed: ~p, ~p, ~p", [C, E, S]),
-%% ?FAIL({accept, C, E, S})
-%% end.
-
-
sock_close(Sock) ->
try socket:close(Sock) of
ok ->
@@ -26351,12 +28774,12 @@ which_local_socket_addr(local = Domain) ->
#{family => Domain,
path => mk_unique_path()};
-%% This gets the local address (not 127.0...)
+%% This gets the local socket address (not 127.0...)
%% We should really implement this using the (new) net module,
%% but until that gets the necessary functionality...
which_local_socket_addr(Domain) ->
- case which_local_host_info(Domain) of
- {ok, {_Name, _Flags, Addr}} ->
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, #{addr := Addr}} ->
#{family => Domain,
addr => Addr};
{error, Reason} ->
@@ -26364,55 +28787,15 @@ which_local_socket_addr(Domain) ->
end.
-%% Returns the interface (name), flags and address (not 127...)
-%% of the local host.
-which_local_host_info(Domain) ->
- case inet:getifaddrs() of
- {ok, IFL} ->
- which_local_host_info(Domain, IFL);
- {error, _} = ERROR ->
- ERROR
- end.
-
-which_local_host_info(_Domain, []) ->
- ?FAIL(no_address);
-which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) ->
- which_local_host_info(Domain, IFL);
-which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) ->
- which_local_host_info(Domain, IFL);
-which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) ->
- which_local_host_info(Domain, IFL);
-which_local_host_info(Domain, [{Name, IFO}|IFL]) ->
- case which_local_host_info2(Domain, IFO) of
- {ok, {Flags, Addr}} ->
- {ok, {Name, Flags, Addr}};
- {error, _} ->
- which_local_host_info(Domain, IFL)
- end;
-which_local_host_info(Domain, [_|IFL]) ->
- which_local_host_info(Domain, IFL).
-
-which_local_host_info2(Domain, IFO) ->
- case lists:keysearch(flags, 1, IFO) of
- {value, {flags, Flags}} ->
- which_local_host_info2(Domain, IFO, Flags);
- false ->
- {error, no_flags}
- end.
-which_local_host_info2(_Domain, [], _Flags) ->
- {error, no_address};
-which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags)
- when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) ->
- {ok, {Flags, Addr}};
-which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags)
- when (size(Addr) =:= 8) andalso
- (element(1, Addr) =/= 0) andalso
- (element(1, Addr) =/= 16#fe80) ->
- {ok, {Flags, Addr}};
-which_local_host_info2(Domain, [_|IFO], Flags) ->
- which_local_host_info2(Domain, IFO, Flags).
+which_local_addr(local = _Domain) ->
+ mk_unique_path();
+%% This gets the local address (not 127.0...)
+%% We should really implement this using the (new) net module,
+%% but until that gets the necessary functionality...
+which_local_addr(Domain) ->
+ ?LIB:which_local_addr(Domain).
@@ -26425,12 +28808,12 @@ which_local_host_info2(Domain, [_|IFO], Flags) ->
%% We don't do that here, but since we can only do that (find a
%% multicast address) for specific platforms, we check that we are
%% on of those platforms here.
-has_ip_multicast_support() ->
+has_support_ip_multicast() ->
case os:type() of
{unix, OsName} when (OsName =:= linux) orelse
(OsName =:= sunos) ->
- case which_local_host_info(inet) of
- {ok, {_Name, Flags, _Addr}} ->
+ case ?LIB:which_local_host_info(inet) of
+ {ok, #{flags := Flags}} ->
case lists:member(multicast, Flags) of
true ->
ok;
@@ -26440,26 +28823,64 @@ has_ip_multicast_support() ->
{error, Reason} ->
not_supported({multicast, Reason})
end;
+ {unix, OsName} ->
+ skip(?F("Not Supported: platform ~w", [OsName]));
Type ->
- not_supported({multicast, Type})
+ skip(?F("Not Supported: platform ~p", [Type]))
end.
-has_ip_add_membership_support() ->
- has_socket_option_ip_support(add_membership).
+has_support_sock_acceptconn() ->
+ has_support_socket_option_sock(acceptconn).
+
+has_support_sock_bindtodevice() ->
+ has_support_socket_option_sock(bindtodevice).
+
+has_support_sock_broadcast() ->
+ has_support_socket_option_sock(broadcast),
+ case ?LIB:which_local_host_info(inet) of
+ {ok, #{flags := Flags}} ->
+ case lists:member(broadcast, Flags) of
+ true ->
+ ok;
+ false ->
+ not_supported({broadcast, Flags})
+ end;
+ {error, Reason} ->
+ not_supported({broadcast, Reason})
+ end.
+
+has_support_sock_debug() ->
+ has_support_socket_option_sock(debug).
+
+has_support_sock_domain() ->
+ has_support_socket_option_sock(domain).
+
+has_support_sock_dontroute() ->
+ has_support_socket_option_sock(dontroute).
+
+has_support_sock_keepalive() ->
+ has_support_socket_option_sock(keepalive).
+
+
+has_support_ip_add_membership() ->
+ has_support_socket_option_ip(add_membership).
+
+has_support_ip_drop_membership() ->
+ has_support_socket_option_ip(drop_membership).
-has_ip_drop_membership_support() ->
- has_socket_option_ip_support(drop_membership).
+has_support_socket_option_ip(Opt) ->
+ has_support_socket_option(ip, Opt).
-has_socket_option_ip_support(Opt) ->
- has_socket_option_support(ip, Opt).
+has_support_socket_option_sock(Opt) ->
+ has_support_socket_option(socket, Opt).
-has_socket_option_support(Level, Option) ->
+has_support_socket_option(Level, Option) ->
case socket:supports(options, Level, Option) of
true ->
ok;
false ->
- not_supported({options, Level, Option})
+ skip(?F("Not Supported: ~w option ~w", [Level, Option]))
end.
@@ -26491,13 +28912,7 @@ has_support_unix_domain_socket() ->
%% support for IPv6. If not, there is no point in running IPv6 tests.
%% Currently we just skip.
has_support_ipv6() ->
- %% case socket:supports(ipv6) of
- %% true ->
- %% ok;
- %% false ->
- %% {error, not_supported}
- %% end.
- not_yet_implemented().
+ ?LIB:has_support_ipv6().
diff --git a/erts/emulator/test/socket_test_lib.erl b/erts/emulator/test/socket_test_lib.erl
index 4e65c4f3c0..39cbf0c79f 100644
--- a/erts/emulator/test/socket_test_lib.erl
+++ b/erts/emulator/test/socket_test_lib.erl
@@ -32,6 +32,12 @@
%% String and format
f/2,
+ %% Generic 'has support' test function(s)
+ has_support_ipv6/0,
+
+ which_local_host_info/1,
+ which_local_addr/1,
+
%% Skipping
not_yet_implemented/0,
skip/1
@@ -40,6 +46,11 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-define(FAIL(R), exit(R)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
pi(Item) when is_atom(Item) ->
pi(self(), Item).
@@ -88,6 +99,196 @@ f(F, A) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+has_support_ipv6() ->
+ case socket:supports(ipv6) of
+ true ->
+ ok;
+ false ->
+ skip("IPv6 Not Supported")
+ end,
+ Domain = inet6,
+ LocalAddr =
+ case which_local_addr(Domain) of
+ {ok, Addr} ->
+ Addr;
+ {error, R1} ->
+ skip(f("Local Address eval failed: ~p", [R1]))
+ end,
+ ServerSock =
+ case socket:open(Domain, dgram, udp) of
+ {ok, SS} ->
+ SS;
+ {error, R2} ->
+ skip(f("(server) socket open failed: ~p", [R2]))
+ end,
+ LocalSA = #{family => Domain, addr => LocalAddr},
+ ServerPort =
+ case socket:bind(ServerSock, LocalSA) of
+ {ok, P1} ->
+ P1;
+ {error, R3} ->
+ socket:close(ServerSock),
+ skip(f("(server) socket bind failed: ~p", [R3]))
+ end,
+ ServerSA = LocalSA#{port => ServerPort},
+ ClientSock =
+ case socket:open(Domain, dgram, udp) of
+ {ok, CS} ->
+ CS;
+ {error, R4} ->
+ skip(f("(client) socket open failed: ~p", [R4]))
+ end,
+ case socket:bind(ClientSock, LocalSA) of
+ {ok, _} ->
+ ok;
+ {error, R5} ->
+ socket:close(ServerSock),
+ socket:close(ClientSock),
+ skip(f("(client) socket bind failed: ~p", [R5]))
+ end,
+ case socket:sendto(ClientSock, <<"hejsan">>, ServerSA) of
+ ok ->
+ ok;
+ {error, R6} ->
+ socket:close(ServerSock),
+ socket:close(ClientSock),
+ skip(f("failed socket sendto test: ~p", [R6]))
+ end,
+ case socket:recvfrom(ServerSock) of
+ {ok, {_, <<"hejsan">>}} ->
+ socket:close(ServerSock),
+ socket:close(ClientSock),
+ ok;
+ {error, R7} ->
+ socket:close(ServerSock),
+ socket:close(ClientSock),
+ skip(f("failed socket recvfrom test: ~p", [R7]))
+ end.
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% This gets the local address (not {127, _} or {0, ...} or {16#fe80, ...})
+%% We should really implement this using the (new) net module,
+%% but until that gets the necessary functionality...
+which_local_addr(Domain) ->
+ case which_local_host_info(Domain) of
+ {ok, #{addr := Addr}} ->
+ {ok, Addr};
+ {error, _Reason} = ERROR ->
+ ERROR
+ end.
+
+
+%% Returns the interface (name), flags and address (not 127...)
+%% of the local host.
+which_local_host_info(Domain) ->
+ case inet:getifaddrs() of
+ {ok, IFL} ->
+ which_local_host_info(Domain, IFL);
+ {error, _} = ERROR ->
+ ERROR
+ end.
+
+which_local_host_info(_Domain, []) ->
+ {error, no_address};
+which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) ->
+ which_local_host_info(Domain, IFL);
+which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) ->
+ which_local_host_info(Domain, IFL);
+which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) ->
+ which_local_host_info(Domain, IFL);
+which_local_host_info(Domain, [{Name, IFO}|IFL]) ->
+ try which_local_host_info2(Domain, IFO) of
+ Info ->
+ {ok, Info#{name => Name}}
+ catch
+ throw:_:_ ->
+ which_local_host_info(Domain, IFL)
+ end;
+which_local_host_info(Domain, [_|IFL]) ->
+ which_local_host_info(Domain, IFL).
+
+%% which_local_host_info2(Domain, IFO) ->
+%% case lists:keysearch(flags, 1, IFO) of
+%% {value, {flags, Flags}} ->
+%% which_local_host_info2(Domain, IFO, Flags);
+%% false ->
+%% {error, no_flags}
+%% end.
+
+
+%% which_local_host_info2(_Domain, [], _Flags) ->
+%% {error, no_address};
+%% which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags)
+%% when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) ->
+%% {ok, {Flags, Addr}};
+%% which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags)
+%% when (size(Addr) =:= 8) andalso
+%% (element(1, Addr) =/= 0) andalso
+%% (element(1, Addr) =/= 16#fe80) ->
+%% {ok, {Flags, Addr}};
+%% which_local_host_info2(Domain, [_|IFO], Flags) ->
+%% which_local_host_info2(Domain, IFO, Flags).
+
+%% foo(Info, inet = Domain, IFO) ->
+%% foo(Info, Domain, IFO, [flags, addr, netmask, broadaddr, hwaddr]);
+%% foo(Info, inet6 = Domain, IFO) ->
+%% foo(Info, Domain, IFO, [flags, addr, netmask, hwaddr]).
+
+which_local_host_info2(inet = _Domain, IFO) ->
+ Addr = which_local_host_info3(addr, IFO,
+ fun({A, _, _, _}) when (A =/= 127) -> true;
+ (_) -> false
+ end),
+ NetMask = which_local_host_info3(netmask, IFO,
+ fun({_, _, _, _}) -> true;
+ (_) -> false
+ end),
+ BroadAddr = which_local_host_info3(broadaddr, IFO,
+ fun({_, _, _, _}) -> true;
+ (_) -> false
+ end),
+ Flags = which_local_host_info3(flags, IFO, fun(_) -> true end),
+ #{flags => Flags,
+ addr => Addr,
+ broadaddr => BroadAddr,
+ netmask => NetMask};
+which_local_host_info2(inet6 = _Domain, IFO) ->
+ Addr = which_local_host_info3(addr, IFO,
+ fun({A, _, _, _, _, _, _, _})
+ when (A =/= 0) andalso
+ (A =/= 16#fe80) -> true;
+ (_) -> false
+ end),
+ NetMask = which_local_host_info3(netmask, IFO,
+ fun({_, _, _, _, _, _, _, _}) -> true;
+ (_) -> false
+ end),
+ Flags = which_local_host_info3(flags, IFO, fun(_) -> true end),
+ #{flags => Flags,
+ addr => Addr,
+ netmask => NetMask}.
+
+which_local_host_info3(_Key, [], _) ->
+ throw({error, no_address});
+which_local_host_info3(Key, [{Key, Val}|IFO], Check) ->
+ case Check(Val) of
+ true ->
+ Val;
+ false ->
+ which_local_host_info3(Key, IFO, Check)
+ end;
+which_local_host_info3(Key, [_|IFO], Check) ->
+ which_local_host_info3(Key, IFO, Check).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
not_yet_implemented() ->
skip("not yet implemented").
diff --git a/erts/emulator/test/socket_test_ttest_tcp_client.erl b/erts/emulator/test/socket_test_ttest_tcp_client.erl
index b5c5300fd0..f28819ca69 100644
--- a/erts/emulator/test/socket_test_ttest_tcp_client.erl
+++ b/erts/emulator/test/socket_test_ttest_tcp_client.erl
@@ -266,8 +266,9 @@ init(Quiet,
(catch Mod:close(Sock)),
exit(normal);
{error, Reason} ->
- ?E("connect failed: ~p", [Reason]),
- exit({connect, Reason})
+ ?E("connect failed: ~p"
+ "~n ~p", [Reason, ServerInfo]),
+ exit({connect, Reason, ServerInfo})
end.
process_transport(Mod) when is_atom(Mod) ->
diff --git a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl
index ca7eff4437..2fb1242028 100644
--- a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl
+++ b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl
@@ -34,24 +34,24 @@ start(Method, Async, Active, ServerInfo)
when is_list(ServerInfo) ->
Domain = local,
socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Async, Method),
- Active, ServerInfo);
+ ServerInfo, Active);
start(Method, Async, Active, ServerInfo = {Addr, _})
when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
Domain = inet,
socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Async, Method),
- Active, ServerInfo);
+ ServerInfo, Active);
start(Method, Async, Active, ServerInfo = {Addr, _})
when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
Domain = inet6,
socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Async, Method),
- Active, ServerInfo).
+ ServerInfo, Active).
start(Method, Async, Active, ServerInfo, MsgID)
when is_list(ServerInfo) ->
%% This is just a simplification
Domain = local,
socket_test_ttest_tcp_client:start(?MOD(Domain, Async, Method),
- Active, ServerInfo, MsgID);
+ ServerInfo, Active, MsgID);
start(Method, Async, Active, ServerInfo = {Addr, _}, MsgID)
when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
%% This is just a simplification
@@ -62,14 +62,14 @@ start(Method, Async, Active, ServerInfo = {Addr, _}, MsgID)
when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
Domain = inet6,
socket_test_ttest_tcp_client:start(?MOD(Domain, Async, Method),
- Active, ServerInfo, MsgID).
+ ServerInfo, Active, MsgID).
start(Method, Async, Active, ServerInfo, MsgID, MaxOutstanding, RunTime)
when is_list(ServerInfo) ->
Domain = local,
socket_test_ttest_tcp_client:start(false,
?MOD(Domain, Async, Method),
- Active, ServerInfo,
+ ServerInfo, Active,
MsgID, MaxOutstanding, RunTime);
start(Method, Async, Active, ServerInfo = {Addr, _},
MsgID, MaxOutstanding, RunTime)
@@ -77,7 +77,7 @@ start(Method, Async, Active, ServerInfo = {Addr, _},
Domain = inet,
socket_test_ttest_tcp_client:start(false,
?MOD(Domain, Async, Method),
- Active, ServerInfo,
+ ServerInfo, Active,
MsgID, MaxOutstanding, RunTime);
start(Method, Async, Active, ServerInfo = {Addr, _},
MsgID, MaxOutstanding, RunTime)
@@ -85,7 +85,7 @@ start(Method, Async, Active, ServerInfo = {Addr, _},
Domain = inet6,
socket_test_ttest_tcp_client:start(false,
?MOD(Domain, Async, Method),
- Active, ServerInfo,
+ ServerInfo, Active,
MsgID, MaxOutstanding, RunTime).
start(Quiet, Async, Active, Method, ServerInfo, MsgID, MaxOutstanding, RunTime)
@@ -93,7 +93,7 @@ start(Quiet, Async, Active, Method, ServerInfo, MsgID, MaxOutstanding, RunTime)
Domain = local,
socket_test_ttest_tcp_client:start(Quiet,
?MOD(Domain, Async, Method),
- Active, ServerInfo,
+ ServerInfo, Active,
MsgID, MaxOutstanding, RunTime);
start(Quiet, Async, Active, Method, ServerInfo = {Addr, _},
MsgID, MaxOutstanding, RunTime)
@@ -101,7 +101,7 @@ start(Quiet, Async, Active, Method, ServerInfo = {Addr, _},
Domain = inet,
socket_test_ttest_tcp_client:start(Quiet,
?MOD(Domain, Async, Method),
- Active, ServerInfo,
+ ServerInfo, Active,
MsgID, MaxOutstanding, RunTime);
start(Quiet, Async, Active, Method, ServerInfo = {Addr, _},
MsgID, MaxOutstanding, RunTime)
@@ -109,7 +109,7 @@ start(Quiet, Async, Active, Method, ServerInfo = {Addr, _},
Domain = inet6,
socket_test_ttest_tcp_client:start(Quiet,
?MOD(Domain, Async, Method),
- Active, ServerInfo,
+ ServerInfo, Active,
MsgID, MaxOutstanding, RunTime).
stop(Pid) ->
diff --git a/erts/emulator/test/socket_test_ttest_tcp_gen.erl b/erts/emulator/test/socket_test_ttest_tcp_gen.erl
index 05b250e3d9..e59bd881e7 100644
--- a/erts/emulator/test/socket_test_ttest_tcp_gen.erl
+++ b/erts/emulator/test/socket_test_ttest_tcp_gen.erl
@@ -36,19 +36,7 @@
]).
-%% ==========================================================================
-
-%% getopt(Sock, Opt) when is_atom(Opt) ->
-%% case inet:getopts(Sock, [Opt]) of
-%% {ok, [{Opt, Value}]} ->
-%% {ok, Value};
-%% {error, _} = ERROR ->
-%% ERROR
-%% end.
-
-%% setopt(Sock, Opt, Value) when is_atom(Opt) ->
-%% inet:setopts(Sock, [{Opt, Value}]).
-
+-define(LIB, socket_test_lib).
%% ==========================================================================
@@ -106,12 +94,12 @@ listen(Port) ->
listen(Port, #{domain => inet}).
listen(Port, #{domain := Domain}) when is_integer(Port) andalso (Port >= 0) ->
- Opts = [Domain,
- binary, {ip, {0,0,0,0}}, {packet, raw}, {active, false},
- {buffer, 32*1024}],
- case gen_tcp:listen(Port, Opts) of
- {ok, Sock} ->
- {ok, Sock};
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, {_, _, Addr}} ->
+ Opts = [Domain,
+ binary, {ip, Addr}, {packet, raw}, {active, false},
+ {buffer, 32*1024}],
+ gen_tcp:listen(Port, Opts);
{error, _} = ERROR ->
ERROR
end.
diff --git a/erts/emulator/test/socket_test_ttest_tcp_server.erl b/erts/emulator/test/socket_test_ttest_tcp_server.erl
index 27b561d4b7..2394dc7924 100644
--- a/erts/emulator/test/socket_test_ttest_tcp_server.erl
+++ b/erts/emulator/test/socket_test_ttest_tcp_server.erl
@@ -134,12 +134,18 @@ server_init(Starter, Parent, Transport, Active) ->
if
is_integer(PortOrPath) ->
%% This is just for convenience
- Addr = which_addr(),
- ?I("listening on:"
- "~n Addr: ~p (~s)"
- "~n Port: ~w"
- "~n", [Addr, inet:ntoa(Addr), PortOrPath]),
- {Addr, PortOrPath};
+ case Mod:sockname(LSock) of
+ {ok, {Addr, _}} ->
+ ?I("listening on:"
+ "~n Addr: ~p (~s)"
+ "~n Port: ~w"
+ "~n", [Addr,
+ inet:ntoa(Addr),
+ PortOrPath]),
+ {Addr, PortOrPath};
+ {error, SNReason} ->
+ exit({sockname, SNReason})
+ end;
is_list(PortOrPath) ->
?I("listening on:"
"~n Path: ~s"
@@ -569,51 +575,51 @@ handler_maybe_activate(_, _, _) ->
%% ==========================================================================
-which_addr() ->
- case inet:getifaddrs() of
- {ok, IfAddrs} ->
- which_addrs(inet, IfAddrs);
- {error, Reason} ->
- exit({getifaddrs, Reason})
- end.
+%% which_addr() ->
+%% case inet:getifaddrs() of
+%% {ok, IfAddrs} ->
+%% which_addrs(inet, IfAddrs);
+%% {error, Reason} ->
+%% exit({getifaddrs, Reason})
+%% end.
-which_addrs(_Family, []) ->
- exit({getifaddrs, not_found});
-which_addrs(Family, [{"lo", _} | IfAddrs]) ->
- %% Skip
- which_addrs(Family, IfAddrs);
-which_addrs(Family, [{"docker" ++ _, _} | IfAddrs]) ->
- %% Skip docker
- which_addrs(Family, IfAddrs);
-which_addrs(Family, [{"br-" ++ _, _} | IfAddrs]) ->
- %% Skip docker
- which_addrs(Family, IfAddrs);
-which_addrs(Family, [{"en" ++ _, IfOpts} | IfAddrs]) ->
- %% Maybe take this one
- case which_addr(Family, IfOpts) of
- {ok, Addr} ->
- Addr;
- error ->
- which_addrs(Family, IfAddrs)
- end;
-which_addrs(Family, [{_IfName, IfOpts} | IfAddrs]) ->
- case which_addr(Family, IfOpts) of
- {ok, Addr} ->
- Addr;
- error ->
- which_addrs(Family, IfAddrs)
- end.
+%% which_addrs(_Family, []) ->
+%% exit({getifaddrs, not_found});
+%% which_addrs(Family, [{"lo", _} | IfAddrs]) ->
+%% %% Skip
+%% which_addrs(Family, IfAddrs);
+%% which_addrs(Family, [{"docker" ++ _, _} | IfAddrs]) ->
+%% %% Skip docker
+%% which_addrs(Family, IfAddrs);
+%% which_addrs(Family, [{"br-" ++ _, _} | IfAddrs]) ->
+%% %% Skip docker
+%% which_addrs(Family, IfAddrs);
+%% which_addrs(Family, [{"en" ++ _, IfOpts} | IfAddrs]) ->
+%% %% Maybe take this one
+%% case which_addr(Family, IfOpts) of
+%% {ok, Addr} ->
+%% Addr;
+%% error ->
+%% which_addrs(Family, IfAddrs)
+%% end;
+%% which_addrs(Family, [{_IfName, IfOpts} | IfAddrs]) ->
+%% case which_addr(Family, IfOpts) of
+%% {ok, Addr} ->
+%% Addr;
+%% error ->
+%% which_addrs(Family, IfAddrs)
+%% end.
-which_addr(_, []) ->
- error;
-which_addr(inet, [{addr, Addr}|_])
- when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
- {ok, Addr};
-which_addr(inet6, [{addr, Addr}|_])
- when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
- {ok, Addr};
-which_addr(Family, [_|IfOpts]) ->
- which_addr(Family, IfOpts).
+%% which_addr(_, []) ->
+%% error;
+%% which_addr(inet, [{addr, Addr}|_])
+%% when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
+%% {ok, Addr};
+%% which_addr(inet6, [{addr, Addr}|_])
+%% when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
+%% {ok, Addr};
+%% which_addr(Family, [_|IfOpts]) ->
+%% which_addr(Family, IfOpts).
%% ==========================================================================
diff --git a/erts/emulator/test/socket_test_ttest_tcp_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_socket.erl
index 3aa3b2c504..9112748b4c 100644
--- a/erts/emulator/test/socket_test_ttest_tcp_socket.erl
+++ b/erts/emulator/test/socket_test_ttest_tcp_socket.erl
@@ -247,10 +247,16 @@ listen(Path, #{domain := local = Domain} = Opts)
listen(Port, #{domain := Domain} = Opts)
when is_integer(Port) andalso (Port >= 0) ->
%% Bind fills in the rest
- SA = #{family => Domain,
- port => Port},
- Cleanup = fun() -> ok end,
- do_listen(SA, Cleanup, Opts#{proto => tcp}).
+ case ?LIB:which_local_host_info(Domain) of
+ {ok, {_, _, Addr}} ->
+ SA = #{family => Domain,
+ addr => Addr,
+ port => Port},
+ Cleanup = fun() -> ok end,
+ do_listen(SA, Cleanup, Opts#{proto => tcp});
+ {error, _} = ERROR ->
+ ERROR
+ end.
do_listen(SA,
Cleanup,
diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in
index 8b6abb5336..20809d61e8 100644
--- a/erts/etc/unix/etp-commands.in
+++ b/erts/etc/unix/etp-commands.in
@@ -3993,22 +3993,79 @@ end
# ETS table debug
#
+define etp-ets-tab-status-int
+# Args:
+#
+# Non-reentrant
+ if ($arg0 & 0x1)
+ printf "priv"
+ end
+ if ($arg0 & 0x2)
+ printf "prot"
+ end
+ if ($arg0 & 0x4)
+ printf "pub"
+ end
+ if ($arg0 & 0x8)
+ printf "|del"
+ end
+ if ($arg0 & 0x10)
+ printf "|set"
+ end
+ if ($arg0 & 0x20)
+ printf "|bag"
+ end
+ if ($arg0 & 0x40)
+ printf "|dbag"
+ end
+ if ($arg0 & 0x80)
+ printf "|oset"
+ end
+ if ($arg0 & 0x100)
+ printf "|caoset"
+ end
+ if ($arg0 & 0x200)
+ printf "|flocked"
+ end
+ if ($arg0 & 0x400)
+ printf "|fread"
+ end
+ if ($arg0 & 0x800)
+ printf "|named"
+ end
+ if ($arg0 & 0x1000)
+ printf "|busy"
+ end
+end
+
define etp-ets-tables
# Args:
#
# Non-reentrant
- printf "%% Dumping < %lu ETS tables\n", (unsigned long)db_max_tabs
- while $etp_ets_tables_i < db_max_tabs
- if (meta_main_tab[$etp_ets_tables_i].u.next_free & 3) == 0
- printf "%% %d:", $etp_ets_tables_i
- etp-1 ((Eterm)(meta_main_tab[$etp_ets_tables_i].u.tb->common.id)) 0
+ set $sched_ix = 0
+ while $sched_ix < erts_no_schedulers
+ set $ets_tabs = &erts_aligned_scheduler_data[$sched_ix].esd.ets_tables
+ set $no_ets_tabs = *(unsigned long *)&($ets_tabs->count)
+ printf "\n%% %lu ETS tables created on scheduler %lu...\n\n", $no_ets_tabs, (unsigned long)$sched_ix+1
+ set $ets_tab = $ets_tabs->clist
+ set $first_ets_tab = $ets_tab
+ while $ets_tab
+ set $refn = &((ErtsMagicBinary *)$ets_tab->common->btid)->refn
+ printf "%% "
+ etp-1 $ets_tab->common.the_name 0
+ printf " #Ref<0.%u.%u.%u> ", (unsigned)$refn[2], (unsigned)$refn[1], (unsigned)$refn[0]
+ etp-1 $ets_tab->common.owner 0
printf " "
- etp-1 ((Eterm)(meta_main_tab[$etp_ets_tables_i].u.tb->common.owner)) 0
- printf "\n"
+ etp-ets-tab-status-int $ets_tab->common.status
+ printf " (DbTable*)%p\n", $ets_tab
+ if $ets_tab->common.all.next == $first_ets_tab
+ set $ets_tab = (DbTable *) 0
+ else
+ set $ets_tab = $ets_tab->common.all.next
+ end
end
- set $etp_ets_tables_i++
+ set $sched_ix++
end
- set $etp_ets_tables_i = 0
end
document etp-ets-tables
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c
index b4b12fcd86..b567ed81b0 100644
--- a/erts/lib_src/pthread/ethread.c
+++ b/erts/lib_src/pthread/ethread.c
@@ -208,9 +208,9 @@ ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx)
"popl %%eax\n\t"
"movl $0x0, %0\n\t"
"xorl %%ecx, %%eax\n\t"
- "jz no_cpuid\n\t"
+ "jz 1f\n\t"
"movl $0x1, %0\n\t"
- "no_cpuid:\n\t"
+ "1:\n\t"
: "=r"(have_cpuid)
:
: "%eax", "%ecx", "cc");
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index f67b660a08..f77e9e863d 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index 25eb0b2f4a..73a0bd4f72 100644
--- a/erts/preloaded/ebin/socket.beam
+++ b/erts/preloaded/ebin/socket.beam
Binary files differ
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index e1bb2ee5c4..38b85915cc 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -95,6 +95,15 @@ ERL_COMPILE_FLAGS += +debug_info -I$(KERNEL_SRC) -I$(KERNEL_INCLUDE)
DIA_PLT = erts-preloaded.plt
DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+ifeq ($(DIAW_EH),true)
+DIA_WARNINGS += -Werror_handling
+endif
+ifeq ($(DIAW_US),true)
+DIA_WARNINGS += -Wunderspecs
+endif
+ifeq ($(DIAW_UR),true)
+DIA_WARNINGS += -Wunmatched_returns
+endif
debug opt: $(TARGET_FILES)
@@ -144,6 +153,7 @@ dialyzer: $(DIA_PLT)
@echo "Running dialyzer on $(basename $(DIA_PLT))"
@dialyzer --plt $< \
../ebin \
+ $(DIA_WARNINGS) \
--verbose
#
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 374facb2a3..4dab3de006 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -427,7 +427,7 @@ accept_opts(L, S, FamilyOpts) ->
case
getopts(
L,
- [active, nodelay, keepalive, delay_send, priority]
+ [active, nodelay, keepalive, delay_send, priority, linger]
++ FamilyOpts)
of
{ok, Opts} ->
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl
index be94e3a867..07e720c44d 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -313,7 +313,8 @@
path := binary() | string()}.
-type sockaddr_in4() :: #{family := inet,
port := port_number(),
- addr := any | loopback | ip4_address()}.
+ %% The 'broadcast' here is the "limited broadcast"
+ addr := any | broadcast | loopback | ip4_address()}.
-type sockaddr_in6() :: #{family := inet6,
port := port_number(),
addr := any | loopback | ip6_address(),
@@ -334,7 +335,7 @@
-define(SOCKADDR_IN6_DEFAULTS, ?SOCKADDR_IN6_DEFAULTS(any)).
-define(SOCKADDR_IN6_DEFAULT(A), (?SOCKADDR_IN6_DEFAULTS(A))#{family => inet6}).
-%% otp - The option is internal to our (OTP) imeplementation.
+%% otp - This option is internal to our (OTP) implementation.
%% socket - The socket layer (SOL_SOCKET).
%% ip - The IP layer (SOL_IP or is it IPPROTO_IP?).
%% ipv6 - The IPv6 layer (SOL_IPV6).
@@ -342,6 +343,7 @@
%% udp - The UDP (User Datagram Protocol) layer (IPPROTO_UDP).
%% sctp - The SCTP (Stream Control Transmission Protocol) layer (IPPROTO_SCTP).
%% Int - Raw level, sent down and used "as is".
+%% Its up to the caller to make sure this is correct!
-type sockopt_level() :: otp |
socket |
ip | ipv6 | tcp | udp | sctp |
@@ -625,11 +627,11 @@
-opaque select_tag() :: atom().
-opaque select_ref() :: reference().
--record(select_info, {tag :: select_tag(), ref :: select_ref()}).
+%% -record(select_info, {tag :: select_tag(), ref :: select_ref()}).
--type select_info() :: #select_info{}.
+-type select_info() :: {select_info, select_tag(), select_ref()}.
--define(SELECT_INFO(T, R), #select_info{tag = T, ref = R}).
+-define(SELECT_INFO(T, R), {select_info, T, R}).
-define(SELECT(T, R), {select, ?SELECT_INFO(T, R)}).
@@ -1146,19 +1148,25 @@ open(Domain, Type, Protocol, Extra) when is_map(Extra) ->
%%
%% bind - bind a name to a socket
%%
+%% Note that Addr can only have the value of broadcast *if* Domain =:= inet!
+%%
-spec bind(Socket, Addr) -> ok | {error, Reason} when
Socket :: socket(),
- Addr :: any | loopback | sockaddr(),
+ Addr :: any | broadcast | loopback | sockaddr(),
Reason :: term().
bind(#socket{ref = SockRef}, Addr)
- when ((Addr =:= any) orelse (Addr =:= loopback)) ->
+ when ((Addr =:= any) orelse
+ (Addr =:= broadcast) orelse
+ (Addr =:= loopback)) ->
try which_domain(SockRef) of
inet ->
nif_bind(SockRef, ?SOCKADDR_IN4_DEFAULT(Addr));
- inet6 ->
- nif_bind(SockRef, ?SOCKADDR_IN6_DEFAULT(Addr))
+ inet6 when (Addr =:= any) orelse (Addr =:= loopback) ->
+ nif_bind(SockRef, ?SOCKADDR_IN6_DEFAULT(Addr));
+ _ ->
+ einval()
catch
%% <WIN32-TEMPORARY>
error:notsup:S ->
@@ -1301,7 +1309,7 @@ connect(#socket{ref = SockRef}, #{family := Fam} = SockAddr, Timeout)
((Timeout =:= nowait) orelse
(Timeout =:= infinity) orelse is_integer(Timeout)) ->
TS = timestamp(Timeout),
- case nif_connect(SockRef, SockAddr) of
+ case nif_connect(SockRef, ensure_sockaddr(SockAddr)) of
ok ->
%% Connected!
ok;
@@ -1559,7 +1567,7 @@ do_send(SockRef, Data, EFlags, Timeout) ->
ok | {error, Reason} when
Socket :: socket(),
Data :: binary(),
- Dest :: null | sockaddr(),
+ Dest :: sockaddr(),
Reason :: term().
sendto(Socket, Data, Dest) ->
@@ -1568,7 +1576,7 @@ sendto(Socket, Data, Dest) ->
-spec sendto(Socket, Data, Dest, Flags) -> ok | {error, Reason} when
Socket :: socket(),
Data :: binary(),
- Dest :: null | sockaddr(),
+ Dest :: sockaddr(),
Flags :: send_flags(),
Reason :: term()
; (Socket, Data, Dest, Timeout :: nowait) -> ok |
@@ -1576,13 +1584,13 @@ sendto(Socket, Data, Dest) ->
{error, Reason} when
Socket :: socket(),
Data :: iodata(),
- Dest :: null | sockaddr(),
+ Dest :: sockaddr(),
SelectInfo :: select_info(),
Reason :: term()
; (Socket, Data, Dest, Timeout) -> ok | {error, Reason} when
Socket :: socket(),
Data :: iodata(),
- Dest :: null | sockaddr(),
+ Dest :: sockaddr(),
Timeout :: timeout(),
Reason :: term().
@@ -1597,14 +1605,14 @@ sendto(Socket, Data, Dest, Timeout) ->
{error, Reason} when
Socket :: socket(),
Data :: binary(),
- Dest :: null | sockaddr(),
+ Dest :: sockaddr(),
Flags :: send_flags(),
SelectInfo :: select_info(),
Reason :: term()
; (Socket, Data, Dest, Flags, Timeout) -> ok | {error, Reason} when
Socket :: socket(),
Data :: binary(),
- Dest :: null | sockaddr(),
+ Dest :: sockaddr(),
Flags :: send_flags(),
Timeout :: timeout(),
Reason :: term().
@@ -1612,15 +1620,6 @@ sendto(Socket, Data, Dest, Timeout) ->
sendto(Socket, Data, Dest, Flags, Timeout) when is_list(Data) ->
Bin = erlang:list_to_binary(Data),
sendto(Socket, Bin, Dest, Flags, Timeout);
-sendto(#socket{ref = SockRef}, Data, Dest, Flags, Timeout)
- when is_binary(Data) andalso
- (Dest =:= null) andalso
- is_list(Flags) andalso
- ((Timeout =:= nowait) orelse
- (Timeout =:= infinity) orelse
- (is_integer(Timeout) andalso (Timeout > 0))) ->
- EFlags = enc_send_flags(Flags),
- do_sendto(SockRef, Data, Dest, EFlags, Timeout);
sendto(#socket{ref = SockRef}, Data, #{family := Fam} = Dest, Flags, Timeout)
when is_binary(Data) andalso
((Fam =:= inet) orelse (Fam =:= inet6) orelse (Fam =:= local)) andalso
@@ -1629,7 +1628,7 @@ sendto(#socket{ref = SockRef}, Data, #{family := Fam} = Dest, Flags, Timeout)
(Timeout =:= infinity) orelse
(is_integer(Timeout) andalso (Timeout > 0))) ->
EFlags = enc_send_flags(Flags),
- do_sendto(SockRef, Data, Dest, EFlags, Timeout).
+ do_sendto(SockRef, Data, ensure_sockaddr(Dest), EFlags, Timeout).
do_sendto(SockRef, Data, Dest, EFlags, Timeout) ->
TS = timestamp(Timeout),
@@ -1820,8 +1819,12 @@ do_sendmsg_rest([B|IOVec], Written) ->
ensure_msghdr(#{ctrl := []} = M) ->
ensure_msghdr(maps:remove(ctrl, M));
-ensure_msghdr(#{iov := IOV} = M) when is_list(IOV) andalso (IOV =/= []) ->
- M#{iov := erlang:iolist_to_iovec(IOV)};
+ensure_msghdr(#{iov := IOV, addr := Addr} = M)
+ when is_list(IOV) andalso (IOV =/= []) ->
+ M#{iov => erlang:iolist_to_iovec(IOV), addr => ensure_sockaddr(Addr)};
+ensure_msghdr(#{iov := IOV} = M)
+ when is_list(IOV) andalso (IOV =/= []) ->
+ M#{iov => erlang:iolist_to_iovec(IOV)};
ensure_msghdr(_) ->
einval().
@@ -2682,7 +2685,7 @@ peername(#socket{ref = SockRef}) ->
SelectInfo :: select_info(),
Reason :: term().
-cancel(#socket{ref = SockRef}, #select_info{tag = Tag, ref = Ref}) ->
+cancel(#socket{ref = SockRef}, ?SELECT_INFO(Tag, Ref)) ->
cancel(SockRef, Tag, Ref).
@@ -2693,17 +2696,17 @@ cancel(#socket{ref = SockRef}, #select_info{tag = Tag, ref = Ref}) ->
%%
%% ===========================================================================
--spec enc_domain(Domain) -> non_neg_integer() when
- Domain :: domain().
+%% -spec enc_domain(Domain) -> non_neg_integer() when
+%% Domain :: domain().
enc_domain(local) -> ?SOCKET_DOMAIN_LOCAL;
enc_domain(inet) -> ?SOCKET_DOMAIN_INET;
enc_domain(inet6) -> ?SOCKET_DOMAIN_INET6;
enc_domain(Domain) -> invalid_domain(Domain).
--spec enc_type(Domain, Type) -> non_neg_integer() when
- Domain :: domain(),
- Type :: type().
+%% -spec enc_type(Domain, Type) -> non_neg_integer() when
+%% Domain :: domain(),
+%% Type :: type().
%% What combos are valid?
enc_type(_, stream) -> ?SOCKET_TYPE_STREAM;
@@ -3373,10 +3376,12 @@ enc_sockopt_key(otp = L, Opt, _, _, _, _) ->
%% +++ SOCKET socket options +++
enc_sockopt_key(socket = _L, acceptconn = _Opt, get = _Dir, _D, _T, _P) ->
?SOCKET_OPT_SOCK_ACCEPTCONN;
+enc_sockopt_key(socket = L, acceptconn = Opt, Dir, _D, _T, _P) ->
+ not_supported({L, Opt, Dir});
enc_sockopt_key(socket = L, acceptfilter = Opt, _Dir, _D, _T, _P) ->
not_supported({L, Opt});
-%% Before linux 3.8, this socket option could be set.
-%% Maximum size of buffer for name: IFNAMSZIZ
+%% Before linux 3.8, this socket option could be set but not get.
+%% Maximum size of buffer for name: IFNAMSIZ
%% So, we let the implementation decide.
enc_sockopt_key(socket = _L, bindtodevice = _Opt, _Dir, _D, _T, _P) ->
?SOCKET_OPT_SOCK_BINDTODEVICE;
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl
index 2305502800..2b9c1b0cf5 100644
--- a/lib/compiler/src/beam_except.erl
+++ b/lib/compiler/src/beam_except.erl
@@ -152,7 +152,7 @@ dig_out_fc(Arity, Is0) ->
({test,_,_,_}) -> false;
(_) -> true
end, Is0),
- {Regs,Acc} = dig_out_fc_1(reverse(Is), Regs0, Acc0),
+ {Regs,Acc} = dig_out_fc_1(reverse(Is), Arity, Regs0, Acc0),
case Regs of
#{{x,0}:={atom,function_clause},{x,1}:=Args} ->
case moves_from_stack(Args, 0, []) of
@@ -165,19 +165,27 @@ dig_out_fc(Arity, Is0) ->
no
end.
-dig_out_fc_1([{block,Bl}|Is], Regs0, Acc) ->
+dig_out_fc_1([{block,Bl}|Is], Arity, Regs0, Acc) ->
Regs = dig_out_fc_block(Bl, Regs0),
- dig_out_fc_1(Is, Regs, Acc);
-dig_out_fc_1([{bs_set_position,_,_}=I|Is], Regs, Acc) ->
- dig_out_fc_1(Is, Regs, [I|Acc]);
-dig_out_fc_1([{bs_get_tail,Src,Dst,Live0}|Is], Regs0, Acc) ->
- Regs = prune_xregs(Live0, Regs0),
- Live = dig_out_stack_live(Regs, Live0),
- I = {bs_get_tail,Src,Dst,Live},
- dig_out_fc_1(Is, Regs, [I|Acc]);
-dig_out_fc_1([_|_], _Regs, _Acc) ->
+ dig_out_fc_1(Is, Arity, Regs, Acc);
+dig_out_fc_1([{bs_set_position,_,_}=I|Is], Arity, Regs, Acc) ->
+ dig_out_fc_1(Is, Arity, Regs, [I|Acc]);
+dig_out_fc_1([{bs_get_tail,Src,Dst,Live0}|Is], Arity, Regs0, Acc) ->
+ case Src of
+ {x,X} when X < Arity ->
+ %% The heuristic for determining the number of live
+ %% registers is likely to give an incorrect result.
+ %% Give up.
+ {#{},[]};
+ _ ->
+ Regs = prune_xregs(Live0, Regs0),
+ Live = dig_out_stack_live(Regs, Live0),
+ I = {bs_get_tail,Src,Dst,Live},
+ dig_out_fc_1(Is, Arity, Regs, [I|Acc])
+ end;
+dig_out_fc_1([_|_], _Arity, _Regs, _Acc) ->
{#{},[]};
-dig_out_fc_1([], Regs, Acc) ->
+dig_out_fc_1([], _Arity, Regs, Acc) ->
{Regs,Acc}.
dig_out_fc_block([{set,[],[],{alloc,Live,_}}|Is], Regs0) ->
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
index 07f4c8b461..08641e2abc 100644
--- a/lib/compiler/src/beam_ssa_codegen.erl
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -764,9 +764,8 @@ defined(Linear, #cg{regs=Regs}) ->
def([{L,#cg_blk{is=Is0,last=Last}=Blk0}|Bs], DefMap0, Regs) ->
Def0 = def_get(L, DefMap0),
- {Is,Def} = def_is(Is0, Regs, Def0, []),
- Successors = successors(Last),
- DefMap = def_successors(Successors, Def, DefMap0),
+ {Is,Def,MaybeDef} = def_is(Is0, Regs, Def0, []),
+ DefMap = def_successors(Last, Def, MaybeDef, DefMap0),
Blk = Blk0#cg_blk{is=Is},
[{L,Blk}|def(Bs, DefMap, Regs)];
def([], _, _) -> [].
@@ -780,6 +779,11 @@ def_get(L, DefMap) ->
def_is([#cg_alloc{anno=Anno0}=I0|Is], Regs, Def, Acc) ->
I = I0#cg_alloc{anno=Anno0#{def_yregs=>Def}},
def_is(Is, Regs, Def, [I|Acc]);
+def_is([#cg_set{op=succeeded,args=[Var]}=I], Regs, Def, Acc) ->
+ %% Var will only be defined on the success branch of the `br`
+ %% for this block.
+ MaybeDef = def_add_yreg(Var, [], Regs),
+ {reverse(Acc, [I]),Def,MaybeDef};
def_is([#cg_set{op=kill_try_tag,args=[#b_var{}=Tag]}=I|Is], Regs, Def0, Acc) ->
Def = ordsets:del_element(Tag, Def0),
def_is(Is, Regs, Def, [I|Acc]);
@@ -822,7 +826,7 @@ def_is([#cg_set{anno=Anno0,dst=Dst}=I0|Is], Regs, Def0, Acc) ->
Def = def_add_yreg(Dst, Def0, Regs),
def_is(Is, Regs, Def, [I|Acc]);
def_is([], _, Def, Acc) ->
- {reverse(Acc),Def}.
+ {reverse(Acc),Def,[]}.
def_add_yreg(Dst, Def, Regs) ->
case is_yreg(Dst, Regs) of
@@ -830,6 +834,12 @@ def_add_yreg(Dst, Def, Regs) ->
false -> Def
end.
+def_successors(#cg_br{bool=#b_var{},succ=Succ,fail=Fail}, Def, MaybeDef, DefMap0) ->
+ DefMap = def_successors([Fail], ordsets:subtract(Def, MaybeDef), DefMap0),
+ def_successors([Succ], Def, DefMap);
+def_successors(Last, Def, [], DefMap) ->
+ def_successors(successors(Last), Def, DefMap).
+
def_successors([S|Ss], Def0, DefMap) ->
case DefMap of
#{S:=Def1} ->
diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl
index 64b9b3e222..e78e4647a8 100644
--- a/lib/compiler/src/beam_ssa_dead.erl
+++ b/lib/compiler/src/beam_ssa_dead.erl
@@ -30,7 +30,7 @@
-import(lists, [append/1,keymember/3,last/1,member/2,
takewhile/2,reverse/1]).
--type used_vars() :: #{beam_ssa:label():=ordsets:ordset(beam_ssa:var_name())}.
+-type used_vars() :: #{beam_ssa:label():=cerl_sets:set(beam_ssa:var_name())}.
-type basic_type_test() :: atom() | {'is_tagged_tuple',pos_integer(),atom()}.
-type type_test() :: basic_type_test() | {'not',basic_type_test()}.
@@ -90,13 +90,11 @@ shortcut_opt(#st{bs=Blocks}=St) ->
%% the diff.)
%%
%% Unfortunately, processing the blocks in reverse post order
- %% potentially makes the time complexity quadratic or even cubic if
- %% the ordset of unset variables grows large, instead of
- %% linear for post order processing. We try to still get reasonable
- %% compilation times by optimizations that will keep the constant
- %% factor as low as possible, and we try to avoid the cubic time
- %% complexity by trying to keep the set of unset variables as small
- %% as possible.
+ %% potentially makes the time complexity quadratic, instead of
+ %% linear for post order processing. We avoid drastic slowdowns by
+ %% limiting how far we search forward to a common block that
+ %% both the success and failure label will reach (see the comment
+ %% in the first clause of shortcut_2/5).
Ls = beam_ssa:rpo(Blocks),
shortcut_opt(Ls, #{}, St).
@@ -124,10 +122,15 @@ shortcut_terminator(#b_br{bool=#b_var{}=Bool,succ=Succ0,fail=Fail0}=Br,
Is, From, Bs, St0) ->
St = St0#st{target=one_way},
RelOp = get_rel_op(Bool, Is),
- SuccBs = bind_var(Bool, #b_literal{val=true}, Bs),
+
+ %% The boolean in a `br` is seldom used by the successors. By
+ %% not binding its value unless it is actually used we might be able
+ %% to skip some work in shortcut/4 and sub/2.
+ SuccBs = bind_var_if_used(Succ0, Bool, #b_literal{val=true}, Bs, St),
BrSucc = shortcut(Succ0, From, SuccBs, St#st{rel_op=RelOp}),
- FailBs = bind_var(Bool, #b_literal{val=false}, Bs),
+ FailBs = bind_var_if_used(Fail0, Bool, #b_literal{val=false}, Bs, St),
BrFail = shortcut(Fail0, From, FailBs, St#st{rel_op=invert_op(RelOp)}),
+
case {BrSucc,BrFail} of
{#b_br{bool=#b_literal{val=true},succ=Succ},
#b_br{bool=#b_literal{val=true},succ=Fail}}
@@ -152,8 +155,14 @@ shortcut_switch([{Lit,L0}|T], Bool, From, Bs, St0) ->
[{Lit,L}|shortcut_switch(T, Bool, From, Bs, St0)];
shortcut_switch([], _, _, _, _) -> [].
+shortcut(L, _From, Bs, #st{rel_op=none,target=one_way}) when map_size(Bs) =:= 0 ->
+ %% There is no way that we can find a suitable branch, because there is no
+ %% relational operator stored, there are no bindings, and the block L can't
+ %% have any phi nodes from which we could pick bindings because when the target
+ %% is `one_way`, it implies the From block has a two-way `br` terminator.
+ #b_br{bool=#b_literal{val=true},succ=L,fail=L};
shortcut(L, From, Bs, St) ->
- shortcut_1(L, From, Bs, ordsets:new(), St).
+ shortcut_1(L, From, Bs, cerl_sets:new(), St).
shortcut_1(L, From, Bs0, UnsetVars0, St) ->
case shortcut_2(L, From, Bs0, UnsetVars0, St) of
@@ -170,7 +179,19 @@ shortcut_1(L, From, Bs0, UnsetVars0, St) ->
end.
%% Try to shortcut this block, branching to a successor.
-shortcut_2(L, From, Bs0, UnsetVars0, St) ->
+shortcut_2(L, From, Bs, UnsetVars, St) ->
+ case cerl_sets:size(UnsetVars) of
+ SetSize when SetSize > 128 ->
+ %% This is an heuristic to limit the search for a forced label
+ %% before it drastically slows down the compiler. Experiments
+ %% with scripts/diffable showed that limits larger than 31 did not
+ %% find any more opportunities for optimization.
+ none;
+ _SetSize ->
+ shortcut_3(L, From, Bs, UnsetVars, St)
+ end.
+
+shortcut_3(L, From, Bs0, UnsetVars0, St) ->
#b_blk{is=Is,last=Last} = get_block(L, St),
case eval_is(Is, From, Bs0, St) of
none ->
@@ -347,7 +368,7 @@ update_unset_vars(L, Is, Br, UnsetVars, #st{skippable=Skippable}) ->
%% Some variables defined in this block are used by
%% successors. We must update the set of unset variables.
SetInThisBlock = [V || #b_set{dst=V} <- Is],
- ordsets:union(UnsetVars, ordsets:from_list(SetInThisBlock))
+ cerl_sets:union(UnsetVars, cerl_sets:from_list(SetInThisBlock))
end.
shortcut_two_way(#b_br{succ=Succ,fail=Fail}, From, Bs0, UnsetVars0, St0) ->
@@ -376,14 +397,14 @@ is_br_safe(UnsetVars, Br, #st{us=Us}=St) ->
%% A two-way branch never branches to a phi node, so there
%% is no need to check for phi nodes here.
- not member(V, UnsetVars) andalso
- ordsets:is_disjoint(Used0, UnsetVars) andalso
- ordsets:is_disjoint(Used1, UnsetVars);
+ not cerl_sets:is_element(V, UnsetVars) andalso
+ cerl_sets:is_disjoint(Used0, UnsetVars) andalso
+ cerl_sets:is_disjoint(Used1, UnsetVars);
#b_br{succ=Same,fail=Same} ->
%% An unconditional branch must not jump to
%% a phi node.
not is_forbidden(Same, St) andalso
- ordsets:is_disjoint(map_get(Same, Us), UnsetVars)
+ cerl_sets:is_disjoint(map_get(Same, Us), UnsetVars)
end.
is_forbidden(L, St) ->
@@ -500,6 +521,15 @@ eval_switch_1([], _Arg, _PrevOp, Fail) ->
%% Fail is now either the failure label or 'none'.
Fail.
+bind_var_if_used(L, Var, Val0, Bs, #st{us=Us}) ->
+ case cerl_sets:is_element(Var, map_get(L, Us)) of
+ true ->
+ Val = get_value(Val0, Bs),
+ Bs#{Var=>Val};
+ false ->
+ Bs
+ end.
+
bind_var(Var, Val0, Bs) ->
Val = get_value(Val0, Bs),
Bs#{Var=>Val}.
@@ -989,7 +1019,7 @@ used_vars([{L,#b_blk{is=Is}=Blk}|Bs], UsedVars0, Skip0) ->
%% shortcut_opt/1.
Successors = beam_ssa:successors(Blk),
- Used0 = used_vars_succ(Successors, L, UsedVars0, []),
+ Used0 = used_vars_succ(Successors, L, UsedVars0, cerl_sets:new()),
Used = used_vars_blk(Blk, Used0),
UsedVars = used_vars_phis(Is, L, Used, UsedVars0),
@@ -1000,8 +1030,8 @@ used_vars([{L,#b_blk{is=Is}=Blk}|Bs], UsedVars0, Skip0) ->
%% shortcut_opt/1.
Defined0 = [Def || #b_set{dst=Def} <- Is],
- Defined = ordsets:from_list(Defined0),
- MaySkip = ordsets:is_disjoint(Defined, Used0),
+ Defined = cerl_sets:from_list(Defined0),
+ MaySkip = cerl_sets:is_disjoint(Defined, Used0),
case MaySkip of
true ->
Skip = Skip0#{L=>true},
@@ -1018,11 +1048,11 @@ used_vars_succ([S|Ss], L, LiveMap, Live0) ->
#{Key:=Live} ->
%% The successor has a phi node, and the value for
%% this block in the phi node is a variable.
- used_vars_succ(Ss, L, LiveMap, ordsets:union(Live, Live0));
+ used_vars_succ(Ss, L, LiveMap, cerl_sets:union(Live, Live0));
#{S:=Live} ->
%% No phi node in the successor, or the value for
%% this block in the phi node is a literal.
- used_vars_succ(Ss, L, LiveMap, ordsets:union(Live, Live0));
+ used_vars_succ(Ss, L, LiveMap, cerl_sets:union(Live, Live0));
#{} ->
%% A peek_message block which has not been processed yet.
used_vars_succ(Ss, L, LiveMap, Live0)
@@ -1040,7 +1070,7 @@ used_vars_phis(Is, L, Live0, UsedVars0) ->
case [{P,V} || {#b_var{}=V,P} <- PhiArgs] of
[_|_]=PhiVars ->
PhiLive0 = rel2fam(PhiVars),
- PhiLive = [{{L,P},ordsets:union(ordsets:from_list(Vs), Live0)} ||
+ PhiLive = [{{L,P},cerl_sets:union(cerl_sets:from_list(Vs), Live0)} ||
{P,Vs} <- PhiLive0],
maps:merge(UsedVars, maps:from_list(PhiLive));
[] ->
@@ -1050,14 +1080,14 @@ used_vars_phis(Is, L, Live0, UsedVars0) ->
end.
used_vars_blk(#b_blk{is=Is,last=Last}, Used0) ->
- Used = ordsets:union(Used0, beam_ssa:used(Last)),
+ Used = cerl_sets:union(Used0, cerl_sets:from_list(beam_ssa:used(Last))),
used_vars_is(reverse(Is), Used).
used_vars_is([#b_set{op=phi}|Is], Used) ->
used_vars_is(Is, Used);
used_vars_is([#b_set{dst=Dst}=I|Is], Used0) ->
- Used1 = ordsets:union(Used0, beam_ssa:used(I)),
- Used = ordsets:del_element(Dst, Used1),
+ Used1 = cerl_sets:union(Used0, cerl_sets:from_list(beam_ssa:used(I))),
+ Used = cerl_sets:del_element(Dst, Used1),
used_vars_is(Is, Used);
used_vars_is([], Used) ->
Used.
@@ -1066,8 +1096,9 @@ used_vars_is([], Used) ->
%%% Common utilities.
%%%
-sub(#b_set{args=Args}=I, Sub) ->
- I#b_set{args=[sub_arg(A, Sub) || A <- Args]}.
+sub(#b_set{args=Args}=I, Sub) when map_size(Sub) =/= 0 ->
+ I#b_set{args=[sub_arg(A, Sub) || A <- Args]};
+sub(I, _Sub) -> I.
sub_arg(#b_var{}=Old, Sub) ->
case Sub of
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index 229edc6a1d..d87c66c272 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -1939,12 +1939,24 @@ verify_merge_is(_) ->
is_merge_allowed(_, #b_blk{}, #b_blk{is=[#b_set{op=peek_message}|_]}) ->
false;
-is_merge_allowed(L, #b_blk{last=#b_br{}}=Blk, #b_blk{}) ->
+is_merge_allowed(L, #b_blk{last=#b_br{}}=Blk, #b_blk{is=Is}) ->
%% The predecessor block must have exactly one successor (L) for
%% the merge to be safe.
case beam_ssa:successors(Blk) of
- [L] -> true;
- [_|_] -> false
+ [L] ->
+ case Is of
+ [#b_set{op=phi,args=[_]}|_] ->
+ %% The type optimizer pass must have been
+ %% turned off, since it would have removed this
+ %% redundant phi node. Refuse to merge the blocks
+ %% to ensure that this phi node remains at the
+ %% beginning of a block.
+ false;
+ _ ->
+ true
+ end;
+ [_|_] ->
+ false
end;
is_merge_allowed(_, #b_blk{last=#b_switch{}}, #b_blk{}) ->
false.
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index 7ef604d444..7f816b9802 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -1463,25 +1463,51 @@ fix_receive([], _Defs, Blocks, Count) ->
{Blocks,Count}.
%% find_loop_exit([Label], Blocks) -> Label | none.
-%% Find the block to which control is transferred when the
-%% the receive loop is exited.
-
-find_loop_exit([L1,L2|_Ls], Blocks) ->
- Path1 = beam_ssa:rpo([L1], Blocks),
- Path2 = beam_ssa:rpo([L2], Blocks),
- find_loop_exit_1(Path1, cerl_sets:from_list(Path2));
-find_loop_exit(_, _) -> none.
-
-find_loop_exit_1([?BADARG_BLOCK | T], OtherPath) ->
- %% ?BADARG_BLOCK is a marker and not an actual block, so we can't consider
- %% it to be a common block even if both paths cross it.
- find_loop_exit_1(T, OtherPath);
-find_loop_exit_1([H|T], OtherPath) ->
- case cerl_sets:is_element(H, OtherPath) of
- true -> H;
- false -> find_loop_exit_1(T, OtherPath)
+%% Given the list of all blocks with the remove_message instructions
+%% for this receive, find the block to which control is transferred
+%% when the receive loop is exited (if any).
+
+find_loop_exit([_,_|_]=RmBlocks, Blocks) ->
+ %% We used to only analyze the path from two of the remove_message
+ %% blocks. That would fail to find a common block if one or both
+ %% of the blocks happened to raise an exception. To be sure that
+ %% we always find a common block if there is one (shared by at
+ %% least two clauses), we must analyze the path from all
+ %% remove_message blocks.
+ {Dominators,_} = beam_ssa:dominators(Blocks),
+ RmSet = cerl_sets:from_list(RmBlocks),
+ Rpo = beam_ssa:rpo(RmBlocks, Blocks),
+ find_loop_exit_1(Rpo, RmSet, Dominators);
+find_loop_exit(_, _) ->
+ %% There is (at most) a single clause. There is no common
+ %% loop exit block.
+ none.
+
+find_loop_exit_1([?BADARG_BLOCK|Ls], RmSet, Dominators) ->
+ %% ?BADARG_BLOCK is a marker and not an actual block, so it is not
+ %% the block we are looking for.
+ find_loop_exit_1(Ls, RmSet, Dominators);
+find_loop_exit_1([L|Ls], RmSet, Dominators) ->
+ DomBy = map_get(L, Dominators),
+ case any(fun(E) -> cerl_sets:is_element(E, RmSet) end, DomBy) of
+ true ->
+ %% This block is dominated by one of the remove_message blocks,
+ %% which means that the block is part of only one clause.
+ %% It is not the block we are looking for.
+ find_loop_exit_1(Ls, RmSet, Dominators);
+ false ->
+ %% This block is the first block that is not dominated by
+ %% any of the blocks with remove_message instructions,
+ %% which means that at least two of the receive clauses
+ %% will ultimately transfer control to it. It is the block
+ %% we are looking for.
+ L
end;
-find_loop_exit_1([], _) -> none.
+find_loop_exit_1([], _, _) ->
+ %% None of clauses transfers control to a common block after the receive
+ %% statement. That means that the receive statement is a the end of a
+ %% function (or that all clauses raise exceptions).
+ none.
%% find_rm_blocks(StartLabel, Blocks) -> [Label].
%% Find all blocks that start with remove_message within the receive
diff --git a/lib/compiler/src/beam_ssa_share.erl b/lib/compiler/src/beam_ssa_share.erl
index 426efa2cc9..73983bd34a 100644
--- a/lib/compiler/src/beam_ssa_share.erl
+++ b/lib/compiler/src/beam_ssa_share.erl
@@ -303,8 +303,12 @@ canonical_is([#b_ret{arg=Arg}], VarMap, Acc0) ->
Acc0
end,
{{ret,canonical_arg(Arg, VarMap),Acc1},VarMap};
-canonical_is([#b_br{bool=#b_var{},fail=Fail}], VarMap, Acc) ->
- {{br,succ,Fail,Acc},VarMap};
+canonical_is([#b_br{bool=#b_var{}=Arg,fail=Fail}], VarMap, Acc) ->
+ %% A previous buggy version of this code omitted the canonicalized
+ %% argument in the return value. Unfortunately, that worked most
+ %% of the time, except when `br` terminator referenced a variable
+ %% defined in a previous block instead of in the same block.
+ {{br,canonical_arg(Arg, VarMap),succ,Fail,Acc},VarMap};
canonical_is([#b_br{succ=Succ}], VarMap, Acc) ->
{{br,Succ,Acc},VarMap};
canonical_is([], VarMap, Acc) ->
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl
index 68920e7dd3..3c06c83e2e 100644
--- a/lib/compiler/src/beam_ssa_type.erl
+++ b/lib/compiler/src/beam_ssa_type.erl
@@ -160,6 +160,10 @@ opt_finish_1([Arg | Args], [TypeMap | TypeMaps], ParamInfo0) ->
case join(maps:values(TypeMap)) of
any ->
opt_finish_1(Args, TypeMaps, ParamInfo0);
+ none ->
+ %% This function will never be called. Pretend that we don't
+ %% know the type for this argument.
+ opt_finish_1(Args, TypeMaps, ParamInfo0);
JoinedType ->
JoinedType = verified_type(JoinedType),
ParamInfo = ParamInfo0#{ Arg => validator_anno(JoinedType) },
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index ebe9631e09..349d74eb58 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -1068,8 +1068,11 @@ verify_get_map(Fail, Src, List, Vst0) ->
%% {get_map_elements,{f,7},{x,1},{list,[{atom,a},{x,1},{atom,b},{x,2}]}}.
%%
%% If 'a' exists but not 'b', {x,1} is overwritten when we jump to {f,7}.
+%%
+%% We must be careful to preserve the uninitialized status for Y registers
+%% that have been allocated but not yet defined.
clobber_map_vals([Key,Dst|T], Map, Vst0) ->
- case is_reg_defined(Dst, Vst0) of
+ case is_reg_initialized(Dst, Vst0) of
true ->
Vst = extract_term(term, {bif,map_get}, [Key, Map], Dst, Vst0),
clobber_map_vals(T, Map, Vst);
@@ -1079,6 +1082,17 @@ clobber_map_vals([Key,Dst|T], Map, Vst0) ->
clobber_map_vals([], _Map, Vst) ->
Vst.
+is_reg_initialized({x,_}=Reg, #vst{current=#st{xs=Xs}}) ->
+ is_map_key(Reg, Xs);
+is_reg_initialized({y,_}=Reg, #vst{current=#st{ys=Ys}}) ->
+ case Ys of
+ #{Reg:=Val} ->
+ Val =/= uninitialized;
+ #{} ->
+ false
+ end;
+is_reg_initialized(V, #vst{}) -> error({not_a_register, V}).
+
extract_map_keys([Key,_Val|T]) ->
[Key|extract_map_keys(T)];
extract_map_keys([]) -> [].
@@ -1604,13 +1618,8 @@ infer_types_1(#value{op={bif,'=:='},args=[LHS,RHS]}) ->
end;
infer_types_1(#value{op={bif,element},args=[{integer,Index}=Key,Tuple]}) ->
fun(Val, S) ->
- case is_value_alive(Tuple, S) of
- true ->
- Type = {tuple,[Index], #{ Key => get_term_type(Val, S) }},
- update_type(fun meet/2, Type, Tuple, S);
- false ->
- S
- end
+ Type = {tuple,[Index], #{ Key => get_term_type(Val, S) }},
+ update_type(fun meet/2, Type, Tuple, S)
end;
infer_types_1(#value{op={bif,is_atom},args=[Src]}) ->
infer_type_test_bif({atom,[]}, Src);
@@ -1634,10 +1643,7 @@ infer_types_1(#value{op={bif,is_tuple},args=[Src]}) ->
infer_type_test_bif({tuple,[0],#{}}, Src);
infer_types_1(#value{op={bif,tuple_size}, args=[Tuple]}) ->
fun({integer,Arity}, S) ->
- case is_value_alive(Tuple, S) of
- true -> update_type(fun meet/2, {tuple,Arity,#{}}, Tuple, S);
- false -> S
- end;
+ update_type(fun meet/2, {tuple,Arity,#{}}, Tuple, S);
(_, S) -> S
end;
infer_types_1(_) ->
@@ -1645,10 +1651,7 @@ infer_types_1(_) ->
infer_type_test_bif(Type, Src) ->
fun({atom,true}, S) ->
- case is_value_alive(Src, S) of
- true -> update_type(fun meet/2, Type, Src, S);
- false -> S
- end;
+ update_type(fun meet/2, Type, Src, S);
(_, S) ->
S
end.
@@ -1885,10 +1888,6 @@ check_try_catch_tags(Type, {y,N}=Reg, Vst) ->
ok
end.
-is_reg_defined({x,_}=Reg, #vst{current=#st{xs=Xs}}) -> is_map_key(Reg, Xs);
-is_reg_defined({y,_}=Reg, #vst{current=#st{ys=Ys}}) -> is_map_key(Reg, Ys);
-is_reg_defined(V, #vst{}) -> error({not_a_register, V}).
-
assert_term(Src, Vst) ->
_ = get_term_type(Src, Vst),
ok.
@@ -2285,9 +2284,6 @@ get_raw_type(#value_ref{}=Ref, #vst{current=#st{vs=Vs}}) ->
get_raw_type(Src, #vst{}) ->
get_literal_type(Src).
-is_value_alive(#value_ref{}=Ref, #vst{current=#st{vs=Vs}}) ->
- is_map_key(Ref, Vs).
-
get_literal_type(nil=T) -> T;
get_literal_type({atom,A}=T) when is_atom(A) -> T;
get_literal_type({float,F}=T) when is_float(F) -> T;
@@ -2469,25 +2465,44 @@ merge_vrefs(RefA, RefB, Merge, Counter) ->
merge_values(Merge, VsA, VsB) ->
maps:fold(fun(Spec, New, Acc) ->
- merge_values_1(Spec, New, VsA, VsB, Acc)
+ mv_1(Spec, New, VsA, VsB, Acc)
end, #{}, Merge).
-merge_values_1(Same, Same, VsA, VsB, Acc) ->
+mv_1(Same, Same, VsA, VsB, Acc0) ->
%% We're merging different versions of the same value, so it's safe to
%% reuse old entries if the type's unchanged.
- #value{type=TypeA}=EntryA = map_get(Same, VsA),
- #value{type=TypeB}=EntryB = map_get(Same, VsB),
+ #value{type=TypeA,args=Args}=EntryA = map_get(Same, VsA),
+ #value{type=TypeB,args=Args}=EntryB = map_get(Same, VsB),
+
Entry = case join(TypeA, TypeB) of
TypeA -> EntryA;
TypeB -> EntryB;
JoinedType -> EntryA#value{type=JoinedType}
end,
- Acc#{ Same => Entry };
-merge_values_1({RefA, RefB}, New, VsA, VsB, Acc) ->
+
+ Acc = Acc0#{ Same => Entry },
+
+ %% Type inference may depend on values that are no longer reachable from a
+ %% register, so all arguments must be merged into the new state.
+ mv_args(Args, VsA, VsB, Acc);
+mv_1({RefA, RefB}, New, VsA, VsB, Acc) ->
#value{type=TypeA} = map_get(RefA, VsA),
#value{type=TypeB} = map_get(RefB, VsB),
Acc#{ New => #value{op=join,args=[],type=join(TypeA, TypeB)} }.
+mv_args([#value_ref{}=Arg | Args], VsA, VsB, Acc0) ->
+ case Acc0 of
+ #{ Arg := _ } ->
+ mv_args(Args, VsA, VsB, Acc0);
+ #{} ->
+ Acc = mv_1(Arg, Arg, VsA, VsB, Acc0),
+ mv_args(Args, VsA, VsB, Acc)
+ end;
+mv_args([_ | Args], VsA, VsB, Acc) ->
+ mv_args(Args, VsA, VsB, Acc);
+mv_args([], _VsA, _VsB, Acc) ->
+ Acc.
+
merge_fragility(FragileA, FragileB) ->
cerl_sets:union(FragileA, FragileB).
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 28db8986ff..0325c714d0 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -268,8 +268,11 @@ expand_opt(r21, Os) ->
[no_put_tuple2 | expand_opt(no_bsm3, Os)];
expand_opt({debug_info_key,_}=O, Os) ->
[encrypt_debug_info,O|Os];
-expand_opt(no_type_opt, Os) ->
- [no_ssa_opt_type_start,
+expand_opt(no_type_opt=O, Os) ->
+ %% Be sure to keep the no_type_opt option so that it will
+ %% be recorded in the BEAM file, allowing the test suites
+ %% to recompile the file with this option.
+ [O,no_ssa_opt_type_start,
no_ssa_opt_type_continue,
no_ssa_opt_type_finish | Os];
expand_opt(O, Os) -> [O|Os].
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index db8eb7e2e1..7be23fbb93 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -109,6 +109,8 @@ NO_MOD_OPT = $(NO_OPT)
NO_SSA_OPT = $(NO_OPT)
+NO_TYPE_OPT = $(NO_OPT)
+
NO_OPT_MODULES= $(NO_OPT:%=%_no_opt_SUITE)
NO_OPT_ERL_FILES= $(NO_OPT_MODULES:%=%.erl)
POST_OPT_MODULES= $(NO_OPT:%=%_post_opt_SUITE)
@@ -121,6 +123,8 @@ NO_MOD_OPT_MODULES= $(NO_MOD_OPT:%=%_no_module_opt_SUITE)
NO_MOD_OPT_ERL_FILES= $(NO_MOD_OPT_MODULES:%=%.erl)
NO_SSA_OPT_MODULES= $(NO_SSA_OPT:%=%_no_ssa_opt_SUITE)
NO_SSA_OPT_ERL_FILES= $(NO_SSA_OPT_MODULES:%=%.erl)
+NO_TYPE_OPT_MODULES= $(NO_TYPE_OPT:%=%_no_type_opt_SUITE)
+NO_TYPE_OPT_ERL_FILES= $(NO_TYPE_OPT_MODULES:%=%.erl)
ERL_FILES= $(MODULES:%=%.erl)
CORE_FILES= $(CORE_MODULES:%=%.core)
@@ -150,7 +154,7 @@ EBIN = .
# ----------------------------------------------------
make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES) \
- $(INLINE_ERL_FILES) $(R21_ERL_FILES) $(NO_MOD_OPT_ERL_FILES)
+ $(INLINE_ERL_FILES) $(R21_ERL_FILES) $(NO_MOD_OPT_ERL_FILES) $(NO_TYPE_OPT_ERL_FILES)
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
> $(EMAKEFILE)
$(ERL_TOP)/make/make_emakefile +no_copt +no_postopt \
@@ -169,6 +173,8 @@ make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES
-o$(EBIN) $(NO_MOD_OPT_MODULES) >> $(EMAKEFILE)
$(ERL_TOP)/make/make_emakefile +from_core $(ERL_COMPILE_FLAGS) \
-o$(EBIN) $(CORE_MODULES) >> $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile +no_type_opt $(ERL_COMPILE_FLAGS) \
+ -o$(EBIN) $(NO_TYPE_OPT_MODULES) >> $(EMAKEFILE)
tests debug opt: make_emakefile
erl $(ERL_MAKE_FLAGS) -make
@@ -202,6 +208,10 @@ docs:
%_no_module_opt_SUITE.erl: %_SUITE.erl
sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
+%_no_type_opt_SUITE.erl: %_SUITE.erl
+ sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
+
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -216,7 +226,8 @@ release_tests_spec: make_emakefile
$(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \
$(INLINE_ERL_FILES) $(R21_ERL_FILES) \
$(NO_MOD_OPT_ERL_FILES) \
- $(NO_SSA_OPT_ERL_FILES) "$(RELSYSDIR)"
+ $(NO_SSA_OPT_ERL_FILES) \
+ $(NO_TYPE_OPT_ERL_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) $(CORE_FILES) "$(RELSYSDIR)"
for file in $(ERL_DUMMY_FILES); do \
module=`basename $$file .erl`; \
diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl
index 67947dc292..f52239f2a8 100644
--- a/lib/compiler/test/beam_except_SUITE.erl
+++ b/lib/compiler/test/beam_except_SUITE.erl
@@ -72,11 +72,25 @@ bs_get_tail(Config) ->
{function_clause,
[{?MODULE,bs_get_tail_1,[<<>>,0,0,Config],_}|_]}} =
(catch bs_get_tail_1(id(<<>>), 0, 0, Config)),
+
+ ok = bs_get_tail_2(<<"W">>, <<"X">>, <<"Z">>),
+ ok = bs_get_tail_2(<<"M">>, <<"X">>, <<"Z">>),
+ {'EXIT',
+ {function_clause,
+ [{?MODULE,do_get_bs_tail_2,[<<"A">>,<<"B">>,[],<<"C">>],_}|_]}} =
+ (catch bs_get_tail_2(<<"A">>, <<"B">>, <<"C">>)),
+
ok.
bs_get_tail_1(<<_:32, Rest/binary>>, Z1, Z2, F1) ->
{Rest,Z1,Z2,F1}.
+bs_get_tail_2(A, B, C) ->
+ do_get_bs_tail_2(A, B, [], C).
+
+do_get_bs_tail_2(<<"W">>, <<"X">>, _, <<"Z">>) -> ok;
+do_get_bs_tail_2(<<"M">>, <<"X">>, _, <<"Z">>) -> ok.
+
coverage(_) ->
File = {file,"fake.erl"},
ok = fc(a),
diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl
index dd1b7ddcd3..3b510f3528 100644
--- a/lib/compiler/test/beam_ssa_SUITE.erl
+++ b/lib/compiler/test/beam_ssa_SUITE.erl
@@ -23,7 +23,7 @@
init_per_group/2,end_per_group/2,
calls/1,tuple_matching/1,recv/1,maps/1,
cover_ssa_dead/1,combine_sw/1,share_opt/1,
- beam_ssa_dead_crash/1]).
+ beam_ssa_dead_crash/1,stack_init/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -39,7 +39,8 @@ groups() ->
cover_ssa_dead,
combine_sw,
share_opt,
- beam_ssa_dead_crash
+ beam_ssa_dead_crash,
+ stack_init
]}].
init_per_suite(Config) ->
@@ -524,9 +525,11 @@ do_comb_sw_2(X) ->
erase(?MODULE).
share_opt(_Config) ->
- ok = do_share_opt(0).
+ ok = do_share_opt_1(0),
+ ok = do_share_opt_2(),
+ ok.
-do_share_opt(A) ->
+do_share_opt_1(A) ->
%% The compiler would be stuck in an infinite loop in beam_ssa_share.
case A of
0 -> a;
@@ -535,6 +538,26 @@ do_share_opt(A) ->
end,
receive after 1 -> ok end.
+do_share_opt_2() ->
+ ok = sopt_2({[pointtopoint], [{dstaddr,any}]}, ok),
+ ok = sopt_2({[broadcast], [{broadaddr,any}]}, ok),
+ ok = sopt_2({[], []}, ok),
+ ok.
+
+sopt_2({Flags, Opts}, ok) ->
+ Broadcast = lists:member(broadcast, Flags),
+ P2P = lists:member(pointtopoint, Flags),
+ case Opts of
+ %% The following two clauses would be combined to one, silently
+ %% discarding the guard test of the P2P variable.
+ [{broadaddr,_}|Os] when Broadcast ->
+ sopt_2({Flags, Os}, ok);
+ [{dstaddr,_}|Os] when P2P ->
+ sopt_2({Flags, Os}, ok);
+ [] ->
+ ok
+ end.
+
beam_ssa_dead_crash(_Config) ->
not_A_B = do_beam_ssa_dead_crash(id(false), id(true)),
not_A_not_B = do_beam_ssa_dead_crash(false, false),
@@ -589,6 +612,30 @@ do_beam_ssa_dead_crash(A, B) ->
end
end.
+stack_init(_Config) ->
+ 6 = stack_init(a, #{a => [1,2,3]}),
+ 0 = stack_init(missing, #{}),
+ ok.
+
+stack_init(Key, Map) ->
+ %% beam_ssa_codegen would wrongly assume that y(0) would always be
+ %% initialized by the `get_map_elements` instruction that follows, and
+ %% would set up the stack frame using an `allocate` instruction and
+ %% would not generate an `init` instruction to initialize y(0).
+ Res = case Map of
+ #{Key := Elements} ->
+ %% Elements will be assigned to y(0) if the key Key exists.
+ lists:foldl(fun(El, Acc) ->
+ Acc + El
+ end, 0, Elements);
+ #{} ->
+ %% y(0) will be left uninitialized when the key is not
+ %% present in the map.
+ 0
+ end,
+ %% y(0) would be uninitialized here if the key was not present in the map
+ %% (if the second clause was executed).
+ id(Res).
%% The identity function.
id(I) -> I.
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 076a604aa4..a99dee48aa 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -24,7 +24,8 @@
integers/1,numbers/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,find_best/1,
- test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1]).
+ test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1,
+ none_argument/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -49,7 +50,8 @@ groups() ->
test_size,
cover_lists_functions,
list_append,
- bad_binary_unit
+ bad_binary_unit,
+ none_argument
]}].
init_per_suite(Config) ->
@@ -518,5 +520,24 @@ bad_binary_unit(_Config) ->
false = is_binary(Bitstring),
ok.
+%% ERL-1013: The compiler would crash during the type optimization pass.
+none_argument(_Config) ->
+ Binary = id(<<3:16, 42>>),
+ error = id(case Binary of
+ <<Len:16, Body/binary>> when length(Body) == Len - 2 ->
+ %% The type for Body will be none. It means
+ %% that this clause will never match and that
+ %% uncompress/1 will never be called.
+ uncompress(Body);
+ _ ->
+ error
+ end),
+ ok.
+
+uncompress(CompressedBinary) ->
+ %% The type for CompressedBinary is none, which beam_ssa_type
+ %% did not handle properly.
+ zlib:uncompress(CompressedBinary).
+
id(I) ->
I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 6b1438abdd..20f6cb2691 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -681,11 +681,16 @@ infer_on_eq_4(T) ->
%% ERIERL-348; types were inferred for dead values, causing validation to fail.
+-record(idv, {key}).
+
infer_dead_value(Config) when is_list(Config) ->
a = idv_1({a, b, c, d, e, f, g}, {0, 0, 0, 0, 0, 0, 0}),
b = idv_1({a, b, c, d, 0, 0, 0}, {a, b, c, d, 0, 0, 0}),
c = idv_1({0, 0, 0, 0, 0, f, g}, {0, 0, 0, 0, 0, f, g}),
error = idv_1(gurka, gaffel),
+
+ ok = idv_2(id(#idv{})),
+
ok.
idv_1({_A, _B, _C, _D, _E, _F, _G},
@@ -700,6 +705,23 @@ idv_1({_A, _B, _C, _D, _E, F, G},
idv_1(_A, _B) ->
error.
+%% ERL-995: The first solution to ERIERL-348 was incomplete and caused
+%% validation to fail when living values depended on delayed type inference on
+%% "dead" values.
+
+idv_2(State) ->
+ Flag = (State#idv.key == undefined),
+ case id(gurka) of
+ {_} -> id([Flag]);
+ _ -> ok
+ end,
+ if
+ Flag -> idv_called_once(State);
+ true -> ok
+ end.
+
+idv_called_once(_State) -> ok.
+
%%%-------------------------------------------------------------------------
transform_remove(Remove, Module) ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 752491f0f8..8cd864c59e 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -431,6 +431,20 @@ elusive_common_exit(_Config) ->
self() ! {1, a},
self() ! {2, b},
{[z], [{2,b},{1,a}]} = elusive_loop([x,y,z], 2, []),
+
+ CodeServer = whereis(code_server),
+ Self = self(),
+ Self ! {Self, abc},
+ Self ! {CodeServer, []},
+ Self ! {Self, other},
+ try elusive2([]) of
+ Unexpected ->
+ ct:fail("Expected an exception; got ~p\n", [Unexpected])
+ catch
+ throw:[other, CodeServer, Self] ->
+ ok
+ end,
+
ok.
elusive_loop(List, 0, Results) ->
@@ -449,4 +463,25 @@ elusive_loop(List, ToReceive, Results) ->
%% that it would not insert all necessary copy instructions.
elusive_loop(RemList, ToReceive-1, [Result | Results]).
+
+elusive2(Acc) ->
+ receive
+ {Pid, abc} ->
+ ok;
+ {Pid, []} ->
+ ok;
+ {Pid, Res} ->
+ %% beam_ssa_pre_codegen:find_loop_exit/2 attempts to find
+ %% the first block of the common code after the receive
+ %% statement. It used to only look at the two last clauses
+ %% of the receive. In this function, the last two clauses
+ %% don't have any common block, so it would be assumed
+ %% that there was no common block for any of the
+ %% clauses. That would mean that copy instructions would
+ %% not be inserted as needed.
+ throw([Res | Acc])
+ end,
+ %% Common code.
+ elusive2([Pid | Acc]).
+
id(I) -> I.
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
index 3348c6e9ea..34410e4b2a 100644
--- a/lib/compiler/test/test_lib.erl
+++ b/lib/compiler/test/test_lib.erl
@@ -97,7 +97,8 @@ get_data_dir(Config) ->
Data2 = re:replace(Data1, "_post_opt_SUITE", "_SUITE", Opts),
Data3 = re:replace(Data2, "_inline_SUITE", "_SUITE", Opts),
Data4 = re:replace(Data3, "_r21_SUITE", "_SUITE", Opts),
- Data = re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts),
+ Data5 = re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts),
+ Data = re:replace(Data5, "_no_type_opt_SUITE", "_SUITE", Opts),
re:replace(Data, "_no_ssa_opt_SUITE", "_SUITE", Opts).
is_cloned_mod(Mod) ->
diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c
index db71007505..76dc0e2ab8 100644
--- a/lib/erl_interface/src/decode/decode_fun.c
+++ b/lib/erl_interface/src/decode/decode_fun.c
@@ -52,7 +52,10 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
switch (get8(s)) {
case ERL_FUN_EXT:
/* mark as old (R7 and older) external fun */
- if (p != NULL) p->arity = -1;
+ if (p != NULL) {
+ p->type = EI_FUN_CLOSURE;
+ p->arity = -1;
+ }
/* first number of free vars (environment) */
n = get32be(s);
/* then the pid */
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
index 187705a0b5..5e777c1164 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java
@@ -106,9 +106,9 @@ public class OtpOutputStream extends ByteArrayOutputStream {
}
/**
- * Trims the capacity of this <tt>OtpOutputStream</tt> instance to be the
+ * Trims the capacity of this <code>OtpOutputStream</code> instance to be the
* buffer's current size. An application can use this operation to minimize
- * the storage of an <tt>OtpOutputStream</tt> instance.
+ * the storage of an <code>OtpOutputStream</code> instance.
*/
public void trimToSize() {
resize(super.count);
@@ -125,7 +125,7 @@ public class OtpOutputStream extends ByteArrayOutputStream {
}
/**
- * Increases the capacity of this <tt>OtpOutputStream</tt> instance, if
+ * Increases the capacity of this <code>OtpOutputStream</code> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
@@ -939,7 +939,7 @@ public class OtpOutputStream extends ByteArrayOutputStream {
* @param o
* the Erlang term to write.
* @param level
- * the compression level (<tt>0..9</tt>)
+ * the compression level (<code>0..9</code>)
*/
public void write_compressed(final OtpErlangObject o, final int level) {
@SuppressWarnings("resource")
diff --git a/lib/kernel/doc/src/logger_disk_log_h.xml b/lib/kernel/doc/src/logger_disk_log_h.xml
index aa577f3c62..3d8e82ce7c 100644
--- a/lib/kernel/doc/src/logger_disk_log_h.xml
+++ b/lib/kernel/doc/src/logger_disk_log_h.xml
@@ -133,7 +133,7 @@ logger:add_handler(my_disk_log_h, logger_disk_log_h,
#{config => #{file => "./my_disk_log",
type => wrap,
max_no_files => 4,
- max_no_bytes => 10000},
+ max_no_bytes => 10000,
filesync_repeat_interval => 1000}}).
</code>
<p>To use the disk_log handler instead of the default standard
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 8eab36e308..5bff9cc292 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_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.
@@ -2512,8 +2512,10 @@ re_register_name(Config) when is_list(Config) ->
Me = self(),
Pid1 = spawn(fun() -> proc(Me) end),
yes = global:register_name(name, Pid1),
+ wait_for_monitor(Pid1),
Pid2 = spawn(fun() -> proc(Me) end),
_ = global:re_register_name(name, Pid2),
+ wait_for_monitor(Pid2),
Pid2 ! die,
Pid1 ! die,
receive {Pid1, MonitoredBy1} -> [] = MonitoredBy1 end,
@@ -2522,6 +2524,15 @@ re_register_name(Config) when is_list(Config) ->
init_condition(Config),
ok.
+wait_for_monitor(Pid) ->
+ case process_info(Pid, monitored_by) of
+ {monitored_by, []} ->
+ timer:sleep(1),
+ wait_for_monitor(Pid);
+ {monitored_by, [_]} ->
+ ok
+ end.
+
proc(Parent) ->
receive die -> ok end,
{monitored_by, MonitoredBy} = process_info(self(), monitored_by),
diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl
index 298a364a91..173e25c520 100644
--- a/lib/kernel/test/interactive_shell_SUITE.erl
+++ b/lib/kernel/test/interactive_shell_SUITE.erl
@@ -23,7 +23,8 @@
init_per_group/2,end_per_group/2,
get_columns_and_rows/1, exit_initial/1, job_control_local/1,
job_control_remote/1,
- job_control_remote_noshell/1,ctrl_keys/1]).
+ job_control_remote_noshell/1,ctrl_keys/1,
+ get_columns_and_rows_escript/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
%% For spawn
@@ -40,7 +41,8 @@ suite() ->
{timetrap,{minutes,3}}].
all() ->
- [get_columns_and_rows, exit_initial, job_control_local,
+ [get_columns_and_rows_escript,get_columns_and_rows,
+ exit_initial, job_control_local,
job_control_remote, job_control_remote_noshell,
ctrl_keys].
@@ -72,6 +74,60 @@ end_per_group(_GroupName, Config) ->
-define(dbg(Data),noop).
-endif.
+string_to_term(Str) ->
+ {ok,Tokens,_EndLine} = erl_scan:string(Str ++ "."),
+ {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
+ {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
+ Value.
+
+run_unbuffer_escript(Rows, Columns, EScript, NoTermStdIn, NoTermStdOut) ->
+ DataDir = filename:join(filename:dirname(code:which(?MODULE)), "interactive_shell_SUITE_data"),
+ TmpFile = filename:join(DataDir, "tmp"),
+ ok = file:write_file(TmpFile, <<>>),
+ CommandModifier =
+ case {NoTermStdIn, NoTermStdOut} of
+ {false, false} -> "";
+ {true, false} -> io_lib:format(" < ~s", [TmpFile]);
+ {false, true} -> io_lib:format(" > ~s ; cat ~s", [TmpFile, TmpFile]);
+ {true, true} -> io_lib:format(" > ~s < ~s ; cat ~s", [TmpFile, TmpFile, TmpFile])
+ end,
+ Command = io_lib:format("unbuffer -p bash -c \"stty rows ~p; stty columns ~p; escript ~s ~s\"",
+ [Rows, Columns, EScript, CommandModifier]),
+ %% io:format("Command: ~s ~n", [Command]),
+ Out = os:cmd(Command),
+ %% io:format("Out: ~p ~n", [Out]),
+ string_to_term(Out).
+
+get_columns_and_rows_escript(Config) when is_list(Config) ->
+ ExpectUnbufferInstalled =
+ try
+ "79" = string:trim(os:cmd("unbuffer -p bash -c \"stty columns 79 ; tput cols\"")),
+ true
+ catch
+ _:_ -> false
+ end,
+ case ExpectUnbufferInstalled of
+ false ->
+ {skip,
+ "The unbuffer tool (https://core.tcl-lang.org/expect/index) does not seem to be installed.~n"
+ "On Ubuntu/Debian: \"sudo apt-get install expect\""};
+ true ->
+ DataDir = filename:join(filename:dirname(code:which(?MODULE)), "interactive_shell_SUITE_data"),
+ IoColumnsErl = filename:join(DataDir, "io_columns.erl"),
+ IoRowsErl = filename:join(DataDir, "io_rows.erl"),
+ [
+ begin
+ {ok, 42} = run_unbuffer_escript(99, 42, IoColumnsErl, NoTermStdIn, NoTermStdOut),
+ {ok, 99} = run_unbuffer_escript(99, 42, IoRowsErl, NoTermStdIn, NoTermStdOut)
+ end
+ ||
+ {NoTermStdIn, NoTermStdOut} <- [{false, false}, {true, false}, {false, true}]
+ ],
+ {error,enotsup} = run_unbuffer_escript(99, 42, IoRowsErl, true, true),
+ {error,enotsup} = run_unbuffer_escript(99, 42, IoColumnsErl, true, true),
+ ok
+ end.
+
%% Test that the shell can access columns and rows.
get_columns_and_rows(Config) when is_list(Config) ->
case proplists:get_value(default_shell,Config) of
diff --git a/lib/kernel/test/interactive_shell_SUITE_data/.gitignore b/lib/kernel/test/interactive_shell_SUITE_data/.gitignore
new file mode 100644
index 0000000000..1c2f433de1
--- /dev/null
+++ b/lib/kernel/test/interactive_shell_SUITE_data/.gitignore
@@ -0,0 +1 @@
+tmp \ No newline at end of file
diff --git a/lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl b/lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl
new file mode 100644
index 0000000000..32d0cf25df
--- /dev/null
+++ b/lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl
@@ -0,0 +1,6 @@
+-module(io_columns).
+
+-export([main/1]).
+
+main(_) ->
+ io:format("~p",[io:columns()]).
diff --git a/lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl b/lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl
new file mode 100644
index 0000000000..53ceb464b0
--- /dev/null
+++ b/lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl
@@ -0,0 +1,6 @@
+-module(io_rows).
+
+-export([main/1]).
+
+main(_) ->
+ io:format("~p",[io:rows()]).
diff --git a/lib/megaco/test/Makefile b/lib/megaco/test/Makefile
index 4ddd73eea1..b4e31765b8 100644
--- a/lib/megaco/test/Makefile
+++ b/lib/megaco/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. 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.
@@ -102,6 +102,9 @@ endif
ERL_COMPILE_FLAGS += $(MEGACO_ERL_COMPILE_FLAGS)
+# We have a behaviour in the test catalog (megaco_test_generator)
+ERL_COMPILE_FLAGS += -pa ../../megaco/test
+
ERL_PATH = -pa ../../megaco/examples/simple \
-pa ../../megaco/ebin \
-pa ../../et/ebin
diff --git a/lib/megaco/test/megaco_SUITE.erl b/lib/megaco/test/megaco_SUITE.erl
index 38590f9fee..f7b8ffe032 100644
--- a/lib/megaco/test/megaco_SUITE.erl
+++ b/lib/megaco/test/megaco_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,21 @@
-module(megaco_SUITE).
--compile(export_all).
+-export([
+ suite/0,
+ all/0,
+ groups/0,
+
+ init_per_suite/1,
+ end_per_suite/1,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ t/0, t/1,
+ init/0
+ ]).
-include("megaco_test_lib.hrl").
-include_lib("megaco/include/megaco.hrl").
@@ -96,6 +110,20 @@ groups() ->
{flex, [], [{megaco_flex_test, all}]}].
init_per_suite(Config) ->
+ io:format("~w:init_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n OS Type: ~p"
+ "~n OS Version: ~s"
+ "~n",
+ [?MODULE,
+ Config,
+ os:type(),
+ case os:version() of
+ {Major, Minor, Release} ->
+ ?F("~w.~w.~w", [Major, Minor, Release]);
+ Str when is_list(Str) ->
+ Str
+ end]),
Config.
end_per_suite(_Config) ->
diff --git a/lib/megaco/test/megaco_actions_test.erl b/lib/megaco/test/megaco_actions_test.erl
index fcbe4f12fa..498e5c91cb 100644
--- a/lib/megaco/test/megaco_actions_test.erl
+++ b/lib/megaco/test/megaco_actions_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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.
@@ -20,13 +20,30 @@
%%
%%----------------------------------------------------------------------
-%% Purpose: Verify that it is possible to separatelly encode
+%% Purpose: Verify that it is possible to separately encode
%% the action requests list. Do this with all codec's
%% that supports partial encode.
%%----------------------------------------------------------------------
-module(megaco_actions_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ t/0, t/1,
+
+ pretty_text/1,
+ flex_pretty_text/1,
+ compact_text/1,
+ flex_compact_text/1,
+ erl_dist/1,
+ erl_dist_mc/1
+ ]).
-include("megaco_test_lib.hrl").
-include_lib("megaco/include/megaco.hrl").
@@ -364,9 +381,6 @@ sleep(X) ->
receive after X -> ok end.
-error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A).
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
i(F) ->
@@ -376,8 +390,8 @@ i(F, A) ->
print(info, get(verbosity), "", F, A).
-d(F) ->
- d(F, []).
+%% d(F) ->
+%% d(F, []).
d(F, A) ->
print(debug, get(verbosity), "DBG: ", F, A).
@@ -391,20 +405,10 @@ print(Severity, Verbosity, P, F, A) ->
print(printable(Severity,Verbosity), P, F, A).
print(true, P, F, A) ->
- io:format("~s~p:~s: " ++ F ++ "~n", [P, self(), get(sname) | A]);
+ io:format("*** [~s] ~s ~p ~s ***"
+ "~n " ++ F ++ "~n",
+ [?FTS(), P, self(), get(sname) | A]);
print(_, _, _, _) ->
ok.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-random_init() ->
- {A,B,C} = now(),
- random:seed(A,B,C).
-
-random() ->
- 10 * random:uniform(50).
-
-apply_load_timer() ->
- erlang:send_after(random(), self(), apply_load_timeout).
-
diff --git a/lib/megaco/test/megaco_app_test.erl b/lib/megaco/test/megaco_app_test.erl
index 981d93f5dd..fff2d8c7d4 100644
--- a/lib/megaco/test/megaco_app_test.erl
+++ b/lib/megaco/test/megaco_app_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-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.
@@ -20,29 +20,42 @@
%%----------------------------------------------------------------------
%% Purpose: Verify the application specifics of the Megaco application
%%----------------------------------------------------------------------
+
-module(megaco_app_test).
--compile(export_all).
+-export([
+ all/0,
+
+ app/0, app/1,
+ appup/0, appup/1
+ ]).
-include_lib("common_test/include/ct.hrl").
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
+
all() ->
[
app,
appup
].
+
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
+
app() ->
[{doc, "Test that the megaco app file is ok"}].
app(Config) when is_list(Config) ->
ok = test_server:app_test(megaco).
+
+
%%--------------------------------------------------------------------
+
appup() ->
[{doc, "Test that the megaco appup file is ok"}].
appup(Config) when is_list(Config) ->
diff --git a/lib/megaco/test/megaco_appup_test.erl b/lib/megaco/test/megaco_appup_test.erl
index 8dc3ad51a0..a06d274844 100644
--- a/lib/megaco/test/megaco_appup_test.erl
+++ b/lib/megaco/test/megaco_appup_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-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.
@@ -22,8 +22,23 @@
%%----------------------------------------------------------------------
-module(megaco_appup_test).
--compile(export_all).
--compile({no_auto_import,[error/1]}).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_suite/1,
+ end_per_suite/1,
+
+ init_per_group/2,
+ end_per_group/2,
+
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ appup_file/1
+ ]).
+
+-compile({no_auto_import, [error/1]}).
-include_lib("common_test/include/ct.hrl").
-include("megaco_test_lib.hrl").
@@ -76,6 +91,10 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Perform a simple check of the appup file
+appup_file(suite) ->
+ [];
+appup_file(doc) ->
+ ["Perform a simple check of the appup file"];
appup_file(Config) when is_list(Config) ->
ok = ?t:appup_test(megaco).
diff --git a/lib/megaco/test/megaco_call_flow_test.erl b/lib/megaco/test/megaco_call_flow_test.erl
index eb4574862d..03caf705ba 100644
--- a/lib/megaco/test/megaco_call_flow_test.erl
+++ b/lib/megaco/test/megaco_call_flow_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,7 +38,85 @@
-module(megaco_call_flow_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ pretty/1,
+ compact/1,
+ pretty_flex/1,
+ compact_flex/1,
+ bin/1,
+ ber/1,
+ per/1,
+ standard_erl/1,
+ compressed_erl/1,
+
+ t/0, t/1
+
+ ]).
+
+-export([
+ msg1/0, msg1/1,
+ msg2/0, msg2/1,
+ msg3/0, msg3/1,
+ msg4/0, msg4/1,
+ msg5a/0, msg5a/1,
+ msg5b/0, msg5b/1,
+ msg6/0, msg6/1,
+ msg7/0, msg7/1,
+ msg9/0, msg9/1,
+ msg10/0, msg10/1,
+ msg11/0, msg11/1,
+ msg12/0, msg12/1,
+ msg13/0, msg13/1,
+ msg14/0, msg14/1,
+ msg15/0, msg15/1,
+ msg16/0, msg16/1,
+ msg17a/0, msg17a/1,
+ msg17b/0, msg17b/1,
+ msg18a/0, msg18a/1,
+ msg18b/0, msg18b/1,
+ msg18c/0, msg18c/1,
+ msg18d/0, msg18d/1,
+ msg19a/0, msg19a/1,
+ msg19b/0, msg19b/1,
+ msg20/0, msg20/1,
+ msg21/0, msg21/1,
+ msg22a/0, msg22a/1,
+ msg22b/0, msg22b/1,
+ msg23a/0, msg23a/1,
+ msg23b/0, msg23b/1
+
+ ]).
+
+-export([
+ encoders/0,
+ msg_sizes/0,
+ coding_times/0,
+ encoding_times/0,
+ decoding_times/0,
+ coding_times_stat/0,
+ encoding_times_stat/0,
+ decoding_times_stat/0,
+ size_stat/0,
+ gnuplot_gif/0,
+ gnuplot_size_gif/0,
+
+ gen_byte_msg/2,
+ gen_header_file_binary/1,
+ gen_ber_header/0,
+ gen_ber_bin_header/0,
+ gen_per_header/0,
+ single_meter/4,
+ count/2
+ ]).
+
-include_lib("megaco/include/megaco.hrl").
-include_lib("megaco/include/megaco_message_v1.hrl").
-include("megaco_test_lib.hrl").
@@ -53,16 +131,20 @@ init_per_testcase(Case, Config) ->
end_per_testcase(Case, Config) ->
megaco_test_lib:end_per_testcase(Case, Config).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Top test case
all() ->
- [{group, text}, {group, binary}].
+ [{group, text}, {group, binary}, {group, erl}].
groups() ->
- [{text, [], [pretty, compact]},
- {flex, [], [pretty_flex, compact_flex]},
- {binary, [], [bin, ber, per]}].
+ [
+ {text, [], [pretty, compact]},
+ {flex, [], [pretty_flex, compact_flex]},
+ {binary, [], [bin, ber, per]},
+ {erl, [], [standard_erl, compressed_erl]}
+ ].
init_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/megaco/test/megaco_codec_test.erl b/lib/megaco/test/megaco_codec_test.erl
index 007136f83e..0dfbabcc81 100644
--- a/lib/megaco/test/megaco_codec_test.erl
+++ b/lib/megaco/test/megaco_codec_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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.
@@ -25,7 +25,18 @@
-module(megaco_codec_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ t/0, t/1,
+ init/0
+ ]).
-include("megaco_test_lib.hrl").
-include_lib("megaco/include/megaco.hrl").
diff --git a/lib/megaco/test/megaco_codec_test_lib.erl b/lib/megaco/test/megaco_codec_test_lib.erl
index 6eee5caaaa..7a3d4e6cf8 100644
--- a/lib/megaco/test/megaco_codec_test_lib.erl
+++ b/lib/megaco/test/megaco_codec_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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.
@@ -993,15 +993,15 @@ expect_exec([#expect_instruction{description = Desc,
skip({What, Why}) when is_atom(What) andalso is_list(Why) ->
Reason = lists:flatten(io_lib:format("~p: ~s", [What, Why])),
- exit({skipped, Reason});
+ ?SKIP(Reason);
skip({What, Why}) ->
Reason = lists:flatten(io_lib:format("~p: ~p", [What, Why])),
- exit({skipped, Reason});
+ ?SKIP(Reason);
skip(Reason) when is_list(Reason) ->
- exit({skipped, Reason});
+ ?SKIP(Reason);
skip(Reason1) ->
Reason2 = lists:flatten(io_lib:format("~p", [Reason1])),
- exit({skipped, Reason2}).
+ ?SKIP(Reason2).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/megaco/test/megaco_config_test.erl b/lib/megaco/test/megaco_config_test.erl
index 02e06a722a..d46806927a 100644
--- a/lib/megaco/test/megaco_config_test.erl
+++ b/lib/megaco/test/megaco_config_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,24 @@
-module(megaco_config_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ config/1,
+ transaction_id_counter_mg/1,
+ transaction_id_counter_mgc/1,
+ otp_7216/1,
+ otp_8167/1,
+ otp_8183/1,
+
+ t/0, t/1
+ ]).
-include("megaco_test_lib.hrl").
-include_lib("megaco/include/megaco.hrl").
@@ -37,6 +54,19 @@ t(Case) -> megaco_test_lib:t({?MODULE, Case}).
min(M) -> timer:minutes(M).
%% Test server callbacks
+init_per_testcase(Case, Config) when (Case =:= otp_7216) orelse
+ (Case =:= otp_8167) orelse
+ (Case =:= otp_8183) ->
+ i("try starting megaco_config"),
+ case megaco_config:start_link() of
+ {ok, _} ->
+ C = lists:keydelete(tc_timeout, 1, Config),
+ do_init_per_testcase(Case, [{tc_timeout, min(3)}|C]);
+ {error, Reason} ->
+ i("Failed starting megaco_config: "
+ "~n ~p", [Reason]),
+ {skip, ?F("Failed starting config: ~p", [Reason])}
+ end;
init_per_testcase(Case, Config) ->
C = lists:keydelete(tc_timeout, 1, Config),
do_init_per_testcase(Case, [{tc_timeout, min(3)}|C]).
@@ -45,6 +75,12 @@ do_init_per_testcase(Case, Config) ->
process_flag(trap_exit, true),
megaco_test_lib:init_per_testcase(Case, Config).
+end_per_testcase(Case, Config) when (Case =:= otp_7216) orelse
+ (Case =:= otp_8167) orelse
+ (Case =:= otp_8183) ->
+ (catch megaco_config:stop()),
+ process_flag(trap_exit, false),
+ megaco_test_lib:end_per_testcase(Case, Config);
end_per_testcase(Case, Config) ->
process_flag(trap_exit, false),
megaco_test_lib:end_per_testcase(Case, Config).
@@ -60,14 +96,17 @@ end_per_testcase(Case, Config) ->
%% Top test case
all() ->
- [config, {group, transaction_id_counter},
- {group, tickets}].
+ [
+ config,
+ {group, transaction_id_counter},
+ {group, tickets}
+ ].
groups() ->
- [{transaction_id_counter, [],
- [transaction_id_counter_mg,
- transaction_id_counter_mgc]},
- {tickets, [], [otp_7216, otp_8167, otp_8183]}].
+ [
+ {transaction_id_counter, [], transaction_id_counter_cases()},
+ {tickets, [], tickets_cases()}
+ ].
init_per_group(_GroupName, Config) ->
Config.
@@ -75,6 +114,19 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+transaction_id_counter_cases() ->
+ [
+ transaction_id_counter_mg,
+ transaction_id_counter_mgc
+ ].
+
+tickets_cases() ->
+ [
+ otp_7216,
+ otp_8167,
+ otp_8183
+ ].
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Config test case
@@ -736,9 +788,6 @@ otp_7216(Config) when is_list(Config) ->
put(tc, otp_7216),
p("start"),
- p("start the megaco config process"),
- megaco_config:start_link(),
-
LocalMid1 = {deviceName, "local-mid-1"},
%% LocalMid2 = {deviceName, "local-mid-2"},
RemoteMid1 = {deviceName, "remote-mid-1"},
@@ -859,9 +908,6 @@ otp_8167(Config) when is_list(Config) ->
put(tc, otp8167),
p("start"),
- p("start the megaco config process"),
- megaco_config:start_link(),
-
LocalMid1 = {deviceName, "local-mid-1"},
LocalMid2 = {deviceName, "local-mid-2"},
RemoteMid1 = {deviceName, "remote-mid-1"},
@@ -981,9 +1027,6 @@ otp_8183(Config) when is_list(Config) ->
put(tc, otp8183),
p("start"),
- p("start the megaco config process"),
- megaco_config:start_link(),
-
LocalMid1 = {deviceName, "local-mid-1"},
LocalMid2 = {deviceName, "local-mid-2"},
RemoteMid1 = {deviceName, "remote-mid-1"},
@@ -1122,28 +1165,18 @@ i(F) ->
i(F, []).
i(F, A) ->
- print(info, get(verbosity), now(), get(tc), "INF", F, A).
+ print(info, get(verbosity), get(tc), "INF", F, A).
printable(_, debug) -> true;
printable(info, info) -> true;
printable(_,_) -> false.
-print(Severity, Verbosity, Ts, Tc, P, F, A) ->
- print(printable(Severity,Verbosity), Ts, Tc, P, F, A).
+print(Severity, Verbosity, Tc, P, F, A) ->
+ print(printable(Severity,Verbosity), Tc, P, F, A).
-print(true, Ts, Tc, P, F, A) ->
+print(true, Tc, P, F, A) ->
io:format("*** [~s] ~s ~p ~s:~w ***"
"~n " ++ F ++ "~n",
- [format_timestamp(Ts), P, self(), get(sname), Tc | A]);
-print(_, _, _, _, _, _) ->
+ [?FTS(), P, self(), get(sname), Tc | A]);
+print(_, _, _, _, _) ->
ok.
-
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
-
diff --git a/lib/megaco/test/megaco_digit_map_test.erl b/lib/megaco/test/megaco_digit_map_test.erl
index 998e829b67..e03d38497c 100644
--- a/lib/megaco/test/megaco_digit_map_test.erl
+++ b/lib/megaco/test/megaco_digit_map_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-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,7 +24,27 @@
%%----------------------------------------------------------------------
-module(megaco_digit_map_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ otp_5750_01/1,
+ otp_5750_02/1,
+ otp_5799_01/1,
+ otp_5826_01/1,
+ otp_5826_02/1,
+ otp_5826_03/1,
+ otp_7449_1/1,
+ otp_7449_2/1,
+
+ t/0, t/1
+ ]).
+
-include("megaco_test_lib.hrl").
@@ -44,16 +64,18 @@ end_per_testcase(Case, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [{group, tickets}].
+ [
+ {group, tickets}
+ ].
groups() ->
- [{tickets, [],
- [{group, otp_5750}, {group, otp_5799},
- {group, otp_5826}, {group, otp_7449}]},
- {otp_5750, [], [otp_5750_01, otp_5750_02]},
- {otp_5799, [], [otp_5799_01]},
- {otp_5826, [], [otp_5826_01, otp_5826_02, otp_5826_03]},
- {otp_7449, [], [otp_7449_1, otp_7449_2]}].
+ [
+ {tickets, [], tickets_cases()},
+ {otp_5750, [], otp_5750_cases()},
+ {otp_5799, [], otp_5799_cases()},
+ {otp_5826, [], otp_5826_cases()},
+ {otp_7449, [], otp_7449_cases()}
+ ].
init_per_group(_GroupName, Config) ->
Config.
@@ -62,6 +84,38 @@ end_per_group(_GroupName, Config) ->
Config.
+tickets_cases() ->
+ [
+ {group, otp_5750},
+ {group, otp_5799},
+ {group, otp_5826},
+ {group, otp_7449}
+ ].
+
+otp_5750_cases() ->
+ [
+ otp_5750_01,
+ otp_5750_02
+ ].
+
+otp_5799_cases() ->
+ [
+ otp_5799_01
+ ].
+
+otp_5826_cases() ->
+ [
+ otp_5826_01,
+ otp_5826_02,
+ otp_5826_03
+ ].
+
+otp_7449_cases() ->
+ [
+ otp_7449_1,
+ otp_7449_2
+ ].
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/megaco/test/megaco_examples_test.erl b/lib/megaco/test/megaco_examples_test.erl
index 10ca0375f6..fdf9fe29ff 100644
--- a/lib/megaco/test/megaco_examples_test.erl
+++ b/lib/megaco/test/megaco_examples_test.erl
@@ -25,7 +25,20 @@
-module(megaco_examples_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ simple/1,
+
+ t/0, t/1
+ ]).
+
-include("megaco_test_lib.hrl").
-include_lib("megaco/include/megaco.hrl").
diff --git a/lib/megaco/test/megaco_flex_test.erl b/lib/megaco/test/megaco_flex_test.erl
index 999d1abc6c..27c46a3b47 100644
--- a/lib/megaco/test/megaco_flex_test.erl
+++ b/lib/megaco/test/megaco_flex_test.erl
@@ -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.
@@ -219,18 +219,5 @@ p(F, A) ->
TC = get(tc),
io:format("*** [~s] ~p ~w ***"
"~n " ++ F ++ "~n",
- [formated_timestamp(), self(), TC | A]).
-
-formated_timestamp() ->
- format_timestamp(erlang:now()).
-
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY, MM, DD} = Date,
- {Hour, Min, Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
-
+ [?FTS(), self(), TC | A]).
diff --git a/lib/megaco/test/megaco_load_test.erl b/lib/megaco/test/megaco_load_test.erl
index 511e5a2e8e..9cce9e70ce 100644
--- a/lib/megaco/test/megaco_load_test.erl
+++ b/lib/megaco/test/megaco_load_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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,7 +24,33 @@
%%----------------------------------------------------------------------
-module(megaco_load_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ single_user_light_load/1,
+ single_user_medium_load/1,
+ single_user_heavy_load/1,
+ single_user_extreme_load/1,
+
+ multi_user_light_load/1,
+ multi_user_medium_load/1,
+ multi_user_heavy_load/1,
+ multi_user_extreme_load/1,
+
+ t/0, t/1
+ ]).
+
+-export([
+ do_multi_load/3,
+ multi_load_collector/7
+ ]).
+
-include("megaco_test_lib.hrl").
-include_lib("megaco/include/megaco.hrl").
@@ -66,8 +92,6 @@
t() -> megaco_test_lib:t(?MODULE).
t(Case) -> megaco_test_lib:t({?MODULE, Case}).
-min(M) -> timer:minutes(M).
-
%% Test server callbacks
init_per_testcase(single_user_light_load = Case, Config) ->
C = lists:keydelete(tc_timeout, 1, Config),
@@ -108,15 +132,33 @@ end_per_testcase(Case, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [single_user_light_load,
- single_user_medium_load, single_user_heavy_load,
- single_user_extreme_load, multi_user_light_load,
- multi_user_medium_load, multi_user_heavy_load,
- multi_user_extreme_load].
+ [
+ {group, single},
+ {group, multi}
+ ].
groups() ->
- [].
-
+ [
+ {single, [], single_cases()},
+ {multi, [], multi_cases()}
+ ].
+
+single_cases() ->
+ [
+ single_user_light_load,
+ single_user_medium_load,
+ single_user_heavy_load,
+ single_user_extreme_load
+ ].
+
+multi_cases() ->
+ [
+ multi_user_light_load,
+ multi_user_medium_load,
+ multi_user_heavy_load,
+ multi_user_extreme_load
+ ].
+
init_per_group(_GroupName, Config) ->
Config.
@@ -326,6 +368,17 @@ load_controller(Config, Fun) when is_list(Config) and is_function(Fun) ->
d("load_controller -> "
"loader [~p] terminated with ok~n", [Loader]),
ok;
+ {'EXIT', Loader, {skipped, {fatal, Reason, File, Line}}} ->
+ i("load_controller -> "
+ "loader [~p] terminated with fatal skip"
+ "~n Reason: ~p"
+ "~n At: ~p:~p", [Loader, Reason, File, Line]),
+ ?SKIP(Reason);
+ {'EXIT', Loader, {skipped, Reason}} ->
+ i("load_controller -> "
+ "loader [~p] terminated with skip"
+ "~n Reason: ~p", [Loader, Reason]),
+ ?SKIP(Reason);
{'EXIT', Loader, Reason} ->
i("load_controller -> "
"loader [~p] terminated with"
@@ -629,14 +682,6 @@ make_mids([MgNode|MgNodes], Mids) ->
exit("Test node must be started with '-sname'")
end.
-tim() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
-sleep(X) -> receive after X -> ok end.
-
-error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A).
-
maybe_display_system_info(NumLoaders) when NumLoaders > 50 ->
[{display_system_info, timer:seconds(2)}];
maybe_display_system_info(NumLoaders) when NumLoaders > 10 ->
@@ -647,50 +692,32 @@ maybe_display_system_info(_) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+min(M) -> timer:minutes(M).
+
i(F) ->
i(F, []).
i(F, A) ->
- print(info, get(verbosity), now(), get(tc), "INF", F, A).
+ print(info, get(verbosity), get(tc), "INF", F, A).
d(F) ->
d(F, []).
d(F, A) ->
- print(debug, get(verbosity), now(), get(tc), "DBG", F, A).
+ print(debug, get(verbosity), get(tc), "DBG", F, A).
printable(_, debug) -> true;
printable(info, info) -> true;
printable(_,_) -> false.
-print(Severity, Verbosity, Ts, Tc, P, F, A) ->
- print(printable(Severity,Verbosity), Ts, Tc, P, F, A).
+print(Severity, Verbosity, Tc, P, F, A) ->
+ print(printable(Severity,Verbosity), Tc, P, F, A).
-print(true, Ts, Tc, P, F, A) ->
+print(true, Tc, P, F, A) ->
io:format("*** [~s] ~s ~p ~s:~w ***"
"~n " ++ F ++ "~n",
- [format_timestamp(Ts), P, self(), get(sname), Tc | A]);
-print(_, _, _, _, _, _) ->
+ [?FTS(), P, self(), get(sname), Tc | A]);
+print(_, _, _, _, _) ->
ok.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-random_init() ->
- {A,B,C} = now(),
- random:seed(A,B,C).
-
-random() ->
- 10 * random:uniform(50).
-
-apply_load_timer() ->
- erlang:send_after(random(), self(), apply_load_timeout).
-
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
diff --git a/lib/megaco/test/megaco_mess_test.erl b/lib/megaco/test/megaco_mess_test.erl
index d3216c2a6d..3fd39a9e58 100644
--- a/lib/megaco/test/megaco_mess_test.erl
+++ b/lib/megaco/test/megaco_mess_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. 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.
@@ -281,6 +281,8 @@
-define(VERSION, 1).
+-define(USER_MOD, megaco_mess_user_test).
+
-define(TEST_VERBOSITY, debug).
-define(MGC_VERBOSITY, debug).
-define(MG_VERBOSITY, debug).
@@ -303,26 +305,48 @@
-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)).
-define(SEND(Expr),
- ?VERIFY(ok, megaco_mess_user_test:apply_proxy(fun() -> Expr end))).
+ ?VERIFY(ok, ?USER_MOD:apply_proxy(fun() -> Expr end))).
-define(USER(Expected, Reply),
- megaco_mess_user_test:reply(?MODULE,
- ?LINE,
- fun(Actual) ->
- case ?VERIFY(Expected, Actual) of
- Expected -> {ok, Reply};
- UnExpected -> {error, {reply_verify,
- ?MODULE,
- ?LINE,
- UnExpected}}
- end
- end)).
-
-%% t() -> megaco_test_lib:t(?MODULE).
-%% t(Case) -> megaco_test_lib:t({?MODULE, Case}).
-
-
-min(M) -> timer:minutes(M).
+ ?USER_MOD:reply(?MODULE,
+ ?LINE,
+ fun(Actual) ->
+ case ?VERIFY(Expected, Actual) of
+ Expected -> {ok, Reply};
+ UnExpected -> {error, {reply_verify,
+ ?MODULE,
+ ?LINE,
+ UnExpected}}
+ end
+ end)).
+
+%% Some generator (utility) macros
+-define(GM_START(), megaco_start).
+-define(GM_STOP(), megaco_stop).
+-define(GM_START_USER(M, RI, C), {megaco_start_user, M, RI, C}).
+-define(GM_START_USER(M, RI), ?GM_START_USER(M, RI, [])).
+-define(GM_STOP_USER(), megaco_stop_user).
+-define(GMSI(I), {megaco_system_info, I}).
+-define(GMSI_USERS(), ?GMSI(users)).
+-define(GMSI_CONNS(), ?GMSI(connections)).
+-define(GMCAST(Reqs, Opts), {megaco_cast, Reqs, Opts}).
+-define(GMCAST(Reqs), ?GMCAST(Reqs, [])).
+-define(GMCB(CB, VF), {megaco_callback, CB, VF}).
+-define(GMCB_CONNECT(VF), ?GMCB(handle_connect, VF)).
+-define(GMCB_TRANS_REP(VF), ?GMCB(handle_trans_reply, VF)).
+-define(GMT(T), {megaco_trace, T}).
+-define(GMT_ENABLE(), ?GMT(enable)).
+-define(GMT_DISABLE(), ?GMT(disable)).
+-define(GD(D), {debug, D}).
+-define(GD_ENABLE(), ?GD(true)).
+-define(GD_DISABLE(), ?GD(false)).
+-define(GS(T), {sleep, T}).
+
+-define(GSND(T, D), {send, T, D}).
+-define(GERCV(T, VF, TO), {expect_receive, T, {VF, TO}}).
+
+
+min(M) -> ?MINS(M).
%% Test server callbacks
init_per_testcase(otp_7189 = Case, Config) ->
@@ -396,8 +420,19 @@ groups() ->
init_per_suite(Config) ->
io:format("~w:init_per_suite -> entry with"
- "~n Config: ~p"
- "~n", [?MODULE, Config]),
+ "~n Config: ~p"
+ "~n OS Type: ~p"
+ "~n OS Version: ~s"
+ "~n",
+ [?MODULE,
+ Config,
+ os:type(),
+ case os:version() of
+ {Major, Minor, Release} ->
+ ?F("~w.~w.~w", [Major, Minor, Release]);
+ Str when is_list(Str) ->
+ Str
+ end]),
Config.
end_per_suite(_Config) ->
@@ -491,12 +526,12 @@ request_and_reply_plain(suite) ->
request_and_reply_plain(Config) when is_list(Config) ->
?ACQUIRE_NODES(1, Config),
d("request_and_reply_plain -> start proxy",[]),
- megaco_mess_user_test:start_proxy(),
+ ?USER_MOD:start_proxy(),
PrelMid = preliminary_mid,
MgMid = ipv4_mid(4711),
MgcMid = ipv4_mid(),
- UserMod = megaco_mess_user_test,
+ UserMod = ?USER_MOD,
d("request_and_reply_plain -> start megaco app",[]),
?VERIFY(ok, application:start(megaco)),
UserConfig = [{user_mod, UserMod}, {send_mod, UserMod},
@@ -564,6 +599,7 @@ request_and_reply_plain(Config) when is_list(Config) ->
ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% OTP-4760
@@ -1715,9 +1751,6 @@ rarpaop_mg_event_sequence(Port, EncMod, EncConf) ->
ScrVerifyFun = ?rarpaop_mg_verify_service_change_rep_msg_fun(),
PendVerifyFun = ?rarpaop_mg_verify_pending_msg_fun(TransId),
NrVerifyFun = ?rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId),
-%% ScrVerifyFun = rarpaop_mg_verify_service_change_rep_msg_fun(),
-%% PendVerifyFun = rarpaop_mg_verify_pending_msg_fun(TransId),
-%% NrVerifyFun = rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId),
EvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -2359,9 +2392,6 @@ strar_mg_event_sequence(text, tcp) ->
ConnectVerify = ?strar_mg_verify_handle_connect_fun(),
ServiceChangeReplyVerify = ?strar_mg_verify_service_change_reply_fun(),
NotifyReplyVerify = ?strar_mg_verify_notify_reply_fun(),
-%% ConnectVerify = strar_mg_verify_handle_connect_fun(),
-%% ServiceChangeReplyVerify = strar_mg_verify_service_change_reply_fun(),
-%% NotifyReplyVerify = fun strar_mg_verify_notify_reply/1,
EvSeq = [
{debug, true},
megaco_start,
@@ -3437,9 +3467,6 @@ raraa_mg_event_sequence(text, tcp) ->
ScrVerifyFun = ?raraa_mg_verify_service_change_rep_msg_fun(),
NrVerifyFun = ?raraa_mg_verify_notify_rep_msg_fun(TermId,
TransId, ReqId, CtxId),
-%% ScrVerifyFun = raraa_mg_verify_service_change_rep_msg_fun(),
-%% NrVerifyFun = raraa_mg_verify_notify_rep_msg_fun(TermId,
-%% TransId, ReqId, CtxId),
EvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -4048,9 +4075,6 @@ rarana_mg_event_sequence(text, tcp) ->
ScrVerifyFun = ?rarana_mg_verify_service_change_rep_msg_fun(),
NrVerifyFun = ?rarana_mg_verify_notify_rep_msg_fun(TermId,
TransId, ReqId, CtxId),
-%% ScrVerifyFun = rarana_mg_verify_service_change_rep_msg_fun(),
-%% NrVerifyFun = rarana_mg_verify_notify_rep_msg_fun(TermId,
-%% TransId, ReqId, CtxId),
EvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -4663,9 +4687,6 @@ rarala_mg_event_sequence(text, tcp) ->
ScrVerifyFun = ?rarala_mg_verify_service_change_rep_msg_fun(),
NrVerifyFun = ?rarala_mg_verify_notify_rep_msg_fun(TermId,
TransId, ReqId, CtxId),
-%% ScrVerifyFun = rarala_mg_verify_service_change_rep_msg_fun(),
-%% NrVerifyFun = rarala_mg_verify_notify_rep_msg_fun(TermId,
-%% TransId, ReqId, CtxId),
EvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -5298,15 +5319,6 @@ trarar_mg_event_sequence(text, tcp) ->
?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 3, 3),
NrVerifyFun4 =
?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 4, 4),
-%% ScrVerifyFun = trarar_mg_verify_service_change_rep_msg_fun(),
-%% NrVerifyFun1 =
-%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 1, 1),
-%% NrVerifyFun2 =
-%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 2, 2),
-%% NrVerifyFun3 =
-%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 3, 3),
-%% NrVerifyFun4 =
-%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 4, 4),
EvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -5983,11 +5995,6 @@ pap_mg_event_sequence(text, tcp) ->
?pap_mg_verify_pending_msg_fun(TransId),
NrVerifyFun =
?pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId),
-%% ScrVerifyFun = pap_mg_verify_service_change_rep_msg_fun(),
-%% PendingVerifyFun =
-%% pap_mg_verify_pending_msg_fun(TransId),
-%% NrVerifyFun =
-%% pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId),
EvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -6380,10 +6387,6 @@ rapalr_mgc_event_sequence(text, tcp) ->
NrVerifyFun =
?rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId),
AckVerifyFun = ?rapalr_mgc_verify_trans_ack_msg_fun(TransId),
-%% ScrVerifyFun = rapalr_mgc_verify_service_change_req_msg_fun(),
-%% NrVerifyFun =
-%% rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId),
-%% AckVerifyFun = rapalr_mgc_verify_trans_ack_msg_fun(TransId),
EvSeq = [{debug, false},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -6866,12 +6869,12 @@ dist(Config) when is_list(Config) ->
?SKIP("Needs a re-write..."),
[_Local, Dist] = ?ACQUIRE_NODES(2, Config),
d("dist -> start proxy",[]),
- megaco_mess_user_test:start_proxy(),
+ ?USER_MOD:start_proxy(),
PrelMid = preliminary_mid,
MgMid = ipv4_mid(4711),
MgcMid = ipv4_mid(),
- UserMod = megaco_mess_user_test,
+ UserMod = ?USER_MOD,
d("dist -> start megaco app",[]),
?VERIFY(ok, application:start(megaco)),
UserConfig = [{user_mod, UserMod}, {send_mod, UserMod},
@@ -6977,7 +6980,7 @@ dist(Config) when is_list(Config) ->
?RECEIVE([]),
d("dist -> stop proxy",[]),
- megaco_mess_user_test:stop_proxy(),
+ ?USER_MOD:stop_proxy(),
d("dist -> done", []),
ok.
@@ -7444,9 +7447,6 @@ otp_5805_mg_event_sequence(text, tcp) ->
?otp_5805_mg_verify_service_change_rep_msg_fun(),
EDVerify =
?otp_5805_mg_verify_error_descriptor_msg_fun(),
-%% ServiceChangeReplyVerifyFun =
-%% otp_5805_mg_verify_service_change_rep_msg_fun(),
-%% EDVerify = otp_5805_mg_verify_error_descriptor_msg_fun(),
MgEvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -7939,8 +7939,6 @@ otp_5881_mgc_event_sequence(text, tcp) ->
%% Pending = otp_5881_pending_msg(Mid,2),
ServiceChangeVerifyFun = ?otp_5881_mgc_verify_service_change_req_msg_fun(),
NotifyReqVerifyFun = ?otp_5881_mgc_verify_notify_req_msg_fun(),
-%% ServiceChangeVerifyFun = otp_5881_verify_service_change_req_msg_fun(),
-%% NotifyReqVerifyFun = otp_5881_verify_notify_request_fun(),
MgcEvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -8211,8 +8209,6 @@ otp_5887_mgc_event_sequence(text, tcp) ->
NotifyReply = otp_5887_notify_reply_msg(Mid, 2, 0, TermId),
ServiceChangeVerifyFun = ?otp_5887_mgc_verify_service_change_req_msg_fun(),
NotifyReqVerifyFun = ?otp_5887_mgc_verify_notify_req_msg_fun(),
-%% ServiceChangeVerifyFun = otp_5887_verify_service_change_req_msg_fun(),
-%% NotifyReqVerifyFun = otp_5887_verify_notify_request_fun(),
MgcEvSeq = [{debug, true},
{decode, DecodeFun},
{encode, EncodeFun},
@@ -8362,7 +8358,7 @@ otp_6253(Config) when is_list(Config) ->
MgMid = ipv4_mid(4711),
?VERIFY(ok, application:start(megaco)),
- ?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, megaco_mess_user_test},
+ ?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, ?USER_MOD},
{request_timer, infinity},
{reply_timer, infinity}])),
@@ -8668,8 +8664,6 @@ otp_6275_mgc_event_sequence(text, tcp) ->
NotifyReq = otp_6275_mgc_notify_request_msg(Mid, 2, 1, TermId, 1),
SCRVerifyFun = ?otp_6275_mgc_verify_service_change_req_msg_fun(),
NotifyReplyVerifyFun = ?otp_6275_mgc_verify_notify_rep_msg_fun(),
-%% SCRVerifyFun = otp_6275_mgc_verify_service_change_req_fun(),
-%% NotifyReplyVerifyFun = otp_6275_mgc_verify_notify_reply_fun(),
MgcEvSeq =
[{debug, true},
{decode, DecodeFun},
@@ -11015,12 +11009,12 @@ otp_6865_request_and_reply_plain_extra1(Config) when is_list(Config) ->
ok = megaco_tc_controller:insert(extra_transport_info, ExtraInfo),
d("start proxy",[]),
- megaco_mess_user_test:start_proxy(),
+ ?USER_MOD:start_proxy(),
PrelMid = preliminary_mid,
MgMid = ipv4_mid(4711),
MgcMid = ipv4_mid(),
- UserMod = megaco_mess_user_test,
+ UserMod = ?USER_MOD,
d("start megaco app",[]),
?VERIFY(ok, application:start(megaco)),
UserConfig = [{user_mod, UserMod}, {send_mod, UserMod},
@@ -12286,15 +12280,15 @@ otp_7189_mg_event_sequence(text, tcp) ->
?otp_7189_mg_verify_service_change_rep_msg_fun(),
NotifyReqVerify = ?otp_7189_mg_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId),
EvSeq = [
- {debug, true},
+ ?GD_ENABLE(),
{decode, DecodeFun},
{encode, EncodeFun},
{connect, 2944},
- {send, "service-change-request", ServiceChangeReq},
- {expect_receive, "service-change-reply", {ServiceChangeReplyVerifyFun, 2000}},
- {expect_receive, "notify request", {NotifyReqVerify, 2000}},
- {sleep, 100},
- {send, "pending", Pending},
+ ?GSND("service-change-request", ServiceChangeReq),
+ ?GERCV("service-change-reply", ServiceChangeReplyVerifyFun, ?SECS(5)),
+ ?GERCV("notify request", NotifyReqVerify, ?SECS(5)),
+ ?GS(100),
+ ?GSND("pending", Pending),
{expect_closed, timer:seconds(120)},
disconnect
],
@@ -12532,7 +12526,7 @@ otp_7259(Config) when is_list(Config) ->
megaco_test_generic_transport:incomming_message(Pid, NotifyReply),
d("[MG] await the generator reply"),
- await_completion([MgId], 5000),
+ await_completion([MgId], 7000),
%% Tell Mg to stop
i("[MG] stop generator"),
@@ -12832,13 +12826,13 @@ otp_7713(Config) when is_list(Config) ->
i("starting"),
d("start proxy",[]),
- megaco_mess_user_test:start_proxy(),
+ ?USER_MOD:start_proxy(),
Extra = otp7713_extra,
PrelMid = preliminary_mid,
MgMid = ipv4_mid(4711),
MgcMid = ipv4_mid(),
- UserMod = megaco_mess_user_test,
+ UserMod = ?USER_MOD,
d("start megaco app",[]),
?VERIFY(ok, application:start(megaco)),
UserConfig = [{user_mod, UserMod}, {send_mod, UserMod},
@@ -12954,10 +12948,11 @@ otp_8183_request1(Config) when is_list(Config) ->
i("wait some before issuing the notify reply (twice)"),
sleep(500),
- i("send the notify reply, twice times"),
+ i("send the notify reply - twice"),
NotifyReply =
otp_8183_r1_mgc_notify_reply_msg(MgcMid, TransId2, Cid2, TermId2),
megaco_test_generic_transport:incomming_message(Pid, NotifyReply),
+ sleep(100), %% This is to "make sure" the events come in the "right" order
megaco_test_generic_transport:incomming_message(Pid, NotifyReply),
d("await the generator reply"),
@@ -13228,13 +13223,33 @@ otp_8183_r1_mg_verify_notify_rep_fun(Nr) ->
end.
-endif.
-otp_8183_r1_mg_verify_notify_rep(Nr,
+otp_8183_r1_mg_verify_notify_rep(
+ Nr,
{handle_trans_reply, _CH, ?VERSION, {ok, Nr, [AR]}, _}) ->
io:format("otp_8183_r1_mg_verify_notify_rep -> ok"
"~n Nr: ~p"
"~n AR: ~p"
"~n", [Nr, AR]),
{ok, AR, ok};
+otp_8183_r1_mg_verify_notify_rep(
+ ExpNr,
+ {handle_trans_reply, _CH, ?VERSION, {ok, ActNr, [AR]}, _}) ->
+ io:format("otp_8183_r1_mg_verify_notify_rep -> error"
+ "~n Expected Nr: ~p"
+ "~n Actual Nr: ~p"
+ "~n AR: ~p"
+ "~n", [ExpNr, ActNr, AR]),
+ Error = {unexpected_nr, ExpNr, ActNr},
+ {error, Error, ok};
+otp_8183_r1_mg_verify_notify_rep(
+ Nr,
+ {handle_trans_reply, _CH, ?VERSION, Res, _}) ->
+ io:format("otp_8183_r1_mg_verify_notify_rep -> error"
+ "~n Nr: ~p"
+ "~n Res: ~p"
+ "~n", [Nr, Res]),
+ Error = {unexpected_result, Nr, Res},
+ {error, Error, ok};
otp_8183_r1_mg_verify_notify_rep(Nr, Else) ->
io:format("otp_8183_r1_mg_verify_notify_rep -> unknown"
"~n Nr: ~p"
diff --git a/lib/megaco/test/megaco_mess_user_test.erl b/lib/megaco/test/megaco_mess_user_test.erl
index b5a554112e..d2a9c0f290 100644
--- a/lib/megaco/test/megaco_mess_user_test.erl
+++ b/lib/megaco/test/megaco_mess_user_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -86,13 +86,13 @@ reply(Mod, Line, Fun) when is_function(Fun) ->
{?MODULE, Pid, UserCallback} ->
UserReply = Fun(UserCallback),
Pid ! {?MODULE, self(), UserReply},
- UserReply;
- Other ->
- megaco_test_lib:error(Other, Mod, Line),
- {error, Other}
-%% after 1000 ->
-%% megaco_test_lib:error(timeout, Mod, Line),
-%% {error, timeout}
+ UserReply%% ;
+ %% Other ->
+ %% megaco_test_lib:error(Other, Mod, Line),
+ %% {error, Other}
+ after 10000 ->
+ megaco_test_lib:error(timeout, Mod, Line),
+ {error, timeout}
end.
call(UserCallback) ->
diff --git a/lib/megaco/test/megaco_mib_test.erl b/lib/megaco/test/megaco_mib_test.erl
index 06ac7c08ed..9d1d408f18 100644
--- a/lib/megaco/test/megaco_mib_test.erl
+++ b/lib/megaco/test/megaco_mib_test.erl
@@ -264,7 +264,7 @@ connect(Config) when is_list(Config) ->
d("connect -> (Mg1) service change result: ~p", [Res1]),
%% Collect the statistics
- progress("collect MG1 statustics (after service change)"),
+ progress("collect MG1 statistics (after service change)"),
{ok, Mg1Stats1} = get_stats(Mg1, 1),
d("connect -> stats for Mg1: ~n~p", [Mg1Stats1]),
progress("collect MGC statistics (after MG1 service change)"),
@@ -279,7 +279,7 @@ connect(Config) when is_list(Config) ->
d("connect -> (Mg2) service change result: ~p", [Res2]),
%% Collect the statistics
- progress("collect MG2 statustics (after service change)"),
+ progress("collect MG2 statistics (after service change)"),
{ok, Mg2Stats1} = get_stats(Mg2, 1),
d("connect -> stats for Mg1: ~n~p", [Mg2Stats1]),
progress("collect MGC statistics (after MG2 service change)"),
@@ -751,7 +751,7 @@ mgc_init(Config) ->
d("mgc_init -> entry"),
Mid = get_conf(local_mid, Config),
RI = get_conf(receive_info, Config),
- d("mgc_init -> start megaco"),
+ i("mgc_init -> start megaco"),
application:start(megaco),
d("mgc_init -> start megaco user"),
megaco:start_user(Mid, []),
@@ -763,7 +763,7 @@ mgc_init(Config) ->
RH = megaco:user_info(Mid,receive_handle),
d("mgc_init -> parse receive info"),
ListenTo = mgc_parse_receive_info(RI, RH),
- d("mgc_init -> start transports"),
+ i("mgc_init -> start transport(s)"),
{Tcp, Udp} = mgc_start_transports(ListenTo),
{Mid, Tcp, Udp}.
@@ -948,7 +948,7 @@ mgc_start_transports([{_Port, RH}|_ListenTo], _TcpSup, _UdpSup) ->
mgc_start_tcp(RH, Port, undefined) ->
- d("start tcp transport"),
+ i("start tcp transport"),
case megaco_tcp:start_transport() of
{ok, Sup} ->
mgc_start_tcp(RH, Port, Sup);
@@ -956,7 +956,7 @@ mgc_start_tcp(RH, Port, undefined) ->
throw({error, {failed_starting_tcp_transport, Else}})
end;
mgc_start_tcp(RH, Port, Sup) when is_pid(Sup) ->
- d("tcp listen on ~p", [Port]),
+ i("tcp listen on ~p", [Port]),
Opts = [{port, Port},
{receive_handle, RH},
{tcp_options, [{nodelay, true}]}],
@@ -986,7 +986,7 @@ mgc_tcp_create_listen(Sup, Opts, MaxN, N, _InitialReason)
mgc_start_udp(RH, Port, undefined) ->
- d("start udp transport"),
+ i("start udp transport"),
case megaco_udp:start_transport() of
{ok, Sup} ->
mgc_start_udp(RH, Port, Sup);
@@ -994,7 +994,7 @@ mgc_start_udp(RH, Port, undefined) ->
throw({error, {failed_starting_udp_transport, Else}})
end;
mgc_start_udp(RH, Port, Sup) ->
- d("open udp ~p", [Port]),
+ i("open udp ~p", [Port]),
Opts = [{port, Port}, {receive_handle, RH}],
case megaco_udp:open(Sup, Opts) of
{ok, _SendHandle, _ControlPid} ->
@@ -1119,7 +1119,7 @@ mg_init(Config) ->
d("mg_init -> entry"),
Mid = get_conf(local_mid, Config),
RI = get_conf(receive_info, Config),
- d("mg_init -> start megaco"),
+ i("mg_init -> start megaco"),
application:start(megaco),
d("mg_init -> start megaco user"),
megaco:start_user(Mid, []),
@@ -1131,7 +1131,7 @@ mg_init(Config) ->
RH = megaco:user_info(Mid,receive_handle),
d("mg_init -> parse receive info"),
{MgcPort,RH1} = mg_parse_receive_info(RI, RH),
- d("mg_init -> start transport with"),
+ i("mg_init -> start transport(s)"),
ConnHandle = mg_start_transport(MgcPort, RH1),
{Mid, ConnHandle}.
@@ -1255,16 +1255,6 @@ mg_close_conn(CH) ->
SendMod -> exit(Pid, Reason)
end.
-% display_tuple(T) when tuple(T), size(T) > 0 ->
-% i("size(T): ~p", [size(T)]),
-% display_tuple(T,1).
-
-% display_tuple(T,P) when P > size(T) ->
-% ok;
-% display_tuple(T,P) ->
-% i("T[~p]: ~p", [P,element(P,T)]),
-% display_tuple(T,P+1).
-
mg_parse_receive_info(RI, RH) ->
d("mg_parse_receive_info -> get encoding module"),
@@ -1292,7 +1282,7 @@ mg_start_transport(_, #megaco_receive_handle{send_mod = Mod}) ->
mg_start_tcp(MgcPort, RH) ->
- d("start tcp transport"),
+ i("start tcp transport"),
case megaco_tcp:start_transport() of
{ok, Sup} ->
{ok, LocalHost} = inet:gethostname(),
@@ -1316,7 +1306,7 @@ mg_start_tcp(MgcPort, RH) ->
mg_start_udp(MgcPort, RH) ->
- d("start udp transport"),
+ i("start udp transport"),
case megaco_udp:start_transport() of
{ok, Sup} ->
%% Some linux (Ubuntu) has "crap" in their /etc/hosts, that
@@ -1723,6 +1713,7 @@ progress(F) ->
progress(F, []).
progress(F, A) ->
+ io:format("~s " ++ F ++ "~n", [?FTS()|A]),
io:format(user, "~s " ++ F ++ "~n", [?FTS()|A]).
diff --git a/lib/megaco/test/megaco_mreq_test.erl b/lib/megaco/test/megaco_mreq_test.erl
index e6a5ed3181..ba20329ab3 100644
--- a/lib/megaco/test/megaco_mreq_test.erl
+++ b/lib/megaco/test/megaco_mreq_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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,7 +24,21 @@
%%----------------------------------------------------------------------
-module(megaco_mreq_test).
--compile(export_all).
+-export([
+ all/0,
+ groups/0,
+
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2,
+
+ req_and_rep/1,
+ req_and_pending/1,
+ req_and_cancel/1,
+
+ t/0, t/1
+ ]).
-include("megaco_test_lib.hrl").
-include_lib("megaco/include/megaco.hrl").
@@ -51,16 +65,19 @@
-define(MG_START(Pid, Mid, Enc, Transp, Verb),
megaco_test_mg:start(Pid, Mid, Enc, Transp, Verb)).
--define(MG_STOP(Pid), megaco_test_mg:stop(Pid)).
--define(MG_GET_STATS(Pid, No), megaco_test_mg:get_stats(Pid, No)).
--define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)).
--define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)).
--define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)).
--define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)).
--define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)).
--define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)).
+-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)).
+-define(MG_GET_STATS(Pid), megaco_test_mg:get_stats(Pid)).
+-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)).
+-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)).
+-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)).
+-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)).
+-define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)).
+-define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)).
-define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
t() -> megaco_test_lib:t(?MODULE).
t(Case) -> megaco_test_lib:t({?MODULE, Case}).
@@ -74,6 +91,7 @@ end_per_testcase(Case, Config) ->
process_flag(trap_exit, false),
megaco_test_lib:end_per_testcase(Case, Config).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
@@ -228,7 +246,7 @@ req_and_rep_stop_mg(MGs) ->
req_and_rep_get_mg_stats([], Acc) ->
lists:reverse(Acc);
req_and_rep_get_mg_stats([{Name, Pid}|Mgs], Acc) ->
- {ok, Stats} = ?MG_GET_STATS(Pid, 1),
+ {ok, Stats} = ?MG_GET_STATS(Pid),
d("req_and_rep_get_mg_stats -> stats for ~s: ~n~p~n", [Name, Stats]),
req_and_rep_get_mg_stats(Mgs, [{Name, Stats}|Acc]).
@@ -399,11 +417,13 @@ req_and_cancel(Config) when is_list(Config) ->
req_and_cancel_analyze_result({ok,{_PV,Res}}) ->
- d("req_and_cancel -> notify request result: ~n ~p", [Res]),
+ i("req_and_cancel -> notify request result: ~n ~p", [Res]),
req_and_cancel_analyze_result2(Res);
req_and_cancel_analyze_result(Unexpected) ->
exit({unexpected_result,Unexpected}).
+req_and_cancel_analyze_result2({error,{user_cancel,req_and_cancel}}) ->
+ ok;
req_and_cancel_analyze_result2([]) ->
ok;
req_and_cancel_analyze_result2([{error,{user_cancel,req_and_cancel}}|Res]) ->
@@ -429,9 +449,6 @@ sleep(X) ->
receive after X -> ok end.
-error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A).
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
i(F) ->
@@ -441,8 +458,8 @@ i(F, A) ->
print(info, get(verbosity), "", F, A).
-d(F) ->
- d(F, []).
+%% d(F) ->
+%% d(F, []).
d(F, A) ->
print(debug, get(verbosity), "DBG: ", F, A).
@@ -456,20 +473,9 @@ print(Severity, Verbosity, P, F, A) ->
print(printable(Severity,Verbosity), P, F, A).
print(true, P, F, A) ->
- io:format("~s~p:~s: " ++ F ++ "~n", [P, self(), get(sname) | A]);
+ io:format("*** [~s] ~s ~p ~s ***"
+ "~n " ++ F ++ "~n",
+ [?FTS(), P, self(), get(sname) | A]);
print(_, _, _, _) ->
ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-random_init() ->
- {A,B,C} = now(),
- random:seed(A,B,C).
-
-random() ->
- 10 * random:uniform(50).
-
-apply_load_timer() ->
- erlang:send_after(random(), self(), apply_load_timeout).
-
diff --git a/lib/megaco/test/megaco_pending_limit_test.erl b/lib/megaco/test/megaco_pending_limit_test.erl
index ef3b7e51cf..e0c0468d99 100644
--- a/lib/megaco/test/megaco_pending_limit_test.erl
+++ b/lib/megaco/test/megaco_pending_limit_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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.
@@ -2065,23 +2065,12 @@ await_completion(Ids) ->
?ERROR({failed, Reply})
end.
-%% await_completion(Ids, Timeout) ->
-%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of
-%% {ok, Reply} ->
-%% d("OK => Reply: ~n~p", [Reply]),
-%% ok;
-%% {error, Reply} ->
-%% d("ERROR => Reply: ~n~p", [Reply]),
-%% ?ERROR({failed, Reply})
-%% end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sleep(X) -> receive after X -> ok end.
-%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2089,49 +2078,30 @@ i(F) ->
i(F, []).
i(F, A) ->
- print(info, get(verbosity), now(), get(tc), "INF", F, A).
+ print(info, get(verbosity), get(tc), "INF", F, A).
d(F) ->
d(F, []).
d(F, A) ->
- print(debug, get(verbosity), now(), get(tc), "DBG", F, A).
+ print(debug, get(verbosity), get(tc), "DBG", F, A).
printable(_, debug) -> true;
printable(info, info) -> true;
printable(_,_) -> false.
-print(Severity, Verbosity, Ts, Tc, P, F, A) ->
- print(printable(Severity,Verbosity), Ts, Tc, P, F, A).
+print(Severity, Verbosity, Tc, P, F, A) ->
+ print(printable(Severity,Verbosity), Tc, P, F, A).
-print(true, Ts, Tc, P, F, A) ->
+print(true, Tc, P, F, A) ->
io:format("*** [~s] ~s ~p ~s:~w ***"
"~n " ++ F ++ "~n",
- [format_timestamp(Ts), P, self(), get(sname), Tc | A]);
-print(_, _, _, _, _, _) ->
+ [?FTS(), P, self(), get(sname), Tc | A]);
+print(_, _, _, _, _) ->
ok.
-%% print(F, A) ->
-%% io:format("*** [~s] ***"
-%% "~n " ++ F ++ "~n",
-%% [format_timestamp(now()) | A]).
-
-format_timestamp(Now) -> megaco:format_timestamp(Now).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% random_init() ->
-%% {A,B,C} = now(),
-%% random:seed(A,B,C).
-
-%% random() ->
-%% 10 * random:uniform(50).
-
-%% apply_load_timer() ->
-%% erlang:send_after(random(), self(), apply_load_timeout).
-
-
-
diff --git a/lib/megaco/test/megaco_segment_test.erl b/lib/megaco/test/megaco_segment_test.erl
index ddb8b9f06b..47f708a14b 100644
--- a/lib/megaco/test/megaco_segment_test.erl
+++ b/lib/megaco/test/megaco_segment_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. 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.
@@ -7718,29 +7718,9 @@ await_completion(Ids) ->
?ERROR({failed, Reply})
end.
-%% await_completion(Ids, Timeout) ->
-%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of
-%% {ok, Reply} ->
-%% d("OK => Reply: ~n~p", [Reply]),
-%% ok;
-%% {error, {OK, ERROR}} ->
-%% d("ERROR => "
-%% "~n OK: ~p"
-%% "~n ERROR: ~p", [OK, ERROR]),
-%% ?ERROR({failed, ERROR});
-%% {error, Reply} ->
-%% d("ERROR => Reply: ~n~p", [Reply]),
-%% ?ERROR({failed, Reply})
-%% end.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% tim() ->
-%% {A,B,C} = erlang:now(),
-%% A*1000000000+B*1000+(C div 1000).
-
-
make_node_name(Name) ->
case string:tokens(atom_to_list(node()), [$@]) of
[_,Host] ->
@@ -7754,8 +7734,6 @@ make_node_name(Name) ->
sleep(X) -> receive after X -> ok end.
-%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -7763,44 +7741,31 @@ i(F) ->
i(F, []).
i(F, A) ->
- print(info, get(verbosity), now(), get(tc), "INF", F, A).
+ print(info, get(verbosity), get(tc), "INF", F, A).
d(F) ->
d(F, []).
d(F, A) ->
- print(debug, get(verbosity), now(), get(tc), "DBG", F, A).
+ print(debug, get(verbosity), get(tc), "DBG", F, A).
printable(_, debug) -> true;
printable(info, info) -> true;
printable(_,_) -> false.
-print(Severity, Verbosity, Ts, Tc, P, F, A) ->
- print(printable(Severity,Verbosity), Ts, Tc, P, F, A).
+print(Severity, Verbosity, Tc, P, F, A) ->
+ print(printable(Severity, Verbosity), Tc, P, F, A).
-print(true, Ts, Tc, P, F, A) ->
+print(true, Tc, P, F, A) ->
io:format("*** [~s] ~s ~p ~s:~w ***"
"~n " ++ F ++ "~n",
- [format_timestamp(Ts), P, self(), get(sname), Tc | A]);
-print(_, _, _, _, _, _) ->
+ [?FTS(), P, self(), get(sname), Tc | A]);
+print(_, _, _, _, _) ->
ok.
-format_timestamp(Now) -> megaco:format_timestamp(Now).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% random_init() ->
-%% {A,B,C} = now(),
-%% random:seed(A,B,C).
-
-%% random() ->
-%% 10 * random:uniform(50).
-
-%% apply_load_timer() ->
-%% erlang:send_after(random(), self(), apply_load_timeout).
-
-
diff --git a/lib/megaco/test/megaco_tcp_test.erl b/lib/megaco/test/megaco_tcp_test.erl
index a1865ad690..cc66a40f43 100644
--- a/lib/megaco/test/megaco_tcp_test.erl
+++ b/lib/megaco/test/megaco_tcp_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -117,15 +117,39 @@ end_per_testcase(Case, Config) ->
%% Test case definitions
%%======================================================================
all() ->
- [{group, start}, {group, sending}, {group, errors}].
+ [
+ {group, start},
+ {group, sending},
+ {group, errors}
+ ].
groups() ->
- [{start, [],
- [start_normal, start_invalid_opt, start_and_stop]},
- {sending, [], [sendreceive, block_unblock]},
- {errors, [],
- [socket_failure, accept_process, accept_supervisor,
- connection_supervisor, tcp_server]}].
+ [{start, [], start_cases()},
+ {sending, [], sending_cases()},
+ {errors, [], errors_cases()}].
+
+start_cases() ->
+ [
+ start_normal,
+ start_invalid_opt,
+ start_and_stop
+ ].
+
+sending_cases() ->
+ [
+ sendreceive,
+ block_unblock
+ ].
+
+errors_cases() ->
+ [
+ socket_failure,
+ accept_process,
+ accept_supervisor,
+ connection_supervisor,
+ tcp_server
+ ].
+
init_per_group(_GroupName, Config) ->
Config.
@@ -196,17 +220,8 @@ start_and_stop(Config) when is_list(Config) ->
Client = client_start_command_handler(ClientNode, ClientCmds),
p("client command handler started: ~p", [Client]),
- ok =
- receive
- {listening, Server} ->
- p("received listening message from server [~p] => "
- "send continue to client [~p]~n", [Server, Client]),
- Client ! {continue, self()},
- ok
- after 5000 ->
- {error, server_timeout}
- end,
-
+ await_server_listening(Server, Client),
+
await_command_handler_completion([Server, Client], timer:seconds(20)),
p("done"),
ok.
@@ -335,16 +350,7 @@ sendreceive(Config) when is_list(Config) ->
Client = client_start_command_handler(ClientNode, ClientCmds),
p("client command handler started: ~p", [Client]),
- ok =
- receive
- {listening, Server} ->
- p("received listening message from server [~p] => "
- "send continue to client [~p]~n", [Server, Client]),
- Client ! {continue, self()},
- ok
- after 5000 ->
- {error, server_timeout}
- end,
+ await_server_listening(Server, Client),
await_command_handler_completion([Server, Client], timer:seconds(20)),
p("done"),
@@ -544,27 +550,9 @@ block_unblock(Config) when is_list(Config) ->
Client = client_start_command_handler(ClientNode, ClientCmds),
p("client command handler started: ~p", [Client]),
- ok =
- receive
- {listening, Server} ->
- p("received listening message from server [~p] => "
- "send continue to client [~p]~n", [Server, Client]),
- Client ! {continue, self()},
- ok
- after 5000 ->
- {error, server_timeout}
- end,
-
- ok =
- receive
- {blocked, Client} ->
- p("received blocked message from client [~p] => "
- "send continue to server [~p]~n", [Client, Server]),
- Server ! {continue, self()},
- ok
- after 5000 ->
- {error, timeout}
- end,
+ await_server_listening(Server, Client),
+
+ await_client_blocked(Server, Client),
await_command_handler_completion([Server, Client], timer:seconds(30)),
p("done"),
@@ -908,6 +896,42 @@ process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg)
%% Internal functions
%%======================================================================
+await_server_listening(Server, Client) ->
+ receive
+ {listening, Server} ->
+ p("received listening message from server [~p] => "
+ "send continue to client [~p]"
+ "~n", [Server, Client]),
+ Client ! {continue, self()},
+ ok
+ after 5000 ->
+ %% There is no normal reason why this should take any time.
+ %% Normally, this takes a few milli seconds. So, if we are not
+ %% up and running after 5 seconds, we give up and skip!!
+ exit(Server, kill),
+ exit(Client, kill),
+ ?SKIP("Server timeout (listen)")
+ end.
+
+
+await_client_blocked(Server, Client) ->
+ receive
+ {blocked, Client} ->
+ p("received blocked message from client [~p] => "
+ "send continue to server [~p]~n", [Client, Server]),
+ Server ! {continue, self()},
+ ok
+ after 5000 ->
+ %% There is no normal reason why this should take any time.
+ %% Normally, this takes a few milli seconds. So, if we are not
+ %% up and running after 5 seconds, we give up and skip!!
+ exit(Client, kill),
+ exit(Server, kill),
+ ?SKIP("Client timeout (blocked)")
+ end.
+
+
+
%% ------- Server command handler and utility functions ----------
server_start_command_handler(Node, Commands) ->
@@ -1214,23 +1238,14 @@ p(F, A) ->
p(S, F, A) when is_list(S) ->
io:format("*** [~s] ~p ~s ***"
"~n " ++ F ++ "~n",
- [format_timestamp(now()), self(), S | A]);
+ [?FTS(), self(), S | A]);
p(_S, F, A) ->
io:format("*** [~s] ~p ~s *** "
"~n " ++ F ++ "~n",
- [format_timestamp(now()), self(), "undefined" | A]).
+ [?FTS(), self(), "undefined" | A]).
ms() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
+ erlang:monotonic_time(milli_seconds).
+
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
diff --git a/lib/megaco/test/megaco_test_deliver.erl b/lib/megaco/test/megaco_test_deliver.erl
index 78033f0e36..c042d9c9a7 100644
--- a/lib/megaco/test/megaco_test_deliver.erl
+++ b/lib/megaco/test/megaco_test_deliver.erl
@@ -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.
@@ -186,4 +186,4 @@ i(F) ->
i(F, []).
i(F, A) ->
- io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
+ io:format("*** [~s] ~p ~w:" ++ F ++ "~n", [?FTS(), self(), ?MODULE | A]).
diff --git a/lib/megaco/test/megaco_test_generator.erl b/lib/megaco/test/megaco_test_generator.erl
index 63f66bda07..8ea7f5ddf7 100644
--- a/lib/megaco/test/megaco_test_generator.erl
+++ b/lib/megaco/test/megaco_test_generator.erl
@@ -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.
@@ -47,7 +47,6 @@
print/3, print/4
]).
--export([behaviour_info/1]).
%% Internal exports
-export([start/4]).
@@ -65,6 +64,7 @@
-include_lib("megaco/include/megaco.hrl").
+-include("megaco_test_lib.hrl").
%%----------------------------------------------------------------------
@@ -90,15 +90,32 @@
%%% API
%%%=========================================================================
-behaviour_info(callbacks) ->
- [
- {init, 1},
- {handle_parse, 2},
- {handle_exec, 2},
- {terminate, 2}
- ];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args) -> {ok, State} | {error, Reason} when
+ Args :: term(),
+ State :: term(),
+ Reason :: term().
+
+-callback handle_parse(Instruction, State) ->
+ {ok, NewInstruction, NewState} |
+ {error, Reason} when
+ Instruction :: term(),
+ State :: term(),
+ NewInstruction :: term(),
+ NewState :: term(),
+ Reason :: term().
+
+-callback handle_exec(Instruction, State) ->
+ {ok, NewState} |
+ {error, Reason} when
+ Instruction :: term(),
+ State :: term(),
+ NewState :: term(),
+ Reason :: term().
+
+-callback terminate(Reason, State) ->
+ megaco:void() when
+ Reason :: term(),
+ State :: term().
%%----------------------------------------------------------------------
@@ -533,22 +550,13 @@ print(P, F, A) ->
print([], undefined, F, A) ->
io:format("*** [~s] ~p *** " ++
"~n " ++ F ++ "~n",
- [format_timestamp(now()),self()|A]);
+ [?FTS(), self() | A]);
print(P, undefined, F, A) ->
io:format("*** [~s] ~p ~s *** " ++
"~n " ++ F ++ "~n",
- [format_timestamp(now()),self(),P|A]);
+ [?FTS(), self(), P | A]);
print(P, N, F, A) ->
io:format("*** [~s] ~p ~s~s *** " ++
"~n " ++ F ++ "~n",
- [format_timestamp(now()),self(),N,P|A]).
-
+ [?FTS(), self(), N, P | A]).
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY, MM, DD} = Date,
- {Hour, Min, Sec} = Time,
- FormatDate =
- io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY, MM, DD, Hour, Min, Sec, round(N3/1000)]),
- lists:flatten(FormatDate).
diff --git a/lib/megaco/test/megaco_test_generic_transport.erl b/lib/megaco/test/megaco_test_generic_transport.erl
index 3185e4c6b6..cd387f748a 100644
--- a/lib/megaco/test/megaco_test_generic_transport.erl
+++ b/lib/megaco/test/megaco_test_generic_transport.erl
@@ -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.
@@ -59,7 +59,7 @@
receive_handle}).
-include_lib("megaco/include/megaco.hrl").
-%% -include("megaco_test_lib.hrl").
+-include("megaco_test_lib.hrl").
-define(SERVER, ?MODULE).
@@ -335,21 +335,11 @@ d(F) ->
d(F, []).
d(F, A) ->
- print(now(), F, A).
+ print(F, A).
-print(Ts, F, A) ->
+print(F, A) ->
io:format("*** [~s] GENERIC TRANSPORT [~p] ***"
"~n " ++ F ++ "~n",
- [format_timestamp(Ts), self() | A]).
-
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
-
+ [?FTS(), self() | A]).
diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl
index 0617b96456..7c8c287e7c 100644
--- a/lib/megaco/test/megaco_test_lib.erl
+++ b/lib/megaco/test/megaco_test_lib.erl
@@ -318,9 +318,9 @@ t({Mod, {group, Name} = Group, Groups}, Config)
[Name, Error]),
[{failed, {Mod, Group}, Error}]
catch
- exit:{skipped, SkipReason} ->
+ exit:{skip, SkipReason} ->
io:format(" => skipping group: ~p~n", [SkipReason]),
- [{skipped, {Mod, Group}, SkipReason, 0}];
+ [{skip, {Mod, Group}, SkipReason, 0}];
error:undef ->
[t({Mod, Case, Groups}, Config) ||
Case <- GroupsAndCases];
@@ -383,9 +383,9 @@ t(Mod, Config) when is_atom(Mod) ->
io:format(" => suite init failed: ~p~n", [Error]),
[{failed, {Mod, init_per_suite}, Error}]
catch
- exit:{skipped, SkipReason} ->
+ exit:{skip, SkipReason} ->
io:format(" => skipping suite: ~p~n", [SkipReason]),
- [{skipped, {Mod, init_per_suite}, SkipReason, 0}];
+ [{skip, {Mod, init_per_suite}, SkipReason, 0}];
error:undef ->
[t({Mod, Case, Groups}, Config) || Case <- Cases];
T:E ->
@@ -458,10 +458,10 @@ wait_for_evaluator(Pid, Mod, Fun, Config, Errors, AccTime) ->
megaco:report_event(20, Mod, ?MODULE, Label ++ " failed",
[TestCase, Config, {return, Fail}, Errors]),
{failed, {Mod,Fun}, Fail, Time};
- {'EXIT', Pid, {skipped, Reason}, Time} ->
+ {'EXIT', Pid, {skip, Reason}, Time} ->
megaco:report_event(20, Mod, ?MODULE, Label ++ " skipped",
- [TestCase, Config, {skipped, Reason}]),
- {skipped, {Mod, Fun}, Errors, Time};
+ [TestCase, Config, {skip, Reason}]),
+ {skip, {Mod, Fun}, Errors, Time};
{'EXIT', Pid, Reason, Time} ->
megaco:report_event(20, Mod, ?MODULE, Label ++ " crashed",
[TestCase, Config, {'EXIT', Reason}]),
@@ -492,14 +492,14 @@ do_eval(ReplyTo, Mod, Fun, Config) ->
error:undef ->
%% p("do_eval -> error - undef", []),
ReplyTo ! {'EXIT', self(), undef, 0};
- exit:{skipped, Reason} ->
+ exit:{skip, Reason} ->
%% p("do_eval -> exit - skipped"
%% "~n Reason: ~p", [Reason]),
T2 = os:timestamp(),
Time = timer:now_diff(T2, T1),
display_tc_time(Time),
display_system_info("after (skipped)", Mod, Fun),
- ReplyTo ! {'EXIT', self(), {skipped, Reason}, Time};
+ ReplyTo ! {'EXIT', self(), {skip, Reason}, Time};
exit:{suite_failed, Reason} ->
%% p("do_eval -> exit - suite-failed"
%% "~n Reason: ~p", [Reason]),
@@ -616,9 +616,9 @@ display_result(Res) when is_list(Res) ->
Ok = [{MF, Time} || {ok, MF, _, Time} <- Res],
Nyi = [MF || {nyi, MF, _, _Time} <- Res],
SkippedGrps = [{{M,G}, Reason} ||
- {skipped, {M, {group, G}}, Reason, _Time} <- Res],
+ {skip, {M, {group, G}}, Reason, _Time} <- Res],
SkippedCases = [{MF, Reason} ||
- {skipped, {_M, F} = MF, Reason, _Time} <- Res,
+ {skip, {_M, F} = MF, Reason, _Time} <- Res,
is_atom(F)],
FailedGrps = [{{M,G}, Reason} ||
{failed, {M, {group, G}}, Reason, _Time} <- Res],
@@ -730,15 +730,18 @@ log(Format, Args, Mod, Line) ->
[self(), Mod, Line] ++ Args)
end.
+skip(Reason) ->
+ exit({skip, Reason}).
+
skip(Actual, File, Line) ->
- log("Skipping test case~n", [], File, Line),
- String = lists:flatten(io_lib:format("Skipping test case ~p(~p): ~p~n",
- [File, Line, Actual])),
- exit({skipped, String}).
+ log("Skipping test case: ~p~n", [Actual], File, Line),
+ String = f("~p(~p): ~p~n", [File, Line, Actual]),
+ skip(String).
fatal_skip(Actual, File, Line) ->
error(Actual, File, Line),
- exit({skipped, {fatal, Actual, File, Line}}).
+ skip({fatal, Actual, File, Line}).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -750,7 +753,8 @@ flush() ->
after 1000 ->
[]
end.
-
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Check if process is alive and kicking
still_alive(Pid) ->
@@ -988,11 +992,14 @@ node_to_name_and_host(Node) ->
start_nodes([Node | Nodes], File, Line) ->
case net_adm:ping(Node) of
pong ->
+ p("node ~p already running", [Node]),
start_nodes(Nodes, File, Line);
pang ->
[Name, Host] = node_to_name_and_host(Node),
+ p("try start node ~p", [Node]),
case slave:start_link(Host, Name) of
{ok, NewNode} when NewNode =:= Node ->
+ p("node ~p started - now set path, cwd and sync", [Node]),
Path = code:get_path(),
{ok, Cwd} = file:get_cwd(),
true = rpc:call(Node, code, set_path, [Path]),
@@ -1001,6 +1008,7 @@ start_nodes([Node | Nodes], File, Line) ->
{_, []} = rpc:multicall(global, sync, []),
start_nodes(Nodes, File, Line);
Other ->
+ p("failed starting node ~p: ~p", [Node, Other]),
fatal_skip({cannot_start_node, Node, Other}, File, Line)
end
end;
@@ -1014,4 +1022,4 @@ f(F, A) ->
lists:flatten(io_lib:format(F, A)).
p(F, A) ->
- io:format("~p~w:" ++ F ++ "~n", [self(), ?MODULE |A]).
+ io:format("~s ~p " ++ F ++ "~n", [?FTS(), self() | A]).
diff --git a/lib/megaco/test/megaco_test_lib.hrl b/lib/megaco/test/megaco_test_lib.hrl
index 409f8d52e5..546ecaab9a 100644
--- a/lib/megaco/test/megaco_test_lib.hrl
+++ b/lib/megaco/test/megaco_test_lib.hrl
@@ -32,8 +32,6 @@
-define(ERROR(Reason),
megaco_test_lib:error(Reason, ?MODULE, ?LINE)).
--define(F(FMT, ARGS), lists:flatten(io_lib:format(FMT, ARGS))).
-
-define(OS_BASED_SKIP(Skippable),
megaco_test_lib:os_based_skip(Skippable)).
@@ -83,7 +81,10 @@
-define(SLEEP(MSEC), megaco_test_lib:sleep(MSEC)).
-define(HOURS(T), megaco_test_lib:hours(T)).
--define(MINUTES(T), megaco_test_lib:minutes(T)).
--define(SECONDS(T), megaco_test_lib:seconds(T)).
+-define(MINS(T), megaco_test_lib:minutes(T)).
+-define(MINUTES(T), ?MINS(T)).
+-define(SECS(T), megaco_test_lib:seconds(T)).
+-define(SECONDS(T), ?SECS(T)).
-define(FTS(), megaco:format_timestamp(erlang:timestamp())).
-
+-define(FTS(TS), megaco:format_timestamp(TS)).
+-define(F(F,A), lists:flatten(io_lib:format(F, A))).
diff --git a/lib/megaco/test/megaco_test_megaco_generator.erl b/lib/megaco/test/megaco_test_megaco_generator.erl
index 8a37fa33fe..4e0f2e334c 100644
--- a/lib/megaco/test/megaco_test_megaco_generator.erl
+++ b/lib/megaco/test/megaco_test_megaco_generator.erl
@@ -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.
@@ -118,7 +118,7 @@ init([]) ->
%% ----- instruction parser -----
handle_parse({debug, Debug} = Instruction, State)
- when (Debug == true) orelse (Debug == false) ->
+ when is_boolean(Debug) ->
{ok, Instruction, State};
handle_parse({expect_nothing, To} = Instruction, State)
@@ -126,9 +126,9 @@ handle_parse({expect_nothing, To} = Instruction, State)
{ok, Instruction, State};
handle_parse({megaco_trace, Level} = Instruction, State)
- when (Level == disable) orelse
- (Level == max) orelse
- (Level == min) orelse
+ when (Level =:= disable) orelse
+ (Level =:= max) orelse
+ (Level =:= min) orelse
is_integer(Level) ->
{ok, Instruction, State};
@@ -1096,11 +1096,10 @@ handle_megaco_callback_reply(_, _, _, _) ->
%%----------------------------------------------------------------------
random_init() ->
- {A,B,C} = now(),
- random:seed(A,B,C).
+ ok.
random(N) ->
- random:uniform(N).
+ rand:uniform(N).
get_config(Key, Opts) ->
diff --git a/lib/megaco/test/megaco_test_mg.erl b/lib/megaco/test/megaco_test_mg.erl
index d6a9a8c314..38883c94f0 100644
--- a/lib/megaco/test/megaco_test_mg.erl
+++ b/lib/megaco/test/megaco_test_mg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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.
@@ -79,7 +79,10 @@
reply_counter = 0,
mload_info = undefined,
parent = undefined,
- dsi_timer}).
+ dsi_timer,
+ evs = []}).
+
+-define(EVS_MAX, 10).
%%% --------------------------------------------------------------------
@@ -364,7 +367,7 @@ mg(Parent, Verbosity, Config) ->
MG = #mg{parent = Parent, mid = Mid, dsi_timer = DSITimer},
i("mg -> started"),
put(verbosity, Verbosity),
- case (catch loop(MG)) of
+ case (catch loop(evs(MG, started))) of
{'EXIT', normal} ->
exit(normal);
{'EXIT', Reason} ->
@@ -438,12 +441,12 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
{display_system_info, Time} ->
display_system_info(S#mg.mid),
NewTimer = create_timer(Time, display_system_info),
- loop(S#mg{dsi_timer = NewTimer});
+ loop(evs(S#mg{dsi_timer = NewTimer}, {dsi, Time}));
{verbosity, V, Parent} ->
i("loop -> received new verbosity: ~p", [V]),
put(verbosity,V),
- loop(S);
+ loop(evs(S, {verb, V}));
{stop, Parent} ->
@@ -453,7 +456,7 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
Res = do_stop(Mid),
d("loop -> stop result: ~p", [Res]),
server_reply(Parent, stopped, {ok, Res}),
- exit(normal);
+ done(evs(S, stop), normal);
{{enable_test_code, Tag, Fun}, Parent} ->
i("loop -> enable_test_code: ~p, ~p", [Tag, Fun]),
@@ -463,52 +466,52 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
"~n ets:tab2list(megaco_test_data): ~p",
[Reply,ets:tab2list(megaco_test_data)]),
server_reply(Parent, enable_test_code_reply, Reply),
- loop(S);
+ loop(evs(S, {enable_test_code, Tag}));
{{encode_ar_first, EAF}, Parent} ->
i("loop -> encode_ar_first: ~p", [EAF]),
{Reply, S1} = handle_encode_ar_first(S, EAF),
server_reply(Parent, encode_ar_first_reply, Reply),
- loop(S1#mg{encode_ar_first = EAF});
+ loop(evs(S1#mg{encode_ar_first = EAF}, {enc_arf, EAF}));
%% Give me statistics
{statistics, Parent} ->
i("loop -> got request for statistics", []),
Stats = do_get_statistics(Mid),
server_reply(Parent, statistics_reply, {ok, Stats}),
- loop(S);
+ loop(evs(S, stats));
{reset_stats, Parent} ->
i("loop -> got request to reset stats counters", []),
do_reset_stats(Mid),
server_reply(Parent, reset_stats_ack, ok),
- loop(S);
+ loop(evs(S, rst_stats));
{{user_info, Tag}, Parent} ->
i("loop -> got user_info request for ~w", [Tag]),
Res = do_get_user_info(Mid, Tag),
d("loop -> Res: ~p", [Res]),
server_reply(Parent, user_info_ack, Res),
- loop(S);
+ loop(evs(S, {ui, Tag}));
{{update_user_info, Tag, Val}, Parent} ->
i("loop -> got update_user_info: ~w -> ~p", [Tag, Val]),
Res = do_update_user_info(Mid, Tag, Val),
d("loop -> Res: ~p", [Res]),
server_reply(Parent, update_user_info_ack, Res),
- loop(S);
+ loop(evs(S, {uui, {Tag, Val}}));
{{conn_info, Tag}, Parent} ->
i("loop -> got conn_info request for ~w", [Tag]),
Res = do_get_conn_info(Mid, Tag),
server_reply(Parent, conn_info_ack, Res),
- loop(S);
+ loop(evs(S, {ci, Tag}));
{{update_conn_info, Tag, Val}, Parent} ->
i("loop -> got update_conn_info: ~w -> ~p", [Tag, Val]),
Res = do_update_conn_info(Mid, Tag, Val),
server_reply(Parent, update_conn_info_ack, Res),
- loop(S);
+ loop(evs(S, {uci, {Tag, Val}}));
%% Do a service change
@@ -526,28 +529,28 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
server_reply(Parent, service_change_reply, Error),
S
end,
- loop(S1);
+ loop(evs(S1, svc_ch));
{{group_requests, N}, Parent} when N > 0 ->
i("loop -> received group_requests ~p", [N]),
Reply = {ok, S#mg.group_size},
server_reply(Parent, group_requests_reply, Reply),
- loop(S#mg{group_size = N});
+ loop(evs(S#mg{group_size = N}, {grp_reqs, N}));
{{ack_info, To}, Parent} ->
i("loop -> received request to inform about received ack's ", []),
- loop(S#mg{ack_info = To});
+ loop(evs(S#mg{ack_info = To}, {acki, To}));
{{rep_info, To}, Parent} ->
i("loop -> received request to inform about received rep's ", []),
- loop(S#mg{rep_info = To});
+ loop(evs(S#mg{rep_info = To}, {repi, To}));
%% Make a sync-call
{notify_request, Parent} ->
i("loop -> received request to send notify request ", []),
{Res, S1} = do_handle_notify_request(S),
d("loop -> notify request result: ~p", [Res]),
- loop(S1);
+ loop(evs(S1, not_req));
%% sync-call complete
{notify_request_complete, NotifyReply, Pid} ->
@@ -556,7 +559,7 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
"~n NotifyReply: ~p",
[Pid, NotifyReply]),
server_reply(Parent, notify_request_reply, NotifyReply),
- loop(S#mg{req_handler = undefined});
+ loop(evs(S#mg{req_handler = undefined}, {not_reqc, NotifyReply}));
%% cancel requests
@@ -564,14 +567,14 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
i("loop -> received request to cancel (all) megaco requests ", []),
Res = do_cancel_requests(Mid, Reason),
server_reply(Parent, cancel_request_reply, Res),
- loop(S);
+ loop(evs(S, {creq, Reason}));
%% Apply multi-load
{apply_multi_load, {NL, NR}, Parent} ->
i("loop -> received apply_multi_load request: ~w, ~w", [NL, NR]),
S1 = start_loaders(S, NL, NR),
- loop(S1);
+ loop(evs(S1, {apply_mload, {NL, NR}}));
%% Apply some load
@@ -587,12 +590,12 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
server_reply(Parent, apply_load_ack, Error),
S
end,
- loop(S1);
+ loop(evs(S1, {apply_load, Times}));
{apply_load_timeout, _} ->
d("loop -> received apply_load timeout", []),
S1 = do_apply_load(S),
- loop(S1);
+ loop(evs(S1, apply_loadto));
%% Megaco callback messages
@@ -604,22 +607,35 @@ loop(#mg{parent = Parent, mid = Mid} = S) ->
{Reply, S1} = handle_megaco_request(S, Request),
d("loop -> send (megaco callback) request reply: ~n~p", [Reply]),
From ! {reply, Reply, self()},
- loop(S1);
+ loop(evs(S1, {req, {Request, Mid, From}}));
{'EXIT', Pid, Reason} ->
- i("loop -> received exit signal from ~p: ~n~p", [Pid, Reason]),
+ i("loop -> received exit signal from ~p: "
+ "~n ~p", [Pid, Reason]),
S1 = handle_exit(S, Pid, Reason),
- loop(S1);
+ loop(evs(S1, {exit, {Pid, Reason}}));
Invalid ->
error_msg("received invalid request: ~n~p", [Invalid]),
- loop(S)
+ loop(evs(S, {invalid, Invalid}))
end.
+evs(#mg{evs = EVS} = S, Ev) when (length(EVS) < ?EVS_MAX) ->
+ S#mg{evs = [{?FTS(), Ev}|EVS]};
+evs(#mg{evs = EVS} = S, Ev) ->
+ S#mg{evs = [{?FTS(), Ev}|lists:droplast(EVS)]}.
+
+done(#mg{evs = EVS}, Reason) ->
+ info_msg("Exiting with latest event(s): "
+ "~n ~p"
+ "~n", [EVS]),
+ exit(Reason).
+
+
handle_encode_ar_first(#mg{encode_ar_first = Old} = MG, New)
when (New =:= true) orelse (New =:= false) ->
{{ok, Old}, MG#mg{encode_ar_first = New}};
@@ -776,7 +792,7 @@ do_service_change(#mg{state = State} = MG) ->
{{error, {invalid_state, State}}, MG}.
do_service_change(ConnHandle, Method, EAF, Reason) ->
- d("sending service change using:"
+ d("send service change using:"
"~n ConnHandle: ~p"
"~n Method: ~p"
"~n EAF: ~p"
@@ -844,10 +860,10 @@ loader_main(EAF, N, CH) ->
-handle_exit(#mg{parent = Pid}, Pid, Reason) ->
+handle_exit(#mg{parent = Pid} = S, Pid, Reason) ->
error_msg("received exit from the parent:"
"~n ~p", [Reason]),
- exit({parent_terminated, Reason});
+ done(S, {parent_terminated, Reason});
handle_exit(#mg{parent = Parent, req_handler = Pid} = MG, Pid, Reason) ->
error_msg("received unexpected exit from the request handler:"
@@ -1423,6 +1439,7 @@ sleep(X) ->
receive after X -> ok end.
+info_msg(F,A) -> error_logger:info_msg("MG: " ++ F ++ "~n",A).
error_msg(F,A) -> error_logger:error_msg("MG: " ++ F ++ "~n",A).
@@ -1536,37 +1553,28 @@ print(Severity, Verbosity, P, F, A) ->
print(true, P, F, A) ->
io:format("*** [~s] ~s ~p ~s ***"
"~n " ++ F ++ "~n~n",
- [format_timestamp(now()), P, self(), get(sname) | A]);
+ [?FTS(), P, self(), get(sname) | A]);
print(_, _, _, _) ->
ok.
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
random_init() ->
- {A,B,C} = now(),
- random:seed(A,B,C).
+ ok.
random() ->
random(50).
random(N) ->
- random:uniform(N).
+ rand:uniform(N).
display_system_info(Mid) ->
display_system_info(Mid, "").
display_system_info(Mid, Pre) ->
- TimeStr = format_timestamp(now()),
+ TimeStr = ?FTS(),
MibStr = lists:flatten(io_lib:format("~p ", [Mid])),
megaco_test_lib:display_system_info(MibStr ++ Pre ++ TimeStr).
diff --git a/lib/megaco/test/megaco_test_mgc.erl b/lib/megaco/test/megaco_test_mgc.erl
index 045bc7c9fd..a9027ca68e 100644
--- a/lib/megaco/test/megaco_test_mgc.erl
+++ b/lib/megaco/test/megaco_test_mgc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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,7 +75,10 @@
abort_info = undefined,
req_info = undefined,
mg = [],
- dsi_timer}).
+ dsi_timer,
+ evs = []}).
+
+-define(EVS_MAX, 10).
%%% ------------------------------------------------------------------
@@ -297,7 +300,7 @@ mgc(Parent, Verbosity, Config) ->
dsi_timer = DSITimer},
i("mgc -> started"),
display_system_info("at start "),
- loop(S)
+ loop(evs(S, started))
end.
init(Config) ->
@@ -359,7 +362,7 @@ loop(S) ->
{display_system_info, Time} ->
display_system_info(S#mgc.mid),
NewTimer = create_timer(Time, display_system_info),
- loop(S#mgc{dsi_timer = NewTimer});
+ loop(evs(S#mgc{dsi_timer = NewTimer}, {dsi, Time}));
{stop, Parent} when S#mgc.parent =:= Parent ->
i("loop -> stopping", []),
@@ -371,7 +374,7 @@ loop(S) ->
application:stop(megaco),
i("loop -> stopped", []),
server_reply(Parent, stopped, ok),
- exit(normal);
+ done(evs(S, stop), normal);
{{disconnect, Reason}, Parent} when S#mgc.parent == Parent ->
i("loop -> disconnecting", []),
@@ -379,22 +382,22 @@ loop(S) ->
[Conn|_] = megaco:user_info(Mid, connections),
Res = megaco:disconnect(Conn, {self(), Reason}),
server_reply(Parent, disconnected, Res),
- loop(S);
+ loop(evs(S, {disconnect, Reason}));
{{update_user_info, Tag, Val}, Parent} when S#mgc.parent == Parent ->
i("loop -> got update_user_info: ~w -> ~p", [Tag, Val]),
Res = (catch megaco:update_user_info(S#mgc.mid, Tag, Val)),
d("loop -> Res: ~p", [Res]),
server_reply(Parent, update_user_info_ack, Res),
- loop(S);
-
- {{user_info, Tag}, Parent} when S#mgc.parent == Parent ->
- i("loop -> got user_info request for ~w", [Tag]),
- Res = (catch megaco:user_info(S#mgc.mid, Tag)),
- d("loop -> Res: ~p", [Res]),
- server_reply(Parent, user_info_ack, Res),
- loop(S);
-
+ loop(evs(S, {uui, {Tag, Val}}));
+
+ {{user_info, Tag}, Parent} when S#mgc.parent == Parent ->
+ i("loop -> got user_info request for ~w", [Tag]),
+ Res = (catch megaco:user_info(S#mgc.mid, Tag)),
+ d("loop -> Res: ~p", [Res]),
+ server_reply(Parent, user_info_ack, Res),
+ loop(evs(S, {ui, Tag}));
+
{{update_conn_info, Tag, Val}, Parent} when S#mgc.parent == Parent ->
i("loop -> got update_conn_info: ~w -> ~p", [Tag, Val]),
Conns = megaco:user_info(S#mgc.mid, connections),
@@ -404,7 +407,7 @@ loop(S) ->
Res = lists:map(Fun, Conns),
d("loop -> Res: ~p", [Res]),
server_reply(Parent, update_conn_info_ack, Res),
- loop(S);
+ loop(evs(S, {uci, {Tag, Val}}));
{{conn_info, Tag}, Parent} when S#mgc.parent == Parent ->
i("loop -> got conn_info request for ~w", [Tag]),
@@ -415,11 +418,11 @@ loop(S) ->
Res = lists:map(Fun, Conns),
d("loop -> Res: ~p", [Res]),
server_reply(Parent, conn_info_ack, Res),
- loop(S);
+ loop(evs(S, {ci, Tag}));
%%
- {request_action, {Action, To}, Parent} when S#mgc.parent == Parent ->
+ {request_action, {Action, To}, Parent} when S#mgc.parent == Parent ->
i("loop -> got new request_action: ~p:~w", [Action,To]),
{Reply, S1} =
case lists:member(Action, ?valid_actions) of
@@ -432,7 +435,7 @@ loop(S) ->
{{error, {invalid_action, Action}}, S}
end,
server_reply(Parent, request_action_ack, Reply),
- loop(S1);
+ loop(evs(S1, {req_act, {Action, To}}));
%% Reset stats
@@ -440,7 +443,7 @@ loop(S) ->
i("loop -> got request to reset stats counters"),
do_reset_stats(S#mgc.mid),
server_reply(Parent, reset_stats_ack, ok),
- loop(S);
+ loop(evs(S, rst_stats));
%% Give me statistics
@@ -466,7 +469,7 @@ loop(S) ->
lists:map(GetTrans, megaco:user_info(Mid, connections)),
Reply = {ok, [{gen, Gen}, {trans, Trans}]},
server_reply(Parent, {statistics_reply, 1}, Reply),
- loop(S);
+ loop(evs(S, {stats, 1}));
{{statistics, 2}, Parent} when S#mgc.parent == Parent ->
@@ -477,7 +480,7 @@ loop(S) ->
UdpStats = get_trans_stats(UdpSup, megaco_udp),
Reply = {ok, [{gen, Gen}, {trans, [TcpStats, UdpStats]}]},
server_reply(Parent, {statistics_reply, 2}, Reply),
- loop(S);
+ loop(evs(S, {stats, 2}));
%% Megaco callback messages
@@ -487,28 +490,28 @@ loop(S) ->
{Reply, S1} = handle_megaco_request(Request, S),
d("loop -> send request reply: ~n~p", [Reply]),
reply(From, Reply),
- loop(S1);
+ loop(evs(S1, {req, Request}));
{ack_info, To, Parent} when S#mgc.parent == Parent ->
i("loop -> received request to inform about received ack's ", []),
- loop(S#mgc{ack_info = To});
+ loop(evs(S#mgc{ack_info = To}, {acki, To}));
{abort_info, To, Parent} when S#mgc.parent == Parent ->
i("loop -> received request to inform about received aborts ", []),
- loop(S#mgc{abort_info = To});
+ loop(evs(S#mgc{abort_info = To}, {abi, To}));
{req_info, To, Parent} when S#mgc.parent == Parent ->
i("loop -> received request to inform about received req's ", []),
- loop(S#mgc{req_info = To});
+ loop(evs(S#mgc{req_info = To}, {reqi, To}));
{verbosity, V, Parent} when S#mgc.parent == Parent ->
i("loop -> received new verbosity: ~p", [V]),
put(verbosity,V),
- loop(S);
+ loop(evs(S, {verb, V}));
{'EXIT', Pid, Reason} when S#mgc.tcp_sup =:= Pid ->
@@ -525,7 +528,7 @@ loop(S) ->
i("loop -> stopped", []),
StopReason = {error, {tcp_terminated, Pid, Reason}},
server_reply(S#mgc.parent, stopped, StopReason),
- exit(StopReason);
+ done(evs(S, {tcp_sup_exit, Reason}), StopReason);
{'EXIT', Pid, Reason} when S#mgc.udp_sup =:= Pid ->
@@ -542,15 +545,27 @@ loop(S) ->
i("loop -> stopped", []),
StopReason = {error, {udp_terminated, Pid, Reason}},
server_reply(S#mgc.parent, stopped, StopReason),
- exit(StopReason);
+ done(evs(S, {udp_sup_exit, Reason}), StopReason);
Invalid ->
i("loop -> received invalid request: ~p", [Invalid]),
- loop(S)
+ loop(evs(S, {invalid, Invalid}))
end.
+evs(#mgc{evs = EVS} = S, Ev) when (length(EVS) < ?EVS_MAX) ->
+ S#mgc{evs = [{?FTS(), Ev}|EVS]};
+evs(#mgc{evs = EVS} = S, Ev) ->
+ S#mgc{evs = [{?FTS(), Ev}|lists:droplast(EVS)]}.
+
+done(#mgc{evs = EVS}, Reason) ->
+ info_msg("Exiting with latest event(s): "
+ "~n ~p"
+ "~n", [EVS]),
+ exit(Reason).
+
+
do_reset_stats(Mid) ->
megaco:reset_stats(),
do_reset_trans_stats(megaco:user_info(Mid, connections), []).
@@ -825,10 +840,10 @@ handle_megaco_request({handle_trans_ack, CH, PV, AS, AD},
handle_megaco_request({handle_trans_ack, CH, PV, AS, AD}, S) ->
d("handle_megaco_request(handle_trans_ack) -> entry with"
- "~n CH: ~p"
- "~n PV: ~p"
- "~n AS: ~p"
- "~n AD: ~p", [CH, PV, AS, AD]),
+ "~n Conn Handle: ~p"
+ "~n Prot Version: ~p"
+ "~n Ack Status: ~p"
+ "~n Ack Data: ~p", [CH, PV, AS, AD]),
{ok, S};
handle_megaco_request({handle_unexpected_trans, CH, PV, TR}, S) ->
@@ -1090,6 +1105,7 @@ sleep(X) ->
receive after X -> ok end.
+info_msg(F,A) -> error_logger:info_msg("MGC: " ++ F ++ "~n",A).
error_msg(F,A) -> error_logger:error_msg("MGC: " ++ F ++ "~n",A).
@@ -1153,18 +1169,17 @@ get_conf(Key, Config, Default) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
random_init() ->
- {A,B,C} = now(),
- random:seed(A,B,C).
+ ok.
random(N) ->
- random:uniform(N).
+ rand:uniform(N).
display_system_info(Mid) ->
display_system_info(Mid, "").
display_system_info(Mid, Pre) ->
- TimeStr = format_timestamp(now()),
+ TimeStr = ?FTS(),
MibStr = lists:flatten(io_lib:format("~p ", [Mid])),
megaco_test_lib:display_system_info(MibStr ++ Pre ++ TimeStr).
@@ -1209,14 +1224,6 @@ print(_, _, _, _) ->
print(P, F, A) ->
io:format("*** [~s] ~s ~p ~s ***"
"~n " ++ F ++ "~n~n",
- [format_timestamp(now()), P, self(), get(sname) | A]).
-
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
+ [?FTS(), P, self(), get(sname) | A]).
+
diff --git a/lib/megaco/test/megaco_timer_test.erl b/lib/megaco/test/megaco_timer_test.erl
index d3e8e27636..84c314d8ed 100644
--- a/lib/megaco/test/megaco_timer_test.erl
+++ b/lib/megaco/test/megaco_timer_test.erl
@@ -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.
@@ -362,6 +362,8 @@ integer_timer_start_and_stop(Config) when is_list(Config) ->
case tmr_stop(Ref) of
ok ->
ok;
+ {ok, _} ->
+ ok;
CancelRes ->
?SKIP({cancel_failed, CancelRes})
end
diff --git a/lib/megaco/test/megaco_trans_test.erl b/lib/megaco/test/megaco_trans_test.erl
index fb44a3c6e6..37bc134c8d 100644
--- a/lib/megaco/test/megaco_trans_test.erl
+++ b/lib/megaco/test/megaco_trans_test.erl
@@ -295,7 +295,7 @@ multi_ack_timeout(doc) ->
[];
multi_ack_timeout(Config) when is_list(Config) ->
%% <CONDITIONAL-SKIP>
- Skippable = [win32, {unix, [darwin, linux]}],
+ Skippable = [win32, {unix, [darwin, linux, sunos]}], % Is there any left?
Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
?NON_PC_TC_MAYBE_SKIP(Config, Condition),
%% </CONDITIONAL-SKIP>
@@ -9247,10 +9247,10 @@ await_ack(User, N, Timeout, Expected) when (N > 0) andalso is_integer(Timeout) -
T = tim(),
receive
{ack_received, User, Expected} ->
- d("await_ack -> received another ack"),
+ d("await_ack -> received another expected ack"),
await_ack(User, N-1, Timeout - (tim() - T), Expected);
{ack_received, User, UnExpected} ->
- e("await_ack -> unexpected ack result: ~p", [UnExpected]),
+ e("await_ack -> received unexpected ack result: ~p", [UnExpected]),
exit({unexpected_ack_result, UnExpected, Expected})
after Timeout ->
exit({await_ack_timeout, N})
@@ -9266,35 +9266,6 @@ await_ack(User, N, infinity, Expected) when N > 0 ->
exit({unexpected_ack_result, UnExpected, Expected})
end.
-%% await_req(_User, 0, Timeout) ->
-%% d("await_req -> done when Timeout = ~p", [Timeout]),
-%% ok;
-%% await_req(User, N, Timeout) when (N > 0) andalso is_integer(Timeout) ->
-%% d("await_req -> entry with N: ~p, Timeout: ~p", [N,Timeout]),
-%% T = tim(),
-%% receive
-%% {req_received, User, ARs} ->
-%% d("await_req -> received req(s) when N = ~w", [N]),
-%% N1 = await_req1(N, ARs),
-%% await_req(User, N1, Timeout - (tim() - T))
-%% after Timeout ->
-%% exit({await_req_timeout, N})
-%% end;
-%% await_req(User, N, infinity) when N > 0 ->
-%% d("await_req -> entry with N: ~p", [N]),
-%% receive
-%% {req_received, User, ARs} ->
-%% d("await_req -> received req(s) when N = ~2",[N]),
-%% N1 = await_req1(N, ARs),
-%% await_req(User, N1, infinity)
-%% end.
-
-%% await_req1(N, []) when N >= 0 ->
-%% N;
-%% await_req1(N, [AR|ARs]) when (N > 0) andalso is_record(AR, 'ActionRequest') ->
-%% await_req1(N-1, ARs);
-%% await_req1(N, ARs) ->
-%% exit({unexpected_req_result, N, ARs}).
tim() ->
{A,B,C} = erlang:timestamp(),
diff --git a/lib/megaco/test/megaco_udp_test.erl b/lib/megaco/test/megaco_udp_test.erl
index cc03ec733a..39ff44709e 100644
--- a/lib/megaco/test/megaco_udp_test.erl
+++ b/lib/megaco/test/megaco_udp_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1211,23 +1211,14 @@ p(F, A) ->
p(S, F, A) when is_list(S) ->
io:format("*** [~s] ~p ~s ***"
"~n " ++ F ++ "~n",
- [format_timestamp(now()), self(), S | A]);
+ [?FTS(), self(), S | A]);
p(_S, F, A) ->
io:format("*** [~s] ~p ~s *** "
"~n " ++ F ++ "~n",
- [format_timestamp(now()), self(), "undefined" | A]).
+ [?FTS(), self(), "undefined" | A]).
ms() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
+ erlang:monotonic_time(milli_seconds).
-format_timestamp({_N1, _N2, N3} = Now) ->
- {Date, Time} = calendar:now_to_datetime(Now),
- {YYYY,MM,DD} = Date,
- {Hour,Min,Sec} = Time,
- FormatDate =
- io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
- [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
- lists:flatten(FormatDate).
diff --git a/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
index ffbbdadec0..968e89a745 100644
--- a/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
+++ b/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
@@ -295,7 +295,7 @@ ok</pre>
if the log is large. Notice that the <c>Mnesia</c> system
continues to operate during log dumps.</p>
<p>By default <c>Mnesia</c> either dumps the log whenever
- 100 records have
+ 1000 records have
been written in the log or when three minutes have passed.
This is controlled by the two application parameters
<c>-mnesia dump_log_write_threshold WriteOperations</c> and
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 882de0d613..0f221b0c1f 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -331,35 +331,39 @@ release_schema_commit_lock() ->
%% Special for preparation of add table copy
get_network_copy(Tid, Tab, Cs) ->
-% We can't let the controller queue this one
-% because that may cause a deadlock between schema_operations
-% and initial tableloadings which both takes schema locks.
-% But we have to get copier_done msgs when the other side
-% goes down.
- call({add_other, self()}),
- Reason = {dumper,{add_table_copy, Tid}},
- Work = #net_load{table = Tab,reason = Reason,cstruct = Cs},
- %% I'll need this cause it's linked trough the subscriber
- %% might be solved by using monitor in subscr instead.
- process_flag(trap_exit, true),
- Load = load_table_fun(Work),
- Res = ?CATCH(Load()),
- process_flag(trap_exit, false),
- call({del_other, self()}),
- case Res of
- #loader_done{is_loaded = true} ->
- Tab = Res#loader_done.table_name,
- case Res#loader_done.needs_announce of
- true ->
- i_have_tab(Tab);
- false ->
- ignore
- end,
- Res#loader_done.reply;
- #loader_done{} ->
- Res#loader_done.reply;
- Else ->
- {not_loaded, Else}
+ %% We can't let the controller queue this one
+ %% because that may cause a deadlock between schema_operations
+ %% and initial tableloadings which both takes schema locks.
+ %% But we have to get copier_done msgs when the other side
+ %% goes down.
+ case call({add_other, self()}) of
+ ok ->
+ Reason = {dumper,{add_table_copy, Tid}},
+ Work = #net_load{table = Tab,reason = Reason,cstruct = Cs},
+ %% I'll need this cause it's linked trough the subscriber
+ %% might be solved by using monitor in subscr instead.
+ process_flag(trap_exit, true),
+ Load = load_table_fun(Work),
+ Res = ?CATCH(Load()),
+ process_flag(trap_exit, false),
+ call({del_other, self()}),
+ case Res of
+ #loader_done{is_loaded = true} ->
+ Tab = Res#loader_done.table_name,
+ case Res#loader_done.needs_announce of
+ true ->
+ i_have_tab(Tab);
+ false ->
+ ignore
+ end,
+ Res#loader_done.reply;
+ #loader_done{} ->
+ Res#loader_done.reply;
+ Else ->
+ {not_loaded, Else}
+ end;
+ {error, Else} ->
+ {not_loaded, Else}
end.
%% This functions is invoked from the dumper
@@ -772,6 +776,18 @@ handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
end;
+handle_call({add_other, Who}, _From, State = #state{others=Others0, schema_is_merged=SM}) ->
+ case SM of
+ true ->
+ Others = [Who|Others0],
+ {reply, ok, State#state{others=Others}};
+ false ->
+ {reply, {error, {not_active,schema,node()}}, State}
+ end;
+handle_call({del_other, Who}, _From, State = #state{others=Others0}) ->
+ Others = lists:delete(Who, Others0),
+ {reply, ok, State#state{others=Others}};
+
handle_call(Msg, From, State) when State#state.schema_is_merged /= true ->
%% Buffer early messages
Msgs = State#state.early_msgs,
@@ -803,13 +819,6 @@ handle_call({block_table, [Tab], From}, _Dummy, State) ->
handle_call({check_w2r, _Node, Tab}, _From, State) ->
{reply, val({Tab, where_to_read}), State};
-handle_call({add_other, Who}, _From, State = #state{others=Others0}) ->
- Others = [Who|Others0],
- {reply, ok, State#state{others=Others}};
-handle_call({del_other, Who}, _From, State = #state{others=Others0}) ->
- Others = lists:delete(Who, Others0),
- {reply, ok, State#state{others=Others}};
-
handle_call(Msg, _From, State) ->
error("~p got unexpected call: ~tp~n", [?SERVER_NAME, Msg]),
noreply(State).
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index f68626413e..0222c5b1a0 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -774,10 +774,12 @@ do_sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
N = node(),
receive
{?MODULE, N, granted} ->
+ ?ets_insert(Store, {sticky, true}),
?ets_insert(Store, {{locks, Tab, Key}, write}),
[?ets_insert(Store, {nodes, Node}) || Node <- WNodes],
granted;
{?MODULE, N, {granted, Val}} -> %% for rwlocks
+ ?ets_insert(Store, {sticky, true}),
case opt_lookup_in_client(Val, Oid, write) of
C = #cyclic{} ->
exit({aborted, C});
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index 4cfe16dec0..4e50b46da8 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -83,9 +83,9 @@
going_down = [], tm_started = false, early_connects = [],
connecting, mq = [], remote_node_status = []}).
--define(current_protocol_version, {8,3}).
+-define(current_protocol_version, {8,4}).
--define(previous_protocol_version, {8,2}).
+-define(previous_protocol_version, {8,3}).
start() ->
gen_server:start_link({local, ?MODULE}, ?MODULE,
@@ -196,7 +196,7 @@ protocol_version() ->
%% A sorted list of acceptable protocols the
%% preferred protocols are first in the list
acceptable_protocol_versions() ->
- [protocol_version(), ?previous_protocol_version, {8,1}].
+ [protocol_version(), ?previous_protocol_version].
needs_protocol_conversion(Node) ->
case {?catch_val({protocol, Node}), protocol_version()} of
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index ef38adca1e..d0f5d0e07b 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -697,7 +697,7 @@ schema_coordinator(Client, _Fun, undefined) ->
schema_coordinator(Client, Fun, Controller) when is_pid(Controller) ->
%% Do not trap exit in order to automatically die
%% when the controller dies
-
+ put(transaction_client, Client), %% debug
link(Controller),
unlink(Client),
@@ -730,7 +730,10 @@ api_list2cs(Other) ->
mnesia:abort({badarg, Other}).
vsn_cs2list(Cs) ->
- cs2list(need_old_cstructs(), Cs).
+ cs2list(Cs).
+
+cs2list(false, Cs) ->
+ cs2list(Cs).
cs2list(Cs) when is_record(Cs, cstruct) ->
Tags = record_info(fields, cstruct),
@@ -755,25 +758,6 @@ cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 19 ->
cookie,version],
rec2list(Tags, Tags, 2, Cs).
-cs2list(false, Cs) ->
- cs2list(Cs);
-cs2list({8,3}, Cs) ->
- cs2list(Cs);
-cs2list({8,Minor}, Cs) when Minor =:= 2; Minor =:= 1 ->
- Orig = record_info(fields, cstruct),
- Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
- load_order,access_mode,majority,index,snmp,local_content,
- record_name,attributes,
- user_properties,frag_properties,storage_properties,
- cookie,version],
- CsList = rec2list(Tags, Orig, 2, Cs),
- case proplists:get_value(index, CsList, []) of
- [] -> CsList;
- NewFormat ->
- OldFormat = [Pos || {Pos, _Pref} <- NewFormat],
- lists:keyreplace(index, 1, CsList, {index, OldFormat})
- end.
-
rec2list([index | Tags], [index|Orig], Pos, Rec) ->
Val = element(Pos, Rec),
[{index, lists:map(
@@ -796,19 +780,8 @@ rec2list([], _, _Pos, _Rec) ->
rec2list(Tags, [_|Orig], Pos, Rec) ->
rec2list(Tags, Orig, Pos+1, Rec).
-normalize_cs(Cstructs, Node) ->
- %% backward-compatibility hack; normalize before returning
- case need_old_cstructs([Node]) of
- false ->
- Cstructs;
- Version ->
- %% some other format
- [convert_cs(Version, Cs) || Cs <- Cstructs]
- end.
-
-convert_cs(Version, Cs) ->
- Fields = [Value || {_, Value} <- cs2list(Version, Cs)],
- list_to_tuple([cstruct|Fields]).
+normalize_cs(Cstructs, _Node) ->
+ Cstructs.
list2cs(List) ->
list2cs(List, get_ext_types()).
@@ -1864,11 +1837,7 @@ do_move_table(schema, _FromNode, _ToNode) ->
mnesia:abort({bad_type, schema});
do_move_table(Tab, FromNode, ToNode) when is_atom(FromNode), is_atom(ToNode) ->
TidTs = get_tid_ts_and_lock(schema, write),
- AnyOld = lists:any(fun(Node) -> mnesia_monitor:needs_protocol_conversion(Node) end,
- [ToNode|val({Tab, where_to_write})]),
- if AnyOld -> ignore; %% Leads to deadlock on old nodes
- true -> get_tid_ts_and_lock(Tab, write)
- end,
+ get_tid_ts_and_lock(Tab, write),
insert_schema_ops(TidTs, make_move_table(Tab, FromNode, ToNode));
do_move_table(Tab, FromNode, ToNode) ->
mnesia:abort({badarg, Tab, FromNode, ToNode}).
@@ -3438,15 +3407,14 @@ do_merge_schema(LockTabs0) ->
mnesia_lib:intersect(Ns,NeedsLock))
|| {T,Ns} <- LockTabs],
- NeedsConversion = need_old_cstructs(NeedsLock ++ LockedAlready),
{value, SchemaCs} = lists:keysearch(schema, #cstruct.name, Cstructs),
- SchemaDef = cs2list(NeedsConversion, SchemaCs),
+ SchemaDef = cs2list(false, SchemaCs),
%% Announce that Node is running
A = [{op, announce_im_running, node(), SchemaDef, Running, RemoteRunning}],
do_insert_schema_ops(Store, A),
%% Introduce remote tables to local node
- do_insert_schema_ops(Store, make_merge_schema(Node, NeedsConversion, Cstructs)),
+ do_insert_schema_ops(Store, make_merge_schema(Node, false, Cstructs)),
%% Introduce local tables to remote nodes
Tabs = val({schema, tables}),
@@ -3471,23 +3439,7 @@ do_merge_schema(LockTabs0) ->
end.
fetch_cstructs(Node) ->
- Convert = mnesia_monitor:needs_protocol_conversion(Node),
- case rpc:call(Node, mnesia_controller, get_remote_cstructs, []) of
- {cstructs, Cs0, RemoteRunning1} when Convert ->
- {cstructs, [list2cs(cs2list(Cs)) || Cs <- Cs0], RemoteRunning1};
- Result ->
- Result
- end.
-
-need_old_cstructs() ->
- need_old_cstructs(val({schema, where_to_write})).
-
-need_old_cstructs(Nodes) ->
- Filter = fun(Node) -> mnesia_monitor:needs_protocol_conversion(Node) end,
- case lists:filter(Filter, Nodes) of
- [] -> false;
- Ns -> lists:min([element(1, ?catch_val({protocol, Node})) || Node <- Ns])
- end.
+ rpc:call(Node, mnesia_controller, get_remote_cstructs, []).
tab_to_nodes(Tab) when is_atom(Tab) ->
Cs = val({Tab, cstruct}),
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index 8b79fca1d7..8a4113422a 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -26,7 +26,7 @@
init/1,
non_transaction/5,
transaction/6,
- commit_participant/5,
+ commit_participant/6,
dirty/2,
display_info/2,
do_update_op/3,
@@ -62,13 +62,14 @@
%% Format on coordinators is [{Tid, EtsTabList} .....
-record(prep, {protocol = sym_trans,
- %% async_dirty | sync_dirty | sym_trans | sync_sym_trans | asym_trans
+ %% async_dirty | sync_dirty | sym_trans | sync_sym_trans | asym_trans | sync_asym_trans
records = [],
prev_tab = [], % initiate to a non valid table name
prev_types,
prev_snmp,
types,
- majority = []
+ majority = [],
+ sync = false
}).
-record(participant, {tid, pid, commit, disc_nodes = [],
@@ -250,11 +251,13 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
Commit = new_cr_format(Commit0),
Pid =
- case Protocol of
- asym_trans when node(Tid#tid.pid) /= node() ->
- Args = [tmpid(From), Tid, Commit, DiscNs, RamNs],
+ if
+ node(Tid#tid.pid) =:= node() ->
+ error({internal_error, local_node});
+ Protocol =:= asym_trans orelse Protocol =:= sync_asym_trans ->
+ Args = [Protocol, tmpid(From), Tid, Commit, DiscNs, RamNs],
spawn_link(?MODULE, commit_participant, Args);
- _ when node(Tid#tid.pid) /= node() -> %% *_sym_trans
+ true -> %% *_sym_trans
reply(From, {vote_yes, Tid}),
nopid
end,
@@ -1190,7 +1193,15 @@ do_arrange(Tid, Store, RestoreKey, Prep, N) when RestoreKey == restore_op ->
P2 = Prep#prep{protocol = asym_trans, records = Recs2},
do_arrange(Tid, Store, ?ets_next(Store, RestoreKey), P2, N + 1);
do_arrange(_Tid, _Store, '$end_of_table', Prep, N) ->
- {N, Prep};
+ case Prep of
+ #prep{sync=true, protocol=asym_trans} ->
+ {N, Prep#prep{protocol=sync_asym_trans}};
+ _ ->
+ {N, Prep}
+ end;
+do_arrange(Tid, Store, sticky, Prep, N) ->
+ P2 = Prep#prep{sync=true},
+ do_arrange(Tid, Store, ?ets_next(Store, sticky), P2, N);
do_arrange(Tid, Store, IgnoredKey, Prep, N) -> %% locks, nodes ... local atoms...
do_arrange(Tid, Store, ?ets_next(Store, IgnoredKey), Prep, N).
@@ -1448,7 +1459,8 @@ multi_commit(sync_sym_trans, _Maj = [], Tid, CR, Store) ->
[{tid, Tid}, {outcome, Outcome}]),
Outcome;
-multi_commit(asym_trans, Majority, Tid, CR, Store) ->
+multi_commit(Protocol, Majority, Tid, CR, Store)
+ when Protocol =:= asym_trans; Protocol =:= sync_asym_trans ->
%% This more expensive commit protocol is used when
%% table definitions are changed (schema transactions).
%% It is also used when the involved tables are
@@ -1515,7 +1527,7 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
end,
Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
?ets_insert(Store, Pending),
- {WaitFor, Local} = ask_commit(asym_trans, Tid, CR2, DiscNs, RamNs),
+ {WaitFor, Local} = ask_commit(Protocol, Tid, CR2, DiscNs, RamNs),
SchemaPrep = ?CATCH(mnesia_schema:prepare_commit(Tid, Local, {coord, WaitFor})),
{Votes, Pids} = rec_all(WaitFor, Tid, do_commit, []),
@@ -1563,38 +1575,38 @@ multi_commit(asym_trans, Majority, Tid, CR, Store) ->
%% Returns do_commit or {do_abort, Reason}
rec_acc_pre_commit([Pid | Tail], Tid, Store, Commit, Res, DumperMode,
- GoodPids, SchemaAckPids) ->
+ GoodPids, AckPids) ->
receive
{?MODULE, _, {acc_pre_commit, Tid, Pid, true}} ->
rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
- [Pid | GoodPids], [Pid | SchemaAckPids]);
+ [Pid | GoodPids], [Pid | AckPids]);
{?MODULE, _, {acc_pre_commit, Tid, Pid, false}} ->
rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
- [Pid | GoodPids], SchemaAckPids);
+ [Pid | GoodPids], AckPids);
{?MODULE, _, {acc_pre_commit, Tid, Pid}} ->
%% Kept for backwards compatibility. Remove after Mnesia 4.x
rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
- [Pid | GoodPids], [Pid | SchemaAckPids]);
+ [Pid | GoodPids], [Pid | AckPids]);
{?MODULE, _, {do_abort, Tid, Pid, _Reason}} ->
AbortRes = {do_abort, {bad_commit, node(Pid)}},
rec_acc_pre_commit(Tail, Tid, Store, Commit, AbortRes, DumperMode,
- GoodPids, SchemaAckPids);
+ GoodPids, AckPids);
{mnesia_down, Node} when Node == node(Pid) ->
AbortRes = {do_abort, {bad_commit, Node}},
?SAFE(Pid ! {Tid, AbortRes}), %% Tell him that he has died
rec_acc_pre_commit(Tail, Tid, Store, Commit, AbortRes, DumperMode,
- GoodPids, SchemaAckPids)
+ GoodPids, AckPids)
end;
-rec_acc_pre_commit([], Tid, Store, {Commit,OrigC}, Res, DumperMode, GoodPids, SchemaAckPids) ->
+rec_acc_pre_commit([], Tid, Store, {Commit,OrigC}, Res, DumperMode, GoodPids, AckPids) ->
D = Commit#commit.decision,
case Res of
do_commit ->
%% Now everybody knows that the others
%% has voted yes. We also know that
%% everybody are uncertain.
- prepare_sync_schema_commit(Store, SchemaAckPids),
+ prepare_sync_schema_commit(Store, AckPids),
tell_participants(GoodPids, {Tid, committed}),
D2 = D#decision{outcome = committed},
mnesia_recover:log_decision(D2),
@@ -1606,7 +1618,7 @@ rec_acc_pre_commit([], Tid, Store, {Commit,OrigC}, Res, DumperMode, GoodPids, Sc
do_commit(Tid, Commit, DumperMode),
?eval_debug_fun({?MODULE, rec_acc_pre_commit_done_commit},
[{tid, Tid}]),
- sync_schema_commit(Tid, Store, SchemaAckPids),
+ sync_schema_commit(Tid, Store, AckPids),
mnesia_locker:release_tid(Tid),
?MODULE ! {delete_transaction, Tid};
@@ -1623,6 +1635,7 @@ rec_acc_pre_commit([], Tid, Store, {Commit,OrigC}, Res, DumperMode, GoodPids, Sc
Res.
%% Note all nodes in case of mnesia_down mgt
+%% sync_schema_commit is (ab)used for sync_asym_trans as well.
prepare_sync_schema_commit(_Store, []) ->
ok;
prepare_sync_schema_commit(Store, [Pid | Pids]) ->
@@ -1648,17 +1661,17 @@ tell_participants([Pid | Pids], Msg) ->
tell_participants([], _Msg) ->
ok.
--spec commit_participant(_, _, _, _, _) -> no_return().
+-spec commit_participant(_, _, _, _, _, _) -> no_return().
%% Trap exit because we can get a shutdown from application manager
-commit_participant(Coord, Tid, Bin, DiscNs, RamNs) when is_binary(Bin) ->
+commit_participant(Protocol, Coord, Tid, Bin, DiscNs, RamNs) when is_binary(Bin) ->
process_flag(trap_exit, true),
Commit = binary_to_term(Bin),
- commit_participant(Coord, Tid, Bin, Commit, DiscNs, RamNs);
-commit_participant(Coord, Tid, C = #commit{}, DiscNs, RamNs) ->
+ commit_participant(Protocol, Coord, Tid, Bin, Commit, DiscNs, RamNs);
+commit_participant(Protocol, Coord, Tid, C = #commit{}, DiscNs, RamNs) ->
process_flag(trap_exit, true),
- commit_participant(Coord, Tid, C, C, DiscNs, RamNs).
+ commit_participant(Protocol, Coord, Tid, C, C, DiscNs, RamNs).
-commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
+commit_participant(Protocol, Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?eval_debug_fun({?MODULE, commit_participant, pre}, [{tid, Tid}]),
try mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
{Modified, C = #commit{}, DumperMode} ->
@@ -1683,8 +1696,9 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
mnesia_recover:log_decision(D#decision{outcome = unclear}),
?eval_debug_fun({?MODULE, commit_participant, pre_commit},
[{tid, Tid}]),
- Expect_schema_ack = C#commit.schema_ops /= [],
- reply(Coord, {acc_pre_commit, Tid, self(), Expect_schema_ack}),
+ ExpectAck = C#commit.schema_ops /= []
+ orelse Protocol =:= sync_asym_trans,
+ reply(Coord, {acc_pre_commit, Tid, self(), ExpectAck}),
%% Now we are vulnerable for failures, since
%% we cannot decide without asking others
@@ -1694,7 +1708,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?eval_debug_fun({?MODULE, commit_participant, log_commit},
[{tid, Tid}]),
do_commit(Tid, C, DumperMode),
- case Expect_schema_ack of
+ case ExpectAck of
false -> ignore;
true -> reply(Coord, {schema_commit, Tid, self()})
end,
@@ -1978,7 +1992,7 @@ sync_send_dirty(Tid, [Head | Tail], Tab, WaitFor) ->
Res = do_dirty(Tid, Head),
{WF, Res};
true ->
- {?MODULE, Node} ! {self(), {sync_dirty, Tid, ext_format(Head), Tab}},
+ {?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
sync_send_dirty(Tid, Tail, Tab, [Node | WaitFor])
end;
sync_send_dirty(_Tid, [], _Tab, WaitFor) ->
@@ -1997,11 +2011,11 @@ async_send_dirty(Tid, [Head | Tail], Tab, ReadNode, WaitFor, Res) ->
NewRes = do_dirty(Tid, Head),
async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, NewRes);
ReadNode == Node ->
- {?MODULE, Node} ! {self(), {sync_dirty, Tid, ext_format(Head), Tab}},
+ {?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
NewRes = {'EXIT', {aborted, {node_not_running, Node}}},
async_send_dirty(Tid, Tail, Tab, ReadNode, [Node | WaitFor], NewRes);
true ->
- {?MODULE, Node} ! {self(), {async_dirty, Tid, ext_format(Head), Tab}},
+ {?MODULE, Node} ! {self(), {async_dirty, Tid, Head, Tab}},
async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, Res)
end;
async_send_dirty(_Tid, [], _Tab, _ReadNode, WaitFor, Res) ->
@@ -2058,24 +2072,20 @@ ask_commit(Protocol, Tid, [Head | Tail], DiscNs, RamNs, WaitFor, Local) ->
Node == node() ->
ask_commit(Protocol, Tid, Tail, DiscNs, RamNs, WaitFor, Head);
true ->
- CR = ext_format(Head),
- Msg = {ask_commit, Protocol, Tid, CR, DiscNs, RamNs},
+ Msg = {ask_commit, convert_old(Protocol, Node), Tid, Head, DiscNs, RamNs},
{?MODULE, Node} ! {self(), Msg},
ask_commit(Protocol, Tid, Tail, DiscNs, RamNs, [Node | WaitFor], Local)
end;
ask_commit(_Protocol, _Tid, [], _DiscNs, _RamNs, WaitFor, Local) ->
{WaitFor, Local}.
-ext_format(#commit{ext=[]}=CR) -> CR;
-ext_format(#commit{node=Node, ext=Ext}=CR) ->
+convert_old(sync_asym_trans, Node) ->
case mnesia_monitor:needs_protocol_conversion(Node) of
- true ->
- case lists:keyfind(snmp, 1, Ext) of
- false -> CR#commit{ext=[]};
- {snmp, List} -> CR#commit{ext=List}
- end;
- false -> CR
- end.
+ true -> asym_trans;
+ false -> sync_asym_trans
+ end;
+convert_old(Protocol, _) ->
+ Protocol.
new_cr_format(#commit{ext=[]}=Cr) -> Cr;
new_cr_format(#commit{ext=[{_,_}|_]}=Cr) -> Cr;
@@ -2304,7 +2314,7 @@ reconfigure_participants(_, []) ->
%% tell mnesia_tm on all involved nodes (including the local node)
%% about the outcome.
tell_outcome(Tid, Protocol, Node, CheckNodes, TellNodes) ->
- Outcome = mnesia_recover:what_happened(Tid, Protocol, CheckNodes),
+ Outcome = mnesia_recover:what_happened(Tid, proto(Protocol), CheckNodes),
case Outcome of
aborted ->
rpc:abcast(TellNodes, ?MODULE, {Tid,{do_abort, {mnesia_down, Node}}});
@@ -2313,6 +2323,9 @@ tell_outcome(Tid, Protocol, Node, CheckNodes, TellNodes) ->
end,
Outcome.
+proto(sync_asym_trans) -> asym_trans;
+proto(Proto) -> Proto.
+
do_stop(#state{coordinators = Coordinators}) ->
Msg = {mnesia_down, node()},
lists:foreach(fun({Tid, _}) -> Tid#tid.pid ! Msg end, gb_trees:to_list(Coordinators)),
diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl
index 49bcec14af..c99158945d 100644
--- a/lib/mnesia/test/mnesia_isolation_test.erl
+++ b/lib/mnesia/test/mnesia_isolation_test.erl
@@ -29,7 +29,7 @@
-export([no_conflict/1, simple_queue_conflict/1,
advanced_queue_conflict/1, simple_deadlock_conflict/1,
advanced_deadlock_conflict/1, schema_deadlock/1, lock_burst/1,
- nasty/1, basic_sticky_functionality/1,
+ nasty/1, basic_sticky_functionality/1, sticky_sync/1,
unbound1/1, unbound2/1,
create_table/1, delete_table/1, move_table_copy/1,
add_table_index/1, del_table_index/1, transform_table/1,
@@ -71,7 +71,8 @@ groups() ->
advanced_deadlock_conflict, schema_deadlock, lock_burst,
{group, sticky_locks}, {group, unbound_locking},
{group, admin_conflict}, nasty]},
- {sticky_locks, [], [basic_sticky_functionality]},
+ {sticky_locks, [],
+ [basic_sticky_functionality,sticky_sync]},
{unbound_locking, [], [unbound1, unbound2]},
{admin_conflict, [],
[create_table, delete_table, move_table_copy,
@@ -594,9 +595,49 @@ get_held() ->
mnesia_locker ! {get_table, self(), mnesia_sticky_locks},
receive {mnesia_sticky_locks, Locks} -> Locks end.
+sticky_sync(suite) -> [];
+sticky_sync(Config) when is_list(Config) ->
+ %% BUG ERIERL-768
+ Nodes = [N1, N2] = ?acquire_nodes(2, Config),
+
+ mnesia:create_table(dc, [{type, ordered_set}, {disc_copies, Nodes}]),
+ mnesia:create_table(ec, [{type, ordered_set}, {ram_copies, [N2]}]),
+
+ TestFun =
+ fun(I) ->
+ %% In first transaction we initialise {dc, I} record with value 0
+ First = fun() ->
+ %% Do a lot of writes into ram copies table
+ %% which on the Slave in do_commit will be
+ %% processed first
+ lists:foreach(fun(J) -> ok = mnesia:write(ec, {ec, J, 0}, write) end,
+ lists:seq(1, 750)),
+ %% Then set initial value of {dc, I} record to 0 with sticky_write
+ mnesia:write(dc, {dc, I, 0}, sticky_write)
+ end,
+ ok = mnesia:activity(transaction, First),
+ %% In second transaction we set value of {dc, I} record to 1
+ Upd = fun() ->
+ %% Modify a single ram copies record with ensured lock grant
+ %% (key not used in previous transactions)
+ %% we use this second table only to force asym_trans protocol
+ mnesia:write(ec, {ec, 1001 + I, 0}, write),
+ %% And set final version of {dc, I} record to 1 with sticky_write
+ mnesia:write(dc, {dc, I, 1}, sticky_write)
+ end,
+ ok = mnesia:activity(transaction, Upd)
+ end,
+
+ %% Fill 1000 dc records. At the end all dc records should have value 1.
+ lists:foreach(TestFun, lists:seq(1,1000)),
+ io:format("Written, check content~n",[]),
+ All = fun() -> mnesia:select(dc, [ {{dc, '_', 0}, [] ,['$_']} ]) end,
+ ?match({atomic, []}, rpc:call(N1, mnesia, sync_transaction, [All])),
+ ?match({atomic, []}, rpc:call(N2, mnesia, sync_transaction, [All])),
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ ?verify_mnesia(Nodes, []).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
unbound1(suite) -> [];
unbound1(Config) when is_list(Config) ->
@@ -1036,29 +1077,57 @@ add_table_copy(Config) when is_list(Config) ->
Def = [{ram_copies, [ThisNode]}, {attributes, [key, attr1, attr2]}],
?match({atomic, ok}, mnesia:create_table(Tab, Def)),
insert(Tab, 50),
- {success, [A]} = ?start_activities([ThisNode]),
+ {success, [A]} = ?start_activities([ThisNode]),
mnesia_test_lib:start_sync_transactions([A], 0),
A ! fun() -> mnesia:write({Tab, 1, 1, updated}) end,
?match_receive({A, ok}), %% A is executed
- Pid = spawn_link(?MODULE, op, [self(), mnesia, add_table_copy,
+ Pid = spawn_link(?MODULE, op, [self(), mnesia, add_table_copy,
[Tab, Node2, ram_copies]]),
-
+
?match_receive(timeout), %% op waits for locks occupied by A
A ! end_trans, %% Kill A, locks should be released
- ?match_receive({A,{atomic,end_trans}}),
-
- receive
+ ?match_receive({A,{atomic,end_trans}}),
+
+ receive
Msg -> ?match({Pid, {atomic, ok}}, Msg)
after
timer:seconds(20) -> ?error("Operation timed out", [])
end,
+ ?match_receive({'EXIT', Pid, normal}),
sys:get_status(whereis(mnesia_locker)), % Explicit sync, release locks is async
- ?match([], mnesia:system_info(held_locks)),
- ?match([], mnesia:system_info(lock_queue)),
+ ?match([], mnesia:system_info(held_locks)),
+ ?match([], mnesia:system_info(lock_queue)),
+
+ {atomic, ok} = mnesia:del_table_copy(Tab, Node2),
+ Self = self(),
+ New = spawn_link(Node2,
+ fun () ->
+ application:stop(mnesia),
+ Self ! {self(), ok},
+ io:format(user, "restart mnesia~n", []),
+ Self ! {self(), catch application:start(mnesia)}
+ end),
+ receive {New,ok} -> ok end,
+
+ Add = fun Add() ->
+ case mnesia:add_table_copy(Tab, Node2, disc_copies) of
+ {atomic, ok} -> ok;
+ _R -> io:format(user, "aborted with reason ~p~n", [_R]),
+ timer:sleep(10),
+ Add()
+ end
+ end,
+
+ ?match(ok, Add()),
+ ?match_receive({New,ok}),
+
+ sys:get_status(whereis(mnesia_locker)), % Explicit sync, release locks is async
+ ?match([], mnesia:system_info(held_locks)),
+ ?match([], mnesia:system_info(lock_queue)),
ok.
del_table_copy(suite) -> [];
diff --git a/lib/mnesia/test/mt b/lib/mnesia/test/mt
index a398ee0422..b169734f56 100755
--- a/lib/mnesia/test/mt
+++ b/lib/mnesia/test/mt
@@ -34,8 +34,35 @@ erlcmd="erl -sname a $p $args -mnesia_test_timeout"
erlcmd1="erl -sname a1 $p $args"
erlcmd2="erl -sname a2 $p $args"
-xterm -geometry 70x20+0+550 -T a1 -e $erlcmd1 &
-xterm -geometry 70x20+450+550 -T a2 -e $erlcmd2 &
+if test z"$MT_TERM" = z ; then
+ MT_TERM=xterm
+fi
+
+case $MT_TERM in
+ xterm)
+ geom0="-geometry 142x40+0+0"
+ geom1="-geometry 70x20+0+550"
+ geom2="-geometry 70x20+480+550"
+ title="-T"
+ exec="-e"
+ ;;
+ gnome-terminal)
+ geom0="--geometry 142x40+0+0"
+ geom1="--geometry 70x20+0+740"
+ geom2="--geometry 70x20+700+740"
+ title="--title"
+ exec="--hide-menubar --"
+ ;;
+ *rxvt)
+ geom0="-geometry 142x40+0+0"
+ geom1="-geometry 70x20+0+680"
+ geom2="-geometry 70x20+630+680"
+ title="-title"
+ exec="-e"
+esac
+
+$MT_TERM $geom1 $title a1 $exec $erlcmd1 &
+$MT_TERM $geom2 $title a2 $exec $erlcmd2 &
rm "$latest" 2>/dev/null
ln -s "$log" "$latest"
@@ -51,11 +78,6 @@ echo "Give the following command in order to see the outcome from node a@$h"":"
echo ""
echo " less test_log$$"
-ostype=`uname -s`
-if [ "$ostype" = "SunOS" ] ; then
- /usr/openwin/bin/xterm -geometry 145x40+0+0 -T a -l -lf "$log" -e $erlcmd &
-else
- xterm -geometry 145x40+0+0 -T a -e script -f -c "$erlcmd" "$log" &
-fi
+$MT_TERM $geom0 $title a $exec script -f -c "$erlcmd" "$log" &
tail -f "$log" | egrep 'Eval|<>ERROR|NYI'
diff --git a/lib/observer/src/cdv_bin_cb.erl b/lib/observer/src/cdv_bin_cb.erl
index 91d33474c8..819596b483 100644
--- a/lib/observer/src/cdv_bin_cb.erl
+++ b/lib/observer/src/cdv_bin_cb.erl
@@ -33,42 +33,43 @@ detail_pages() ->
[{"Binary", fun init_bin_page/2}].
init_bin_page(Parent,{Type,Bin}) ->
+ Cs = observer_lib:colors(Parent),
cdv_multi_wx:start_link(
Parent,
- [{"Format \~p",cdv_html_wx,{Type,format_bin_fun("~p",Bin)}},
- {"Format \~tp",cdv_html_wx,{Type,format_bin_fun("~tp",Bin)}},
- {"Format \~w",cdv_html_wx,{Type,format_bin_fun("~w",Bin)}},
- {"Format \~tw",cdv_html_wx,{Type,format_bin_fun("~tw",Bin)}},
- {"Format \~s",cdv_html_wx,{Type,format_bin_fun("~s",Bin)}},
- {"Format \~ts",cdv_html_wx,{Type,format_bin_fun("~ts",Bin)}},
- {"Hex",cdv_html_wx,{Type,hex_binary_fun(Bin)}},
- {"Term",cdv_html_wx,{Type,binary_to_term_fun(Bin)}}]).
+ [{"Format \~p",cdv_html_wx,{Type,format_bin_fun("~p",Bin,Cs)}},
+ {"Format \~tp",cdv_html_wx,{Type,format_bin_fun("~tp",Bin,Cs)}},
+ {"Format \~w",cdv_html_wx,{Type,format_bin_fun("~w",Bin,Cs)}},
+ {"Format \~tw",cdv_html_wx,{Type,format_bin_fun("~tw",Bin,Cs)}},
+ {"Format \~s",cdv_html_wx,{Type,format_bin_fun("~s",Bin,Cs)}},
+ {"Format \~ts",cdv_html_wx,{Type,format_bin_fun("~ts",Bin,Cs)}},
+ {"Hex",cdv_html_wx,{Type,hex_binary_fun(Bin,Cs)}},
+ {"Term",cdv_html_wx,{Type,binary_to_term_fun(Bin,Cs)}}]).
-format_bin_fun(Format,Bin) ->
+format_bin_fun(Format,Bin,Cs) ->
fun() ->
try io_lib:format(Format,[Bin]) of
- Str -> plain_html(lists:flatten(Str))
+ Str -> plain_html(lists:flatten(Str),Cs)
catch error:badarg ->
Warning = "This binary cannot be formatted with " ++ Format,
- observer_html_lib:warning(Warning)
+ observer_html_lib:warning(Warning,Cs)
end
end.
-binary_to_term_fun(Bin) ->
+binary_to_term_fun(Bin,Cs) ->
fun() ->
try binary_to_term(Bin) of
- Term -> plain_html(io_lib:format("~tp",[Term]))
+ Term -> plain_html(io_lib:format("~tp",[Term]),Cs)
catch error:badarg ->
Warning = "This binary cannot be converted to an Erlang term",
- observer_html_lib:warning(Warning)
+ observer_html_lib:warning(Warning,Cs)
end
end.
-define(line_break,25).
-hex_binary_fun(Bin) ->
+hex_binary_fun(Bin,Cs) ->
fun() ->
S = "<<" ++ format_hex(Bin,?line_break) ++ ">>",
- plain_html(io_lib:format("~s",[S]))
+ plain_html(io_lib:format("~s",[S]), Cs)
end.
format_hex(<<>>,_) ->
@@ -82,5 +83,5 @@ format_hex(<<B1:4,B2:4,Bin/binary>>,N) ->
[integer_to_list(B1,16),integer_to_list(B2,16),$,
| format_hex(Bin,N-1)].
-plain_html(Text) ->
- observer_html_lib:plain_page(Text).
+plain_html(Text,Cs) ->
+ observer_html_lib:plain_page(Text,Cs).
diff --git a/lib/observer/src/cdv_html_wx.erl b/lib/observer/src/cdv_html_wx.erl
index 8956173c93..83ee98de6e 100644
--- a/lib/observer/src/cdv_html_wx.erl
+++ b/lib/observer/src/cdv_html_wx.erl
@@ -30,7 +30,8 @@
%% Records
-record(state,
- {panel,
+ {parent,
+ panel,
app, %% which tool is the user
expand_table,
expand_wins=[],
@@ -62,7 +63,7 @@ init(ParentWin, HtmlText, Tab, App) ->
HtmlWin = observer_lib:html_window(ParentWin),
wxHtmlWindow:setPage(HtmlWin,HtmlText),
wx_misc:endBusyCursor(),
- {HtmlWin, #state{panel=HtmlWin,expand_table=Tab,app=App}}.
+ {HtmlWin, #state{parent=ParentWin, panel=HtmlWin,expand_table=Tab,app=App}}.
init(ParentWin, Callback) ->
{HtmlWin, State} = init(ParentWin, "", undefined, cdv),
@@ -70,12 +71,15 @@ init(ParentWin, Callback) ->
%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-handle_info(active, #state{panel=HtmlWin,delayed_fetch=Callback}=State)
+handle_info(active, #state{parent=Parent, 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(),
+ {{expand,Title,Info,Tab},TW} = Callback:get_info(),
+ Cs = observer_lib:colors(Parent),
+ HtmlText = observer_html_lib:expandable_term(Title,Info,Tab,Cs),
+
observer_lib:sync_destroy_progress_dialog(),
wx_misc:beginBusyCursor(),
wxHtmlWindow:setPage(HtmlWin,HtmlText),
@@ -138,7 +142,8 @@ handle_event(#wx{event=#wxHtmlLink{type=command_html_link_clicked,
list_to_integer(Key3)}}},
expand(Id,cdv_term_cb,State);
_ when App =:= obs ->
- observer ! {open_link, Target};
+ observer ! {open_link, Target},
+ State;
_ ->
cdv_virtual_list_wx:start_detail_win(Target),
State
diff --git a/lib/observer/src/cdv_mod_cb.erl b/lib/observer/src/cdv_mod_cb.erl
index 2183e1aa3d..7f2cd0cf87 100644
--- a/lib/observer/src/cdv_mod_cb.erl
+++ b/lib/observer/src/cdv_mod_cb.erl
@@ -85,7 +85,8 @@ init_old_comp_page(Parent, Info) ->
init_info_page(Parent, undefined) ->
init_info_page(Parent, "");
init_info_page(Parent, String) ->
- cdv_html_wx:start_link(Parent,observer_html_lib:plain_page(String)).
+ Cs = observer_lib:colors(Parent),
+ cdv_html_wx:start_link(Parent,observer_html_lib:plain_page(String,Cs)).
format({Bin,q}) when is_binary(Bin) ->
[$'|binary_to_list(Bin)];
diff --git a/lib/observer/src/cdv_persistent_cb.erl b/lib/observer/src/cdv_persistent_cb.erl
index d5da18f7fc..90abc6a4f5 100644
--- a/lib/observer/src/cdv_persistent_cb.erl
+++ b/lib/observer/src/cdv_persistent_cb.erl
@@ -26,7 +26,4 @@
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}.
+ {{expand, "Persistent Terms", PT, Tab}, TW}.
diff --git a/lib/observer/src/cdv_proc_cb.erl b/lib/observer/src/cdv_proc_cb.erl
index 2497b4889e..61bd86f188 100644
--- a/lib/observer/src/cdv_proc_cb.erl
+++ b/lib/observer/src/cdv_proc_cb.erl
@@ -108,7 +108,7 @@ init_stack_page(Parent, Info) ->
init_memory_page(Parent, Info0, Tag, Heading) ->
Info = proplists:get_value(Tag,Info0),
Tab = proplists:get_value(expand_table,Info0),
- Html = observer_html_lib:expandable_term(Heading,Info,Tab),
+ Html = observer_html_lib:expandable_term(Heading,Info,Tab, observer_lib:colors(Parent)),
cdv_html_wx:start_link(Parent,{expand,Html,Tab}).
init_ets_page(Parent, Info) ->
diff --git a/lib/observer/src/cdv_term_cb.erl b/lib/observer/src/cdv_term_cb.erl
index 85da1d227a..a2a7a8750d 100644
--- a/lib/observer/src/cdv_term_cb.erl
+++ b/lib/observer/src/cdv_term_cb.erl
@@ -35,31 +35,32 @@ init_term_page(ParentWin, {Type, [Term, Tab]}) ->
Expanded = expand(Term, true),
BinSaved = expand(Term, Tab),
observer_lib:report_progress({ok,stop_pulse}),
+ Cs = observer_lib:colors(ParentWin),
cdv_multi_wx:start_link(
ParentWin,
- [{"Format \~p",cdv_html_wx,{Type, format_term_fun("~p",BinSaved,Tab)}},
- {"Format \~tp",cdv_html_wx,{Type,format_term_fun("~tp",BinSaved,Tab)}},
- {"Format \~w",cdv_html_wx,{Type,format_term_fun("~w",BinSaved,Tab)}},
- {"Format \~tw",cdv_html_wx,{Type,format_term_fun("~tw",BinSaved,Tab)}},
- {"Format \~s",cdv_html_wx,{Type,format_term_fun("~s",Expanded,Tab)}},
- {"Format \~ts",cdv_html_wx,{Type,format_term_fun("~ts",Expanded,Tab)}}]).
+ [{"Format \~p",cdv_html_wx,{Type, format_term_fun("~p",BinSaved,Tab,Cs)}},
+ {"Format \~tp",cdv_html_wx,{Type,format_term_fun("~tp",BinSaved,Tab,Cs)}},
+ {"Format \~w",cdv_html_wx,{Type,format_term_fun("~w",BinSaved,Tab,Cs)}},
+ {"Format \~tw",cdv_html_wx,{Type,format_term_fun("~tw",BinSaved,Tab,Cs)}},
+ {"Format \~s",cdv_html_wx,{Type,format_term_fun("~s",Expanded,Tab,Cs)}},
+ {"Format \~ts",cdv_html_wx,{Type,format_term_fun("~ts",Expanded,Tab,Cs)}}]).
-format_term_fun(Format,Term,Tab) ->
+format_term_fun(Format,Term,Tab,Cs) ->
fun() ->
observer_lib:report_progress({ok,"Formatting term"}),
observer_lib:report_progress({ok,start_pulse}),
try io_lib:format(Format,[Term]) of
- Str -> {expand, plain_html(Str), Tab}
+ Str -> {expand, plain_html(Str,Cs), Tab}
catch error:badarg ->
Warning = "This term cannot be formatted with " ++ Format,
- observer_html_lib:warning(Warning)
+ observer_html_lib:warning(Warning,Cs)
after
observer_lib:report_progress({ok,stop_pulse})
end
end.
-plain_html(Text) ->
- observer_html_lib:plain_page(Text).
+plain_html(Text,Cs) ->
+ observer_html_lib:plain_page(Text,Cs).
expand(['#CDVBin',Offset,Size,Pos], true) ->
{ok,Bin} = crashdump_viewer:expand_binary({Offset,Size,Pos}),
diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl
index 14877b7eab..51e85e17c1 100644
--- a/lib/observer/src/cdv_virtual_list_wx.erl
+++ b/lib/observer/src/cdv_virtual_list_wx.erl
@@ -96,8 +96,9 @@ start_detail_win_2(Callback,Id) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init([ParentWin, Callback, Owner]) ->
- {Holder,TW} = spawn_table_holder(Callback, Owner),
Panel = wxPanel:new(ParentWin),
+ Attrs = observer_lib:create_attrs(Panel),
+ {Holder,TW} = spawn_table_holder(Callback, Owner, Attrs),
{Grid,MenuCols} = create_list_box(Panel, Holder, Callback, Owner),
Sizer = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Sizer, Grid, [{flag, ?wxEXPAND bor ?wxALL},
@@ -233,7 +234,8 @@ handle_call(new_dump, _From,
Ref = erlang:monitor(process,Holder),
Holder ! stop,
receive {'DOWN',Ref,_,_,_} -> ok end,
- {NewHolder,TW} = spawn_table_holder(Callback, all),
+ Attrs = observer_lib:create_attrs(Grid),
+ {NewHolder,TW} = spawn_table_holder(Callback, all, Attrs),
{reply, ok, State#state{detail_wins=[],holder=NewHolder,trunc_warn=TW}};
handle_call(Msg, _From, State) ->
@@ -329,9 +331,8 @@ handle_event(Event, State) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%TABLE HOLDER%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spawn_table_holder(Callback, Owner) ->
+spawn_table_holder(Callback, Owner, Attrs) ->
{Info,TW} = Callback:get_info(Owner),
- Attrs = observer_lib:create_attrs(),
Parent = self(),
Holder =
case Owner of
diff --git a/lib/observer/src/cdv_wx.erl b/lib/observer/src/cdv_wx.erl
index 7100cc8790..8ad5da857e 100644
--- a/lib/observer/src/cdv_wx.erl
+++ b/lib/observer/src/cdv_wx.erl
@@ -197,8 +197,7 @@ setup(#state{frame=Frame, notebook=Notebook}=State) ->
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),
+ 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),
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
index 8c3eef5411..c4527ba063 100644
--- a/lib/observer/src/observer_app_wx.erl
+++ b/lib/observer/src/observer_app_wx.erl
@@ -48,7 +48,7 @@
usegc = false
}).
--record(paint, {font, pen, brush, sel, links}).
+-record(paint, {font, fg, pen, brush, sel, links}).
-record(app, {ptree, n2p, links, dim}).
-record(box, {x,y, w,h, s1}).
@@ -92,7 +92,8 @@ init([Notebook, Parent, _Config]) ->
Extra = wxBoxSizer:new(?wxVERTICAL),
DrawingArea = wxScrolledWindow:new(P2, [{winid, ?DRAWAREA},
{style,?wxFULL_REPAINT_ON_RESIZE}]),
- wxWindow:setBackgroundColour(DrawingArea, ?wxWHITE),
+ BG = wxWindow:getBackgroundColour(Apps),
+ wxWindow:setBackgroundStyle(DrawingArea, ?wxBG_STYLE_SYSTEM),
wxWindow:setVirtualSize(DrawingArea, 800, 800),
wxSplitterWindow:setMinimumPaneSize(Splitter,50),
wxSizer:add(Extra, DrawingArea, [{flag, ?wxEXPAND},{proportion, 1}]),
@@ -127,7 +128,17 @@ init([Notebook, Parent, _Config]) ->
Font0
end,
SelCol = wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT),
- GreyBrush = wxBrush:new({230,230,240}),
+ {Fg,BGBrush,Pen} =
+ case observer_lib:is_darkmode(BG) of
+ false ->
+ {wxSystemSettings:getColour(?wxSYS_COLOUR_BTNTEXT),
+ wxBrush:new(wxSystemSettings:getColour(?wxSYS_COLOUR_BTNSHADOW)),
+ wxPen:new({80,80,80}, [{width, Scale * 2}])};
+ true ->
+ {wxSystemSettings:getColour(?wxSYS_COLOUR_BTNTEXT),
+ wxBrush:new(wxSystemSettings:getColour(?wxSYS_COLOUR_BTNSHADOW)),
+ wxPen:new({0,0,0}, [{width, Scale * 2}])}
+ end,
SelBrush = wxBrush:new(SelCol),
LinkPen = wxPen:new(SelCol, [{width, Scale * 2}]),
process_flag(trap_exit, true),
@@ -137,8 +148,9 @@ init([Notebook, Parent, _Config]) ->
app_w =DrawingArea,
usegc = UseGC,
paint=#paint{font = Font,
- pen = wxPen:new({80,80,80}, [{width, Scale * 2}]),
- brush= GreyBrush,
+ fg = Fg,
+ pen = Pen,
+ brush= BGBrush,
sel = SelBrush,
links= LinkPen
}
@@ -306,11 +318,11 @@ handle_info({delivery, _Pid, app, _Curr, {[], [], [], []}},
handle_info({delivery, Pid, app, Curr, AppData},
State = #state{panel=Panel, appmon=Pid, current=Curr, usegc=UseGC,
- app_w=AppWin, paint=#paint{font=Font}}) ->
+ app_w=AppWin, paint=#paint{fg=Fg, font=Font}}) ->
GC = if UseGC -> {?wxGC:create(AppWin), false};
true -> {false, wxWindowDC:new(AppWin)}
end,
- setFont(GC, Font, {0,0,0}),
+ setFont(GC, Font, Fg),
App = build_tree(AppData, GC),
destroy_gc(GC),
setup_scrollbar(AppWin, App),
@@ -508,13 +520,13 @@ tree_map([], _ , Acc) -> Acc.
draw(_DC, undefined, _, _) ->
ok;
draw(DC, #app{dim={_W,_H}, ptree=Tree, links=Links}, Sel,
- #paint{font=Font, pen=Pen, brush=Brush, links=LPen, sel=SelBrush}) ->
+ #paint{font=Font, fg=Fg, pen=Pen, brush=Brush, links=LPen, sel=SelBrush}) ->
setPen(DC, LPen),
[draw_xlink(Link, DC) || Link <- Links],
setPen(DC, Pen),
%% ?wxGC:drawRectangle(DC, 2,2, _W-2,_H-2), %% DEBUG
setBrush(DC, Brush),
- setFont(DC, Font, {0,0,0}),
+ setFont(DC, Font, Fg),
draw_tree(Tree, root, DC),
case Sel of
undefined -> ok;
diff --git a/lib/observer/src/observer_defs.hrl b/lib/observer/src/observer_defs.hrl
index 504d0877d9..7902b32cba 100644
--- a/lib/observer/src/observer_defs.hrl
+++ b/lib/observer/src/observer_defs.hrl
@@ -36,6 +36,7 @@
check = false
}).
+-record(colors, {fg, even, odd}).
-record(attrs, {even, odd, searched, deleted, changed_odd, changed_even, new_odd, new_even}).
-define(EVEN(Row), ((Row rem 2) =:= 0)).
-define(BG_EVEN, {230,230,250}).
diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl
index c67fa28c6d..4c92a8faab 100644
--- a/lib/observer/src/observer_html_lib.erl
+++ b/lib/observer/src/observer_html_lib.erl
@@ -24,9 +24,9 @@
%% viewer. No logic or states are kept by this module.
%%
--export([plain_page/1,
- expandable_term/3,
- warning/1]).
+-export([plain_page/2,
+ expandable_term/4,
+ warning/2]).
-include("crashdump_viewer.hrl").
-include("observer_defs.hrl").
@@ -34,8 +34,9 @@
%%%-----------------------------------------------------------------
%%% Display the given information as is, no heading
%%% Empty body if no info exists.
-warning(Info) ->
- header(body(warning_body(Info))).
+warning(Info, Colors0) ->
+ Colors = convert(Colors0),
+ header(body(warning_body(Info), Colors)).
warning_body(Info) ->
[warn(Info)].
@@ -43,18 +44,22 @@ warning_body(Info) ->
%%%-----------------------------------------------------------------
%%% Display the given information as is, no heading
%%% Empty body if no info exists.
-plain_page(Info) ->
- header(body(plain_body(Info))).
+plain_page(Info, Colors0) ->
+ Colors = convert(Colors0),
+ header(body(plain_body(Info), Colors)).
plain_body(Info) ->
[pre(href_proc_port(lists:flatten(Info)))].
%%%-----------------------------------------------------------------
%%% Expanded memory
-expandable_term(Heading,Expanded,Tab) ->
- header(Heading,body(expandable_term_body(Heading,Expanded,Tab))).
+expandable_term(Heading,Expanded,Tab, Colors0) ->
+ Colors = convert(Colors0),
+ header(Heading,
+ body(expandable_term_body(Heading,Expanded,Tab,Colors),
+ Colors)).
-expandable_term_body(Heading,[],_Tab) ->
+expandable_term_body(Heading,[],_Tab, _) ->
[case Heading of
"MsgQueue" -> "No messages were found";
"Message Queue" -> "No messages were found";
@@ -65,7 +70,7 @@ expandable_term_body(Heading,[],_Tab) ->
"SaslLog" -> "No log entry was found";
"Persistent Terms" -> "No persistent terms were found"
end];
-expandable_term_body(Heading,Expanded,Tab) ->
+expandable_term_body(Heading,Expanded,Tab, Colors) ->
Attr = "BORDER=0 CELLPADDING=0 CELLSPACING=1 WIDTH=100%",
[case Heading of
"MsgQueue" ->
@@ -74,7 +79,7 @@ expandable_term_body(Heading,Expanded,Tab) ->
[th("WIDTH=70%","Message"),
th("WIDTH=30%","SeqTraceToken")]) |
element(1, lists:mapfoldl(fun(Msg, Even) ->
- {msgq_table(Tab, Msg, Even),
+ {msgq_table(Tab, Msg, Even, Colors),
not Even}
end,
true, Expanded))]);
@@ -84,7 +89,7 @@ expandable_term_body(Heading,Expanded,Tab) ->
[th("WIDTH=10%","Id"),
th("WIDTH=90%","Message")]) |
element(1, lists:mapfoldl(fun(Msg, {Even,N}) ->
- {msgq_table(Tab, Msg, N, Even),
+ {msgq_table(Tab, Msg, N, Even, Colors),
{not Even, N+1}}
end,
{true,1}, Expanded))]);
@@ -94,7 +99,7 @@ expandable_term_body(Heading,Expanded,Tab) ->
[th("WIDTH=20%","Label"),
th("WIDTH=80%","Term")]) |
element(1, lists:mapfoldl(fun(Entry, Even) ->
- {stackdump_table(Tab, Entry, Even),
+ {stackdump_table(Tab, Entry, Even, Colors),
not Even}
end, true, Expanded))]);
"ProcState" ->
@@ -103,7 +108,7 @@ expandable_term_body(Heading,Expanded,Tab) ->
[th("WIDTH=20%","Label"),
th("WIDTH=80%","Information")]) |
element(1, lists:mapfoldl(fun(Entry, Even) ->
- {proc_state(Tab, Entry,Even),
+ {proc_state(Tab, Entry,Even, Colors),
not Even}
end, true, Expanded))]);
"SaslLog" ->
@@ -115,37 +120,37 @@ expandable_term_body(Heading,Expanded,Tab) ->
[th("WIDTH=30%","Key"),
th("WIDTH=70%","Value")]) |
element(1, lists:mapfoldl(fun(Entry, Even) ->
- {dict_table(Tab, Entry,Even),
+ {dict_table(Tab, Entry, Even, Colors),
not Even}
end, true, Expanded))])
end].
-msgq_table(Tab,{Msg0,Token0}, Even) ->
+msgq_table(Tab,{Msg0,Token0}, Even, Colors) ->
Token = case Token0 of
[] -> "";
_ -> io_lib:fwrite("~w",[Token0])
end,
Msg = all_or_expand(Tab,Msg0),
- tr(color(Even),[td(pre(Msg)), td(Token)]).
+ tr(color(Even, Colors),[td(pre(Msg)), td(Token)]).
-msgq_table(Tab,Msg0, Id, Even) ->
+msgq_table(Tab,Msg0, Id, Even, Colors) ->
Msg = all_or_expand(Tab,Msg0),
- tr(color(Even),[td(integer_to_list(Id)), td(pre(Msg))]).
+ tr(color(Even, Colors),[td(integer_to_list(Id)), td(pre(Msg))]).
-stackdump_table(Tab,{Label0,Term0},Even) ->
+stackdump_table(Tab,{Label0,Term0},Even, Colors) ->
Label = io_lib:format("~w",[Label0]),
Term = all_or_expand(Tab,Term0),
- tr(color(Even), [td("VALIGN=center",pre(Label)), td(pre(Term))]).
+ tr(color(Even, Colors), [td("VALIGN=center",pre(Label)), td(pre(Term))]).
-dict_table(Tab,{Key0,Value0}, Even) ->
+dict_table(Tab,{Key0,Value0}, Even, Colors) ->
Key = all_or_expand(Tab,Key0),
Value = all_or_expand(Tab,Value0),
- tr(color(Even), [td("VALIGN=center",pre(Key)), td(pre(Value))]).
+ tr(color(Even, Colors), [td("VALIGN=center",pre(Key)), td(pre(Value))]).
-proc_state(Tab,{Key0,Value0}, Even) ->
+proc_state(Tab,{Key0,Value0}, Even, Colors) ->
Key = lists:flatten(io_lib:format("~ts",[Key0])),
Value = all_or_expand(Tab,Value0),
- tr(color(Even), [td("VALIGN=center",Key), td(pre(Value))]).
+ tr(color(Even, Colors), [td("VALIGN=center",Key), td(pre(Value))]).
all_or_expand(Tab,Term) ->
Preview = io_lib:format("~tP",[Term,8]),
@@ -171,8 +176,8 @@ all_or_expand(Tab,Bin,_PreviewStr,_Expand)
Term = io_lib:format("~tp", [OBSBin]),
href_proc_port(lists:flatten(Term), true).
-color(true) -> io_lib:format("BGCOLOR=\"#~2.16.0B~2.16.0B~2.16.0B\"", tuple_to_list(?BG_EVEN));
-color(false) -> io_lib:format("BGCOLOR=\"#~2.16.0B~2.16.0B~2.16.0B\"", tuple_to_list(?BG_ODD)).
+color(true, #colors{even=Even}) -> "BGCOLOR="++Even;
+color(false,#colors{odd=Odd}) -> "BGCOLOR="++Odd.
%%%-----------------------------------------------------------------
%%% Internal library
@@ -180,10 +185,10 @@ start_html() ->
"<HTML>\n".
stop_html() ->
"</HTML>".
-start_html_body() ->
- "<BODY BGCOLOR=\"#FFFFFF\">\n".
+start_html_body(#colors{even=Even, fg=Fg}) ->
+ "<BODY BGCOLOR=" ++ Even ++ ">\n <FONT COLOR=" ++ Fg ++ ">\n".
stop_html_body() ->
- "</BODY>\n".
+ "</FONT> </BODY>\n".
header(Body) ->
header("","",Body).
@@ -205,8 +210,8 @@ only_html_header(Title,JavaScript) ->
JavaScript,
"</HEAD>\n"].
-body(Text) ->
- [start_html_body(),
+body(Text, Colors) ->
+ [start_html_body(Colors),
Text,
stop_html_body()].
@@ -417,3 +422,8 @@ warn([]) ->
[];
warn(Warning) ->
font("COLOR=\"#FF0000\"",p([Warning,br(),br()])).
+
+convert(#colors{fg={FR,FB,FG}, even={ER,EB,EG}, odd={OR,OG,OB}}) ->
+ #colors{fg = io_lib:format("\"#~2.16.0B~2.16.0B~2.16.0B\"", [FR,FB,FG]),
+ even = io_lib:format("\"#~2.16.0B~2.16.0B~2.16.0B\"", [ER,EB,EG]),
+ odd = io_lib:format("\"#~2.16.0B~2.16.0B~2.16.0B\"", [OR,OG,OB])}.
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index 7c68b0ebb6..7d115306bd 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -28,8 +28,8 @@
interval_dialog/4, start_timer/1, start_timer/2, stop_timer/1, timer_config/1,
display_info/2, display_info/3, fill_info/2, update_info/2, to_str/1,
create_menus/3, create_menu_item/3,
- create_attrs/0,
- set_listctrl_col_size/2,
+ is_darkmode/1, colors/1, create_attrs/1,
+ set_listctrl_col_size/2, mix/3,
create_status_bar/1,
html_window/1, html_window/2,
make_obsbin/2,
@@ -373,26 +373,44 @@ create_menu_item(separator, Menu, Index) ->
wxMenu:insertSeparator(Menu, Index),
Index+1.
-create_attrs() ->
- Font = wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT),
+colors(Window) ->
+ DarkMode = is_darkmode(wxWindow:getBackgroundColour(Window)),
Text = case wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOXTEXT) of
- {255,255,255,_} -> {10,10,10}; %% Is white on Mac for some reason
- Color -> Color
- end,
- #attrs{even = wxListItemAttr:new(Text, ?BG_EVEN, Font),
- odd = wxListItemAttr:new(Text, ?BG_ODD, Font),
- deleted = wxListItemAttr:new(?FG_DELETED, ?BG_DELETED, Font),
- changed_even = wxListItemAttr:new(Text, mix(?BG_CHANGED,?BG_EVEN), Font),
- changed_odd = wxListItemAttr:new(Text, mix(?BG_CHANGED,?BG_ODD), Font),
- new_even = wxListItemAttr:new(Text, mix(?BG_NEW,?BG_EVEN), Font),
- new_odd = wxListItemAttr:new(Text, mix(?BG_NEW, ?BG_ODD), Font),
- searched = wxListItemAttr:new(Text, ?BG_SEARCHED, Font)
- }.
-
-mix(RGB,_) -> RGB.
-
-%% mix({R,G,B},{MR,MG,MB}) ->
-%% {trunc(R*MR/255), trunc(G*MG/255), trunc(B*MB/255)}.
+ {255,255,255,_} when not DarkMode -> {10,10,10}; %% Is white on Mac for some reason
+ Color -> Color
+ end,
+ Even = wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOX),
+ Odd = mix(Even, wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT), 0.8),
+ #colors{fg=rgb(Text), even=rgb(Even), odd=rgb(Odd)}.
+
+create_attrs(Window) ->
+ Font = wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT),
+ #colors{fg=Text, even=Even, odd=Odd} = colors(Window),
+ #attrs{even = wxListItemAttr:new(Text, Even, Font),
+ odd = wxListItemAttr:new(Text, Odd, Font),
+ deleted = wxListItemAttr:new(?FG_DELETED, ?BG_DELETED, Font),
+ changed_even = wxListItemAttr:new(Text, mix(?BG_CHANGED, ?BG_EVEN, 0.9), Font),
+ changed_odd = wxListItemAttr:new(Text, mix(?BG_CHANGED, ?BG_ODD, 0.9), Font),
+ new_even = wxListItemAttr:new(Text, mix(?BG_NEW, ?BG_EVEN, 0.9), Font),
+ new_odd = wxListItemAttr:new(Text, mix(?BG_NEW, ?BG_ODD, 0.9), Font),
+ searched = wxListItemAttr:new(Text, ?BG_SEARCHED, Font)
+ }.
+
+rgb({R,G,B,_}) -> {R,G,B};
+rgb({_,_,_}=RGB) -> RGB.
+
+mix(RGB,{MR,MG,MB,_}, V) ->
+ mix(RGB, {MR,MG,MB}, V);
+mix({R,G,B,_}, RGB, V) ->
+ mix({R,G,B}, RGB, V);
+mix({R,G,B},{MR,MG,MB}, V) when V =< 1.0 ->
+ {min(255, round(R*V+MR*(1.0-V))),
+ min(255, round(G*V+MG*(1.0-V))),
+ min(255, round(B*V+MB*(1.0-V)))}.
+
+
+is_darkmode({R,G,B,_}) ->
+ ((R+G+B) div 3) < 100.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
index 79271addf2..50a6d6a915 100644
--- a/lib/observer/src/observer_perf_wx.erl
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -55,7 +55,7 @@
-define(wxGC, wxGraphicsContext).
--record(paint, {font, small, pen, pen2, pens, dot_pens, usegc = false}).
+-record(paint, {font, small, fg, pen, pen2, pens, dot_pens, usegc = false}).
start_link(Notebook, Parent, Config) ->
wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
@@ -126,7 +126,16 @@ setup_graph_drawing(Panels) ->
SF = wxFont:new(Scale * (DefSize-2), DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
{F, SF}
end,
- BlackPen = wxPen:new({0,0,0}, [{width, Scale}]),
+ BG = wxWindow:getBackgroundColour((hd(Panels))#win.panel),
+ Fg = case observer_lib:is_darkmode(BG) of
+ false -> {0,0,0};
+ true -> wxSystemSettings:getColour(?wxSYS_COLOUR_BTNTEXT)
+ end,
+
+ PenColor = case observer_lib:is_darkmode(BG) of
+ false -> {0,0,0};
+ true -> {0,0,0}
+ end,
Pens = [wxPen:new(Col, [{width, Scale}, {style, ?wxSOLID}])
|| Col <- tuple_to_list(colors())],
DotPens = [wxPen:new(Col, [{width, Scale}, {style, ?wxDOT}])
@@ -134,8 +143,9 @@ setup_graph_drawing(Panels) ->
#paint{usegc = UseGC,
font = Font,
small = SmallFont,
- pen = ?wxGREY_PEN,
- pen2 = BlackPen,
+ fg = Fg, %% Text color
+ pen = wxPen:new(PenColor),
+ pen2 = wxPen:new(PenColor, [{width, Scale}]),
pens = list_to_tuple(Pens),
dot_pens = list_to_tuple(DotPens)
}.
@@ -525,7 +535,7 @@ draw_win(DC, #win{name=Name, no_samples=Samples, geom=#{scale:={WS,HS}},
DrawBs(),
ok;
-draw_win(DC, #win{no_samples=Samples} = Win,Ti, #paint{small=Small}=Paint) ->
+draw_win(DC, #win{no_samples=Samples} = Win,Ti, #paint{fg=Fg, small=Small}=Paint) ->
%% Draw Error Msg
try draw_borders(DC, Ti, Win, Paint) of
{X0,_Y0,DrawBs} ->
@@ -533,7 +543,7 @@ draw_win(DC, #win{no_samples=Samples} = Win,Ti, #paint{small=Small}=Paint) ->
true -> "Waiting for data";
false -> "Information not available"
end,
- setFont(DC, Small, {0,0,0}),
+ setFont(DC, Small, Fg),
{_,WW} = getSize(DC),
drawText(DC, Text, X0 + 100, WW div 2),
DrawBs(),
@@ -628,7 +638,7 @@ spline_tan(Y0, Y1, Y2, Y3) ->
draw_borders(DC, #ti{secs=Secs, fetch=FetchFreq},
#win{name=Type, geom=Geom, info=Info, max={_,_,Unit,_}},
- #paint{pen=Pen, pen2=Pen2, font=Font, small=Small}) ->
+ #paint{pen=Pen, pen2=Pen2, fg=Fg, font=Font, small=Small}) ->
#{p0:={GraphX0, GraphY0}, p1:={GraphX1,GraphY1}, scale:={ScaleW0,_},
txsz:={TW,TH,SpaceW}, txt:={BottomTextY, MaxTextY}, strs:={Str1,Str2,Str3}} = Geom,
@@ -640,7 +650,7 @@ draw_borders(DC, #ti{secs=Secs, fetch=FetchFreq},
GraphY50 = GraphY0 + (GraphY1 - GraphY0) / 2,
GraphY75 = GraphY0 + 3*(GraphY1 - GraphY0) / 4,
- setFont(DC, Small, {0,0,0}),
+ setFont(DC, Small, Fg),
Align = fun(Str, Y) ->
{StrW, _} = getTextExtent(DC, Str),
drawText(DC, Str, GraphX0 - StrW - ?BW, Y)
@@ -670,11 +680,11 @@ draw_borders(DC, #ti{secs=Secs, fetch=FetchFreq},
strokeLine(DC, GraphX0-3, GraphY50, GraphX1, GraphY50),
strokeLine(DC, GraphX0-3, GraphY75, GraphX1, GraphY75),
- setFont(DC, Font, {0,0,0}),
+ setFont(DC, Font, Fg),
Text = fun(X,Y, Str, PenId) ->
if PenId == 0 ->
- setFont(DC, Font, {0,0,0});
+ setFont(DC, Font, Fg);
PenId > 0 ->
Id = 1 + ((PenId-1) rem tuple_size(colors())),
setFont(DC, Font, element(Id, colors()))
diff --git a/lib/observer/src/observer_port_wx.erl b/lib/observer/src/observer_port_wx.erl
index 00cf1b5fba..5cb6d9bc22 100644
--- a/lib/observer/src/observer_port_wx.erl
+++ b/lib/observer/src/observer_port_wx.erl
@@ -61,7 +61,8 @@
inet}).
-record(opt, {sort_key=2,
- sort_incr=true
+ sort_incr=true,
+ odd_bg
}).
-record(state,
@@ -111,7 +112,10 @@ init([Notebook, Parent, Config]) ->
wxListCtrl:connect(Grid, size, [{skip, true}]),
wxWindow:setFocus(Grid),
- {Panel, #state{grid=Grid, parent=Parent, panel=Panel, timer=Config}}.
+ Even = wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOX),
+ Odd = observer_lib:mix(Even, wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT), 0.8),
+ Opt = #opt{odd_bg=Odd},
+ {Panel, #state{grid=Grid, parent=Parent, panel=Panel, timer=Config, opt=Opt}}.
handle_event(#wx{id=?ID_REFRESH},
State = #state{node=Node, grid=Grid, opt=Opt}) ->
@@ -553,7 +557,7 @@ filter_monitor_info() ->
update_grid(Grid, Sel, Opt, Ports) ->
wx:batch(fun() -> update_grid2(Grid, Sel, Opt, Ports) end).
-update_grid2(Grid, Sel, #opt{sort_key=Sort,sort_incr=Dir}, Ports) ->
+update_grid2(Grid, Sel, #opt{sort_key=Sort,sort_incr=Dir, odd_bg=BG}, Ports) ->
wxListCtrl:deleteAllItems(Grid),
Update =
fun(#port{id = Id,
@@ -563,8 +567,8 @@ update_grid2(Grid, Sel, #opt{sort_key=Sort,sort_incr=Dir}, Ports) ->
controls = Ctrl},
Row) ->
_Item = wxListCtrl:insertItem(Grid, Row, ""),
- if (Row rem 2) =:= 0 ->
- wxListCtrl:setItemBackgroundColour(Grid, Row, ?BG_EVEN);
+ if (Row rem 2) =:= 1 ->
+ wxListCtrl:setItemBackgroundColour(Grid, Row, BG);
true -> ignore
end,
diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl
index 4ab4a78462..6b359f3c44 100644
--- a/lib/observer/src/observer_pro_wx.erl
+++ b/lib/observer/src/observer_pro_wx.erl
@@ -94,7 +94,7 @@ start_link(Notebook, Parent, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init([Notebook, Parent, Config]) ->
- Attrs = observer_lib:create_attrs(),
+ Attrs = observer_lib:create_attrs(Notebook),
Self = self(),
Acc = maps:get(acc, Config, false),
Holder = spawn_link(fun() -> init_table_holder(Self, Acc, Attrs) end),
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index bd5fed0951..637a090a15 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -214,12 +214,14 @@ init_process_page(Panel, Pid) ->
init_message_page(Parent, Pid, Table) ->
Win = observer_lib:html_window(Parent),
+ Cs = observer_lib:colors(Parent),
Update = fun() ->
case observer_wx:try_rpc(node(Pid), erlang, process_info,
[Pid, messages])
of
{messages, Messages} ->
- Html = observer_html_lib:expandable_term("Message Queue", Messages, Table),
+ Html = observer_html_lib:expandable_term("Message Queue", Messages,
+ Table, Cs),
wxHtmlWindow:setPage(Win, Html);
_ ->
throw(process_undefined)
@@ -230,11 +232,12 @@ init_message_page(Parent, Pid, Table) ->
init_dict_page(Parent, Pid, Table) ->
Win = observer_lib:html_window(Parent),
+ Cs = observer_lib:colors(Parent),
Update = fun() ->
case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, dictionary])
of
{dictionary,Dict} ->
- Html = observer_html_lib:expandable_term("Dictionary", Dict, Table),
+ Html = observer_html_lib:expandable_term("Dictionary", Dict, Table, Cs),
wxHtmlWindow:setPage(Win, Html);
_ ->
throw(process_undefined)
@@ -254,6 +257,8 @@ init_stack_page(Parent, Pid) ->
wxListCtrl:insertColumn(LCtrl, 1, Li),
wxListCtrl:setColumnWidth(LCtrl, 1, Scale * 300),
wxListItem:destroy(Li),
+ Even = wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOX),
+ Odd = observer_lib:mix(Even, wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT), 0.8),
Update = fun() ->
case observer_wx:try_rpc(node(Pid), erlang, process_info,
[Pid, current_stacktrace])
@@ -262,8 +267,8 @@ init_stack_page(Parent, Pid) ->
wxListCtrl:deleteAllItems(LCtrl),
wx:foldl(fun({M, F, A, Info}, Row) ->
_Item = wxListCtrl:insertItem(LCtrl, Row, ""),
- ?EVEN(Row) andalso
- wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
+ ?EVEN(Row) orelse
+ wxListCtrl:setItemBackgroundColour(LCtrl, Row, Odd),
wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str({M,F,A})),
FileLine = case Info of
[{file,File},{line,Line}] ->
@@ -288,9 +293,10 @@ init_stack_page(Parent, Pid) ->
init_state_page(Parent, Pid, Table) ->
Win = observer_lib:html_window(Parent),
+ Cs = observer_lib:colors(Parent),
Update = fun() ->
StateInfo = fetch_state_info(Pid),
- Html = observer_html_lib:expandable_term("ProcState", StateInfo, Table),
+ Html = observer_html_lib:expandable_term("ProcState", StateInfo, Table, Cs),
wxHtmlWindow:setPage(Win, Html)
end,
Update(),
@@ -341,6 +347,7 @@ fetch_state_info2(Pid, M) ->
init_log_page(Parent, Pid, Table) ->
Win = observer_lib:html_window(Parent),
+ Cs = observer_lib:colors(Parent),
Update = fun() ->
Fd = spawn_link(fun() -> io_server() end),
rpc:call(node(Pid), rb, rescan, [[{start_log, Fd}]]),
@@ -353,7 +360,7 @@ init_log_page(Parent, Pid, Table) ->
NbBlanks = length(Pref) - 1,
Re = "(<" ++ Pref ++ "\.[^>]{1,}>)[ ]{"++ integer_to_list(NbBlanks) ++ "}",
Look = re:replace(ExpPid, Re, "\\1", [global, {return, list}]),
- Html = observer_html_lib:expandable_term("SaslLog", Look, Table),
+ Html = observer_html_lib:expandable_term("SaslLog", Look, Table, Cs),
wxHtmlWindow:setPage(Win, Html)
end,
Update(),
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index 7bd67a0f0b..32d75f77d4 100644
--- a/lib/observer/src/observer_tv_table.erl
+++ b/lib/observer/src/observer_tv_table.erl
@@ -116,8 +116,8 @@ init([Parent, Opts]) ->
TabId = table_id(Table),
ColumnNames = column_names(Node, Source, TabId),
KeyPos = key_pos(Node, Source, TabId),
-
- Attrs = observer_lib:create_attrs(),
+ Panel = wxPanel:new(Frame),
+ Attrs = observer_lib:create_attrs(Panel),
Self = self(),
Holder = spawn_link(fun() ->
@@ -125,7 +125,6 @@ init([Parent, Opts]) ->
length(ColumnNames), Node, Attrs)
end),
- Panel = wxPanel:new(Frame),
Sizer = wxBoxSizer:new(?wxVERTICAL),
Style = ?wxLC_REPORT bor ?wxLC_VIRTUAL bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
Grid = wxListCtrl:new(Panel, [{style, Style},
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index 9743a6ed42..d622b1423b 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -71,7 +71,7 @@ init([Notebook, Parent, Config]) ->
Style = ?wxLC_REPORT bor ?wxLC_VIRTUAL bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
Self = self(),
- Attrs = observer_lib:create_attrs(),
+ Attrs = observer_lib:create_attrs(Panel),
Holder = spawn_link(fun() -> init_table_holder(Self, Attrs) end),
CBs = [{onGetItemText, fun(_, Item,Col) -> get_row(Holder, Item, Col) end},
{onGetItemAttr, fun(_, Item) -> get_attr(Holder, Item) end}],
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index 84ed99afa5..10d88c994a 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -48,7 +48,7 @@ n1_proc(Creator,_N2,Pid2,Port2,_L) ->
Ref = make_ref(),
Pid = self(),
Bin = list_to_binary(lists:seq(1, 255)),
- <<_:2,SubBin:17/binary,_/bits>> = Bin,
+ <<_:2,SubBin:65/binary,_/bits>> = Bin,
register(named_port,Port),
@@ -102,7 +102,7 @@ remote_proc(P1,Creator) ->
end).
create_binaries() ->
- Sizes = lists:seq(60, 70) ++ lists:seq(120, 140),
+ Sizes = lists:seq(100, 120) ++ lists:seq(200, 240),
[begin
<<H:16/unit:8>> = erlang:md5(<<Size:32>>),
Data = ((H bsl (8*150)) div (H+7919)),
@@ -113,7 +113,7 @@ create_sub_binaries(Bins) ->
[create_sub_binary(Bin, Start, LenSub) ||
Bin <- Bins,
Start <- [0,1,2,3,4,5,10,22],
- LenSub <- [0,1,2,3,4,6,9]].
+ LenSub <- [0,1,2,3,4,6,9,65]].
create_sub_binary(Bin, Start, LenSub) ->
Len = byte_size(Bin) - LenSub - Start,
diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
index c96a5c9f7c..98a2526aab 100644
--- a/lib/os_mon/c_src/cpu_sup.c
+++ b/lib/os_mon/c_src/cpu_sup.c
@@ -359,7 +359,7 @@ static cpu_t *read_procstat(FILE *fp, cpu_t *cpu) {
memset(cpu, 0, sizeof(cpu_t));
return cpu;
}
- sscanf(buffer, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
+ sscanf(buffer, "cpu%u %llu %llu %llu %llu %llu %llu %llu %llu",
&(cpu->id),
&(cpu->user),
&(cpu->nice_user),
diff --git a/lib/snmp/src/agent/snmpa_supervisor.erl b/lib/snmp/src/agent/snmpa_supervisor.erl
index 2cb0556001..7d5c6da2c8 100644
--- a/lib/snmp/src/agent/snmpa_supervisor.erl
+++ b/lib/snmp/src/agent/snmpa_supervisor.erl
@@ -22,7 +22,7 @@
-behaviour(supervisor).
%% External exports
--export([start_link/2]).
+-export([start_link/2, stop/0, stop/1]).
-export([start_sub_sup/1, start_master_sup/1]).
-export([start_sub_agent/3, stop_sub_agent/1]).
@@ -91,6 +91,39 @@ start_link(master, Opts, {takeover, Node}) ->
Else
end.
+
+stop() ->
+ stop(0).
+
+stop(Timeout) ->
+ case whereis(?SERVER) of
+ Pid when is_pid(Pid) ->
+ stop(Pid, Timeout);
+ _ ->
+ not_running
+ end.
+
+%% For some unfathomable reason there is no "nice" way to stop
+%% a supervisor. The "normal" way to do it is:
+%% 1) exit(Pid, kill) (kaboom)
+%% 2) If the caller is the *parent*: exit(Pid, shutdown)
+%% So, here we do it the really ugly way...but since this function is
+%% intended for testing (mostly)...
+stop(Pid, Timeout) when (Timeout =:= 0) ->
+ sys:terminate(Pid, shutdown),
+ ok;
+stop(Pid, Timeout) ->
+ MRef = erlang:monitor(process, Pid),
+ sys:terminate(Pid, shutdown),
+ receive
+ {'DOWN', MRef, process, Pid, _} ->
+ ok
+ after Timeout ->
+ erlang:demonitor(MRef, [flush]),
+ {error, timeout}
+ end.
+
+
get_own_loaded_mibs() ->
AgentInfo = snmpa:info(snmp_master_agent),
[ Name || {Name, _, _} <- loaded_mibs(AgentInfo) ].
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index cf8c95d69f..8e60cecaf9 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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,7 +32,7 @@
%% Management API
start/0, start/1,
start_link/0, start_link/1,
- stop/0,
+ stop/0, stop/1,
monitor/0, demonitor/1,
notify_started/1, cancel_notify_started/1,
@@ -196,7 +196,12 @@ start(Opts) ->
ok.
stop() ->
- snmpm_supervisor:stop().
+ stop(0).
+
+stop(Timeout) when (Timeout =:= infinity) orelse
+ (is_integer(Timeout) andalso (Timeout >= 0)) ->
+ snmpm_supervisor:stop(Timeout).
+
monitor() ->
diff --git a/lib/snmp/src/manager/snmpm_supervisor.erl b/lib/snmp/src/manager/snmpm_supervisor.erl
index c36bbe1bdd..bc66025c6f 100644
--- a/lib/snmp/src/manager/snmpm_supervisor.erl
+++ b/lib/snmp/src/manager/snmpm_supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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,7 +24,7 @@
%% External exports
--export([start_link/2, stop/0]).
+-export([start_link/2, stop/0, stop/1]).
%% supervisor callbacks
-export([init/1]).
@@ -38,26 +38,54 @@
%%%-------------------------------------------------------------------
%%% API
%%%-------------------------------------------------------------------
+
start_link(Type, Opts) ->
?d("start_link -> entry with"
"~n Opts: ~p", [Opts]),
SupName = {local, ?MODULE},
supervisor:start_link(SupName, ?MODULE, [Type, Opts]).
+
stop() ->
+ stop(0).
+
+stop(Timeout) ->
?d("stop -> entry", []),
case whereis(?SERVER) of
Pid when is_pid(Pid) ->
- ?d("stop -> Pid: ~p", [Pid]),
- exit(Pid, shutdown),
- ?d("stop -> stopped", []),
- ok;
+ stop(Pid, Timeout);
_ ->
?d("stop -> not running", []),
not_running
end.
+%% For some unfathomable reason there is no "nice" way to stop
+%% a supervisor. The "normal" way to do it is:
+%% 1) exit(Pid, kill) (kaboom)
+%% 2) If the caller is the *parent*: exit(Pid, shutdown)
+%% So, here we do it the really ugly way...but since this function is
+%% intended for testing (mostly)...
+stop(Pid, Timeout) when (Timeout =:= 0) ->
+ ?d("stop -> Pid: ~p", [Pid]),
+ sys:terminate(Pid, shutdown),
+ ?d("stop -> stopped", []),
+ ok;
+stop(Pid, Timeout) ->
+ ?d("stop -> Pid: ~p", [Pid]),
+ MRef = erlang:monitor(process, Pid),
+ sys:terminate(Pid, shutdown),
+ receive
+ {'DOWN', MRef, process, Pid, _} ->
+ ?d("stop -> stopped", []),
+ ok
+ after Timeout ->
+ ?d("stop -> timeout", []),
+ erlang:demonitor(MRef, [flush]),
+ {error, timeout}
+ end.
+
+
%%%-------------------------------------------------------------------
%%% Callback functions from supervisor
%%%-------------------------------------------------------------------
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 615d6774b9..c0da47dc4c 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -423,7 +423,18 @@ tc_wait(From, Env, M, F, A) ->
"~n ~p"
"~n", [Res]),
From ! {tc_runner_done, self(), Res, get(test_server_loc)},
- exit(Res).
+ %% The point of this is that in some cases we have seen that the
+ %% exit signal having been "passed on" to the CT, which consider any
+ %% exit a fail (even if its {'EXIT', ok}).
+ %% So, just to be on the safe side, convert an 'ok' to a 'normal'.
+ case Res of
+ ok ->
+ exit(normal);
+ {ok, _} ->
+ exit(normal);
+ _ ->
+ exit(Res)
+ end.
tc_run(Mod, Func, Args, Opts) ->
?PRINT2("tc_run -> entry with"
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index 7cd3eae0c7..c31bb92e1f 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -62,7 +62,7 @@
register_user1/1,
- register_agent1/1,
+ register_agent_old/1,
register_agent2/1,
register_agent3/1,
@@ -185,7 +185,6 @@ end_per_suite(Config) when is_list(Config) ->
init_per_testcase(Case, Config) when is_list(Config) ->
- io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
p(Case, "init_per_testcase begin when"
"~n Nodes: ~p~n~n", [erlang:nodes()]),
%% This version of the API, based on Addr and Port, has been deprecated
@@ -204,13 +203,15 @@ init_per_testcase(Case, Config) when is_list(Config) ->
Result =
case lists:member(Case, DeprecatedApiCases) of
true ->
- {skip, api_no_longer_supported};
+ {skip, "API no longer supported"};
false ->
try init_per_testcase2(Case, Config)
catch
- C:{skip, _} = E:_ when ((C =:= throw) orelse (C =:= exit)) ->
+ C:{skip, _} = E:_ when ((C =:= throw) orelse
+ (C =:= exit)) ->
E;
- C:E:_ when ((C =:= throw) orelse (C =:= exit)) ->
+ C:E:_ when ((C =:= throw) orelse
+ (C =:= exit)) ->
{skip, {catched, C, E}}
end
end,
@@ -479,7 +480,7 @@ groups() ->
},
{agent_tests, [],
[
- register_agent1,
+ register_agent_old,
register_agent2,
register_agent3
]
@@ -595,7 +596,7 @@ groups() ->
ipv6_tests() ->
[
- register_agent1,
+ register_agent_old,
simple_sync_get_next3,
simple_async_get2,
simple_sync_get3,
@@ -671,11 +672,11 @@ end_per_group(_GroupName, Config) ->
simple_start_and_stop1(suite) -> [];
simple_start_and_stop1(Config) when is_list(Config) ->
- %% ?SKIP(not_yet_implemented),
- process_flag(trap_exit, true),
- put(tname,ssas1),
- p("starting with Config: ~n~p", [Config]),
+ ?TC_TRY(simple_start_and_stop1,
+ fun() -> do_simple_start_and_stop1(Config) end).
+do_simple_start_and_stop1(Config) ->
+ p("starting with Config: ~n~p", [Config]),
ConfDir = ?config(manager_conf_dir, Config),
DbDir = ?config(manager_db_dir, Config),
@@ -696,7 +697,6 @@ simple_start_and_stop1(Config) when is_list(Config) ->
?SLEEP(1000),
- p("end"),
ok.
@@ -704,9 +704,10 @@ simple_start_and_stop1(Config) when is_list(Config) ->
simple_start_and_stop2(suite) -> [];
simple_start_and_stop2(Config) when is_list(Config) ->
- %% ?SKIP(not_yet_implemented),
- process_flag(trap_exit, true),
- put(tname,ssas2),
+ ?TC_TRY(simple_start_and_stop2,
+ fun() -> do_simple_start_and_stop2(Config) end).
+
+do_simple_start_and_stop2(Config) ->
p("starting with Config: ~p~n", [Config]),
ManagerNode = start_manager_node(),
@@ -744,7 +745,6 @@ simple_start_and_stop2(Config) when is_list(Config) ->
?SLEEP(1000),
- p("end"),
ok.
@@ -752,8 +752,10 @@ simple_start_and_stop2(Config) when is_list(Config) ->
simple_start_and_monitor_crash1(suite) -> [];
simple_start_and_monitor_crash1(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,ssamc1),
+ ?TC_TRY(simple_start_and_monitor_crash1,
+ fun() -> do_simple_start_and_monitor_crash1(Config) end).
+
+do_simple_start_and_monitor_crash1(Config) ->
p("starting with Config: ~n~p", [Config]),
ConfDir = ?config(manager_conf_dir, Config),
@@ -797,7 +799,6 @@ simple_start_and_monitor_crash1(Config) when is_list(Config) ->
?FAIL(timeout)
end,
- p("end"),
ok.
@@ -805,8 +806,10 @@ simple_start_and_monitor_crash1(Config) when is_list(Config) ->
simple_start_and_monitor_crash2(suite) -> [];
simple_start_and_monitor_crash2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,ssamc2),
+ ?TC_TRY(simple_start_and_monitor_crash2,
+ fun() -> do_simple_start_and_monitor_crash2(Config) end).
+
+do_simple_start_and_monitor_crash2(Config) ->
p("starting with Config: ~n~p", [Config]),
ConfDir = ?config(manager_conf_dir, Config),
@@ -851,7 +854,6 @@ simple_start_and_monitor_crash2(Config) when is_list(Config) ->
?FAIL(timeout)
end,
- p("end"),
ok.
@@ -897,8 +899,10 @@ simulate_crash(NumKills, _) ->
notify_started01(suite) -> [];
notify_started01(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,ns01),
+ ?TC_TRY(notify_started01,
+ fun() -> do_notify_started01(Config) end).
+
+do_notify_started01(Config) ->
p("starting with Config: ~n~p", [Config]),
ConfDir = ?config(manager_conf_dir, Config),
@@ -985,37 +989,34 @@ snmpm_starter(Opts, To) ->
notify_started02(suite) -> [];
notify_started02(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,ns02),
+ ?TC_TRY(notify_started02,
+ fun() -> notify_started02_cond(Config) end,
+ fun() -> do_notify_started02(Config) end).
- %% <CONDITIONAL-SKIP>
- %% The point of this is to catch machines running
- %% SLES9 (2.6.5)
+notify_started02_cond(Config) ->
LinuxVersionVerify =
fun() ->
case os:cmd("uname -m") of
"i686" ++ _ ->
-%% io:format("found an i686 machine, "
-%% "now check version~n", []),
case os:version() of
{2, 6, Rev} when Rev >= 16 ->
- true;
+ false;
{2, Min, _} when Min > 6 ->
- true;
+ false;
{Maj, _, _} when Maj > 2 ->
- true;
+ false;
_ ->
- false
+ true
end;
_ ->
- true
+ false
end
end,
Skippable = [{unix, [{linux, LinuxVersionVerify}]}],
Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition).
+
+do_notify_started02(Config) ->
p("starting with Config: ~n~p", [Config]),
ConfDir = ?config(manager_conf_dir, Config),
@@ -1023,10 +1024,10 @@ notify_started02(Config) when is_list(Config) ->
write_manager_conf(ConfDir),
- Opts = [{server, [{verbosity, log}]},
- {net_if, [{verbosity, silence}]},
+ Opts = [{server, [{verbosity, log}]},
+ {net_if, [{verbosity, silence}]},
{note_store, [{verbosity, silence}]},
- {config, [{verbosity, log}, {dir, ConfDir}, {db_dir, DbDir}]}],
+ {config, [{verbosity, debug}, {dir, ConfDir}, {db_dir, DbDir}]}],
p("start snmpm client process"),
NumIterations = 5,
@@ -1056,8 +1057,14 @@ notify_started02(Config) when is_list(Config) ->
p("await snmpm client process exit (max ~p+10000 msec)", [ApproxStartTime]),
receive
+ %% We take this opportunity to check if we got a skip from
+ %% the ctrl process.
+ {'EXIT', Pid2, {skip, SkipReason1}} ->
+ ?SKIP(SkipReason1);
{'EXIT', Pid1, normal} ->
ok;
+ {'EXIT', Pid1, {suite_failed, Reason1}} ->
+ ?FAIL({client, Reason1});
{'EXIT', Pid1, Reason1} ->
?FAIL({client, Reason1})
after ApproxStartTime + 10000 ->
@@ -1070,6 +1077,9 @@ notify_started02(Config) when is_list(Config) ->
receive
{'EXIT', Pid2, normal} ->
ok;
+ {'EXIT', Pid2, {skip, SkipReason2}} ->
+ %% In case of a race
+ ?SKIP(SkipReason2);
{'EXIT', Pid2, Reason2} ->
?FAIL({ctrl, Reason2})
after 5000 ->
@@ -1094,7 +1104,7 @@ ns02_client_await_approx_runtime(Pid) ->
"~n ~p", [Pid, Reason]),
{error, Reason}
- after 15000 ->
+ after 30000 ->
%% Either something is *really* wrong or this machine
%% is dog slow. Either way, this is a skip-reason...
{skip, approx_runtime_timeout}
@@ -1159,6 +1169,12 @@ ns02_ctrl(Opts, N) ->
p("starting"),
ns02_ctrl_loop(Opts, N).
+
+%% We have seen that some times it takes unreasonably long time to
+%% start the manager (it got "stuck" in snmpm_config). But since
+%% we did not have enough verbosity, we do not know how far it got.
+%% So, we try to monitor each start attempt. We allow 5 sec (just
+%% to give slow boxes a chance).
ns02_ctrl_loop(_Opts, 0) ->
p("done"),
exit(normal);
@@ -1166,19 +1182,45 @@ ns02_ctrl_loop(Opts, N) ->
p("entry when N: ~p", [N]),
?SLEEP(2000),
p("start manager"),
- snmpm:start(Opts),
+ TS1 = erlang:system_time(millisecond),
+ {StarterPid, StarterMRef} =
+ erlang:spawn_monitor(fun() -> exit(snmpm:start(Opts)) end),
+ receive
+ {'DOWN', StarterMRef, process, StarterPid, ok} ->
+ TS2 = erlang:system_time(millisecond),
+ p("manager started: ~w ms", [TS2-TS1]),
+ ok
+ after 5000 ->
+ p("manager (~p) start timeout - kill", [StarterPid]),
+ exit(StarterPid, kill),
+ exit({skip, start_timeout})
+ end,
?SLEEP(2000),
p("stop manager"),
- snmpm:stop(),
+ ?SLEEP(100), % Give the verbosity to take effect...
+ TS3 = erlang:system_time(millisecond),
+ case snmpm:stop(5000) of
+ ok ->
+ TS4 = erlang:system_time(millisecond),
+ p("manager stopped: ~p ms", [TS4-TS3]),
+ ok;
+ {error, timeout} ->
+ p("manager stop timeout - kill (cleanup) and skip"),
+ exit(whereis(snmpm_supervisor), kill),
+ exit({skip, stop_timeout})
+ end,
ns02_ctrl_loop(Opts, N-1).
+
%%======================================================================
info(suite) -> [];
info(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,info),
+ ?TC_TRY(info,
+ fun() -> do_info(Config) end).
+
+do_info(Config) ->
p("starting with Config: ~n~p", [Config]),
ConfDir = ?config(manager_conf_dir, Config),
@@ -1206,7 +1248,6 @@ info(Config) when is_list(Config) ->
?SLEEP(1000),
- p("end"),
ok.
verify_info(Info) when is_list(Info) ->
@@ -1246,9 +1287,10 @@ verify_info([{Key, SubKeys}|Keys], Info) ->
register_user1(suite) -> [];
register_user1(Config) when is_list(Config) ->
- %% ?SKIP(not_yet_implemented).
- process_flag(trap_exit, true),
- put(tname,ru1),
+ ?TC_TRY(register_user1,
+ fun() -> do_register_user1(Config) end).
+
+do_register_user1(Config) ->
p("starting with Config: ~p~n", [Config]),
ManagerNode = start_manager_node(),
@@ -1322,7 +1364,6 @@ register_user1(Config) when is_list(Config) ->
?SLEEP(1000),
- p("end"),
ok.
verify_users([], []) ->
@@ -1340,14 +1381,15 @@ verify_users(ActualUsers0, [User|RegUsers]) ->
%%======================================================================
-register_agent1(doc) ->
+register_agent_old(doc) ->
["Test registration of agents with the OLD interface functions"];
-register_agent1(suite) ->
+register_agent_old(suite) ->
[];
-register_agent1(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,ra1),
-
+register_agent_old(Config) when is_list(Config) ->
+ ?TC_TRY(register_agent_old,
+ fun() -> do_register_agent_old(Config) end).
+
+do_register_agent_old(Config) ->
p("starting with Config: ~p~n", [Config]),
ManagerNode = start_manager_node(),
@@ -1462,7 +1504,6 @@ register_agent1(Config) when is_list(Config) ->
?SLEEP(1000),
- p("end"),
ok.
@@ -1473,8 +1514,10 @@ register_agent2(doc) ->
register_agent2(suite) ->
[];
register_agent2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ra2),
+ ?TC_TRY(register_agent2,
+ fun() -> do_register_agent2(Config) end).
+
+do_register_agent2(Config) ->
p("starting with Config: ~p~n", [Config]),
ManagerNode = start_manager_node(),
@@ -1607,7 +1650,6 @@ register_agent2(Config) when is_list(Config) ->
?SLEEP(1000),
- p("end"),
ok.
@@ -1619,8 +1661,10 @@ register_agent3(doc) ->
register_agent3(suite) ->
[];
register_agent3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ra3),
+ ?TC_TRY(register_agent3,
+ fun() -> do_register_agent3(Config) end).
+
+do_register_agent3(Config) ->
p("starting with Config: ~p~n", [Config]),
ManagerNode = start_manager_node(),
@@ -1757,7 +1801,6 @@ register_agent3(Config) when is_list(Config) ->
?SLEEP(1000),
- p("end"),
ok.
@@ -1766,10 +1809,11 @@ register_agent3(Config) when is_list(Config) ->
simple_sync_get1(doc) -> ["Simple sync get-request - Old style (Addr & Port)"];
simple_sync_get1(suite) -> [];
simple_sync_get1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_sync_get1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_sync_get1(Config) end).
- process_flag(trap_exit, true),
- put(tname, ssg1),
+do_simple_sync_get1(Config) ->
p("starting with Config: ~p~n", [Config]),
Node = ?config(manager_node, Config),
@@ -1828,18 +1872,18 @@ simple_sync_get2(doc) ->
["Simple sync get-request - Version 2 API (TargetName)"];
simple_sync_get2(suite) -> [];
simple_sync_get2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ssg2),
- do_simple_sync_get2(Config),
- display_log(Config),
- ok.
+ ?TC_TRY(simple_sync_get2,
+ fun() -> do_simple_sync_get2(Config) end).
do_simple_sync_get2(Config) ->
+ p("starting with Config: ~n~p", [Config]),
Get = fun(Node, TargetName, Oids) ->
mgr_user_sync_get(Node, TargetName, Oids)
end,
PostVerify = fun() -> ok end,
- do_simple_sync_get2(Config, Get, PostVerify).
+ do_simple_sync_get2(Config, Get, PostVerify),
+ display_log(Config),
+ ok.
do_simple_sync_get2(Config, Get, PostVerify) ->
p("starting with Config: ~p~n", [Config]),
@@ -1895,13 +1939,11 @@ simple_sync_get3(doc) ->
["Simple sync get-request - Version 3 API (TargetName and send-opts)"];
simple_sync_get3(suite) -> [];
simple_sync_get3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ssg3),
- do_simple_sync_get3(Config),
- display_log(Config),
- ok.
+ ?TC_TRY(simple_sync_get3,
+ fun() -> do_simple_sync_get3(Config) end).
do_simple_sync_get3(Config) ->
+ p("starting with Config: ~n~p", [Config]),
Self = self(),
Msg = simple_sync_get3,
Fun = fun() -> Self ! Msg end,
@@ -1920,7 +1962,9 @@ do_simple_sync_get3(Config) ->
ok
end
end,
- do_simple_sync_get2(Config, Get, PostVerify).
+ do_simple_sync_get2(Config, Get, PostVerify),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -1929,10 +1973,11 @@ simple_async_get1(doc) ->
["Simple (async) get-request - Old style (Addr & Port)"];
simple_async_get1(suite) -> [];
simple_async_get1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_async_get1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_async_get1(Config) end).
- process_flag(trap_exit, true),
- put(tname, sag1),
+do_simple_async_get1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -2033,8 +2078,10 @@ simple_async_get2(doc) ->
["Simple (async) get-request - Version 2 API (TargetName)"];
simple_async_get2(suite) -> [];
simple_async_get2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sag2),
+ ?TC_TRY(simple_async_get2,
+ fun() -> do_simple_async_get2(Config) end).
+
+do_simple_async_get2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
@@ -2114,8 +2161,10 @@ simple_async_get3(doc) ->
["Simple (async) get-request - Version 3 API (TargetName and send-opts)"];
simple_async_get3(suite) -> [];
simple_async_get3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sag3),
+ ?TC_TRY(simple_async_get3,
+ fun() -> do_simple_async_get3(Config) end).
+
+do_simple_async_get3(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
@@ -2146,10 +2195,11 @@ simple_sync_get_next1(doc) -> ["Simple (sync) get_next-request - "
"Old style (Addr & Port)"];
simple_sync_get_next1(suite) -> [];
simple_sync_get_next1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_sync_get_next1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_sync_get_next1(Config) end).
- process_flag(trap_exit, true),
- put(tname, ssgn1),
+do_simple_sync_get_next1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -2287,8 +2337,10 @@ simple_sync_get_next2(doc) ->
["Simple (sync) get_next-request - Version 2 API (TargetName)"];
simple_sync_get_next2(suite) -> [];
simple_sync_get_next2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ssgn2),
+ ?TC_TRY(simple_sync_get_next2,
+ fun() -> do_simple_sync_get_next2(Config) end).
+
+do_simple_sync_get_next2(Config) ->
p("starting with Config: ~p~n", [Config]),
GetNext = fun(Node, TargetName, Oids) ->
@@ -2440,10 +2492,11 @@ simple_async_get_next1(doc) -> ["Simple (async) get_next-request - "
"Old style (Addr & Port)"];
simple_async_get_next1(suite) -> [];
simple_async_get_next1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_async_get_next1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_async_get_next1(Config) end).
- process_flag(trap_exit, true),
- put(tname, ssgn1),
+do_simple_async_get_next1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -2540,8 +2593,10 @@ simple_async_get_next2(doc) ->
["Simple (async) get_next-request - Version 2 API (TargetName)"];
simple_async_get_next2(suite) -> [];
simple_async_get_next2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ssgn2),
+ ?TC_TRY(simple_async_get_next2,
+ fun() -> do_simple_async_get_next2(Config) end).
+
+do_simple_async_get_next2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -2651,8 +2706,10 @@ simple_async_get_next3(doc) ->
"Version 3 API (TargetName with send-opts)"];
simple_async_get_next3(suite) -> [];
simple_async_get_next3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ssgn2),
+ ?TC_TRY(simple_async_get_next3,
+ fun() -> do_simple_async_get_next3(Config) end).
+
+do_simple_async_get_next3(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -2694,10 +2751,11 @@ simple_sync_set1(doc) -> ["Simple (sync) set-request - "
"Old style (Addr & Port)"];
simple_sync_set1(suite) -> [];
simple_sync_set1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_sync_set1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_sync_set1(Config) end).
- process_flag(trap_exit, true),
- put(tname, sss1),
+do_simple_sync_set1(Config) ->
p("starting with Config: ~p~n", [Config]),
Node = ?config(manager_node, Config),
@@ -2767,8 +2825,10 @@ simple_sync_set2(doc) ->
["Simple (sync) set-request - Version 2 API (TargetName)"];
simple_sync_set2(suite) -> [];
simple_sync_set2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sss2),
+ ?TC_TRY(simple_sync_set2,
+ fun() -> do_simple_sync_set2(Config) end).
+
+do_simple_sync_set2(Config) ->
p("starting with Config: ~p~n", [Config]),
Set = fun(Node, TargetName, VAVs) ->
@@ -2837,8 +2897,10 @@ simple_sync_set3(doc) ->
["Simple (sync) set-request - Version 3 API (TargetName with send-opts)"];
simple_sync_set3(suite) -> [];
simple_sync_set3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sss3),
+ ?TC_TRY(simple_sync_set3,
+ fun() -> do_simple_sync_set3(Config) end).
+
+do_simple_sync_set3(Config) ->
p("starting with Config: ~p~n", [Config]),
Self = self(),
@@ -2866,10 +2928,11 @@ simple_async_set1(doc) -> ["Simple (async) set-request - "
"Old style (Addr & Port)"];
simple_async_set1(suite) -> [];
simple_async_set1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_async_set1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_async_set1(Config) end).
- process_flag(trap_exit, true),
- put(tname, sas1),
+do_simple_async_set1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -2961,8 +3024,10 @@ simple_async_set2(doc) ->
["Simple (async) set-request - Version 2 API (TargetName)"];
simple_async_set2(suite) -> [];
simple_async_set2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sas2),
+ ?TC_TRY(simple_async_set2,
+ fun() -> do_simple_async_set2(Config) end).
+
+do_simple_async_set2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3034,8 +3099,10 @@ simple_async_set3(doc) ->
["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
simple_async_set3(suite) -> [];
simple_async_set3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sas3),
+ ?TC_TRY(simple_async_set3,
+ fun() -> do_simple_async_set3(Config) end).
+
+do_simple_async_set3(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3078,10 +3145,11 @@ simple_sync_get_bulk1(doc) -> ["Simple (sync) get_bulk-request - "
"Old style (Addr & Port)"];
simple_sync_get_bulk1(suite) -> [];
simple_sync_get_bulk1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_sync_get_bulk1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_sync_get_bulk1(Config) end).
- process_flag(trap_exit, true),
- put(tname, ssgb1),
+do_simple_sync_get_bulk1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3252,8 +3320,10 @@ simple_sync_get_bulk2(doc) ->
["Simple (sync) get_bulk-request - Version 2 API (TargetName)"];
simple_sync_get_bulk2(suite) -> [];
simple_sync_get_bulk2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ssgb2),
+ ?TC_TRY(simple_sync_get_bulk2,
+ fun() -> do_simple_sync_get_bulk2(Config) end).
+
+do_simple_sync_get_bulk2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3408,8 +3478,10 @@ simple_sync_get_bulk3(doc) ->
"Version 3 API (TargetName with send-opts)"];
simple_sync_get_bulk3(suite) -> [];
simple_sync_get_bulk3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ssgb3),
+ ?TC_TRY(simple_sync_get_bulk3,
+ fun() -> do_simple_sync_get_bulk3(Config) end).
+
+do_simple_sync_get_bulk3(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3445,10 +3517,11 @@ simple_async_get_bulk1(doc) -> ["Simple (async) get_bulk-request - "
"Old style (Addr & Port)"];
simple_async_get_bulk1(suite) -> [];
simple_async_get_bulk1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(simple_async_get_bulk1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_simple_async_get_bulk1(Config) end).
- process_flag(trap_exit, true),
- put(tname, sagb1),
+do_simple_async_get_bulk1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3591,8 +3664,10 @@ simple_async_get_bulk2(doc) ->
["Simple (async) get_bulk-request - Version 2 API (TargetName)"];
simple_async_get_bulk2(suite) -> [];
simple_async_get_bulk2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sagb2),
+ ?TC_TRY(simple_async_get_bulk2,
+ fun() -> do_simple_async_get_bulk2(Config) end).
+
+do_simple_async_get_bulk2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3747,8 +3822,10 @@ simple_async_get_bulk3(doc) ->
"Version 3 API (TargetName with send-opts)"];
simple_async_get_bulk3(suite) -> [];
simple_async_get_bulk3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, sagb3),
+ ?TC_TRY(simple_async_get_bulk3,
+ fun() -> do_simple_async_get_bulk3(Config) end).
+
+do_simple_async_get_bulk3(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3791,10 +3868,11 @@ misc_async1(doc) -> ["Misc (async) request(s) - "
"Old style (Addr & Port)"];
misc_async1(suite) -> [];
misc_async1(Config) when is_list(Config) ->
- ?SKIP(api_no_longer_supported),
+ ?TC_TRY(misc_async1,
+ fun() -> {skip, "API no longer supported"} end,
+ fun() -> do_misc_async1(Config) end).
- process_flag(trap_exit, true),
- put(tname, ms1),
+do_misc_async1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -3983,8 +4061,10 @@ misc_async2(doc) ->
["Misc (async) request(s) - Version 2 API (TargetName)"];
misc_async2(suite) -> [];
misc_async2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, ms2),
+ ?TC_TRY(misc_async2,
+ fun() -> do_misc_async2(Config) end).
+
+do_misc_async2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -4233,8 +4313,10 @@ verify_trap(Trap, [{Id, Verifier}|Verifiers]) ->
trap1(suite) -> [];
trap1(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,t1),
+ ?TC_TRY(trap1,
+ fun() -> do_trap1(Config) end).
+
+do_trap1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -4386,8 +4468,10 @@ trap1(Config) when is_list(Config) ->
trap2(suite) -> [];
trap2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,t2),
+ ?TC_TRY(trap2,
+ fun() -> do_trap2(Config) end).
+
+do_trap2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -4579,8 +4663,10 @@ trap2(Config) when is_list(Config) ->
inform1(suite) -> [];
inform1(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,i1),
+ ?TC_TRY(inform1,
+ fun() -> do_inform1(Config) end).
+
+do_inform1(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -4706,8 +4792,10 @@ inform1(Config) when is_list(Config) ->
inform2(suite) -> [];
inform2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, i2),
+ ?TC_TRY(inform2,
+ fun() -> do_inform2(Config) end).
+
+do_inform2(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -4878,8 +4966,10 @@ inform2(Config) when is_list(Config) ->
inform3(suite) -> [];
inform3(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,i3),
+ ?TC_TRY(inform3,
+ fun() -> do_inform3(Config) end).
+
+do_inform3(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -5014,8 +5104,10 @@ inform3(Config) when is_list(Config) ->
inform4(suite) -> [];
inform4(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname,i4),
+ ?TC_TRY(inform4,
+ fun() -> do_inform4(Config) end).
+
+do_inform4(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -5134,8 +5226,10 @@ inform4(Config) when is_list(Config) ->
inform_swarm(suite) -> [];
inform_swarm(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, is),
+ ?TC_TRY(inform_swarm,
+ fun() -> do_inform_swarm(Config) end).
+
+do_inform_swarm(Config) ->
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -5306,8 +5400,10 @@ report(Config) when is_list(Config) ->
otp8015_1(doc) -> ["OTP-8015:1 - testing the new api-function."];
otp8015_1(suite) -> [];
otp8015_1(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, otp8015_1),
+ ?TC_TRY(otp8015_1,
+ fun() -> do_otp8015_1(Config) end).
+
+do_otp8015_1(Config) ->
p("starting with Config: ~p~n", [Config]),
ConfDir = ?config(manager_conf_dir, Config),
@@ -5354,8 +5450,10 @@ otp8015_1(Config) when is_list(Config) ->
otp8395_1(doc) -> ["OTP-8395:1 - simple get with ATL sequence numbering."];
otp8395_1(suite) -> [];
otp8395_1(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- put(tname, otp8395_1),
+ ?TC_TRY(otp8395_1,
+ fun() -> do_otp8395_1(Config) end).
+
+do_otp8395_1(Config) ->
do_simple_sync_get2(Config).
diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index 35bc535a80..26b68501e2 100644
--- a/lib/snmp/test/snmp_test_lib.erl
+++ b/lib/snmp/test/snmp_test_lib.erl
@@ -23,6 +23,7 @@
-include_lib("kernel/include/file.hrl").
+-export([tc_try/2, tc_try/3]).
-export([hostname/0, hostname/1, localhost/0, localhost/1, os_type/0, sz/1,
display_suite_info/1]).
-export([non_pc_tc_maybe_skip/4, os_based_skip/1,
@@ -43,10 +44,107 @@
-export([watchdog/3, watchdog_start/1, watchdog_start/2, watchdog_stop/1]).
-export([del_dir/1]).
-export([cover/1]).
--export([p/2, print1/2, print2/2, print/5, formated_timestamp/0]).
+-export([f/2, p/2, print1/2, print2/2, print/5, formated_timestamp/0]).
%% ----------------------------------------------------------------------
+%% Run test-case
+%%
+
+%% *** tc_try/2,3 ***
+%% Case: Basically the test case name
+%% TCCondFun: A fun that is evaluated before the actual test case
+%% The point of this is that it can performs checks to
+%% see if we shall run the test case at all.
+%% For instance, the test case may only work in specific
+%% conditions.
+%% FCFun: The test case fun
+tc_try(Case, TCFun) ->
+ tc_try(Case, fun() -> ok end, TCFun).
+
+tc_try(Case, TCCondFun, TCFun)
+ when is_atom(Case) andalso
+ is_function(TCCondFun, 0) andalso
+ is_function(TCFun, 0) ->
+ tc_begin(Case),
+ try TCCondFun() of
+ ok ->
+ try
+ begin
+ TCFun(),
+ sleep(seconds(1)),
+ tc_end("ok")
+ end
+ catch
+ C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
+ tc_end( f("skipping(catched,~w,tc)", [C]) ),
+ SKIP;
+ C:E:S ->
+ tc_end( f("failed(catched,~w,tc)", [C]) ),
+ erlang:raise(C, E, S)
+ end;
+ {skip, _} = SKIP ->
+ tc_end("skipping(tc)"),
+ SKIP;
+ {error, Reason} ->
+ tc_end("failed(tc)"),
+ exit({tc_cond_failed, Reason})
+ catch
+ C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
+ tc_end( f("skipping(catched,~w,cond)", [C]) ),
+ SKIP;
+ C:E:S ->
+ tc_end( f("failed(catched,~w,cond)", [C]) ),
+ erlang:raise(C, E, S)
+ end.
+
+
+tc_set_name(N) when is_atom(N) ->
+ tc_set_name(atom_to_list(N));
+tc_set_name(N) when is_list(N) ->
+ put(tc_name, N).
+
+tc_get_name() ->
+ get(tc_name).
+
+tc_begin(TC) ->
+ OldVal = process_flag(trap_exit, true),
+ put(old_trap_exit, OldVal),
+ tc_set_name(TC),
+ tc_print("begin ***",
+ "~n----------------------------------------------------~n", "").
+
+tc_end(Result) when is_list(Result) ->
+ OldVal = erase(old_trap_exit),
+ process_flag(trap_exit, OldVal),
+ tc_print("done: ~s", [Result],
+ "", "----------------------------------------------------~n~n"),
+ ok.
+
+tc_print(F, Before, After) ->
+ tc_print(F, [], Before, After).
+
+tc_print(F, A, Before, After) ->
+ Name = tc_which_name(),
+ FStr = f("*** [~s][~s][~p] " ++ F ++ "~n",
+ [formated_timestamp(),Name,self()|A]),
+ io:format(user, Before ++ FStr ++ After, []).
+
+tc_which_name() ->
+ case tc_get_name() of
+ undefined ->
+ case get(sname) of
+ undefined ->
+ "";
+ SName when is_list(SName) ->
+ SName
+ end;
+ Name when is_list(Name) ->
+ Name
+ end.
+
+
+%% ----------------------------------------------------------------------
%% Misc functions
%%
@@ -202,11 +300,14 @@ non_pc_tc_maybe_skip(Config, Condition, File, Line)
%% test-server...
ok;
_ ->
- case Condition() of
+ try Condition() of
true ->
skip(non_pc_testcase, File, Line);
false ->
ok
+ catch
+ C:E:S ->
+ skip({condition, C, E, S}, File, Line)
end
end
end.
@@ -712,6 +813,9 @@ cover([Suite, Case] = Args) when is_atom(Suite) andalso is_atom(Case) ->
%% (debug) Print functions
%%
+f(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
+
p(Mod, Case) when is_atom(Mod) andalso is_atom(Case) ->
case get(test_case) of
undefined ->
diff --git a/lib/snmp/test/snmp_test_lib.hrl b/lib/snmp/test/snmp_test_lib.hrl
index 99b86a928c..f077f15d3e 100644
--- a/lib/snmp/test/snmp_test_lib.hrl
+++ b/lib/snmp/test/snmp_test_lib.hrl
@@ -18,15 +18,11 @@
%% The Initial Developer of the Original Code is Ericsson AB.
%% %CopyrightEnd%
%%
+
%%----------------------------------------------------------------------
-%% Purpose: Define common macros for testing
+%% Purpose: Define common macros for (the snmp) testing
%%----------------------------------------------------------------------
-%% - (some of the) Macros stolen from the test server -
-
-%% -define(line,put(test_server_loc,{?MODULE,?LINE}),).
-
-
%% - Misc macros -
-ifndef(APPLICATION).
@@ -45,6 +41,8 @@
%% - Test case macros -
+-define(TC_TRY(C, TC), snmp_test_lib:tc_try(C, TC)).
+-define(TC_TRY(C, TCCond, TC), snmp_test_lib:tc_try(C, TCCond, TC)).
-define(OS_BASED_SKIP(Skippable),
snmp_test_lib:os_based_skip(Skippable)).
-define(NON_PC_TC_MAYBE_SKIP(Config, Condition),
diff --git a/lib/ssh/doc/src/ssh_client_channel.xml b/lib/ssh/doc/src/ssh_client_channel.xml
index cd28b95fd3..e6683dbd0b 100644
--- a/lib/ssh/doc/src/ssh_client_channel.xml
+++ b/lib/ssh/doc/src/ssh_client_channel.xml
@@ -150,12 +150,12 @@
<tag><c>{init_args(), list()}</c></tag>
<item><p>The list of arguments to the <c>init</c> function of the callback module.</p></item>
- <tag><c>{cm, ssh:connection_ref()}</c></tag>
+ <tag><c>{cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>}</c></tag>
<item><p>Reference to the <c>ssh</c> connection as returned by
<seealso marker="ssh#connect-3">ssh:connect/3</seealso>.
</p></item>
- <tag><c>{channel_id, ssh:channel_id()}</c></tag>
+ <tag><c>{channel_id, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}</c></tag>
<item><p>Id of the <c>ssh</c> channel as returned by
<seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seealso>.
</p></item>
@@ -198,7 +198,7 @@
{ok, ChannelRef} | {error, Reason}</name>
<fsummary>Starts a process that handles an SSH channel.</fsummary>
<type>
- <v>SshConnection = ssh:connection_ref()</v>
+ <v>SshConnection = <seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso></v>
<d>As returned by <seealso marker="ssh#connect-3">ssh:connect/3</seealso></d>
<v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
@@ -374,7 +374,7 @@
function and all channels are to handle the following message.</p>
<taglist>
- <tag><c>{ssh_channel_up, ssh:channel_id(), ssh:connection_ref()}</c></tag>
+ <tag><c>{ssh_channel_up, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>}</c></tag>
<item><p>This is the first message that the channel receives.
It is sent just before the <seealso
marker="#init-1">init/1</seealso> function
@@ -393,21 +393,21 @@
ChannelId, State}</name>
<fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
<type>
- <v>Msg = ssh_connection:event()</v>
+ <v>Msg = <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso></v>
<v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
<v>State = term()</v>
</type>
<desc>
<p>Handles SSH Connection Protocol messages that may need
service-specific attention. For details,
- see <seealso marker="ssh_connection"> ssh_connection:event()</seealso>.
+ see <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso>.
</p>
<p>The following message is taken care of by the
<c>ssh_client_channel</c> behavior.</p>
<taglist>
- <tag><c>{closed, ssh:channel_id()}</c></tag>
+ <tag><c>{closed, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}</c></tag>
<item><p>The channel behavior sends a close message to the
other side, if such a message has not already been sent.
Then it terminates the channel with reason <c>normal</c>.</p></item>
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
index 2a701929f6..9fa1da659c 100644
--- a/lib/ssh/doc/src/ssh_connection.xml
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -40,128 +40,119 @@
<p>The <url href="http://www.ietf.org/rfc/rfc4254.txt">SSH Connection Protocol</url>
is used by clients and servers, that is, SSH channels, to communicate over the
SSH connection. The API functions in this module send SSH Connection Protocol events,
- which are received as messages by the remote channel.
- If the receiving channel is an Erlang process, the
- messages have the format
- <c><![CDATA[{ssh_cm, connection_ref(), ssh_event_msg()}]]></c>.
+ which are received as messages by the remote channel handling the remote channel.
+ The Erlang format of thoose messages is
+ (see also <seealso marker="#type-event">below</seealso>):
+ </p>
+ <p><c>{ssh_cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>, </c><seealso marker="#type-channel_msg"><c>channel_msg()</c></seealso><c>}</c>
+ </p>
+ <p>
If the <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior is used to
implement the channel process, these messages are handled by
<seealso marker="ssh_client_channel#Module:handle_ssh_msg-2">handle_ssh_msg/2</seealso>.</p>
</description>
- <section>
- <title>DATA TYPES</title>
-
- <p>Type definitions that are used more than once in this module,
- or abstractions to indicate the intended use of the data
- type, or both:</p>
-
- <taglist>
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false </c></p></item>
- <tag><c>string() =</c></tag>
- <item><p>list of ASCII characters</p></item>
- <tag><c>timeout() =</c></tag>
- <item><p><c>infinity | integer()</c> in milliseconds</p></item>
- <tag><c>connection_ref() =</c></tag>
- <item><p>opaque() -as returned by
- <c>ssh:connect/3</c> or sent to an SSH channel processes</p></item>
- <tag><c>channel_id() =</c></tag>
- <item><p><c>integer()</c></p></item>
- <tag><c>ssh_data_type_code() =</c></tag>
- <item><p><c>1</c> ("stderr") | <c>0</c> ("normal") are
- valid values, see
- <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url> Section 5.2.</p></item>
- <tag><c>ssh_request_status() =</c></tag>
- <item><p> <c>success | failure</c></p></item>
- <tag><c>event() =</c></tag>
- <item><p><c>{ssh_cm, connection_ref(), ssh_event_msg()}</c></p></item>
- <tag><c>ssh_event_msg() =</c></tag>
- <item><p><c>data_events() | status_events() | terminal_events()</c></p></item>
- <tag><c>reason() =</c></tag>
- <item><p><c>timeout | closed</c></p></item>
- </taglist>
-
- <taglist>
- <tag><em>data_events()</em></tag>
- <item>
- <taglist>
- <tag><c><![CDATA[{data, channel_id(), ssh_data_type_code(), Data :: binary()}]]></c></tag>
- <item><p>Data has arrived on the channel. This event is sent as a
- result of calling <seealso marker="ssh_connection#send-3">
- ssh_connection:send/[3,4,5]</seealso>.</p></item>
-
- <tag><c><![CDATA[{eof, channel_id()}]]></c></tag>
- <item><p>Indicates that the other side sends no more data.
- This event is sent as a result of calling <seealso
- marker="ssh_connection#send_eof-2"> ssh_connection:send_eof/2</seealso>.
- </p></item>
- </taglist>
- </item>
+ <datatypes>
+ <datatype>
+ <name name="ssh_data_type_code"/>
+ <desc>
+ <p>The valid values are <c>0</c> ("normal") and <c>1</c> ("stderr"), see
+ <url href="https://tools.ietf.org/html/rfc4254#page-8">RFC 4254, Section 5.2</url>.</p>
+ </desc>
+ </datatype>
- <tag><em>status_events()</em></tag>
- <item>
+ <datatype>
+ <name name="result"/>
+ <name name="reason"/>
+ <desc>
+ <p>The result of a call.</p>
+ <p>If the request reached the peer, was handled and the response
+ reached the requesting node the <seealso marker="#type-req_status">req_status()</seealso>
+ is the status reported from the peer.</p>
+ <p>If not, the <seealso marker="#type-reason">reason()</seealso> indicates what went wrong:</p>
+ <taglist>
+ <tag><c>closed</c></tag>
+ <item>indicates that the channel or connection was closed when trying to send the request
+ </item>
+ <tag><c>timeout</c></tag>
+ <item>indicates that the operation exceeded a time limit
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
- <taglist>
- <tag><c><![CDATA[{signal, channel_id(), ssh_signal()}]]></c></tag>
- <item><p>A signal can be delivered to the remote process/service
- using the following message. Some systems do not support
- signals, in which case they are to ignore this message. There is
- currently no function to generate this event as the signals
- referred to are on OS-level and not something generated by an
- Erlang program.</p></item>
+ <datatype>
+ <name name="req_status"/>
+ <desc>
+ <p>The status of a request.
+ Coresponds to the <c>SSH_MSG_CHANNEL_SUCCESS</c> and <c>SSH_MSG_CHANNEL_FAILURE</c> values in
+ <url href="https://tools.ietf.org/html/rfc4254#section-5.4">RFC 4254, Section 5.4</url>.
+ </p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{exit_signal, channel_id(), ExitSignal :: string(), ErrorMsg ::string(),
- LanguageString :: string()}]]></c></tag>
+ <datatype_title>SSH Connection Protocol: General</datatype_title>
+ <datatype>
+ <name name="event"/>
+ <name name="channel_msg"/>
+ <desc>
+ <p>As mentioned in the introduction, the
+ <url href="https://tools.ietf.org/html/rfc4254">SSH Connection Protocol</url>
+ events are handled as messages. When writing a channel handling process without using
+ the support by the <seealso marker="ssh_client_channel">ssh_client_channel</seealso>
+ behavior the process must handle thoose messages.
+ </p>
+ </desc>
+ </datatype>
- <item><p>A remote execution can terminate violently because of a signal.
- Then this message can be received. For details on valid string
- values, see <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url>
- Section 6.10, which shows a special case of these signals.</p></item>
+ <datatype>
+ <name name="want_reply"/>
+ <desc>
+ <p>Messages that include a <c>WantReply</c> expect the channel handling
+ process to call <seealso marker="ssh_connection#reply_request-4">
+ ssh_connection:reply_request/4</seealso>
+ with the boolean value of <c>WantReply</c> as the second argument.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{exit_status, channel_id(), ExitStatus :: integer()}]]></c></tag>
- <item><p>When the command running at the other end terminates, the
- following message can be sent to return the exit status of the
- command. A zero <c>exit_status</c> usually means that the command
- terminated successfully. This event is sent as a result of calling
- <seealso marker="ssh_connection#exit_status-3">
- ssh_connection:exit_status/3</seealso>.</p></item>
- <tag><c><![CDATA[{closed, channel_id()}]]></c></tag>
- <item><p>This event is sent as a result of calling
- <seealso marker="ssh_connection#close-2">ssh_connection:close/2</seealso>.
- Both the handling of this event and sending it are taken care of by the
- <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior.</p></item>
-
- </taglist>
- </item>
+ <datatype_title>Data Transfer (RFC 4254, section 5.2)</datatype_title>
+ <datatype>
+ <name name="data_ch_msg"/>
+ <desc>
+ <p>Data has arrived on the channel. This event is sent as a result of calling
+ <seealso marker="ssh_connection#send-3"> ssh_connection:send/[3,4,5]</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <tag><em>terminal_events()</em></tag>
- <item>
- <p>Channels implementing a shell and command execution on the
- server side are to handle the following messages that can be sent by client-
- channel processes.</p>
+ <datatype_title>Closing a Channel (RFC 4254, section 5.3)</datatype_title>
+ <datatype>
+ <name name="eof_ch_msg"/>
+ <desc>
+ <p>Indicates that the other side sends no more data. This event is sent as a result of calling
+ <seealso marker="ssh_connection#send_eof-2"> ssh_connection:send_eof/2</seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="closed_ch_msg"/>
+ <desc>
+ <p>This event is sent as a result of calling
+ <seealso marker="ssh_connection#close-2">ssh_connection:close/2</seealso>.
+ Both the handling of this event and sending it are taken care of by the
+ <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior.</p>
+ </desc>
+ </datatype>
- <p>Events that include a <c>WantReply</c> expect the event handling
- process to call <seealso marker="ssh_connection#reply_request-4">
- ssh_connection:reply_request/4</seealso>
- with the boolean value of <c>WantReply</c> as the second argument.</p>
- <taglist>
- <tag><c><![CDATA[{env, channel_id(), WantReply :: boolean(),
- Var ::string(), Value :: string()}]]></c></tag>
- <item><p>Environment variables can be passed to the shell/command
- to be started later. This event is sent as a result of calling <seealso
- marker="ssh_connection#setenv-5"> ssh_connection:setenv/5</seealso>.
- </p></item>
-
- <tag><c><![CDATA[{pty, channel_id(),
- WantReply :: boolean(), {Terminal :: string(), CharWidth :: integer(),
- RowHeight :: integer(), PixelWidth :: integer(), PixelHeight :: integer(),
- TerminalModes :: [{Opcode :: atom() | integer(),
- Value :: integer()}]}}]]></c></tag>
- <item><p>A pseudo-terminal has been requested for the
+ <datatype_title>Requesting a Pseudo-Terminal (RFC 4254, section 6.2)</datatype_title>
+ <datatype>
+ <name name="pty_ch_msg"/>
+ <name name="term_mode"/>
+ <desc>
+ <p>A pseudo-terminal has been requested for the
session. <c>Terminal</c> is the value of the TERM environment
variable value, that is, <c>vt100</c>. Zero dimension parameters must
be ignored. The character/row dimensions override the pixel
@@ -169,46 +160,103 @@
drawable area of the window. <c>Opcode</c> in the
<c>TerminalModes</c> list is the mnemonic name, represented
as a lowercase Erlang atom, defined in
- <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url>, Section 8.
+ <url href="https://tools.ietf.org/html/rfc4254#section-8">RFC 4254</url>, Section 8.
It can also be an <c>Opcode</c> if the mnemonic name is not listed in the
RFC. Example: <c>OP code: 53, mnemonic name ECHO erlang atom:
echo</c>. This event is sent as a result of calling <seealso
- marker="ssh_connection#ptty_alloc/4">ssh_connection:ptty_alloc/4</seealso>.</p></item>
+ marker="ssh_connection#ptty_alloc/4">ssh_connection:ptty_alloc/4</seealso>.</p>
+ </desc>
+ </datatype>
+
- <tag><c><![CDATA[{shell, WantReply :: boolean()}]]></c></tag>
- <item><p>This message requests that the user default shell
+ <datatype_title>Environment Variable Passing (RFC 4254, section 6.4)</datatype_title>
+ <datatype>
+ <name name="env_ch_msg"/>
+ <desc>
+ <p>Environment variables can be passed to the shell/command
+ to be started later. This event is sent as a result of calling <seealso
+ marker="ssh_connection#setenv-5"> ssh_connection:setenv/5</seealso>.
+ </p>
+ </desc>
+ </datatype>
+
+
+ <datatype_title>Starting a Shell or Command (RFC 4254, section 6.5)</datatype_title>
+ <datatype>
+ <name name="shell_ch_msg"/>
+ <desc>
+ <p>This message requests that the user default shell
is started at the other end. This event is sent as a result of calling
<seealso marker="ssh_connection#shell-2"> ssh_connection:shell/2</seealso>.
- </p></item>
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="exec_ch_msg"/>
+ <desc>
+ <p>This message requests that the server starts
+ execution of the given command. This event is sent as a result of calling <seealso
+ marker="ssh_connection#exec-4">ssh_connection:exec/4 </seealso>.
+ </p>
+ </desc>
+ </datatype>
+
- <tag><c><![CDATA[{window_change, channel_id(), CharWidth() :: integer(),
- RowHeight :: integer(), PixWidth :: integer(), PixHeight :: integer()}]]></c></tag>
- <item><p>When the window (terminal) size changes on the client
+ <datatype_title>Window Dimension Change Message (RFC 4254, section 6.7)</datatype_title>
+ <datatype>
+ <name name="window_change_ch_msg"/>
+ <desc>
+ <p>When the window (terminal) size changes on the client
side, it <em>can</em> send a message to the server side to inform it of
- the new dimensions. No API function generates this event.</p></item>
+ the new dimensions. No API function generates this event.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{exec, channel_id(),
- WantReply :: boolean(), Cmd :: string()}]]></c></tag>
- <item><p>This message requests that the server starts
- execution of the given command. This event is sent as a result of calling <seealso
- marker="ssh_connection#exec-4">ssh_connection:exec/4 </seealso>.
- </p></item>
- </taglist>
- </item>
- </taglist>
- </section>
+ <datatype_title>Signals (RFC 4254, section 6.9)</datatype_title>
+ <datatype>
+ <name name="signal_ch_msg"/>
+ <desc>
+ <p>A signal can be delivered to the remote process/service
+ using the following message. Some systems do not support
+ signals, in which case they are to ignore this message. There is
+ currently no function to generate this event as the signals
+ referred to are on OS-level and not something generated by an
+ Erlang program.</p>
+ </desc>
+ </datatype>
+
+
+ <datatype_title>Returning Exit Status (RFC 4254, section 6.10)</datatype_title>
+ <datatype>
+ <name name="exit_status_ch_msg"/>
+ <desc>
+ <p>When the command running at the other end terminates, the
+ following message can be sent to return the exit status of the
+ command. A zero <c>exit_status</c> usually means that the command
+ terminated successfully. This event is sent as a result of calling
+ <seealso marker="ssh_connection#exit_status-3">
+ ssh_connection:exit_status/3</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="exit_signal_ch_msg"/>
+ <desc>
+ <p>A remote execution can terminate violently because of a signal.
+ Then this message can be received. For details on valid string
+ values, see <url href="https://tools.ietf.org/html/rfc4254#section-6.10">RFC 4254</url>
+ Section 6.10, which shows a special case of these signals.</p>
+ </desc>
+ </datatype>
+
+ </datatypes>
+
<funcs>
<func>
- <name since="">adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok</name>
+ <name since="" name="adjust_window" arity="3"/>
<fsummary>Adjusts the SSH flow control window.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- <v>NumOfBytes = integer()</v>
- </type>
- <desc>
+ <desc>
<p>Adjusts the SSH flow control window. This is to be done by both the
client- and server-side channel processes.</p>
@@ -221,17 +269,12 @@
</func>
<func>
- <name since="">close(ConnectionRef, ChannelId) -> ok</name>
+ <name since="" name="close" arity="2"/>
<fsummary>Sends a close message on the channel <c>ChannelId</c>.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- </type>
<desc>
<p>A server- or client-channel process can choose to close their session by
sending a close event.
</p>
-
<note><p>This function is called by the <c>ssh_client_channel</c>
behavior when the channel is terminated, see <seealso
marker="ssh_client_channel"> ssh_client_channel(3)</seealso>. Thus, channels implemented
@@ -240,57 +283,61 @@
</func>
<func>
- <name since="">exec(ConnectionRef, ChannelId, Command, TimeOut) -> ssh_request_status() |
- {error, reason()}</name>
+ <name since="" name="exec" arity="4"/>
<fsummary>Requests that the server starts the execution of the given command.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- <v>Command = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Is to be called by a client-channel process to request that the server starts
executing the given command. The result is several messages according to the
following pattern. The last message is a channel close message, as the <c>exec</c>
request is a one-time execution that closes the channel when it is done.</p>
- <taglist>
- <tag><c>N x {ssh_cm, connection_ref(),
- {data, channel_id(), ssh_data_type_code(), Data :: binary()}}</c></tag>
+ <!--taglist>
+ <tag><c>N x {ssh_cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>, {data, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>, </c><seealso marker="#type-ssh_data_type_code">ssh_data_type_code()</seealso><c>, Data :: binary()}}</c></tag>
<item><p>The result of executing the command can be only one line
or thousands of lines depending on the command.</p></item>
- <tag><c>0 or 1 x {ssh_cm, connection_ref(), {eof, channel_id()}}</c></tag>
+ <tag><c>0 or 1 x {ssh_cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>, {eof, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}}</c></tag>
<item><p>Indicates that no more data is to be sent.</p></item>
- <tag><c>0 or 1 x {ssh_cm,
- connection_ref(), {exit_signal,
- channel_id(), ExitSignal :: string(), ErrorMsg :: string(), LanguageString :: string()}}</c></tag>
+ <tag><c>0 or 1 x {ssh_cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>, {exit_signal, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>, ExitSignal :: string(), ErrorMsg :: string(), LanguageString :: string()}}</c></tag>
<item><p>Not all systems send signals. For details on valid string
values, see RFC 4254, Section 6.10</p></item>
- <tag><c>0 or 1 x {ssh_cm, connection_ref(), {exit_status,
- channel_id(), ExitStatus :: integer()}}</c></tag>
+ <tag><c>0 or 1 x {ssh_cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>, {exit_status, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>, ExitStatus :: integer()}}</c></tag>
<item><p>It is recommended by the SSH Connection Protocol to send this
message, but that is not always the case.</p></item>
- <tag><c>1 x {ssh_cm, connection_ref(),
- {closed, channel_id()}}</c></tag>
+ <tag><c>1 x {ssh_cm, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>, {closed, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}}</c></tag>
<item><p>Indicates that the <c>ssh_client_channel</c> started for the
execution of the command has now been shut down.</p></item>
+ </taglist-->
+
+ <taglist>
+ <tag>N x <seealso marker="#type-data_ch_msg">data message(s)</seealso></tag>
+ <item><p>The result of executing the command can be only one line
+ or thousands of lines depending on the command.</p></item>
+
+ <tag>0 or 1 x <seealso marker="#type-eof_ch_msg">eof message</seealso></tag>
+ <item><p>Indicates that no more data is to be sent.</p></item>
+
+ <tag>0 or 1 x <seealso marker="#type-exit_signal_ch_msg">exit signal message</seealso></tag>
+ <item><p>Not all systems send signals. For details on valid string
+ values, see RFC 4254, Section 6.10</p></item>
+
+ <tag>0 or 1 x <seealso marker="#type-exit_status_ch_msg">exit status message</seealso></tag>
+ <item><p>It is recommended by the SSH Connection Protocol to send this
+ message, but that is not always the case.</p></item>
+
+ <tag>1 x <seealso marker="#type-closed_ch_msg">closed status message</seealso></tag>
+ <item><p>Indicates that the <c>ssh_client_channel</c> started for the
+ execution of the command has now been shut down.</p></item>
</taglist>
</desc>
</func>
<func>
- <name since="">exit_status(ConnectionRef, ChannelId, Status) -> ok</name>
+ <name since="" name="exit_status" arity="3"/>
<fsummary>Sends the exit status of a command to the client.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref() </v>
- <v>ChannelId = channel_id()</v>
- <v>Status = integer()</v>
- </type>
<desc>
<p>Is to be called by a server-channel process to send the exit status of a command
to the client.</p>
@@ -298,16 +345,10 @@
</func>
<func>
- <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>
+ <name since="OTP 17.5" name="ptty_alloc" arity="3"/>
+ <name since="OTP 17.4" name="ptty_alloc" arity="4"/>
<fsummary>Sends an SSH Connection Protocol <c>pty_req</c>,
to allocate a pseudo-terminal.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- <v>Options = proplists:proplist()</v>
- </type>
<desc>
<p>Sends an SSH Connection Protocol <c>pty_req</c>, to allocate a pseudo-terminal.
Is to be called by an SSH client process.</p>
@@ -339,14 +380,8 @@
</func>
<func>
- <name since="">reply_request(ConnectionRef, WantReply, Status, ChannelId) -> ok</name>
+ <name since="" name="reply_request" arity="4"/>
<fsummary>Sends status replies to requests that want such replies.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>WantReply = boolean()</v>
- <v>Status = ssh_request_status()</v>
- <v>ChannelId = channel_id()</v>
- </type>
<desc>
<p>Sends status replies to requests where the requester has
stated that it wants a status report, that is, <c>WantReply = true</c>.
@@ -361,14 +396,15 @@
<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>
+ ok | Error</name>
<fsummary>Sends channel data.</fsummary>
<type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
+ <v>ConnectionRef = <seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso></v>
+ <v>ChannelId = <seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso></v>
<v>Data = binary()</v>
- <v>Type = ssh_data_type_code()</v>
+ <v>Type = <seealso marker="#type-ssh_data_type_code">ssh_data_type_code()</seealso></v>
<v>Timeout = timeout()</v>
+ <v>Error = {error, <seealso marker="#type-reason">reason()</seealso>}</v>
</type>
<desc>
<p>Is to be called by client- and server-channel processes to send data to each other.
@@ -380,29 +416,17 @@
</func>
<func>
- <name since="">send_eof(ConnectionRef, ChannelId) -> ok | {error, closed}</name>
+ <name since="" name="send_eof" arity="2"/>
<fsummary>Sends EOF on channel <c>ChannelId</c>.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- </type>
<desc>
<p>Sends EOF on channel <c>ChannelId</c>.</p>
</desc>
</func>
<func>
- <name since="">session_channel(ConnectionRef, Timeout) -></name>
- <name since="">session_channel(ConnectionRef, InitialWindowSize,
- MaxPacketSize, Timeout) -> {ok, channel_id()} | {error, reason()}</name>
+ <name since="" name="session_channel" arity="2"/>
+ <name since="" name="session_channel" arity="4"/>
<fsummary>Opens a channel for an SSH session.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>InitialWindowSize = integer()</v>
- <v>MaxPacketSize = integer()</v>
- <v>Timeout = timeout()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Opens a channel for an SSH session. The channel id returned from this function
is the id used as input to the other functions in this module.</p>
@@ -410,17 +434,9 @@
</func>
<func>
- <name since="">setenv(ConnectionRef, ChannelId, Var, Value, TimeOut) -> ssh_request_status() |
- {error, reason()}</name>
+ <name since="" name="setenv" arity="5"/>
<fsummary>Environment variables can be passed to the
shell/command to be started later.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- <v>Var = string()</v>
- <v>Value = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Environment variables can be passed before starting the
shell/command. Is to be called by a client channel processes.</p>
@@ -428,14 +444,9 @@
</func>
<func>
- <name since="">shell(ConnectionRef, ChannelId) -> ok | failure | {error, closed}
- </name>
+ <name since="" name="shell" arity="2"/>
<fsummary>Requests that the user default shell (typically defined in
/etc/passwd in Unix systems) is to be executed at the server end.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- </type>
<desc>
<p>Is to be called by a client channel process to request that the user default
shell (typically defined in /etc/passwd in Unix systems) is executed
@@ -448,15 +459,8 @@
</func>
<func>
- <name since="">subsystem(ConnectionRef, ChannelId, Subsystem, Timeout) -> ssh_request_status() |
- {error, reason()}</name>
+ <name since="" name="subsystem" arity="4"/>
<fsummary>Requests to execute a predefined subsystem on the server.</fsummary>
- <type>
- <v>ConnectionRef = connection_ref()</v>
- <v>ChannelId = channel_id()</v>
- <v>Subsystem = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Is to be called by a client-channel process for requesting to execute a predefined
subsystem on the server.
diff --git a/lib/ssh/doc/src/ssh_server_channel.xml b/lib/ssh/doc/src/ssh_server_channel.xml
index a4e18bbfbf..87c745c9fb 100644
--- a/lib/ssh/doc/src/ssh_server_channel.xml
+++ b/lib/ssh/doc/src/ssh_server_channel.xml
@@ -112,7 +112,7 @@
function and all channels are to handle the following message.</p>
<taglist>
- <tag><c>{ssh_channel_up, ssh:channel_id(), ssh:connection_ref()}</c></tag>
+ <tag><c>{ssh_channel_up, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>, </c><seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso><c>}</c></tag>
<item><p>This is the first message that the channel receives.
This is especially useful if the
server wants to send a message to the client without first
@@ -129,21 +129,21 @@
ChannelId, State}</name>
<fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
<type>
- <v>Msg = ssh_connection:event()</v>
+ <v>Msg = <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso></v>
<v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
<v>State = term()</v>
</type>
<desc>
<p>Handles SSH Connection Protocol messages that may need
service-specific attention. For details,
- see <seealso marker="ssh_connection"> ssh_connection:event()</seealso>.
+ see <seealso marker="ssh_connection#type-event">ssh_connection:event()</seealso>.
</p>
<p>The following message is taken care of by the
<c>ssh_server_channel</c> behavior.</p>
<taglist>
- <tag><c>{closed, ssh:channel_id()}</c></tag>
+ <tag><c>{closed, </c><seealso marker="ssh:ssh#type-channel_id">ssh:channel_id()</seealso><c>}</c></tag>
<item><p>The channel behavior sends a close message to the
other side, if such a message has not already been sent.
Then it terminates the channel with reason <c>normal</c>.</p></item>
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index c89092798d..f9f1e0953b 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -37,60 +37,112 @@
SSH.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <p>Type definitions that are used more than once in this module,
- or abstractions to indicate the intended use of the data type, or both:
- </p>
-
- <taglist>
- <tag><c>reason()</c></tag>
- <item>
- <p>= <c>atom() | string() | tuple() </c>A description of the reason why an operation failed.</p>
- <p>
- 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>
- <p>
+ <datatypes>
+ <datatype>
+ <name name="sftp_option"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype_title>Error cause</datatype_title>
+ <datatype>
+ <name name="reason"/>
+ <desc>
+ <p>A description of the reason why an operation failed.</p>
+ <p>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/html/draft-ietf-secsh-filexfer-13#page-49">draft-ietf-secsh-filexfer-13</url>
+ section 9.1.
The codes are named as <c>SSH_FX_*</c> which are transformed into lowercase of the star-part.
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>The <c>tuple()</c> reason are other errors like for example <c>{exit_status,1}</c>.
</p>
- </item>
+ </desc>
+ </datatype>
- <tag><c>connection_ref() =</c></tag>
- <item><p><c>opaque()</c> - as returned by
- <seealso marker="ssh#connect-3"><c>ssh:connect/3</c></seealso></p></item>
+ <datatype_title>Crypto operations for open_tar</datatype_title>
+ <datatype>
+ <name name="tar_crypto_spec"/>
+ <name name="encrypt_spec"/>
+ <name name="decrypt_spec"/>
+ <desc>
+ <p>Specifies the encryption or decryption applied to tar files when using
+ <seealso marker="#open_tar/3">open_tar/3</seealso> or
+ <seealso marker="#open_tar/4">open_tar/4</seealso>.
+ </p>
+ <p>The encryption or decryption is applied to the generated stream of
+ bytes prior to sending the resulting stream to the SFTP server.
+ </p>
+ <p>For code examples see Section
+ <seealso marker="using_ssh#example-with-encryption">Example with encryption</seealso>
+ in the ssh Users Guide.
+ </p>
+ </desc>
+ </datatype>
- <tag><c>timeout()</c></tag>
- <item><p>= <c>infinity | integer()</c> in milliseconds. Default infinity.</p></item>
- </taglist>
- </section>
+ <datatype>
+ <name name="init_fun"/>
+ <name name="chunk_size"/>
+ <name name="crypto_state"/>
+ <desc>
+ <p>The <c>init_fun()</c> in the
+ <seealso marker="#type-tar_crypto_spec">tar_crypto_spec</seealso>
+ is applied once prior to any other <c>crypto</c>
+ operation. The intention is that this function initiates the encryption or
+ decryption for example by calling
+ <seealso marker="crypto:crypto#crypto_init/4">crypto:crypto_init/4</seealso>
+ or similar. The <c>crypto_state()</c> is the state such a function may return.
+ </p>
+ <p>If the selected cipher needs to have the input data partioned into
+ blocks of a certain size, the <c>init_fun()</c> should return the second
+ form of return value with the <c>chunk_size()</c> set to the block size.
+ If the <c>chunk_size()</c> is <c>undefined</c>, the size of the <c>PlainBin</c>s varies,
+ because this is intended for stream crypto, whereas a fixed <c>chunk_size()</c> is intended for block crypto.
+ A <c>chunk_size()</c> can be changed in the return from the <c>crypto_fun()</c>.
+ The value can be changed between <c>pos_integer()</c> and <c>undefined</c>.
+ </p>
+ </desc>
+ </datatype>
- <section>
- <title>Time-outs</title>
- <p>If the request functions for the SFTP channel return <c>{error, timeout}</c>,
- no answer was received from the server within the expected time.</p>
- <p>The request may have reached the server and may have been performed.
- However, no answer was received from the server within the expected time.</p>
- </section>
+ <datatype>
+ <name name="crypto_fun"/>
+ <name name="crypto_result"/>
+ <desc>
+ <p>The initial <c>crypto_state()</c> returned from the
+ <seealso marker="#type-init_fun">init_fun()</seealso>
+ is folded into repeated applications of the <c>crypto_fun()</c> in the
+ <seealso marker="#type-tar_crypto_spec">tar_crypto_spec</seealso>.
+ The binary returned from that fun is sent to the remote SFTP server and
+ the new <c>crypto_state()</c> is used in the next call of the
+ <c>crypto_fun()</c>.
+ </p>
+ <p>If the <c>crypto_fun()</c> reurns a <c>chunk_size()</c>, that value
+ is as block size for further blocks in calls to <c>crypto_fun()</c>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="final_fun"/>
+ <desc>
+ <p>If doing encryption,
+ the <c>final_fun()</c> in the
+ <seealso marker="#type-tar_crypto_spec">tar_crypto_spec</seealso>
+ is applied to the last piece of data.
+ The <c>final_fun()</c> is responsible for padding (if needed) and
+ encryption of that last piece.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name since="">apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, reason()}</name>
+ <name name="apread" arity="4" since=""/>
<fsummary>Reads asynchronously from an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>N = term()</v>
- </type>
<desc><p>The <c><![CDATA[apread/4]]></c> function reads from a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#aread-3"><c>aread/3</c></seealso> functions.</p>
@@ -98,17 +150,8 @@
</func>
<func>
- <name since="">apwrite(ChannelPid, Handle, Position, Data) -> {async, N} | {error, reason()}</name>
+ <name name="apwrite" arity="4" since=""/>
<fsummary>Writes asynchronously to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>Data = binary()</v>
- <v>Timeout = timeout()</v>
- <v>N = term()</v>
- </type>
<desc><p>The <c><![CDATA[apwrite/4]]></c> function writes to a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#awrite-3"><c>awrite/3</c></seealso> functions.</p>
@@ -116,15 +159,8 @@
</func>
<func>
- <name since="">aread(ChannelPid, Handle, Len) -> {async, N} | {error, reason()}</name>
+ <name name="aread" arity="3" since=""/>
<fsummary>Reads asynchronously from an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>N = term()</v>
- </type>
<desc>
<p>Reads from an open file, without waiting for the result. If the
handle is valid, the function returns <c><![CDATA[{async, N}]]></c>, where <c>N</c>
@@ -137,16 +173,8 @@
</func>
<func>
- <name since="">awrite(ChannelPid, Handle, Data) -> {async, N} | {error, reason()}</name>
+ <name name="awrite" arity="3" since=""/>
<fsummary>Writes asynchronously to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Len = integer()</v>
- <v>Data = binary()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes to an open file, without waiting for the result. If the
handle is valid, the function returns <c><![CDATA[{async, N}]]></c>, where <c>N</c>
@@ -159,28 +187,18 @@
</func>
<func>
- <name since="">close(ChannelPid, Handle) -></name>
- <name since="">close(ChannelPid, Handle, Timeout) -> ok | {error, reason()}</name>
+ <name name="close" arity="2" since=""/>
+ <name name="close" arity="3" since=""/>
<fsummary>Closes an open handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Closes a handle to an open file or directory on the server.</p>
</desc>
</func>
<func>
- <name since="">delete(ChannelPid, Name) -></name>
- <name since="">delete(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name name="delete" arity="2" since=""/>
+ <name name="delete" arity="3" since=""/>
<fsummary>Deletes a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Deletes the file specified by <c><![CDATA[Name]]></c>.
</p>
@@ -188,14 +206,9 @@
</func>
<func>
- <name since="">del_dir(ChannelPid, Name) -></name>
- <name since="">del_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name name="del_dir" arity="2" since=""/>
+ <name name="del_dir" arity="3" since=""/>
<fsummary>Deletes an empty directory.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Deletes a directory specified by <c><![CDATA[Name]]></c>.
The directory must be empty before it can be successfully deleted.
@@ -204,16 +217,9 @@
</func>
<func>
- <name since="">list_dir(ChannelPid, Path) -></name>
- <name since="">list_dir(ChannelPid, Path, Timeout) -> {ok, Filenames} | {error, reason()}</name>
+ <name name="list_dir" arity="2" since=""/>
+ <name name="list_dir" arity="3" since=""/>
<fsummary>Lists the directory.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Path = string()</v>
- <v>Filenames = [Filename]</v>
- <v>Filename = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Lists the given directory on the server, returning the
filenames as a list of strings.</p>
@@ -221,14 +227,9 @@
</func>
<func>
- <name since="">make_dir(ChannelPid, Name) -></name>
- <name since="">make_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()}</name>
+ <name name="make_dir" arity="2" since=""/>
+ <name name="make_dir" arity="3" since=""/>
<fsummary>Creates a directory.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Creates a directory specified by <c><![CDATA[Name]]></c>. <c><![CDATA[Name]]></c>
must be a full path to a new directory. The directory can only be
@@ -237,14 +238,9 @@
</func>
<func>
- <name since="">make_symlink(ChannelPid, Name, Target) -></name>
- <name since="">make_symlink(ChannelPid, Name, Target, Timeout) -> ok | {error, reason()}</name>
+ <name name="make_symlink" arity="3" since=""/>
+ <name name="make_symlink" arity="4" since=""/>
<fsummary>Creates a symbolic link.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Target = string()</v>
- </type>
<desc>
<p>Creates a symbolic link pointing to <c><![CDATA[Target]]></c> with the
name <c><![CDATA[Name]]></c>.
@@ -252,32 +248,19 @@
</desc>
</func>
- <func>
- <name since="">open(ChannelPid, File, Mode) -></name>
- <name since="">open(ChannelPid, File, Mode, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <func>
+ <name name="open" arity="3" since=""/>
+ <name name="open" arity="4" since=""/>
<fsummary>Opens a file and returns a handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>File = string()</v>
- <v>Mode = [Modeflag]</v>
- <v>Modeflag = read | write | creat | trunc | append | binary</v>
- <v>Timeout = timeout()</v>
- <v>Handle = term()</v>
- </type>
<desc>
<p>Opens a file on the server and returns a handle, which
can be used for reading or writing.</p>
</desc>
</func>
<func>
- <name since="">opendir(ChannelPid, Path) -></name>
- <name since="">opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | {error, reason()}</name>
+ <name name="opendir" arity="2" since=""/>
+ <name name="opendir" arity="3" since=""/>
<fsummary>Opens a directory and returns a handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Path = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Opens a handle to a directory on the server. The handle
can be used for reading directory contents.</p>
@@ -285,72 +268,36 @@
</func>
<func>
- <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>
+ <name name="open_tar" arity="3" since="OTP 17.4"/>
+ <name name="open_tar" arity="4" since="OTP 17.4"/>
<fsummary>Opens a tar file on the server to which <c>ChannelPid</c>
is connected and returns a handle.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Path = string()</v>
- <v>Mode = [read] | [write] | [read,EncryptOpt] | [write,DecryptOpt]</v>
- <v>EncryptOpt = {crypto,{InitFun,EncryptFun,CloseFun}}</v>
- <v>DecryptOpt = {crypto,{InitFun,DecryptFun}}</v>
- <v>InitFun = (fun() -> {ok,CryptoState}) | (fun() -> {ok,CryptoState,ChunkSize})</v>
- <v>CryptoState = any()</v>
- <v>ChunkSize = undefined | pos_integer()</v>
- <v>EncryptFun = (fun(PlainBin,CryptoState) -> EncryptResult)</v>
- <v>EncryptResult = {ok,EncryptedBin,CryptoState} | {ok,EncryptedBin,CryptoState,ChunkSize}</v>
- <v>PlainBin = binary()</v>
- <v>EncryptedBin = binary()</v>
- <v>DecryptFun = (fun(EncryptedBin,CryptoState) -> DecryptResult)</v>
- <v>DecryptResult = {ok,PlainBin,CryptoState} | {ok,PlainBin,CryptoState,ChunkSize}</v>
- <v>CloseFun = (fun(PlainBin,CryptoState) -> {ok,EncryptedBin})</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Opens a handle to a tar file on the server, associated with <c>ChannelPid</c>.
- The handle can be used for remote tar creation and extraction, as defined by the
- <seealso marker="stdlib:erl_tar#init-3">erl_tar:init/3</seealso> function.
- </p>
-
- <p> For code exampel see Section
- <seealso marker="using_ssh">SFTP Client with TAR Compression and Encryption</seealso> in
- the ssh Users Guide. </p>
-
- <p>The <c>crypto</c> mode option is applied to the generated stream of bytes prior to sending
- them to the SFTP server. This is intended for encryption but can be used for other
- purposes.
+ The handle can be used for remote tar creation and extraction. The actual writing
+ and reading is performed by calls to
+ <seealso marker="stdlib:erl_tar#add-3">erl_tar:add/3,4</seealso> and
+ <seealso marker="stdlib:erl_tar#extract-2">erl_tar:extract/2</seealso>.
+ Note: The
+ <seealso marker="stdlib:erl_tar#init-3">erl_tar:init/3</seealso> function should not
+ be called, that one is called by this open_tar function.
</p>
- <p>The <c>InitFun</c> is applied once
- prior to any other <c>crypto</c> operation. The returned <c>CryptoState</c> is then folded into
- repeated applications of the <c>EncryptFun</c> or <c>DecryptFun</c>. The binary returned
- from those funs are sent further to the remote SFTP server. Finally, if doing encryption,
- the <c>CloseFun</c> is applied to the last piece of data. The <c>CloseFun</c> is
- responsible for padding (if needed) and encryption of that last piece.
+ <p>For code examples see Section
+ <seealso marker="using_ssh#sftp-client-with-tar-compression">SFTP Client with TAR Compression</seealso>
+ in the ssh Users Guide.
</p>
- <p>The <c>ChunkSize</c> defines the size of the <c>PlainBin</c>s that <c>EncodeFun</c> is applied
- to. If the <c>ChunkSize</c> is <c>undefined</c>, the size of the <c>PlainBin</c>s varies,
- because this is intended for stream crypto, whereas a fixed <c>ChunkSize</c> is intended for block crypto.
- <c>ChunkSize</c>s can be changed in the return from the <c>EncryptFun</c> or
- <c>DecryptFun</c>. The value can be changed between <c>pos_integer()</c> and <c>undefined</c>.
+ <p>The <c>crypto</c> mode option is explained in the data types section above, see
+ <seealso marker="#Crypto operations for open_tar">Crypto operations for open_tar</seealso>.
+ Encryption is assumed if the <c>Mode</c> contains <c>write</c>, and
+ decryption if the <c>Mode</c> contains <c>read</c>.
</p>
-
</desc>
</func>
<func>
- <name since="">position(ChannelPid, Handle, Location) -></name>
- <name since="">position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition | {error, reason()}</name>
+ <name name="position" arity="3" since=""/>
+ <name name="position" arity="4" since=""/>
<fsummary>Sets the file position of a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Location = Offset
- | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof</v>
- <v>Offset = integer()</v>
- <v>Timeout = timeout()</v>
- <v>NewPosition = integer()</v>
- </type>
<desc>
<p>Sets the file position of the file referenced by <c><![CDATA[Handle]]></c>.
Returns <c><![CDATA[{ok, NewPosition}]]></c> (as an absolute offset) if
@@ -384,17 +331,9 @@
</func>
<func>
- <name since="">pread(ChannelPid, Handle, Position, Len) -></name>
- <name since="">pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
+ <name name="pread" arity="4" since=""/>
+ <name name="pread" arity="5" since=""/>
<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>
- </type>
<desc><p>The <c><![CDATA[pread/3,4]]></c> function reads from a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#read-3"><c>read/3,4</c></seealso> functions.</p>
@@ -402,16 +341,9 @@
</func>
<func>
- <name since="">pwrite(ChannelPid, Handle, Position, Data) -> ok</name>
- <name since="">pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, reason()}</name>
+ <name name="pwrite" arity="4" since=""/>
+ <name name="pwrite" arity="5" since=""/>
<fsummary>Writes to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Data = iolist()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc><p>The <c><![CDATA[pwrite/3,4]]></c> function writes to a specified position,
combining the <seealso marker="#position-3"><c>position/3</c></seealso> and
<seealso marker="#write-3"><c>write/3,4</c></seealso> functions.</p>
@@ -419,16 +351,9 @@
</func>
<func>
- <name since="">read(ChannelPid, Handle, Len) -></name>
- <name since="">read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | {error, reason()}</name>
+ <name name="read" arity="3" since=""/>
+ <name name="read" arity="4" since=""/>
<fsummary>Reads from an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Len = integer()</v>
- <v>Timeout = timeout()</v>
- <v>Data = string() | binary()</v>
- </type>
<desc>
<p>Reads <c><![CDATA[Len]]></c> bytes from the file referenced by
<c><![CDATA[Handle]]></c>. Returns <c><![CDATA[{ok, Data}]]></c>, <c><![CDATA[eof]]></c>, or
@@ -440,32 +365,19 @@
</desc>
</func>
- <func>
- <name since="">read_file(ChannelPid, File) -></name>
- <name since="">read_file(ChannelPid, File, Timeout) -> {ok, Data} | {error, reason()}</name>
+ <func>
+ <name name="read_file" arity="2" since=""/>
+ <name name="read_file" arity="3" since=""/>
<fsummary>Reads a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>File = string()</v>
- <v>Data = binary()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Reads a file from the server, and returns the data in a binary.</p>
</desc>
</func>
- <func>
- <name since="">read_file_info(ChannelPid, Name) -></name>
- <name since="">read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()}</name>
+ <func>
+ <name name="read_file_info" arity="2" since=""/>
+ <name name="read_file_info" arity="3" since=""/>
<fsummary>Gets information about a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Handle = term()</v>
- <v>Timeout = timeout()</v>
- <v>FileInfo = record()</v>
- </type>
<desc>
<p>Returns a <c><![CDATA[file_info]]></c> record from the file system object specified by
<c><![CDATA[Name]]></c> or <c><![CDATA[Handle]]></c>. See
@@ -474,38 +386,26 @@
</p>
<p>
Depending on the underlying OS:es links might be followed and info on the final file, directory
- etc is returned. See <seealso marker="#read_link_info-2">ssh_sftp::read_link_info/2</seealso>
+ etc is returned. See <seealso marker="#read_link_info-2">read_link_info/2</seealso>
on how to get information on links instead.
</p>
</desc>
</func>
<func>
- <name since="">read_link(ChannelPid, Name) -></name>
- <name since="">read_link(ChannelPid, Name, Timeout) -> {ok, Target} | {error, reason()}</name>
+ <name name="read_link" arity="2" since=""/>
+ <name name="read_link" arity="3" since=""/>
<fsummary>Reads symbolic link.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Target = string()</v>
- </type>
<desc>
<p>Reads the link target from the symbolic link specified by <c><![CDATA[name]]></c>.
</p>
</desc>
</func>
- <func>
- <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>
+ <func>
+ <name since="" name="read_link_info" arity="2"/>
+ <name since="" name="read_link_info" arity="3"/>
<fsummary>Gets information about a symbolic link.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Handle = term()</v>
- <v>Timeout = timeout()</v>
- <v>FileInfo = record()</v>
- </type>
<desc>
<p>Returns a <c><![CDATA[file_info]]></c> record from the symbolic
link specified by <c><![CDATA[Name]]></c> or <c><![CDATA[Handle]]></c>.
@@ -517,15 +417,9 @@
</func>
<func>
- <name since="">rename(ChannelPid, OldName, NewName) -> </name>
- <name since="">rename(ChannelPid, OldName, NewName, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="rename" arity="3"/>
+ <name since="" name="rename" arity="4"/>
<fsummary>Renames a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>OldName = string()</v>
- <v>NewName = string()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Renames a file named <c><![CDATA[OldName]]></c> and gives it the name
<c><![CDATA[NewName]]></c>.
@@ -535,25 +429,27 @@
<func>
<name since="">start_channel(ConnectionRef) -></name>
- <name since="">start_channel(ConnectionRef, Options) ->
- {ok, Pid} | {error, reason()|term()}</name>
+ <name since="">start_channel(ConnectionRef, SftpOptions) ->
+ {ok, ChannelPid} | Error</name>
+ <name since="">start_channel(Host) -></name>
<name since="">start_channel(Host, Options) -></name>
- <name since="">start_channel(Host, Port, Options) ->
- {ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
-
+ <name since="">start_channel(Host, Port, Options) -></name>
<name since="">start_channel(TcpSocket) -></name>
<name since="">start_channel(TcpSocket, Options) ->
- {ok, Pid, ConnectionRef} | {error, reason()|term()}</name>
+ {ok, ChannelPid, ConnectionRef} | Error</name>
<fsummary>Starts an SFTP client.</fsummary>
<type>
- <v>Host = string()</v>
- <v>ConnectionRef = connection_ref()</v>
- <v>Port = integer()</v>
- <v>TcpSocket = port()</v>
- <d>The socket is supposed to be from <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso> or <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso> with option <c>{active,false}</c></d>
- <v>Options = [{Option, Value}]</v>
+ <v>Host = <seealso marker="ssh:ssh#type-host">ssh:host()</seealso></v>
+ <v>Port = <seealso marker="kernel:inet#type-port_number">inet:port_number()</seealso></v>
+ <v>TcpSocket = <seealso marker="ssh:ssh#type-open_socket">ssh:open_socket()</seealso></v>
+ <v>Options = [ <seealso marker="#type-sftp_option">sftp_option()</seealso>
+ | <seealso marker="ssh:ssh#type-client_option">ssh:client_option()</seealso> ]</v>
+ <v>SftpOptions = [ <seealso marker="#type-sftp_option">sftp_option()</seealso> ]</v>
+ <v>ChannelPid = pid()</v>
+ <v>ConnectionRef = <seealso marker="ssh:ssh#type-connection_ref">ssh:connection_ref()</seealso></v>
+ <v>Error = {error, <seealso marker="#type-reason">reason()</seealso>}</v>
</type>
<desc>
<p>If no connection reference is provided, a connection is set
@@ -594,11 +490,8 @@
</func>
<func>
- <name since="">stop_channel(ChannelPid) -> ok</name>
+ <name since="" name="stop_channel" arity="1"/>
<fsummary>Stops the SFTP client channel.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- </type>
<desc>
<p>Stops an SFTP channel. Does not close the SSH connection.
Use <seealso marker="ssh#close-1">ssh:close/1</seealso> to close it.</p>
@@ -606,16 +499,9 @@
</func>
<func>
- <name since="">write(ChannelPid, Handle, Data) -></name>
- <name since="">write(ChannelPid, Handle, Data, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="write" arity="3"/>
+ <name since="" name="write" arity="4"/>
<fsummary>Writes to an open file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Handle = term()</v>
- <v>Position = integer()</v>
- <v>Data = iolist()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes <c><![CDATA[data]]></c> to the file referenced by <c><![CDATA[Handle]]></c>.
The file is to be opened with <c><![CDATA[write]]></c> or <c><![CDATA[append]]></c>
@@ -625,15 +511,9 @@
</func>
<func>
- <name since="">write_file(ChannelPid, File, Iolist) -></name>
- <name since="">write_file(ChannelPid, File, Iolist, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="write_file" arity="3"/>
+ <name since="" name="write_file" arity="4"/>
<fsummary>Writes a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>File = string()</v>
- <v>Iolist = iolist()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes a file to the server. The file is created if it does not exist
but overwritten if it exists.</p>
@@ -641,15 +521,9 @@
</func>
<func>
- <name since="">write_file_info(ChannelPid, Name, Info) -></name>
- <name since="">write_file_info(ChannelPid, Name, Info, Timeout) -> ok | {error, reason()}</name>
+ <name since="" name="write_file_info" arity="3"/>
+ <name since="" name="write_file_info" arity="4"/>
<fsummary>Writes information for a file.</fsummary>
- <type>
- <v>ChannelPid = pid()</v>
- <v>Name = string()</v>
- <v>Info = record()</v>
- <v>Timeout = timeout()</v>
- </type>
<desc>
<p>Writes file information from a <c><![CDATA[file_info]]></c> record to the
file specified by <c><![CDATA[Name]]></c>. See
diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml
index ee72784add..0d7b340399 100644
--- a/lib/ssh/doc/src/ssh_sftpd.xml
+++ b/lib/ssh/doc/src/ssh_sftpd.xml
@@ -35,36 +35,23 @@
<p>Specifies a channel process to handle an SFTP subsystem.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <taglist>
- <tag><c>subsystem_spec() =</c></tag>
- <item><p><c>{subsystem_name(), {channel_callback(), channel_init_args()}}</c></p></item>
- <tag><c>subsystem_name() =</c></tag>
- <item><p><c>"sftp"</c></p></item>
- <tag><c>channel_callback() =</c></tag>
- <item><p><c>atom()</c> - Name of the Erlang module implementing the subsystem using the
- <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (replaces ssh_daemon_channel) behaviour.</p></item>
- <tag><c>channel_init_args() =</c></tag>
- <item><p><c>list()</c> - The one given as argument to function <c>subsystem_spec/1</c>.</p></item>
- </taglist>
- </section>
<funcs>
<func>
- <name since="">subsystem_spec(Options) -> subsystem_spec()</name>
+ <name name="subsystem_spec" arity="1" since=""/>
<fsummary>Returns the subsystem specification that allows an SSH daemon to handle the subsystem "sftp".</fsummary>
- <type>
- <v>Options = [{Option, Value}]</v>
- </type>
<desc>
<p>Is to be used together with <c>ssh:daemon/[1,2,3]</c></p>
+ <p>The <c>Name</c> is <c>"sftp"</c> and
+ <c>CbMod</c> is the name of the Erlang module implementing the subsystem using the
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (replaces ssh_daemon_channel) behaviour.
+ </p>
<p>Options:</p>
<taglist>
- <tag><c><![CDATA[{cwd, String}]]></c></tag>
+ <tag><c>cwd</c></tag>
<item>
<p>Sets the initial current working directory for the server.</p>
</item>
- <tag><c><![CDATA[{file_handler, CallbackModule}]]></c></tag>
+ <tag><c>file_handler</c></tag>
<item>
<p>Determines which module to call for accessing
the file server. The default value is <c>ssh_sftpd_file</c>, which uses the
@@ -72,13 +59,13 @@
APIs to access the standard OTP file server. This option can be used to plug in
other file servers.</p>
</item>
- <tag><c><![CDATA[{max_files, Integer}]]></c></tag>
+ <tag><c>max_files</c></tag>
<item>
<p>The default value is <c>0</c>, which means that there is no upper limit.
If supplied, the number of filenames returned to the SFTP client per <c>READDIR</c>
request is limited to at most the given value.</p>
</item>
- <tag><c><![CDATA[{root, String}]]></c></tag>
+ <tag><c>root</c></tag>
<item>
<p>Sets the SFTP root directory. Then the user cannot see any files
above this root. If, for example, the root directory is set to <c>/tmp</c>,
@@ -86,7 +73,7 @@
<c>cd /etc</c>, the user moves to <c>/tmp/etc</c>.
</p>
</item>
- <tag><c><![CDATA[{sftpd_vsn, integer()}]]></c></tag>
+ <tag><c>sftpd_vsn</c></tag>
<item>
<p>Sets the SFTP version to use. Defaults to 5. Version 6 is under
development and limited.</p>
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index 4455d5ecc5..5c56dee81d 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -232,9 +232,10 @@
</section>
<section>
- <title>SFTP Client with TAR Compression and Encryption</title>
-
- <p>Example of writing and then reading a tar file follows:</p>
+ <title>SFTP Client with TAR Compression</title>
+ <section>
+ <title>Basic example</title>
+ <p>This is an example of writing and then reading a tar file:</p>
<code type="erl">
{ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]),
ok = erl_tar:add(HandleWrite, .... ),
@@ -248,8 +249,12 @@
{ok,NameValueList} = erl_tar:extract(HandleRead,[memory]),
ok = erl_tar:close(HandleRead),
</code>
+ </section>
- <p>The previous write and read example can be extended with encryption and decryption as follows:</p>
+ <section>
+ <title>Example with encryption</title>
+ <p>The previous <seealso marker="using_ssh#basic-example">Basic example</seealso>
+ can be extended with encryption and decryption as follows:</p>
<code type="erl">
%% First three parameters depending on which crypto type we select:
Key = &lt;&lt;"This is a 256 bit key. abcdefghi">>,
@@ -297,6 +302,7 @@ Cr = {InitFun,DecryptFun},
ok = erl_tar:close(HandleRead),
</code>
</section>
+ </section>
<section>
<marker id="usersguide_creating_a_subsystem"/>
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index ff5aee14d7..32f10c797d 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -66,6 +66,8 @@
cipher_alg/0,
mac_alg/0,
compression_alg/0,
+ host/0,
+ open_socket/0,
ip_port/0
]).
diff --git a/lib/ssh/src/ssh_client_channel.erl b/lib/ssh/src/ssh_client_channel.erl
index f985d8e273..3bd1e1fdf1 100644
--- a/lib/ssh/src/ssh_client_channel.erl
+++ b/lib/ssh/src/ssh_client_channel.erl
@@ -52,7 +52,7 @@
-callback handle_msg(Msg ::term(), State :: term()) ->
{ok, State::term()} | {stop, ChannelId::ssh:channel_id(), State::term()}.
--callback handle_ssh_msg({ssh_cm, ConnectionRef::ssh:connection_ref(), SshMsg::term()},
+-callback handle_ssh_msg(ssh_connection:event(),
State::term()) -> {ok, State::term()} |
{stop, ChannelId::ssh:channel_id(),
State::term()}.
diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl
index 9a060b8304..d6b50613f9 100644
--- a/lib/ssh/src/ssh_connect.hrl
+++ b/lib/ssh/src/ssh_connect.hrl
@@ -263,11 +263,8 @@
-record(connection, {
requests = [], %% [{ChannelId, Pid}...] awaiting reply on request,
channel_cache,
- port_bindings,
channel_id_seed,
cli_spec,
- address,
- port,
options,
exec,
system_supervisor,
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 83f85b1d8e..c5316bf133 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -60,13 +60,121 @@
request_failure_msg/0,
request_success_msg/1,
- bind/4, unbind/3, unbind_channel/2,
- bound_channel/3, encode_ip/1
+ encode_ip/1
]).
-type connection_ref() :: ssh:connection_ref().
-type channel_id() :: ssh:channel_id().
+-type req_status() :: success | failure .
+-type reason() :: closed | timeout .
+
+-type result() :: req_status() | {error, reason()} .
+
+-type ssh_data_type_code() :: non_neg_integer(). % Only 0 and 1 are used
+
+
+%%% The SSH Connection Protocol
+
+-export_type([event/0,
+ channel_msg/0,
+ want_reply/0,
+ data_ch_msg/0,
+ eof_ch_msg/0,
+ signal_ch_msg/0,
+ exit_signal_ch_msg/0,
+ exit_status_ch_msg/0,
+ closed_ch_msg/0,
+ env_ch_msg/0,
+ pty_ch_msg/0,
+ shell_ch_msg/0,
+ window_change_ch_msg/0,
+ exec_ch_msg/0
+ ]).
+
+-type event() :: {ssh_cm, ssh:connection_ref(), channel_msg()}.
+-type channel_msg() :: data_ch_msg()
+ | eof_ch_msg()
+ | closed_ch_msg()
+ | pty_ch_msg()
+ | env_ch_msg()
+ | shell_ch_msg()
+ | exec_ch_msg()
+ | signal_ch_msg()
+ | window_change_ch_msg()
+ | exit_status_ch_msg()
+ | exit_signal_ch_msg()
+ .
+
+-type want_reply() :: boolean().
+
+-type data_ch_msg() :: {data,
+ ssh:channel_id(),
+ ssh_data_type_code(),
+ Data :: binary()
+ } .
+-type eof_ch_msg() :: {eof,
+ ssh:channel_id()
+ } .
+-type signal_ch_msg() :: {signal,
+ ssh:channel_id(),
+ SignalName :: string()
+ } .
+-type exit_signal_ch_msg() :: {exit_signal, ssh:channel_id(),
+ ExitSignal :: string(),
+ ErrorMsg :: string(),
+ LanguageString :: string()} .
+-type exit_status_ch_msg() :: {exit_status,
+ ssh:channel_id(),
+ ExitStatus :: non_neg_integer()
+ } .
+-type closed_ch_msg() :: {closed,
+ ssh:channel_id()
+ } .
+-type env_ch_msg() :: {env,
+ ssh:channel_id(),
+ want_reply(),
+ Var :: string(),
+ Value :: string()
+ } .
+-type pty_ch_msg() :: {pty,
+ ssh:channel_id(),
+ want_reply(),
+ {Terminal :: string(),
+ CharWidth :: non_neg_integer(),
+ RowHeight :: non_neg_integer(),
+ PixelWidth :: non_neg_integer(),
+ PixelHeight :: non_neg_integer(),
+ TerminalModes :: [term_mode()]
+ }
+ } .
+
+-type term_mode() :: {Opcode :: atom() | byte(),
+ Value :: non_neg_integer()} .
+
+-type shell_ch_msg() :: {shell,
+ ssh:channel_id(),
+ want_reply()
+ } .
+-type window_change_ch_msg() :: {window_change,
+ ssh:channel_id(),
+ CharWidth :: non_neg_integer(),
+ RowHeight :: non_neg_integer(),
+ PixelWidth :: non_neg_integer(),
+ PixelHeight :: non_neg_integer()
+ } .
+-type exec_ch_msg() :: {exec,
+ ssh:channel_id(),
+ want_reply(),
+ Command :: string()
+ } .
+
+%%% This function is soley to convince all
+%%% checks that the type event() exists...
+-export([dummy/1]).
+-spec dummy(event()) -> false.
+dummy(_) -> false.
+
%%--------------------------------------------------------------------
%%% API
%%--------------------------------------------------------------------
@@ -77,14 +185,21 @@
%% application, a system command, or some built-in subsystem.
%% --------------------------------------------------------------------
--spec session_channel(connection_ref(), timeout()) ->
- {ok, channel_id()} | {error, timeout | closed}.
+-spec session_channel(ConnectionRef, Timeout) -> Result when
+ ConnectionRef :: ssh:connection_ref(),
+ Timeout :: timeout(),
+ Result :: {ok, ssh:channel_id()} | {error, reason()} .
session_channel(ConnectionHandler, Timeout) ->
session_channel(ConnectionHandler, ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE, Timeout).
--spec session_channel(connection_ref(), integer(), integer(), timeout()) ->
- {ok, channel_id()} | {error, timeout | closed}.
+
+-spec session_channel(ConnectionRef, InitialWindowSize, MaxPacketSize, Timeout) -> Result when
+ ConnectionRef :: ssh:connection_ref(),
+ InitialWindowSize :: pos_integer(),
+ MaxPacketSize :: pos_integer(),
+ Timeout :: timeout(),
+ Result :: {ok, ssh:channel_id()} | {error, reason()} .
session_channel(ConnectionHandler, InitialWindowSize, MaxPacketSize, Timeout) ->
case ssh_connection_handler:open_channel(ConnectionHandler, "session", <<>>,
@@ -100,8 +215,11 @@ session_channel(ConnectionHandler, InitialWindowSize, MaxPacketSize, Timeout) ->
%% Description: Will request that the server start the
%% execution of the given command.
%%--------------------------------------------------------------------
--spec exec(connection_ref(), channel_id(), string(), timeout()) ->
- success | failure | {error, timeout | closed}.
+-spec exec(ConnectionRef, ChannelId, Command, Timeout) -> result() when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ Command :: string(),
+ Timeout :: timeout().
exec(ConnectionHandler, ChannelId, Command, TimeOut) ->
ssh_connection_handler:request(ConnectionHandler, self(), ChannelId, "exec",
@@ -112,8 +230,10 @@ exec(ConnectionHandler, ChannelId, Command, TimeOut) ->
%% defined in /etc/passwd in UNIX systems) be started at the other
%% end.
%%--------------------------------------------------------------------
--spec shell(connection_ref(), channel_id()) ->
- ok | success | failure | {error, timeout}.
+-spec shell(ConnectionRef, ChannelId) -> Result when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ Result :: ok | success | failure | {error, timeout} .
shell(ConnectionHandler, ChannelId) ->
ssh_connection_handler:request(ConnectionHandler, self(), ChannelId,
@@ -122,8 +242,11 @@ shell(ConnectionHandler, ChannelId) ->
%%
%% Description: Executes a predefined subsystem.
%%--------------------------------------------------------------------
--spec subsystem(connection_ref(), channel_id(), string(), timeout()) ->
- success | failure | {error, timeout | closed}.
+-spec subsystem(ConnectionRef, ChannelId, Subsystem, Timeout) -> result() when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ Subsystem :: string(),
+ Timeout :: timeout().
subsystem(ConnectionHandler, ChannelId, SubSystem, TimeOut) ->
ssh_connection_handler:request(ConnectionHandler, self(),
@@ -134,12 +257,13 @@ subsystem(ConnectionHandler, ChannelId, SubSystem, TimeOut) ->
%%--------------------------------------------------------------------
-spec send(connection_ref(), channel_id(), iodata()) ->
ok | {error, timeout | closed}.
+
send(ConnectionHandler, ChannelId, Data) ->
send(ConnectionHandler, ChannelId, 0, Data, infinity).
--spec send(connection_ref(), channel_id(), integer()| iodata(), timeout() | iodata()) ->
- ok | {error, timeout | closed}.
+-spec send(connection_ref(), channel_id(), iodata(), timeout()) -> ok | {error, reason()};
+ (connection_ref(), channel_id(), ssh_data_type_code(), iodata()) -> ok | {error, reason()}.
send(ConnectionHandler, ChannelId, Data, TimeOut) when is_integer(TimeOut) ->
send(ConnectionHandler, ChannelId, 0, Data, TimeOut);
@@ -151,14 +275,15 @@ send(ConnectionHandler, ChannelId, Type, Data) ->
send(ConnectionHandler, ChannelId, Type, Data, infinity).
--spec send(connection_ref(), channel_id(), integer(), iodata(), timeout()) ->
- ok | {error, timeout | closed}.
+-spec send(connection_ref(), channel_id(), ssh_data_type_code(), iodata(), timeout()) -> ok | {error, reason()}.
send(ConnectionHandler, ChannelId, Type, Data, TimeOut) ->
ssh_connection_handler:send(ConnectionHandler, ChannelId,
Type, Data, TimeOut).
%%--------------------------------------------------------------------
--spec send_eof(connection_ref(), channel_id()) -> ok | {error, closed}.
+-spec send_eof(ConnectionRef, ChannelId) -> ok | {error, closed} when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id().
%%
%%
%% Description: Sends eof on the channel <ChannelId>.
@@ -167,7 +292,10 @@ send_eof(ConnectionHandler, Channel) ->
ssh_connection_handler:send_eof(ConnectionHandler, Channel).
%%--------------------------------------------------------------------
--spec adjust_window(connection_ref(), channel_id(), integer()) -> ok.
+-spec adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ NumOfBytes :: integer().
%%
%%
%% Description: Adjusts the ssh flowcontrol window.
@@ -176,8 +304,12 @@ adjust_window(ConnectionHandler, Channel, Bytes) ->
ssh_connection_handler:adjust_window(ConnectionHandler, Channel, Bytes).
%%--------------------------------------------------------------------
--spec setenv(connection_ref(), channel_id(), string(), string(), timeout()) ->
- success | failure | {error, timeout | closed}.
+-spec setenv(ConnectionRef, ChannelId, Var, Value, Timeout) -> result() when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ Var :: string(),
+ Value :: string(),
+ Timeout :: timeout().
%%
%%
%% Description: Environment variables may be passed to the shell/command to be
@@ -189,7 +321,9 @@ setenv(ConnectionHandler, ChannelId, Var, Value, TimeOut) ->
%%--------------------------------------------------------------------
--spec close(connection_ref(), channel_id()) -> ok.
+-spec close(ConnectionRef, ChannelId) -> ok when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id().
%%
%%
%% Description: Sends a close message on the channel <ChannelId>.
@@ -198,7 +332,11 @@ close(ConnectionHandler, ChannelId) ->
ssh_connection_handler:close(ConnectionHandler, ChannelId).
%%--------------------------------------------------------------------
--spec reply_request(connection_ref(), boolean(), success | failure, channel_id()) -> ok.
+-spec reply_request(ConnectionRef, WantReply, Status, ChannelId) -> ok when
+ ConnectionRef :: ssh:connection_ref(),
+ WantReply :: boolean(),
+ Status :: req_status(),
+ ChannelId :: ssh:channel_id().
%%
%%
%% Description: Send status replies to requests that want such replies.
@@ -211,15 +349,20 @@ reply_request(_,false, _, _) ->
%%--------------------------------------------------------------------
%% Description: Sends a ssh connection protocol pty_req.
%%--------------------------------------------------------------------
--spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist()) ->
- success | failure | {error, timeout}.
+-spec ptty_alloc(ConnectionRef, ChannelId, Options) -> result() when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ Options :: proplists:proplist().
ptty_alloc(ConnectionHandler, Channel, Options) ->
ptty_alloc(ConnectionHandler, Channel, Options, infinity).
--spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist(), timeout()) ->
- success | failure | {error, timeout | closed}.
+-spec ptty_alloc(ConnectionRef, ChannelId, Options, Timeout) -> result() when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ Options :: proplists:proplist(),
+ Timeout :: timeout().
ptty_alloc(ConnectionHandler, Channel, Options0, TimeOut) ->
TermData = backwards_compatible(Options0, []), % FIXME
@@ -252,6 +395,10 @@ signal(ConnectionHandler, Channel, Sig) ->
"signal", false, [?string(Sig)], 0).
+-spec exit_status(ConnectionRef, ChannelId, Status) -> ok when
+ ConnectionRef :: ssh:connection_ref(),
+ ChannelId :: ssh:channel_id(),
+ Status :: integer().
exit_status(ConnectionHandler, Channel, Status) ->
ssh_connection_handler:request(ConnectionHandler, Channel,
"exit-status", false, [?uint32(Status)], 0).
@@ -713,29 +860,6 @@ request_success_msg(Data) ->
%%%----------------------------------------------------------------
%%%
%%%
-bind(IP, Port, ChannelPid, Connection) ->
- Binds = [{{IP, Port}, ChannelPid}
- | lists:keydelete({IP, Port}, 1,
- Connection#connection.port_bindings)],
- Connection#connection{port_bindings = Binds}.
-
-unbind(IP, Port, Connection) ->
- Connection#connection{
- port_bindings =
- lists:keydelete({IP, Port}, 1,
- Connection#connection.port_bindings)}.
-unbind_channel(ChannelPid, Connection) ->
- Binds = [{Bind, ChannelP} || {Bind, ChannelP}
- <- Connection#connection.port_bindings,
- ChannelP =/= ChannelPid],
- Connection#connection{port_bindings = Binds}.
-
-bound_channel(IP, Port, Connection) ->
- case lists:keysearch({IP, Port}, 1, Connection#connection.port_bindings) of
- {value, {{IP, Port}, ChannelPid}} -> ChannelPid;
- _ -> undefined
- end.
-
encode_ip(Addr) when is_tuple(Addr) ->
case catch inet_parse:ntoa(Addr) of
{'EXIT',_} -> false;
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 8f32966a12..e984cbb21b 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -386,16 +386,24 @@ init_connection_handler(Role, Socket, Opts) ->
D);
{stop, Error} ->
- Sups = ?GET_INTERNAL_OPT(supervisors, Opts),
- C = #connection{system_supervisor = proplists:get_value(system_sup, Sups),
- sub_system_supervisor = proplists:get_value(subsystem_sup, Sups),
- connection_supervisor = proplists:get_value(connection_sup, Sups)
- },
+ D = try
+ %% Only servers have supervisorts defined in Opts
+ Sups = ?GET_INTERNAL_OPT(supervisors, Opts),
+ #connection{system_supervisor = proplists:get_value(system_sup, Sups),
+ sub_system_supervisor = proplists:get_value(subsystem_sup, Sups),
+ connection_supervisor = proplists:get_value(connection_sup, Sups)
+ }
+ of
+ C ->
+ #data{connection_state=C}
+ catch
+ _:_ ->
+ #data{connection_state=#connection{}}
+ end,
gen_statem:enter_loop(?MODULE,
[],
{init_error,Error},
- #data{connection_state=C,
- socket=Socket})
+ D#data{socket=Socket})
end.
@@ -406,7 +414,6 @@ init([Role,Socket,Opts]) ->
{Protocol, Callback, CloseTag} = ?GET_OPT(transport, Opts),
C = #connection{channel_cache = ssh_client_channel:cache_create(),
channel_id_seed = 0,
- port_bindings = [],
requests = [],
options = Opts},
D0 = #data{starter = ?GET_INTERNAL_OPT(user_pid, Opts),
@@ -1550,7 +1557,7 @@ terminate({shutdown,"Connection closed"}, _StateName, D) ->
terminate({shutdown,{init,Reason}}, StateName, D) ->
%% Error in initiation. "This error should not occur".
- log(error, D, io_lib:format("Shutdown in init (StateName=~p): ~p~n",[StateName,Reason])),
+ log(error, D, "Shutdown in init (StateName=~p): ~p~n", [StateName,Reason]),
stop_subsystem(D),
close_transport(D);
@@ -1952,12 +1959,12 @@ send_disconnect(Code, Reason, DetailedText, Module, Line, StateName, D0) ->
call_disconnectfun_and_log_cond(LogMsg, DetailedText, Module, Line, StateName, D) ->
case disconnect_fun(LogMsg, D) of
void ->
- log(info, D,
- io_lib:format("~s~n"
- "State = ~p~n"
- "Module = ~p, Line = ~p.~n"
- "Details:~n ~s~n",
- [LogMsg, StateName, Module, Line, DetailedText]));
+ log(info, D,
+ "~s~n"
+ "State = ~p~n"
+ "Module = ~p, Line = ~p.~n"
+ "Details:~n ~s~n",
+ [LogMsg, StateName, Module, Line, DetailedText]);
_ ->
ok
end.
@@ -2021,6 +2028,9 @@ fold_keys(Keys, Fun, Extra) ->
end, [], Keys).
%%%----------------------------------------------------------------
+log(Tag, D, Format, Args) ->
+ log(Tag, D, io_lib:format(Format,Args)).
+
log(Tag, D, Reason) ->
case atom_to_list(Tag) of % Dialyzer-technical reasons...
"error" -> do_log(error_msg, Reason, D);
@@ -2028,36 +2038,56 @@ log(Tag, D, Reason) ->
"info" -> do_log(info_msg, Reason, D)
end.
-do_log(F, Reason, #data{ssh_params = #ssh{role = Role} = S
- }) ->
- VSN =
- case application:get_key(ssh,vsn) of
- {ok,Vsn} -> Vsn;
- undefined -> ""
- end,
- PeerVersion =
- case Role of
- server -> S#ssh.c_version;
- client -> S#ssh.s_version
- end,
- CryptoInfo =
- try
- [{_,_,CI}] = crypto:info_lib(),
- <<"(",CI/binary,")">>
+
+do_log(F, Reason0, #data{ssh_params = S}) ->
+ Reason =
+ try io_lib:format("~s",[Reason0])
+ of _ -> Reason0
catch
- _:_ -> ""
- end,
- Other =
- case Role of
- server -> "Client";
- client -> "Server"
+ _:_ -> io_lib:format("~p",[Reason0])
end,
- error_logger:F("Erlang SSH ~p ~s ~s.~n"
- "~s: ~p~n"
- "~s~n",
- [Role, VSN, CryptoInfo,
- Other, PeerVersion,
- Reason]).
+ case S of
+ #ssh{role = Role} when Role==server ;
+ Role==client ->
+ {PeerRole,PeerVersion} =
+ case Role of
+ server -> {"Client", S#ssh.c_version};
+ client -> {"Server", S#ssh.s_version}
+ end,
+ error_logger:F("Erlang SSH ~p ~s ~s.~n"
+ "~s: ~p~n"
+ "~s~n",
+ [Role,
+ ssh_log_version(), crypto_log_info(),
+ PeerRole, PeerVersion,
+ Reason]);
+ _ ->
+ error_logger:F("Erlang SSH ~s ~s.~n"
+ "~s~n",
+ [ssh_log_version(), crypto_log_info(),
+ Reason])
+ end.
+
+crypto_log_info() ->
+ try
+ [{_,_,CI}] = crypto:info_lib(),
+ case crypto:info_fips() of
+ enabled ->
+ <<"(",CI/binary,". FIPS enabled)">>;
+ not_enabled ->
+ <<"(",CI/binary,". FIPS available but not enabled)">>;
+ _ ->
+ <<"(",CI/binary,")">>
+ end
+ catch
+ _:_ -> ""
+ end.
+
+ssh_log_version() ->
+ case application:get_key(ssh,vsn) of
+ {ok,Vsn} -> Vsn;
+ undefined -> ""
+ end.
%%%----------------------------------------------------------------
not_connected_filter({connection_reply, _Data}) -> true;
diff --git a/lib/ssh/src/ssh_server_channel.erl b/lib/ssh/src/ssh_server_channel.erl
index 555080e9ee..1905c40c98 100644
--- a/lib/ssh/src/ssh_server_channel.erl
+++ b/lib/ssh/src/ssh_server_channel.erl
@@ -37,7 +37,7 @@
-callback handle_msg(Msg ::term(), State :: term()) ->
{ok, State::term()} | {stop, ChannelId::ssh:channel_id(), State::term()}.
--callback handle_ssh_msg({ssh_cm, ConnectionRef::ssh:connection_ref(), SshMsg::term()},
+-callback handle_ssh_msg(ssh_connection:event(),
State::term()) -> {ok, State::term()} |
{stop, ChannelId::ssh:channel_id(),
State::term()}.
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index 1b2ba5a50b..4b6e187c3a 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -92,24 +92,63 @@
-define(XF(S), S#state.xf).
-define(REQID(S), S#state.req_id).
+-type sftp_option() :: {timeout, timeout()}
+ | {sftp_vsn, pos_integer()}
+ | {window_size, pos_integer()}
+ | {packet_size, pos_integer()} .
+
+-type reason() :: atom() | string() | tuple() .
+
%%====================================================================
%% API
%%====================================================================
+
+
+%%%================================================================
+%%%
+
+%%%----------------------------------------------------------------
+%%% start_channel/1
+
start_channel(Cm) when is_pid(Cm) ->
start_channel(Cm, []);
+
start_channel(Socket) when is_port(Socket) ->
start_channel(Socket, []);
-start_channel(Host) when is_list(Host) ->
+
+start_channel(Host) ->
start_channel(Host, []).
+
+%%%----------------------------------------------------------------
+%%% start_channel/2
+
+%%% -spec:s are as if Dialyzer handled signatures for separate
+%%% function clauses.
+
+-spec start_channel(ssh:open_socket(),
+ [ssh:client_options() | sftp_option()]
+ )
+ -> {ok,pid(),ssh:connection_ref()} | {error,reason()};
+
+ (ssh:connection_ref(),
+ [sftp_option()]
+ )
+ -> {ok,pid()} | {ok,pid(),ssh:connection_ref()} | {error,reason()};
+
+ (ssh:host(),
+ [ssh:client_options() | sftp_option()]
+ )
+ -> {ok,pid(),ssh:connection_ref()} | {error,reason()} .
+
start_channel(Socket, UserOptions) when is_port(Socket) ->
- {SshOpts, _ChanOpts, SftpOpts} = handle_options(UserOptions),
+ {SshOpts, ChanOpts, SftpOpts} = handle_options(UserOptions),
Timeout = % A mixture of ssh:connect and ssh_sftp:start_channel:
proplists:get_value(connect_timeout, SshOpts,
proplists:get_value(timeout, SftpOpts, infinity)),
case ssh:connect(Socket, SshOpts, Timeout) of
{ok,Cm} ->
- case start_channel(Cm, UserOptions) of
+ case start_channel(Cm, ChanOpts ++ SftpOpts) of
{ok, Pid} ->
{ok, Pid, Cm};
Error ->
@@ -144,6 +183,16 @@ start_channel(Cm, UserOptions) when is_pid(Cm) ->
start_channel(Host, UserOptions) ->
start_channel(Host, 22, UserOptions).
+
+%%%----------------------------------------------------------------
+%%% start_channel/3
+
+-spec start_channel(ssh:host(),
+ inet:port_number(),
+ [ssh:client_option() | sftp_option()]
+ )
+ -> {ok,pid(),ssh:connection_ref()} | {error,reason()}.
+
start_channel(Host, Port, UserOptions) ->
{SshOpts, ChanOpts, SftpOpts} = handle_options(UserOptions),
Timeout = % A mixture of ssh:connect and ssh_sftp:start_channel:
@@ -168,6 +217,15 @@ start_channel(Host, Port, UserOptions) ->
Error
end.
+%%% Helper for start_channel
+
+wait_for_version_negotiation(Pid, Timeout) ->
+ call(Pid, wait_for_version_negotiation, Timeout).
+
+%%%----------------------------------------------------------------
+-spec stop_channel(ChannelPid) -> ok when
+ ChannelPid :: pid().
+
stop_channel(Pid) ->
case is_process_alive(Pid) of
true ->
@@ -185,20 +243,63 @@ stop_channel(Pid) ->
ok
end.
-wait_for_version_negotiation(Pid, Timeout) ->
- call(Pid, wait_for_version_negotiation, Timeout).
-
+%%%----------------------------------------------------------------
+-spec open(ChannelPid, Name, Mode) -> {ok, Handle} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Mode :: [read | write | append | binary | raw],
+ Handle :: term(),
+ Error :: {error, reason()} .
open(Pid, File, Mode) ->
open(Pid, File, Mode, ?FILEOP_TIMEOUT).
+-spec open(ChannelPid, Name, Mode, Timeout) -> {ok, Handle} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Mode :: [read | write | append | binary | raw],
+ Timeout :: timeout(),
+ Handle :: term(),
+ Error :: {error, reason()} .
open(Pid, File, Mode, FileOpTimeout) ->
call(Pid, {open, false, File, Mode}, FileOpTimeout).
+
+-type tar_crypto_spec() :: encrypt_spec() | decrypt_spec() .
+
+-type encrypt_spec() :: {init_fun(), crypto_fun(), final_fun()} .
+-type decrypt_spec() :: {init_fun(), crypto_fun()} .
+
+-type init_fun() :: fun(() -> {ok,crypto_state()})
+ | fun(() -> {ok,crypto_state(),chunk_size()}) .
+
+-type crypto_fun() :: fun((TextIn::binary(), crypto_state()) -> crypto_result()) .
+-type crypto_result() :: {ok,TextOut::binary(),crypto_state()}
+ | {ok,TextOut::binary(),crypto_state(),chunk_size()} .
+
+-type final_fun() :: fun((FinalTextIn::binary(),crypto_state()) -> {ok,FinalTextOut::binary()}) .
+
+-type chunk_size() :: undefined | pos_integer().
+-type crypto_state() :: any() .
+
+
+-spec open_tar(ChannelPid, Path, Mode) -> {ok, Handle} | Error when
+ ChannelPid :: pid(),
+ Path :: string(),
+ Mode :: [read | write | {crypto, tar_crypto_spec()} ],
+ Handle :: term(),
+ Error :: {error, reason()} .
open_tar(Pid, File, Mode) ->
open_tar(Pid, File, Mode, ?FILEOP_TIMEOUT).
+-spec open_tar(ChannelPid, Path, Mode, Timeout) -> {ok, Handle} | Error when
+ ChannelPid :: pid(),
+ Path :: string(),
+ Mode :: [read | write | {crypto, tar_crypto_spec()} ],
+ Timeout :: timeout(),
+ Handle :: term(),
+ Error :: {error, reason()} .
open_tar(Pid, File, Mode, FileOpTimeout) ->
case {lists:member(write,Mode),
lists:member(read,Mode),
- Mode -- [read,write]} of
+ Mode -- [write,read]} of
{true,false,[]} ->
{ok,Handle} = open(Pid, File, [write], FileOpTimeout),
erl_tar:init(Pid, write,
@@ -264,13 +365,33 @@ open_tar(Pid, File, Mode, FileOpTimeout) ->
end.
+-spec opendir(ChannelPid, Path) -> {ok, Handle} | Error when
+ ChannelPid :: pid(),
+ Path :: string(),
+ Handle :: term(),
+ Error :: {error, reason()} .
opendir(Pid, Path) ->
opendir(Pid, Path, ?FILEOP_TIMEOUT).
+-spec opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | Error when
+ ChannelPid :: pid(),
+ Path :: string(),
+ Timeout :: timeout(),
+ Handle :: term(),
+ Error :: {error, reason()} .
opendir(Pid, Path, FileOpTimeout) ->
call(Pid, {opendir, false, Path}, FileOpTimeout).
+-spec close(ChannelPid, Handle) -> ok | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Error :: {error, reason()} .
close(Pid, Handle) ->
close(Pid, Handle, ?FILEOP_TIMEOUT).
+-spec close(ChannelPid, Handle, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Timeout :: timeout(),
+ Error :: {error, reason()} .
close(Pid, Handle, FileOpTimeout) ->
call(Pid, {close,false,Handle}, FileOpTimeout).
@@ -279,47 +400,149 @@ readdir(Pid,Handle) ->
readdir(Pid,Handle, FileOpTimeout) ->
call(Pid, {readdir,false,Handle}, FileOpTimeout).
+-spec pread(ChannelPid, Handle, Position, Len) -> {ok, Data} | eof | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Position :: integer(),
+ Len :: integer(),
+ Data :: string() | binary(),
+ Error :: {error, reason()}.
pread(Pid, Handle, Offset, Len) ->
pread(Pid, Handle, Offset, Len, ?FILEOP_TIMEOUT).
+
+-spec pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Position :: integer(),
+ Len :: integer(),
+ Timeout :: timeout(),
+ Data :: string() | binary(),
+ Error :: {error, reason()}.
pread(Pid, Handle, Offset, Len, FileOpTimeout) ->
call(Pid, {pread,false,Handle, Offset, Len}, FileOpTimeout).
+
+-spec read(ChannelPid, Handle, Len) -> {ok, Data} | eof | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Len :: integer(),
+ Data :: string() | binary(),
+ Error :: {error, reason()}.
read(Pid, Handle, Len) ->
read(Pid, Handle, Len, ?FILEOP_TIMEOUT).
+
+-spec read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Len :: integer(),
+ Timeout :: timeout(),
+ Data :: string() | binary(),
+ Error :: {error, reason()}.
read(Pid, Handle, Len, FileOpTimeout) ->
call(Pid, {read,false,Handle, Len}, FileOpTimeout).
+
%% TODO this ought to be a cast! Is so in all practical meaning
%% even if it is obscure!
+-spec apread(ChannelPid, Handle, Position, Len) -> {async, N} | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Position :: integer(),
+ Len :: integer(),
+ Error :: {error, reason()},
+ N :: term() .
apread(Pid, Handle, Offset, Len) ->
call(Pid, {pread,true,Handle, Offset, Len}, infinity).
%% TODO this ought to be a cast!
+-spec aread(ChannelPid, Handle, Len) -> {async, N} | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Len :: integer(),
+ Error :: {error, reason()},
+ N :: term() .
aread(Pid, Handle, Len) ->
call(Pid, {read,true,Handle, Len}, infinity).
+
+-spec pwrite(ChannelPid, Handle, Position, Data) -> ok | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Position :: integer(),
+ Data :: iolist(),
+ Error :: {error, reason()}.
pwrite(Pid, Handle, Offset, Data) ->
pwrite(Pid, Handle, Offset, Data, ?FILEOP_TIMEOUT).
+
+-spec pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Position :: integer(),
+ Data :: iolist(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
pwrite(Pid, Handle, Offset, Data, FileOpTimeout) ->
call(Pid, {pwrite,false,Handle,Offset,Data}, FileOpTimeout).
+
+-spec write(ChannelPid, Handle, Data) -> ok | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Data :: iodata(),
+ Error :: {error, reason()}.
write(Pid, Handle, Data) ->
write(Pid, Handle, Data, ?FILEOP_TIMEOUT).
+
+-spec write(ChannelPid, Handle, Data, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Data :: iodata(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
write(Pid, Handle, Data, FileOpTimeout) ->
call(Pid, {write,false,Handle,Data}, FileOpTimeout).
%% TODO this ought to be a cast! Is so in all practical meaning
%% even if it is obscure!
+-spec apwrite(ChannelPid, Handle, Position, Data) -> {async, N} | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Position :: integer(),
+ Data :: binary(),
+ Error :: {error, reason()},
+ N :: term() .
apwrite(Pid, Handle, Offset, Data) ->
call(Pid, {pwrite,true,Handle,Offset,Data}, infinity).
%% TODO this ought to be a cast! Is so in all practical meaning
%% even if it is obscure!
+-spec awrite(ChannelPid, Handle, Data) -> {async, N} | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Data :: binary(),
+ Error :: {error, reason()},
+ N :: term() .
awrite(Pid, Handle, Data) ->
call(Pid, {write,true,Handle,Data}, infinity).
+-spec position(ChannelPid, Handle, Location) -> {ok, NewPosition} | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Location :: Offset | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof,
+ Offset :: integer(),
+ NewPosition :: integer(),
+ Error :: {error, reason()}.
position(Pid, Handle, Pos) ->
position(Pid, Handle, Pos, ?FILEOP_TIMEOUT).
+
+-spec position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition} | Error when
+ ChannelPid :: pid(),
+ Handle :: term(),
+ Location :: Offset | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof,
+ Timeout :: timeout(),
+ Offset :: integer(),
+ NewPosition :: integer(),
+ Error :: {error, reason()}.
position(Pid, Handle, Pos, FileOpTimeout) ->
call(Pid, {position, Handle, Pos}, FileOpTimeout).
@@ -328,8 +551,21 @@ real_path(Pid, Path) ->
real_path(Pid, Path, FileOpTimeout) ->
call(Pid, {real_path, false, Path}, FileOpTimeout).
+
+-spec read_file_info(ChannelPid, Name) -> {ok, FileInfo} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ FileInfo :: file:file_info(),
+ Error :: {error, reason()}.
read_file_info(Pid, Name) ->
read_file_info(Pid, Name, ?FILEOP_TIMEOUT).
+
+-spec read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Timeout :: timeout(),
+ FileInfo :: file:file_info(),
+ Error :: {error, reason()}.
read_file_info(Pid, Name, FileOpTimeout) ->
call(Pid, {read_file_info,false,Name}, FileOpTimeout).
@@ -338,18 +574,57 @@ get_file_info(Pid, Handle) ->
get_file_info(Pid, Handle, FileOpTimeout) ->
call(Pid, {get_file_info,false,Handle}, FileOpTimeout).
+
+-spec write_file_info(ChannelPid, Name, FileInfo) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ FileInfo :: file:file_info(),
+ Error :: {error, reason()}.
write_file_info(Pid, Name, Info) ->
write_file_info(Pid, Name, Info, ?FILEOP_TIMEOUT).
+
+-spec write_file_info(ChannelPid, Name, FileInfo, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ FileInfo :: file:file_info(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
write_file_info(Pid, Name, Info, FileOpTimeout) ->
call(Pid, {write_file_info,false,Name, Info}, FileOpTimeout).
+
+-spec read_link_info(ChannelPid, Name) -> {ok, FileInfo} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ FileInfo :: file:file_info(),
+ Error :: {error, reason()}.
read_link_info(Pid, Name) ->
read_link_info(Pid, Name, ?FILEOP_TIMEOUT).
+
+-spec read_link_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ FileInfo :: file:file_info(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
read_link_info(Pid, Name, FileOpTimeout) ->
call(Pid, {read_link_info,false,Name}, FileOpTimeout).
+
+-spec read_link(ChannelPid, Name) -> {ok, Target} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Target :: string(),
+ Error :: {error, reason()}.
read_link(Pid, LinkName) ->
read_link(Pid, LinkName, ?FILEOP_TIMEOUT).
+
+-spec read_link(ChannelPid, Name, Timeout) -> {ok, Target} | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Target :: string(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
read_link(Pid, LinkName, FileOpTimeout) ->
case call(Pid, {read_link,false,LinkName}, FileOpTimeout) of
{ok, [{Name, _Attrs}]} ->
@@ -358,28 +633,79 @@ read_link(Pid, LinkName, FileOpTimeout) ->
ErrMsg
end.
+-spec make_symlink(ChannelPid, Name, Target) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Target :: string(),
+ Error :: {error, reason()} .
make_symlink(Pid, Name, Target) ->
make_symlink(Pid, Name, Target, ?FILEOP_TIMEOUT).
+-spec make_symlink(ChannelPid, Name, Target, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Target :: string(),
+ Timeout :: timeout(),
+ Error :: {error, reason()} .
make_symlink(Pid, Name, Target, FileOpTimeout) ->
call(Pid, {make_symlink,false, Name, Target}, FileOpTimeout).
+
+-spec rename(ChannelPid, OldName, NewName) -> ok | Error when
+ ChannelPid :: pid(),
+ OldName :: string(),
+ NewName :: string(),
+ Error :: {error, reason()}.
rename(Pid, FromFile, ToFile) ->
rename(Pid, FromFile, ToFile, ?FILEOP_TIMEOUT).
+
+-spec rename(ChannelPid, OldName, NewName, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ OldName :: string(),
+ NewName :: string(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
rename(Pid, FromFile, ToFile, FileOpTimeout) ->
call(Pid, {rename,false,FromFile, ToFile}, FileOpTimeout).
+-spec delete(ChannelPid, Name) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Error :: {error, reason()} .
delete(Pid, Name) ->
delete(Pid, Name, ?FILEOP_TIMEOUT).
+-spec delete(ChannelPid, Name, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Timeout :: timeout(),
+ Error :: {error, reason()} .
delete(Pid, Name, FileOpTimeout) ->
call(Pid, {delete,false,Name}, FileOpTimeout).
+-spec make_dir(ChannelPid, Name) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Error :: {error, reason()} .
make_dir(Pid, Name) ->
make_dir(Pid, Name, ?FILEOP_TIMEOUT).
+-spec make_dir(ChannelPid, Name, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Timeout :: timeout(),
+ Error :: {error, reason()} .
make_dir(Pid, Name, FileOpTimeout) ->
call(Pid, {make_dir,false,Name}, FileOpTimeout).
+-spec del_dir(ChannelPid, Name) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Error :: {error, reason()} .
del_dir(Pid, Name) ->
del_dir(Pid, Name, ?FILEOP_TIMEOUT).
+-spec del_dir(ChannelPid, Name, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ Name :: string(),
+ Timeout :: timeout(),
+ Error :: {error, reason()} .
del_dir(Pid, Name, FileOpTimeout) ->
call(Pid, {del_dir,false,Name}, FileOpTimeout).
@@ -396,9 +722,21 @@ recv_window(Pid, FileOpTimeout) ->
call(Pid, recv_window, FileOpTimeout).
+-spec list_dir(ChannelPid, Path) -> {ok,FileNames} | Error when
+ ChannelPid :: pid(),
+ Path :: string(),
+ FileNames :: [FileName],
+ FileName :: string(),
+ Error :: {error, reason()} .
list_dir(Pid, Name) ->
list_dir(Pid, Name, ?FILEOP_TIMEOUT).
-
+-spec list_dir(ChannelPid, Path, Timeout) -> {ok,FileNames} | Error when
+ ChannelPid :: pid(),
+ Path :: string(),
+ Timeout :: timeout(),
+ FileNames :: [FileName],
+ FileName :: string(),
+ Error :: {error, reason()} .
list_dir(Pid, Name, FileOpTimeout) ->
case opendir(Pid, Name, FileOpTimeout) of
{ok,Handle} ->
@@ -429,9 +767,20 @@ do_list_dir(Pid, Handle, FileOpTimeout, Acc) ->
end.
+-spec read_file(ChannelPid, File) -> {ok, Data} | Error when
+ ChannelPid :: pid(),
+ File :: string(),
+ Data :: binary(),
+ Error :: {error, reason()}.
read_file(Pid, Name) ->
read_file(Pid, Name, ?FILEOP_TIMEOUT).
+-spec read_file(ChannelPid, File, Timeout) -> {ok, Data} | Error when
+ ChannelPid :: pid(),
+ File :: string(),
+ Data :: binary(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
read_file(Pid, Name, FileOpTimeout) ->
case open(Pid, Name, [read, binary], FileOpTimeout) of
{ok, Handle} ->
@@ -453,9 +802,20 @@ read_file_loop(Pid, Handle, PacketSz, FileOpTimeout, Acc) ->
Error
end.
+-spec write_file(ChannelPid, File, Data) -> ok | Error when
+ ChannelPid :: pid(),
+ File :: string(),
+ Data :: iodata(),
+ Error :: {error, reason()}.
write_file(Pid, Name, List) ->
write_file(Pid, Name, List, ?FILEOP_TIMEOUT).
+-spec write_file(ChannelPid, File, Data, Timeout) -> ok | Error when
+ ChannelPid :: pid(),
+ File :: string(),
+ Data :: iodata(),
+ Timeout :: timeout(),
+ Error :: {error, reason()}.
write_file(Pid, Name, List, FileOpTimeout) when is_list(List) ->
write_file(Pid, Name, list_to_binary(List), FileOpTimeout);
write_file(Pid, Name, Bin, FileOpTimeout) ->
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 5ec12e2d04..bf921f0ff3 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -58,7 +58,17 @@
%%====================================================================
%% API
%%====================================================================
--spec subsystem_spec(list()) -> subsystem_spec().
+-spec subsystem_spec(Options) -> Spec when
+ Options :: [ {cwd, string()} |
+ {file_handler, CallbackModule::string()} |
+ {max_files, integer()} |
+ {root, string()} |
+ {sftpd_vsn, integer()}
+ ],
+ Spec :: {Name, {CbMod,Options}},
+ Name :: string(),
+ CbMod :: atom() .
+
subsystem_spec(Options) ->
{"sftp", {?MODULE, Options}}.
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 3aa6e09c2c..05590666da 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -207,6 +207,10 @@
<datatype>
<name name="sign_scheme"/>
</datatype>
+
+ <datatype>
+ <name name="group"/>
+ </datatype>
<datatype>
<name name="kex_algo"/>
@@ -363,7 +367,20 @@
</p>
</desc>
</datatype>
-
+
+ <datatype>
+ <name name="supported_groups"/>
+ <desc>
+ <p>TLS 1.3 introduces the "supported_groups" extension that is used for negotiating
+ the Diffie-Hellman parameters in a TLS 1.3 handshake. Both client and server
+ can specify a list of parameters that they are willing to use.
+ </p>
+ <p> If it is not specified it will use a default list ([x25519, x448, secp256r1, secp384r1]) that
+ is filtered based on the installed crypto library version.
+ </p>
+ </desc>
+ </datatype>
+
<datatype>
<name name="secure_renegotiation"/>
<desc><p>Specifies if to reject renegotiation attempt that does
@@ -919,6 +936,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
<name name="dh_der"/>
<desc><p>The DER-encoded Diffie-Hellman parameters. If
specified, it overrides option <c>dhfile</c>.</p>
+ <warning><p>The <c>dh_der</c> option is not supported by TLS 1.3. Use the
+ <c>supported_groups</c> option instead.</p></warning>
</desc>
</datatype>
@@ -928,6 +947,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
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>
+ <warning><p>The <c>dh_file</c> option is not supported by TLS 1.3. Use the
+ <c>supported_groups</c> option instead.</p></warning>
</desc>
</datatype>
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index d8c0e30973..4a381745d4 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -255,7 +255,8 @@ enc_handshake(#client_hello{client_version = {Major, Minor},
CmLength = byte_size(BinCompMethods),
BinCipherSuites = list_to_binary(CipherSuites),
CsLength = byte_size(BinCipherSuites),
- ExtensionsBin = ssl_handshake:encode_hello_extensions(HelloExtensions),
+ ExtensionsBin = ssl_handshake:encode_hello_extensions(HelloExtensions,
+ dtls_v1:corresponding_tls_version({Major, Minor})),
{?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SIDLength), SessionID/binary,
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 20b1e85ceb..7ff9aed8ea 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -128,7 +128,8 @@
tls_alert/0,
srp_param_type/0,
named_curve/0,
- sign_scheme/0]).
+ sign_scheme/0,
+ group/0]).
%% -------------------------------------------------------------------------------------------------------
@@ -243,7 +244,7 @@
secp160r2. % exported
-type group() :: secp256r1 | secp384r1 | secp521r1 | ffdhe2048 |
- ffdhe3072 | ffdhe4096 | ffdhe6144 | ffdhe8192.
+ ffdhe3072 | ffdhe4096 | ffdhe6144 | ffdhe8192. % exported
-type srp_param_type() :: srp_1024 |
srp_1536 |
@@ -296,6 +297,7 @@
{ciphers, cipher_suites()} |
{eccs, [named_curve()]} |
{signature_algs_cert, signature_schemes()} |
+ {supported_groups, supported_groups()} |
{secure_renegotiate, secure_renegotiation()} |
{depth, allowed_cert_chain_length()} |
{verify_fun, custom_verify()} |
@@ -342,6 +344,7 @@
-type protocol_versions() :: [protocol_version()].
-type signature_algs() :: [{hash(), sign_algo()}].
-type signature_schemes() :: [sign_scheme()].
+-type supported_groups() :: [group()].
-type custom_user_lookup() :: {Lookupfun :: fun(), UserState :: any()}.
-type padding_check() :: boolean().
-type beast_mitigation() :: one_n_minus_one | zero_n | disabled.
@@ -979,7 +982,8 @@ cipher_suites(all) ->
%% Description: Returns all default and all supported cipher suites for a
%% TLS/DTLS version
%%--------------------------------------------------------------------
-cipher_suites(Base, Version) when Version == 'tlsv1.2';
+cipher_suites(Base, Version) when Version == 'tlsv1.3';
+ Version == 'tlsv1.2';
Version == 'tlsv1.1';
Version == tlsv1;
Version == sslv3 ->
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index f4a91cac52..c16e2331ff 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -38,7 +38,7 @@
cipher_init/3, nonce_seed/2, decipher/6, cipher/5, aead_encrypt/6, 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,
+ srp_suites/1, srp_suites_anon/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,
@@ -284,7 +284,7 @@ all_suites({3, _} = Version) ->
suites(Version)
++ chacha_suites(Version)
++ psk_suites(Version)
- ++ srp_suites()
+ ++ srp_suites(Version)
++ rc4_suites(Version)
++ des_suites(Version)
++ rsa_suites(Version);
@@ -313,8 +313,8 @@ chacha_suites(_) ->
%% Description: Returns a list of the anonymous cipher suites, only supported
%% if explicitly set by user. Intended only for testing.
%%--------------------------------------------------------------------
-anonymous_suites({3, N}) ->
- srp_suites_anon() ++ anonymous_suites(N);
+anonymous_suites({3, N} = Version) ->
+ srp_suites_anon(Version) ++ anonymous_suites(N);
anonymous_suites({254, _} = Version) ->
dtls_v1:anonymous_suites(Version);
anonymous_suites(4) ->
@@ -375,7 +375,7 @@ psk_suites(_) ->
%%--------------------------------------------------------------------
psk_suites_anon({3, N}) ->
psk_suites_anon(N);
-psk_suites_anon(3) ->
+psk_suites_anon(3 = N) ->
[
?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
?TLS_PSK_WITH_AES_256_GCM_SHA384,
@@ -401,8 +401,8 @@ psk_suites_anon(3) ->
?TLS_PSK_WITH_AES_128_CCM,
?TLS_PSK_WITH_AES_128_CCM_8,
?TLS_ECDHE_PSK_WITH_RC4_128_SHA
- ] ++ psk_suites_anon(0);
-psk_suites_anon(_) ->
+ ] ++ psk_suites_anon(N-1);
+psk_suites_anon(N) when N > 0 ->
[?TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
?TLS_PSK_WITH_AES_256_CBC_SHA,
?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
@@ -413,14 +413,18 @@ psk_suites_anon(_) ->
?TLS_PSK_WITH_3DES_EDE_CBC_SHA,
?TLS_ECDHE_PSK_WITH_RC4_128_SHA,
?TLS_DHE_PSK_WITH_RC4_128_SHA,
- ?TLS_PSK_WITH_RC4_128_SHA].
+ ?TLS_PSK_WITH_RC4_128_SHA];
+psk_suites_anon(0) ->
+ [].
%%--------------------------------------------------------------------
--spec srp_suites() -> [ssl_cipher_format:cipher_suite()].
+-spec srp_suites(tls_record:tls_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the SRP cipher suites, only supported
%% if explicitly set by user.
%%--------------------------------------------------------------------
-srp_suites() ->
+srp_suites({3,0}) ->
+ [];
+srp_suites(_) ->
[?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
@@ -429,12 +433,14 @@ srp_suites() ->
?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA].
%%--------------------------------------------------------------------
--spec srp_suites_anon() -> [ssl_cipher_format:cipher_suite()].
+-spec srp_suites_anon(tls_record:tls_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the SRP anonymous cipher suites, only supported
%% if explicitly set by user.
%%--------------------------------------------------------------------
-srp_suites_anon() ->
+srp_suites_anon({3,0}) ->
+ [];
+srp_suites_anon(_) ->
[?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
?TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
?TLS_SRP_SHA_WITH_AES_256_CBC_SHA].
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index de12de646c..2483509228 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1275,10 +1275,17 @@ 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{handshake_env = #handshake_env{negotiated_protocol = undefined}} = State, _) ->
+ #state{handshake_env = #handshake_env{alpn = undefined,
+ negotiated_protocol = undefined}} = State, _) ->
hibernate_after(?FUNCTION_NAME, State, [{reply, From, {error, protocol_not_negotiated}}]);
connection({call, From}, negotiated_protocol,
- #state{handshake_env = #handshake_env{negotiated_protocol = SelectedProtocol}} = State, _) ->
+ #state{handshake_env = #handshake_env{alpn = undefined,
+ negotiated_protocol = SelectedProtocol}} = State, _) ->
+ hibernate_after(?FUNCTION_NAME, State,
+ [{reply, From, {ok, SelectedProtocol}}]);
+connection({call, From}, negotiated_protocol,
+ #state{handshake_env = #handshake_env{alpn = SelectedProtocol,
+ negotiated_protocol = undefined}} = State, _) ->
hibernate_after(?FUNCTION_NAME, State,
[{reply, From, {ok, SelectedProtocol}}]);
connection({call, From}, Msg, State, Connection) ->
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index c6698bc74a..bd2efa9fbb 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -58,7 +58,7 @@
]).
%% Encode
--export([encode_handshake/2, encode_hello_extensions/1, encode_extensions/1, encode_extensions/2,
+-export([encode_handshake/2, encode_hello_extensions/2, encode_extensions/1, encode_extensions/2,
encode_client_protocol_negotiation/2, encode_protocols_advertised_on_server/1]).
%% Decode
-export([decode_handshake/3, decode_vector/1, decode_hello_extensions/4, decode_extensions/3,
@@ -534,14 +534,14 @@ encode_handshake(#next_protocol{selected_protocol = SelectedProtocol}, _Version)
PaddingLength = 32 - ((byte_size(SelectedProtocol) + 2) rem 32),
{?NEXT_PROTOCOL, <<?BYTE((byte_size(SelectedProtocol))), SelectedProtocol/binary,
?BYTE(PaddingLength), 0:(PaddingLength * 8)>>};
-encode_handshake(#server_hello{server_version = {Major, Minor},
+encode_handshake(#server_hello{server_version = {Major, Minor} = Version,
random = Random,
session_id = Session_ID,
cipher_suite = CipherSuite,
compression_method = Comp_method,
extensions = Extensions}, _Version) ->
SID_length = byte_size(Session_ID),
- ExtensionsBin = encode_hello_extensions(Extensions),
+ ExtensionsBin = encode_hello_extensions(Extensions, Version),
{?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID/binary,
CipherSuite/binary, ?BYTE(Comp_method), ExtensionsBin/binary>>};
@@ -589,7 +589,9 @@ encode_handshake(#certificate_verify{signature = BinSig, hashsign_algorithm = Ha
encode_handshake(#finished{verify_data = VerifyData}, _Version) ->
{?FINISHED, VerifyData}.
-encode_hello_extensions(Extensions) ->
+encode_hello_extensions(_, {3, 0}) ->
+ <<>>;
+encode_hello_extensions(Extensions, _) ->
encode_extensions(hello_extensions_list(Extensions), <<>>).
encode_extensions(Exts) ->
@@ -707,7 +709,25 @@ encode_extensions([#key_share_server_hello{server_share = ServerShare0} | Rest],
encode_extensions([#key_share_hello_retry_request{selected_group = Group0} | Rest], Acc) ->
Group = tls_v1:group_to_enum(Group0),
encode_extensions(Rest, <<?UINT16(?KEY_SHARE_EXT),
- ?UINT16(2), ?UINT16(Group), Acc/binary>>).
+ ?UINT16(2), ?UINT16(Group), Acc/binary>>);
+encode_extensions([#psk_key_exchange_modes{ke_modes = KEModes0} | Rest], Acc) ->
+ KEModes = encode_psk_key_exchange_modes(KEModes0),
+ KEModesLen = byte_size(KEModes),
+ ExtLen = KEModesLen + 1,
+ encode_extensions(Rest, <<?UINT16(?PSK_KEY_EXCHANGE_MODES_EXT),
+ ?UINT16(ExtLen), ?BYTE(KEModesLen), KEModes/binary, Acc/binary>>);
+encode_extensions([#pre_shared_key_client_hello{
+ offered_psks = #offered_psks{
+ identities = Identities0,
+ binders = Binders0} = PSKs} | Rest], Acc) ->
+ Identities = encode_psk_identities(Identities0),
+ Binders = encode_psk_binders(Binders0),
+ Len = byte_size(Identities) + byte_size(Binders),
+ encode_extensions(Rest, <<?UINT16(?PRE_SHARED_KEY_EXT),
+ ?UINT16(Len), Identities/binary, Binders/binary, Acc/binary>>);
+encode_extensions([#pre_shared_key_server_hello{selected_identity = Identity} | Rest], Acc) ->
+ encode_extensions(Rest, <<?UINT16(?PRE_SHARED_KEY_EXT),
+ ?UINT16(2), ?UINT16(Identity), Acc/binary>>).
encode_client_protocol_negotiation(undefined, _) ->
@@ -1256,6 +1276,8 @@ handle_server_hello_extensions(RecordCB, Random, CipherSuite, Compression,
%% We also ignore the ALPN extension during renegotiation (see encode_alpn/2).
[Protocol] when not Renegotiation ->
{ConnectionStates, alpn, Protocol};
+ [_] when Renegotiation ->
+ {ConnectionStates, alpn, undefined};
undefined ->
NextProtocolNegotiation = maps:get(next_protocol_negotiation, Exts, undefined),
Protocol = handle_next_protocol(NextProtocolNegotiation, NextProtoSelector, Renegotiation),
@@ -1486,8 +1508,12 @@ extension_value(#signature_algorithms_cert{signature_scheme_list = Schemes}) ->
Schemes;
extension_value(#key_share_client_hello{client_shares = ClientShares}) ->
ClientShares;
+extension_value(#key_share_server_hello{server_share = ServerShare}) ->
+ ServerShare;
extension_value(#client_hello_versions{versions = Versions}) ->
- Versions.
+ Versions;
+extension_value(#server_hello_selected_version{selected_version = SelectedVersion}) ->
+ SelectedVersion.
%%--------------------------------------------------------------------
@@ -2089,6 +2115,41 @@ encode_key_share_entry(#key_share_entry{
Len = byte_size(KeyExchange),
<<?UINT16((tls_v1:group_to_enum(Group))),?UINT16(Len),KeyExchange/binary>>.
+encode_psk_key_exchange_modes(KEModes) ->
+ encode_psk_key_exchange_modes(lists:reverse(KEModes), <<>>).
+%%
+encode_psk_key_exchange_modes([], Acc) ->
+ Acc;
+encode_psk_key_exchange_modes([psk_ke|T], Acc) ->
+ encode_psk_key_exchange_modes(T, <<?BYTE(?PSK_KE),Acc/binary>>);
+encode_psk_key_exchange_modes([psk_dhe_ke|T], Acc) ->
+ encode_psk_key_exchange_modes(T, <<?BYTE(?PSK_DHE_KE),Acc/binary>>).
+
+
+encode_psk_identities(Identities) ->
+ encode_psk_identities(Identities, <<>>).
+%%
+encode_psk_identities([], Acc) ->
+ Len = byte_size(Acc),
+ <<?UINT16(Len), Acc/binary>>;
+encode_psk_identities([#psk_identity{
+ identity = Identity,
+ obfuscated_ticket_age = Age}|T], Acc) ->
+ IdLen = byte_size(Identity),
+ encode_psk_identities(T, <<Acc/binary,?UINT16(IdLen),Identity/binary,Age/binary>>).
+
+
+encode_psk_binders(Binders) ->
+ encode_psk_binders(Binders, <<>>).
+%%
+encode_psk_binders([], Acc) ->
+ Len = byte_size(Acc),
+ <<?UINT16(Len), Acc/binary>>;
+encode_psk_binders([Binder|T], Acc) ->
+ Len = byte_size(Binder),
+ encode_psk_binders(T, <<Acc/binary,?BYTE(Len),Binder/binary>>).
+
+
hello_extensions_list(HelloExtensions) ->
[Ext || {_, Ext} <- maps:to_list(HelloExtensions), Ext =/= undefined].
@@ -2441,6 +2502,33 @@ decode_extensions(<<?UINT16(?KEY_SHARE_EXT), ?UINT16(Len),
#key_share_hello_retry_request{
selected_group = tls_v1:enum_to_group(Group)}});
+decode_extensions(<<?UINT16(?PSK_KEY_EXCHANGE_MODES_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
+ <<?BYTE(PLen),KEModes:PLen/binary>> = ExtData,
+ decode_extensions(Rest, Version, MessageType,
+ Acc#{psk_key_exchange_modes =>
+ #psk_key_exchange_modes{
+ ke_modes = decode_psk_key_exchange_modes(KEModes)}});
+
+decode_extensions(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>,
+ Version, MessageType = client_hello, Acc) ->
+ <<?UINT16(IdLen),Identities:IdLen/binary,?UINT16(BLen),Binders:BLen/binary>> = ExtData,
+ decode_extensions(Rest, Version, MessageType,
+ Acc#{pre_shared_key =>
+ #pre_shared_key_client_hello{
+ offered_psks = #offered_psks{
+ identities = decode_psk_identities(Identities),
+ binders = decode_psk_binders(Binders)}}});
+
+decode_extensions(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>,
+ Version, MessageType = server_hello, Acc) ->
+ <<?UINT16(Identity)>> = ExtData,
+ decode_extensions(Rest, Version, MessageType,
+ Acc#{pre_shared_key =>
+ #pre_shared_key_server_hello{
+ selected_identity = Identity}});
%% Ignore data following the ClientHello (i.e.,
%% extensions) if not understood.
@@ -2500,6 +2588,38 @@ decode_protocols(<<?BYTE(Len), Protocol:Len/binary, Rest/binary>>, Acc) ->
decode_protocols(_Bytes, _Acc) ->
{error, invalid_protocols}.
+
+decode_psk_key_exchange_modes(KEModes) ->
+ decode_psk_key_exchange_modes(KEModes, []).
+%%
+decode_psk_key_exchange_modes(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_psk_key_exchange_modes(<<?BYTE(?PSK_KE), Rest/binary>>, Acc) ->
+ decode_psk_key_exchange_modes(Rest, [psk_ke|Acc]);
+decode_psk_key_exchange_modes(<<?BYTE(?PSK_DHE_KE), Rest/binary>>, Acc) ->
+ decode_psk_key_exchange_modes(Rest, [psk_dhe_ke|Acc]).
+
+
+decode_psk_identities(Identities) ->
+ decode_psk_identities(Identities, []).
+%%
+decode_psk_identities(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_psk_identities(<<?UINT16(Len), Identity:Len/binary, Age:4/binary, Rest/binary>>, Acc) ->
+ decode_psk_identities(Rest, [#psk_identity{
+ identity = Identity,
+ obfuscated_ticket_age = Age}|Acc]).
+
+
+decode_psk_binders(Binders) ->
+ decode_psk_binders(Binders, []).
+%%
+decode_psk_binders(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_psk_binders(<<?BYTE(Len), Binder:Len/binary, Rest/binary>>, Acc) ->
+ decode_psk_binders(Rest, [Binder|Acc]).
+
+
%% encode/decode stream of certificate data to/from list of certificate data
certs_to_list(ASN1Certs) ->
certs_to_list(ASN1Certs, []).
@@ -2666,7 +2786,7 @@ filter_unavailable_ecc_suites(_, Suites) ->
handle_renegotiation_extension(Role, RecordCB, Version, Info, Random, NegotiatedCipherSuite,
ClientCipherSuites, Compression,
ConnectionStates0, Renegotiation, SecureRenegotation) ->
- {ok, ConnectionStates} = handle_renegotiation_info(RecordCB, Role, Info, ConnectionStates0,
+ {ok, ConnectionStates} = handle_renegotiation_info(Version, RecordCB, Role, Info, ConnectionStates0,
Renegotiation, SecureRenegotation,
ClientCipherSuites),
hello_pending_connection_states(RecordCB, Role,
@@ -2936,11 +3056,11 @@ renegotiation_info(_RecordCB, server, ConnectionStates, true) ->
#renegotiation_info{renegotiated_connection = undefined}
end.
-handle_renegotiation_info(_RecordCB, _, #renegotiation_info{renegotiated_connection = ?byte(0)},
+handle_renegotiation_info(_, _RecordCB, _, #renegotiation_info{renegotiated_connection = ?byte(0)},
ConnectionStates, false, _, _) ->
{ok, ssl_record:set_renegotiation_flag(true, ConnectionStates)};
-handle_renegotiation_info(_RecordCB, server, undefined, ConnectionStates, _, _, CipherSuites) ->
+handle_renegotiation_info(_, _RecordCB, server, undefined, ConnectionStates, _, _, CipherSuites) ->
case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
true ->
{ok, ssl_record:set_renegotiation_flag(true, ConnectionStates)};
@@ -2948,10 +3068,10 @@ handle_renegotiation_info(_RecordCB, server, undefined, ConnectionStates, _, _,
{ok, ssl_record:set_renegotiation_flag(false, ConnectionStates)}
end;
-handle_renegotiation_info(_RecordCB, _, undefined, ConnectionStates, false, _, _) ->
+handle_renegotiation_info(_, _RecordCB, _, undefined, ConnectionStates, false, _, _) ->
{ok, ssl_record:set_renegotiation_flag(false, ConnectionStates)};
-handle_renegotiation_info(_RecordCB, client, #renegotiation_info{renegotiated_connection = ClientServerVerify},
+handle_renegotiation_info(_, _RecordCB, client, #renegotiation_info{renegotiated_connection = ClientServerVerify},
ConnectionStates, true, _, _) ->
ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
CData = maps:get(client_verify_data, ConnectionState),
@@ -2962,7 +3082,7 @@ handle_renegotiation_info(_RecordCB, client, #renegotiation_info{renegotiated_co
false ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, client_renegotiation))
end;
-handle_renegotiation_info(_RecordCB, server, #renegotiation_info{renegotiated_connection = ClientVerify},
+handle_renegotiation_info(_, _RecordCB, server, #renegotiation_info{renegotiated_connection = ClientVerify},
ConnectionStates, true, _, CipherSuites) ->
case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
@@ -2978,11 +3098,13 @@ handle_renegotiation_info(_RecordCB, server, #renegotiation_info{renegotiated_co
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, server_renegotiation))
end
end;
+handle_renegotiation_info({3,0}, _RecordCB, client, undefined, ConnectionStates, true, _SecureRenegotation, _) ->
+ {ok, ssl_record:set_renegotiation_flag(true, ConnectionStates)};
-handle_renegotiation_info(RecordCB, client, undefined, ConnectionStates, true, SecureRenegotation, _) ->
+handle_renegotiation_info(_, RecordCB, client, undefined, ConnectionStates, true, SecureRenegotation, _) ->
handle_renegotiation_info(RecordCB, ConnectionStates, SecureRenegotation);
-handle_renegotiation_info(RecordCB, server, undefined, ConnectionStates, true, SecureRenegotation, CipherSuites) ->
+handle_renegotiation_info(_, RecordCB, server, undefined, ConnectionStates, true, SecureRenegotation, CipherSuites) ->
case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
true ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv}));
@@ -3036,7 +3158,7 @@ empty_extensions({3,4}, client_hello) ->
%% padding => undefined,
key_share => undefined,
pre_shared_key => undefined,
- %% psk_key_exhange_modes => undefined,
+ psk_key_exchange_modes => undefined,
%% early_data => undefined,
%% cookie => undefined,
client_hello_versions => undefined,
@@ -3065,6 +3187,8 @@ empty_extensions({3,4}, hello_retry_request) ->
key_share => undefined,
pre_shared_key => undefined
};
+empty_extensions({3,0}, _) ->
+ empty_extensions();
empty_extensions(_, server_hello) ->
#{renegotiation_info => undefined,
alpn => undefined,
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index c132f75eae..37265e0759 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -379,7 +379,7 @@ do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation) -
%%--------------------------------------------------------------------
enc_handshake(#hello_request{}, {3, N}) when N < 4 ->
{?HELLO_REQUEST, <<>>};
-enc_handshake(#client_hello{client_version = {Major, Minor},
+enc_handshake(#client_hello{client_version = {Major, Minor} = Version,
random = Random,
session_id = SessionID,
cipher_suites = CipherSuites,
@@ -390,7 +390,7 @@ enc_handshake(#client_hello{client_version = {Major, Minor},
CmLength = byte_size(BinCompMethods),
BinCipherSuites = list_to_binary(CipherSuites),
CsLength = byte_size(BinCipherSuites),
- ExtensionsBin = ssl_handshake:encode_hello_extensions(HelloExtensions),
+ ExtensionsBin = ssl_handshake:encode_hello_extensions(HelloExtensions, Version),
{?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SIDLength), SessionID/binary,
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 49d20b3ec0..c29366e717 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -39,7 +39,7 @@
%% Create handshake messages
-export([certificate/5,
certificate_verify/4,
- encrypted_extensions/0]).
+ encrypted_extensions/1]).
-export([do_start/2,
do_negotiated/2,
@@ -61,10 +61,10 @@
%% Create handshake messages
%%====================================================================
-server_hello(MsgType, SessionId, KeyShare, ConnectionStates, ALPN) ->
+server_hello(MsgType, SessionId, KeyShare, ConnectionStates) ->
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates, read),
- Extensions = server_hello_extensions(MsgType, KeyShare, ALPN),
+ Extensions = server_hello_extensions(MsgType, KeyShare),
#server_hello{server_version = {3,3}, %% legacy_version
cipher_suite = SecParams#security_parameters.cipher_suite,
compression_method = 0, %% legacy attribute
@@ -73,6 +73,7 @@ server_hello(MsgType, SessionId, KeyShare, ConnectionStates, ALPN) ->
extensions = Extensions
}.
+
%% The server's extensions MUST contain "supported_versions".
%% Additionally, it SHOULD contain the minimal set of extensions
%% necessary for the client to generate a correct ClientHello pair. As
@@ -80,18 +81,14 @@ server_hello(MsgType, SessionId, KeyShare, ConnectionStates, ALPN) ->
%% extensions that were not first offered by the client in its
%% ClientHello, with the exception of optionally the "cookie" (see
%% Section 4.2.2) extension.
-server_hello_extensions(hello_retry_request = MsgType, KeyShare, _) ->
+server_hello_extensions(hello_retry_request = MsgType, KeyShare) ->
SupportedVersions = #server_hello_selected_version{selected_version = {3,4}},
Extensions = #{server_hello_selected_version => SupportedVersions},
ssl_handshake:add_server_share(MsgType, Extensions, KeyShare);
-server_hello_extensions(MsgType, KeyShare, undefined) ->
+server_hello_extensions(MsgType, KeyShare) ->
SupportedVersions = #server_hello_selected_version{selected_version = {3,4}},
Extensions = #{server_hello_selected_version => SupportedVersions},
- ssl_handshake:add_server_share(MsgType, Extensions, KeyShare);
-server_hello_extensions(MsgType, KeyShare, ALPN0) ->
- Extensions0 = ssl_handshake:add_selected_version(#{}), %% {3,4} (TLS 1.3)
- Extensions1 = ssl_handshake:add_alpn(Extensions0, ALPN0),
- ssl_handshake:add_server_share(MsgType, Extensions1, KeyShare).
+ ssl_handshake:add_server_share(MsgType, Extensions, KeyShare).
server_hello_random(server_hello, #security_parameters{server_random = Random}) ->
@@ -107,10 +104,14 @@ server_hello_random(hello_retry_request, _) ->
?HELLO_RETRY_REQUEST_RANDOM.
-%% TODO: implement support for encrypted_extensions
-encrypted_extensions() ->
+encrypted_extensions(#state{handshake_env = #handshake_env{alpn = undefined}}) ->
#encrypted_extensions{
extensions = #{}
+ };
+encrypted_extensions(#state{handshake_env = #handshake_env{alpn = ALPNProtocol}}) ->
+ Extensions = ssl_handshake:add_alpn(#{}, ALPNProtocol),
+ #encrypted_extensions{
+ extensions = Extensions
}.
@@ -503,7 +504,8 @@ do_start(#client_hello{cipher_suites = ClientCiphers,
ssl_options = #ssl_options{ciphers = ServerCiphers,
signature_algs = ServerSignAlgs,
supported_groups = ServerGroups0,
- alpn_preferred_protocols = ALPNPreferredProtocols},
+ alpn_preferred_protocols = ALPNPreferredProtocols,
+ honor_cipher_order = HonorCipherOrder},
session = #session{own_certificate = Cert}} = State0) ->
ClientGroups0 = maps:get(elliptic_curves, Extensions, undefined),
ClientGroups = get_supported_groups(ClientGroups0),
@@ -530,7 +532,7 @@ do_start(#client_hello{cipher_suites = ClientCiphers,
%% cipher suite, an (EC)DHE group and key share for key establishment,
%% and a signature algorithm/certificate pair to authenticate itself to
%% the client.
- Cipher = Maybe(select_cipher_suite(ClientCiphers, ServerCiphers)),
+ Cipher = Maybe(select_cipher_suite(HonorCipherOrder, ClientCiphers, ServerCiphers)),
Groups = Maybe(select_common_groups(ServerGroups, ClientGroups)),
Maybe(validate_client_key_share(ClientGroups, ClientShares)),
@@ -673,8 +675,7 @@ do_negotiated(start_handshake,
dh_public_value = ClientPublicKey},
ssl_options = #ssl_options{} = SslOpts,
key_share = KeyShare,
- handshake_env = #handshake_env{tls_handshake_history = _HHistory0,
- alpn = ALPN},
+ handshake_env = #handshake_env{tls_handshake_history = _HHistory0},
connection_env = #connection_env{private_key = CertPrivateKey},
static_env = #static_env{
cert_db = CertDbHandle,
@@ -689,7 +690,7 @@ do_negotiated(start_handshake,
try
%% Create server_hello
%% Extensions: supported_versions, key_share, (pre_shared_key)
- ServerHello = server_hello(server_hello, SessionId, KeyShare, ConnectionStates0, ALPN),
+ ServerHello = server_hello(server_hello, SessionId, KeyShare, ConnectionStates0),
{State1, _} = tls_connection:send_handshake(ServerHello, State0),
@@ -699,7 +700,7 @@ do_negotiated(start_handshake,
State3 = ssl_record:step_encryption_state(State2),
%% Create EncryptedExtensions
- EncryptedExtensions = encrypted_extensions(),
+ EncryptedExtensions = encrypted_extensions(State2),
%% Encode EncryptedExtensions
State4 = tls_connection:queue_handshake(EncryptedExtensions, State3),
@@ -881,12 +882,19 @@ do_wait_sh(#server_hello{cipher_suite = SelectedCipherSuite,
end.
-do_wait_ee(#encrypted_extensions{extensions = _Extensions}, State0) ->
+do_wait_ee(#encrypted_extensions{extensions = Extensions}, State0) ->
+
+ ALPNProtocol0 = maps:get(alpn, Extensions, undefined),
+ ALPNProtocol = get_alpn(ALPNProtocol0),
{Ref,_Maybe} = maybe(),
try
- {State0, wait_cert_cr}
+ %% Update state
+ #state{handshake_env = HsEnv} = State0,
+ State1 = State0#state{handshake_env = HsEnv#handshake_env{alpn = ALPNProtocol}},
+
+ {State1, wait_cert_cr}
catch
{Ref, {insufficient_security, no_suitable_groups}} ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_groups);
@@ -1041,10 +1049,9 @@ compare_verify_data(_, _) ->
{error, decrypt_error}.
-send_hello_retry_request(#state{connection_states = ConnectionStates0,
- handshake_env = #handshake_env{alpn = ALPN}} = State0,
+send_hello_retry_request(#state{connection_states = ConnectionStates0} = State0,
no_suitable_key, KeyShare, SessionId) ->
- ServerHello = server_hello(hello_retry_request, SessionId, KeyShare, ConnectionStates0, ALPN),
+ ServerHello = server_hello(hello_retry_request, SessionId, KeyShare, ConnectionStates0),
{State1, _} = tls_connection:send_handshake(ServerHello, State0),
%% Update handshake history
@@ -1725,15 +1732,19 @@ handle_alpn([ServerProtocol|T], ClientProtocols) ->
end.
-select_cipher_suite([], _) ->
+select_cipher_suite(_, [], _) ->
{error, no_suitable_cipher};
-select_cipher_suite([Cipher|ClientCiphers], ServerCiphers) ->
+%% If honor_cipher_order is set to true, use the server's preference for
+%% cipher suite selection.
+select_cipher_suite(true, ClientCiphers, ServerCiphers) ->
+ select_cipher_suite(false, ServerCiphers, ClientCiphers);
+select_cipher_suite(false, [Cipher|ClientCiphers], ServerCiphers) ->
case lists:member(Cipher, tls_v1:suites('TLS_v1.3')) andalso
lists:member(Cipher, ServerCiphers) of
true ->
{ok, Cipher};
false ->
- select_cipher_suite(ClientCiphers, ServerCiphers)
+ select_cipher_suite(false, ClientCiphers, ServerCiphers)
end.
@@ -1869,6 +1880,14 @@ get_key_shares(#key_share_server_hello{server_share = ServerShare}) ->
get_selected_group(#key_share_hello_retry_request{selected_group = SelectedGroup}) ->
SelectedGroup.
+get_alpn(ALPNProtocol0) ->
+ case ssl_handshake:decode_alpn(ALPNProtocol0) of
+ undefined ->
+ undefined;
+ [ALPNProtocol] ->
+ ALPNProtocol
+ end.
+
maybe() ->
Ref = erlang:make_ref(),
Ok = fun(ok) -> ok;
diff --git a/lib/ssl/src/tls_handshake_1_3.hrl b/lib/ssl/src/tls_handshake_1_3.hrl
index 7ae1b93e1c..eb85f216c8 100644
--- a/lib/ssl/src/tls_handshake_1_3.hrl
+++ b/lib/ssl/src/tls_handshake_1_3.hrl
@@ -74,29 +74,52 @@
y % opaque Y[coordinate_length];
}).
+%% RFC 8446 4.2.9. Pre-Shared Key Exchange Modes
+
+%% enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
-define(PSK_KE, 0).
-define(PSK_DHE_KE, 1).
--record(psk_keyexchange_modes, {
+-record(psk_key_exchange_modes, {
ke_modes % ke_modes<1..255>
}).
+
+%% RFC 8446 4.2.10. Early Data Indication
-record(empty, {
}).
-record(early_data_indication, {
indication % uint32 max_early_data_size (new_session_ticket) |
%% #empty{} (client_hello, encrypted_extensions)
}).
--record(psk_identity, {
- identity, % opaque identity<1..2^16-1>
- obfuscated_ticket_age % uint32
- }).
--record(offered_psks, {
- psk_identity, %identities<7..2^16-1>;
- psk_binder_entry %binders<33..2^16-1>, opaque PskBinderEntry<32..255>
- }).
--record(pre_shared_keyextension,{
- extension %OfferedPsks (client_hello) | uint16 selected_identity (server_hello)
- }).
+
+%% RFC 8446 4.2.11. Pre-Shared Key Extension
+-record(psk_identity,
+ {
+ identity, % opaque identity<1..2^16-1>
+ obfuscated_ticket_age % uint32
+ }).
+
+-record(offered_psks,
+ {
+ identities, % PskIdentity identities<7..2^16-1>;
+ binders % PskBinderEntry binders<33..2^16-1>; opaque PskBinderEntry<32..255>
+ }).
+
+%% struct {
+%% select (Handshake.msg_type) {
+%% case client_hello: OfferedPsks;
+%% case server_hello: uint16 selected_identity;
+%% };
+%% } PreSharedKeyExtension;
+-record(pre_shared_key_client_hello,
+ {
+ offered_psks
+ }).
+
+-record(pre_shared_key_server_hello,
+ {
+ selected_identity
+ }).
%% RFC 8446 B.3.1.2.
-record(cookie, {
diff --git a/lib/ssl/src/tls_record_1_3.erl b/lib/ssl/src/tls_record_1_3.erl
index 74321a1ae2..d713062284 100644
--- a/lib/ssl/src/tls_record_1_3.erl
+++ b/lib/ssl/src/tls_record_1_3.erl
@@ -138,6 +138,15 @@ decode_cipher_text(#ssl_tls{type = ?ALERT,
{#ssl_tls{type = ?ALERT,
version = {3,4}, %% Internally use real version
fragment = <<2,47>>}, ConnectionStates0};
+%% TLS 1.3 server can receive a User Cancelled Alert when handshake is
+%% paused and then cancelled on the client side.
+decode_cipher_text(#ssl_tls{type = ?ALERT,
+ version = ?LEGACY_VERSION,
+ fragment = <<2,90>>},
+ ConnectionStates0) ->
+ {#ssl_tls{type = ?ALERT,
+ version = {3,4}, %% Internally use real version
+ fragment = <<2,90>>}, ConnectionStates0};
%% RFC8446 - TLS 1.3
%% D.4. Middlebox Compatibility Mode
%% - If not offering early data, the client sends a dummy
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index dba90aaff0..0925c0facc 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -37,14 +37,29 @@ VSN=$(SSL_VSN)
MODULES = \
ssl_test_lib \
+ ssl_app_env_SUITE\
+ ssl_alert_SUITE\
ssl_bench_test_lib \
ssl_dist_test_lib \
- ssl_alpn_handshake_SUITE \
+ ssl_api_SUITE\
+ tls_api_SUITE\
ssl_basic_SUITE \
ssl_bench_SUITE \
ssl_cipher_SUITE \
ssl_cipher_suite_SUITE \
- openssl_server_cipher_suite_SUITE\
+ openssl_cipher_suite_SUITE\
+ ssl_alpn_SUITE \
+ openssl_alpn_SUITE\
+ ssl_npn_SUITE \
+ openssl_npn_SUITE\
+ openssl_sni_SUITE\
+ ssl_renegotiate_SUITE\
+ openssl_renegotiate_SUITE\
+ openssl_reject_SUITE\
+ ssl_cert_tests\
+ ssl_cert_SUITE\
+ openssl_server_cert_SUITE\
+ openssl_client_cert_SUITE\
ssl_certificate_verify_SUITE\
ssl_crl_SUITE\
ssl_dist_SUITE \
@@ -52,12 +67,12 @@ MODULES = \
ssl_engine_SUITE\
ssl_handshake_SUITE \
ssl_npn_hello_SUITE \
- ssl_npn_handshake_SUITE \
ssl_packet_SUITE \
ssl_payload_SUITE \
ssl_pem_cache_SUITE \
+ ssl_session_SUITE \
ssl_session_cache_SUITE \
- ssl_to_openssl_SUITE \
+ openssl_session_SUITE \
ssl_ECC_SUITE \
ssl_ECC_openssl_SUITE \
ssl_ECC\
@@ -65,6 +80,10 @@ MODULES = \
ssl_sni_SUITE \
ssl_eqc_SUITE \
ssl_rfc_5869_SUITE \
+ tls_1_3_record_SUITE\
+ openssl_tls_1_3_version_SUITE\
+ tls_1_3_version_SUITE\
+ ssl_socket_SUITE\
make_certs \
x509_test \
inet_crypto_dist
diff --git a/lib/ssl/test/openssl_alpn_SUITE.erl b/lib/ssl/test/openssl_alpn_SUITE.erl
new file mode 100644
index 0000000000..5008dba922
--- /dev/null
+++ b/lib/ssl/test/openssl_alpn_SUITE.erl
@@ -0,0 +1,421 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(openssl_alpn_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(OPENSSL_QUIT, "Q\n").
+-define(OPENSSL_RENEGOTIATE, "R\n").
+-define(SLEEP, 1000).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ %% Note: ALPN not supported in sslv3
+ case ssl_test_lib:openssl_sane_dtls_alpn() of
+ true ->
+ [
+ {group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}];
+ false ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'}]
+ end.
+
+groups() ->
+ case ssl_test_lib:openssl_sane_dtls_alpn() of
+ true ->
+ [
+ {'tlsv1.3', [], alpn_tests()},
+ {'tlsv1.2', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()},
+ {'tlsv1.1', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()},
+ {'tlsv1', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()},
+ {'dtlsv1.2', [], alpn_tests()},
+ {'dtlsv1', [], alpn_tests()}
+ ];
+ false ->
+ [
+ {'tlsv1.3', [], alpn_tests()},
+ {'tlsv1.2', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()},
+ {'tlsv1.1', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()},
+ {'tlsv1', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()}
+ ]
+ end.
+
+alpn_tests() ->
+ [erlang_client_alpn_openssl_server_alpn,
+ erlang_server_alpn_openssl_client_alpn,
+ erlang_client_alpn_openssl_server,
+ erlang_client_openssl_server_alpn,
+ erlang_server_alpn_openssl_client,
+ erlang_server_openssl_client_alpn].
+
+alpn_npn_coexist() ->
+ [
+ erlang_client_alpn_npn_openssl_server_alpn_npn,
+ erlang_server_alpn_npn_openssl_client_alpn_npn
+ ].
+rengotiation_tests() ->
+ case ssl_test_lib:sane_openssl_alpn_npn_renegotiate() of
+ true ->
+ [erlang_client_alpn_openssl_server_alpn_renegotiate,
+ erlang_server_alpn_openssl_client_alpn_renegotiate];
+ false ->
+ []
+ end.
+init_per_suite(Config0) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, "Openssl not found"};
+ _ ->
+ case check_openssl_alpn_support(Config0) of
+ {skip, _} = Skip ->
+ Skip;
+ _ ->
+ ct:pal("Version: ~p", [os:cmd("openssl version")]),
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end
+ end
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto),
+ ssl_test_lib:kill_openssl().
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(TestCase, Config) ->
+ ct:timetrap({seconds, 10}),
+ special_init(TestCase, Config).
+
+special_init(TestCase, Config)
+ when TestCase == erlang_client_alpn_openssl_server_alpn_renegotiate;
+ TestCase == erlang_server_alpn_openssl_client_alpn_renegotiate ->
+ {ok, Version} = application:get_env(ssl, protocol_version),
+ ssl_test_lib:check_sane_openssl_renegotaite(Config, Version);
+special_init(TestCase, Config)
+ when TestCase == erlang_client_alpn_npn_openssl_server_alpn_npn;
+ TestCase == erlang_server_alpn_npn_openssl_client_alpn_npn ->
+ ssl_test_lib:check_openssl_npn_support(Config);
+special_init(_, Config) ->
+ Config.
+
+end_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+erlang_client_alpn_openssl_server_alpn(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+
+%%--------------------------------------------------------------------
+
+erlang_server_alpn_openssl_client_alpn(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+
+%%--------------------------------------------------------------------------
+
+erlang_client_alpn_openssl_server(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_client_and_openssl_server_with_opts(Config,
+ [{alpn_advertised_protocols, [<<"spdy/2">>]}],
+ [],
+ Data, fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+
+%%--------------------------------------------------------------------------
+
+erlang_client_openssl_server_alpn(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_client_and_openssl_server_with_opts(Config,
+ [],
+ ["-alpn", "spdy/2"],
+ Data, fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+
+%%--------------------------------------------------------------------------
+
+erlang_server_alpn_openssl_client(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_server_and_openssl_client_with_opts(Config,
+ [{alpn_preferred_protocols, [<<"spdy/2">>]}],
+ [],
+ Data, fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+%%--------------------------------------------------------------------------
+
+erlang_server_openssl_client_alpn(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_server_and_openssl_client_with_opts(Config,
+ [],
+ ["-alpn", "spdy/2"],
+ Data, fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+%%--------------------------------------------------------------------
+
+erlang_client_alpn_openssl_server_alpn_renegotiate(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
+ ct:sleep(?SLEEP),
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+
+%%--------------------------------------------------------------------
+
+erlang_server_alpn_openssl_client_alpn_renegotiate(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
+ ct:sleep(?SLEEP),
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+%%--------------------------------------------------------------------
+
+erlang_client_alpn_npn_openssl_server_alpn_npn(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+
+%%--------------------------------------------------------------------
+
+erlang_server_alpn_npn_openssl_client_alpn_npn(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions -----------------------------------------------
+%%--------------------------------------------------------------------
+check_openssl_alpn_support(Config) ->
+ HelpText = os:cmd("openssl s_client --help"),
+ case string:str(HelpText, "alpn") of
+ 0 ->
+ {skip, "Openssl not compiled with alpn support"};
+ _ ->
+ Config
+ end.
+
+start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callback) ->
+ process_flag(trap_exit, true),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ClientOpts = [{alpn_advertised_protocols, [<<"spdy/2">>]} | ClientOpts0],
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ 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)),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
+ {options, [{reuse_sessions, false} | ClientOpts]}]),
+
+ Callback(Client, OpensslPort),
+
+ %% 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).
+
+start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, Callback) ->
+ process_flag(trap_exit, true),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]} | ServerOpts0],
+
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+
+ Exe = "openssl",
+ Args = ["s_client", "-alpn", "http/1.0,spdy/2", "-msg", "-port",
+ integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-host", "localhost"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ Callback(Server, OpenSslPort),
+
+ ssl_test_lib:close(Server),
+
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
+
+start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, Callback) ->
+ process_flag(trap_exit, true),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ClientOpts = [{alpn_advertised_protocols, [<<"spdy/2">>]},
+ {client_preferred_next_protocols, {client, [<<"spdy/3">>, <<"http/1.1">>]}} | ClientOpts0],
+
+ {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", "-msg", "-alpn", "http/1.1,spdy/2", "-nextprotoneg",
+ "spdy/3", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-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)),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
+ {options, [{reuse_sessions, false} | ClientOpts]}]),
+
+ Callback(Client, OpensslPort),
+
+ %% 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).
+
+start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Callback) ->
+ process_flag(trap_exit, true),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]},
+ {next_protocols_advertised, [<<"spdy/3">>, <<"http/1.1">>]} | ServerOpts0],
+
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-alpn", "http/1.1,spdy/2", "-nextprotoneg", "spdy/3",
+ "-msg", "-port", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-host", "localhost"],
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ Callback(Server, OpenSslPort),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
+
diff --git a/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl b/lib/ssl/test/openssl_cipher_suite_SUITE.erl
index 0d68d84d61..955eb914c0 100644
--- a/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl
+++ b/lib/ssl/test/openssl_cipher_suite_SUITE.erl
@@ -20,7 +20,7 @@
%%
--module(openssl_server_cipher_suite_SUITE).
+-module(openssl_cipher_suite_SUITE).
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -31,19 +31,26 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [
- {group, 'tlsv1.2'},
+ [
+ {group, openssl_server},
+ {group, openssl_client}
+ ].
+
+all_protocol_groups() ->
+ [{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
{group, 'sslv3'},
{group, 'dtlsv1.2'},
{group, 'dtlsv1'}
- ].
+ ].
groups() ->
%% TODO: Enable SRP, PSK suites (needs OpenSSL s_server conf)
%% TODO: Enable all "kex" on DTLS
[
+ {openssl_server, all_protocol_groups()},
+ {openssl_client, all_protocol_groups()},
{'tlsv1.2', [], kex()},
{'tlsv1.1', [], kex()},
{'tlsv1', [], kex()},
@@ -135,6 +142,9 @@ kex() ->
dtls_kex() -> %% Should be all kex in the future
dtls_rsa() ++ dss() ++ anonymous().
+ssl3_kex() ->
+ ssl3_rsa() ++ ssl3_dss() ++ ssl3_anonymous().
+
rsa() ->
[{group, dhe_rsa},
{group, ecdhe_rsa},
@@ -148,6 +158,11 @@ dtls_rsa() ->
%%,{group, rsa_psk}
].
+ssl3_rsa() ->
+ [{group, dhe_rsa},
+ {group, rsa}
+ ].
+
ecdsa() ->
[{group, ecdhe_ecdsa}].
@@ -156,6 +171,10 @@ dss() ->
%%{group, srp_dss}
].
+ssl3_dss() ->
+ [{group, dhe_dss}
+ ].
+
anonymous() ->
[{group, dh_anon},
{group, ecdh_anon}
@@ -165,6 +184,9 @@ anonymous() ->
%%{group, srp_anon}
].
+ssl3_anonymous() ->
+ [{group, dh_anon}].
+
init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
@@ -199,7 +221,12 @@ init_per_group(GroupName, Config) ->
false ->
do_init_per_group(GroupName, Config)
end.
-
+do_init_per_group(openssl_client, Config0) ->
+ Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
+ [{client_type, openssl}, {server_type, erlang} | Config];
+do_init_per_group(openssl_server, Config0) ->
+ Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
+ [{client_type, erlang}, {server_type, openssl} | Config];
do_init_per_group(GroupName, Config) when GroupName == ecdh_anon;
GroupName == ecdhe_rsa;
GroupName == ecdhe_psk ->
@@ -747,8 +774,7 @@ cipher_suite_test(CipherSuite, _Version, Config) ->
ct:log("Testing CipherSuite ~p~n", [CipherSuite]),
ct:log("Server Opts ~p~n", [ServerOpts]),
ct:log("Client Opts ~p~n", [ClientOpts]),
- ssl_test_lib:basic_test([{ciphers, [CipherSuite]} | COpts], SOpts, [{client_type, erlang},
- {server_type, openssl} | Config]).
+ ssl_test_lib:basic_test([{ciphers, [CipherSuite]} | COpts], SOpts, Config).
test_ciphers(Kex, Cipher, Version) ->
diff --git a/lib/ssl/test/openssl_client_cert_SUITE.erl b/lib/ssl/test/openssl_client_cert_SUITE.erl
new file mode 100644
index 0000000000..b327988744
--- /dev/null
+++ b/lib/ssl/test/openssl_client_cert_SUITE.erl
@@ -0,0 +1,350 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(openssl_client_cert_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, openssl_client}
+ ].
+
+groups() ->
+ [
+ {openssl_client, [], protocol_groups()},
+ {'tlsv1.3', [], tls_1_3_protocol_groups()},
+ {'tlsv1.2', [], pre_tls_1_3_protocol_groups()},
+ {'tlsv1.1', [], pre_tls_1_3_protocol_groups()},
+ {'tlsv1', [], pre_tls_1_3_protocol_groups()},
+ {'sslv3', [], ssl_protocol_groups()},
+ {'dtlsv1.2', [], pre_tls_1_3_protocol_groups()},
+ {'dtlsv1', [], pre_tls_1_3_protocol_groups()},
+ {rsa, [], all_version_tests()},
+ {ecdsa, [], all_version_tests()},
+ {dsa, [], all_version_tests()},
+ {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_client_auth,
+ unsupported_sign_algo_cert_client_auth]},
+ {ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()}
+ ].
+
+protocol_groups() ->
+ [{group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+ssl_protocol_groups() ->
+ [{group, rsa},
+ {group, dsa}].
+
+pre_tls_1_3_protocol_groups() ->
+ [{group, rsa},
+ {group, ecdsa},
+ {group, dsa}].
+
+tls_1_3_protocol_groups() ->
+ [{group, rsa_1_3},
+ {group, ecdsa_1_3}].
+
+tls_1_3_tests() ->
+ [
+ hello_retry_request,
+ custom_groups,
+ hello_retry_client_auth,
+ hello_retry_client_auth_empty_cert_accepted,
+ hello_retry_client_auth_empty_cert_rejected
+ ].
+
+all_version_tests() ->
+ [
+ no_auth,
+ auth,
+ client_auth_empty_cert_accepted,
+ client_auth_empty_cert_rejected,
+ client_auth_partial_chain,
+ client_auth_allow_partial_chain,
+ client_auth_do_not_allow_partial_chain,
+ client_auth_partial_chain_fun_fail,
+ missing_root_cert_no_auth
+ %%invalid_signature_client
+ ].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+
+init_per_group(openssl_client, Config0) ->
+ Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
+ [{client_type, openssl}, {server_type, erlang} | Config];
+init_per_group(Group, Config0) when Group == rsa;
+ Group == rsa_1_3 ->
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ COpts = proplists:get_value(client_rsa_opts, Config),
+ SOpts = proplists:get_value(server_rsa_opts, Config),
+ %% Make sure _rsa* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(fun(dhe_rsa) ->
+ true;
+ (ecdhe_rsa) ->
+ true;
+ (_) ->
+ false
+ end, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, rsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+init_per_group(Group, Config0) when Group == ecdsa;
+ Group == ecdsa_1_3 ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg) orelse
+ lists:member(dh, PKAlg)) of
+ true ->
+ Config = ssl_test_lib:make_ecdsa_cert(Config0),
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ %% Make sure ecdh* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(fun(ecdh_ecdsa) ->
+ true;
+ (ecdhe_ecdsa) ->
+ true;
+ (_) ->
+ false
+ end, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, ecdsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))]
+ )];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+init_per_group(Group, Config0) when Group == dsa ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(dss, PKAlg) andalso lists:member(dh, PKAlg) of
+ true ->
+ Config = ssl_test_lib:make_dsa_cert(Config0),
+ COpts = proplists:get_value(client_dsa_opts, Config),
+ SOpts = proplists:get_value(server_dsa_opts, Config),
+ %% Make sure dhe_dss* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(fun(dh_dss) ->
+ true;
+ (dhe_dss) ->
+ true;
+ (_) ->
+ false
+ end, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, dsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+ false ->
+ {skip, "Missing DSS crypto support"}
+ end;
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ [{version, GroupName}
+ | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, "Missing openssl support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+init_per_testcase(TestCase, Config) when
+ TestCase == client_auth_empty_cert_accepted;
+ TestCase == client_auth_empty_cert_rejected ->
+ Version = proplists:get_value(version,Config),
+ case Version of
+ sslv3 ->
+ %% Openssl client sends "No Certificate Reserved" warning ALERT
+ %% instead of sending EMPTY cert message in SSL-3.0 so empty cert test are not
+ %% relevant
+ {skip, openssl_behaves_differently};
+ _ ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config
+ end;
+init_per_testcase(_TestCase, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+no_auth() ->
+ ssl_cert_tests:no_auth().
+
+no_auth(Config) ->
+ ssl_cert_tests:no_auth(Config).
+%%--------------------------------------------------------------------
+auth() ->
+ ssl_cert_tests:auth().
+auth(Config) ->
+ ssl_cert_tests:auth(Config).
+%%--------------------------------------------------------------------
+client_auth_empty_cert_accepted() ->
+ ssl_cert_tests:client_auth_empty_cert_accepted().
+client_auth_empty_cert_accepted(Config) ->
+ ssl_cert_tests:client_auth_empty_cert_accepted(Config).
+%%--------------------------------------------------------------------
+client_auth_empty_cert_rejected() ->
+ ssl_cert_tests:client_auth_empty_cert_rejected().
+client_auth_empty_cert_rejected(Config) ->
+ ssl_cert_tests:client_auth_empty_cert_rejected(Config).
+%%--------------------------------------------------------------------
+client_auth_partial_chain() ->
+ ssl_cert_tests:client_auth_partial_chain().
+client_auth_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_partial_chain(Config).
+
+%%--------------------------------------------------------------------
+client_auth_allow_partial_chain() ->
+ ssl_cert_tests:client_auth_allow_partial_chain().
+client_auth_allow_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_allow_partial_chain(Config).
+%%--------------------------------------------------------------------
+client_auth_do_not_allow_partial_chain() ->
+ ssl_cert_tests:client_auth_do_not_allow_partial_chain().
+client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_do_not_allow_partial_chain(Config).
+
+%%--------------------------------------------------------------------
+client_auth_partial_chain_fun_fail() ->
+ ssl_cert_tests:client_auth_partial_chain_fun_fail().
+client_auth_partial_chain_fun_fail(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_partial_chain_fun_fail(Config).
+
+%%--------------------------------------------------------------------
+missing_root_cert_no_auth() ->
+ ssl_cert_tests:missing_root_cert_no_auth().
+missing_root_cert_no_auth(Config) when is_list(Config) ->
+ ssl_cert_tests:missing_root_cert_no_auth(Config).
+
+%%--------------------------------------------------------------------
+invalid_signature_client() ->
+ ssl_cert_tests:invalid_signature_client().
+invalid_signature_client(Config) when is_list(Config) ->
+ ssl_cert_tests:invalid_signature_client(Config).
+%%--------------------------------------------------------------------
+invalid_signature_server() ->
+ ssl_cert_tests:invalid_signature_client().
+invalid_signature_server(Config) when is_list(Config) ->
+ ssl_cert_tests:invalid_signature_client(Config).
+
+%%--------------------------------------------------------------------
+%% TLS 1.3 Test Cases ------------------------------------------------
+%%--------------------------------------------------------------------
+hello_retry_request() ->
+ ssl_cert_tests:hello_retry_request().
+hello_retry_request(Config) ->
+ ssl_cert_tests:hello_retry_request(Config).
+%%--------------------------------------------------------------------
+custom_groups() ->
+ ssl_cert_tests:custom_groups().
+custom_groups(Config) ->
+ ssl_cert_tests:custom_groups(Config).
+unsupported_sign_algo_cert_client_auth() ->
+ ssl_cert_tests:unsupported_sign_algo_cert_client_auth().
+unsupported_sign_algo_cert_client_auth(Config) ->
+ ssl_cert_tests:unsupported_sign_algo_cert_client_auth(Config).
+unsupported_sign_algo_client_auth() ->
+ ssl_cert_tests:unsupported_sign_algo_client_auth().
+unsupported_sign_algo_client_auth(Config) ->
+ ssl_cert_tests:unsupported_sign_algo_client_auth(Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth() ->
+ ssl_cert_tests:hello_retry_client_auth().
+hello_retry_client_auth(Config) ->
+ ssl_cert_tests:hello_retry_client_auth(Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_accepted() ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_accepted().
+hello_retry_client_auth_empty_cert_accepted(Config) ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_accepted(Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_rejected() ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected().
+hello_retry_client_auth_empty_cert_rejected(Config) ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(Config).
diff --git a/lib/ssl/test/openssl_npn_SUITE.erl b/lib/ssl/test/openssl_npn_SUITE.erl
new file mode 100644
index 0000000000..0294f4997f
--- /dev/null
+++ b/lib/ssl/test/openssl_npn_SUITE.erl
@@ -0,0 +1,311 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(openssl_npn_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(OPENSSL_QUIT, "Q\n").
+-define(OPENSSL_RENEGOTIATE, "R\n").
+-define(SLEEP, 1000).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ %% NPN is not supported in TLS-1.3 (replaced by ALPN and deprecated in TLS 1.2)
+ %% OpenSSL DTLS support for NPN is either not there or broken.
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'}].
+
+groups() ->
+ [{'tlsv1.2', [], npn_tests() ++ npn_renegotiate_tests()},
+ {'tlsv1.1', [], npn_tests() ++ npn_renegotiate_tests()},
+ {'tlsv1', [], npn_tests() ++ npn_renegotiate_tests()}
+ ].
+
+npn_tests() ->
+ [erlang_client_openssl_server_npn,
+ erlang_server_openssl_client_npn,
+ erlang_server_openssl_client_npn_only_client,
+ erlang_server_openssl_client_npn_only_server,
+ erlang_client_openssl_server_npn_only_client,
+ erlang_client_openssl_server_npn_only_server].
+
+npn_renegotiate_tests() ->
+ case ssl_test_lib:sane_openssl_alpn_npn_renegotiate() of
+ true ->
+ [erlang_server_openssl_client_npn_renegotiate,
+ erlang_client_openssl_server_npn_renegotiate];
+ false ->
+ []
+ end.
+
+init_per_suite(Config0) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, "Openssl not found"};
+ _ ->
+ case check_openssl_npn_support(Config0) of
+ {skip, _} = Skip ->
+ Skip;
+ _ ->
+ ct:pal("Version: ~p", [os:cmd("openssl version")]),
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end
+ end
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto),
+ ssl_test_lib:kill_openssl().
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(TestCase, Config) ->
+ ct:timetrap({seconds, 10}),
+ special_init(TestCase, Config).
+
+special_init(TestCase, Config)
+ when TestCase == erlang_client_npn_openssl_server_npn_renegotiate;
+ TestCase == erlang_server_npn_openssl_client_npn_renegotiate ->
+ {ok, Version} = application:get_env(ssl, protocol_version),
+ ssl_test_lib:check_sane_openssl_renegotaite(Config, Version);
+special_init(_, Config) ->
+ Config.
+
+end_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+erlang_client_openssl_server_npn() ->
+ [{doc,"Test erlang client with openssl server doing npn negotiation"}].
+
+erlang_client_openssl_server_npn(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data,
+ fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+
+%%--------------------------------------------------------------------
+erlang_client_openssl_server_npn_renegotiate() ->
+ [{doc,"Test erlang client with openssl server doing npn negotiation and renegotiate"}].
+
+erlang_client_openssl_server_npn_renegotiate(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data,
+ fun(Client, OpensslPort) ->
+ true = port_command(OpensslPort,
+ ?OPENSSL_RENEGOTIATE),
+ ct:sleep(?SLEEP),
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Client, Data)
+ end).
+%%--------------------------------------------------------------------------
+erlang_server_openssl_client_npn() ->
+ [{doc,"Test erlang server with openssl client and npn negotiation"}].
+
+erlang_server_openssl_client_npn(Config) when is_list(Config) ->
+
+ Data = "From openssl to erlang",
+ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data,
+ fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+%%--------------------------------------------------------------------------
+erlang_server_openssl_client_npn_renegotiate() ->
+ [{doc,"Test erlang server with openssl client and npn negotiation with renegotiation"}].
+
+erlang_server_openssl_client_npn_renegotiate(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data,
+ fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort,
+ ?OPENSSL_RENEGOTIATE),
+ ct:sleep(?SLEEP),
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+%%--------------------------------------------------------------------------
+erlang_client_openssl_server_npn_only_server(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_client_and_openssl_server_with_opts(Config, [],
+ ["-nextprotoneg", "spdy/2"], Data,
+ fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+%%--------------------------------------------------------------------------
+
+erlang_client_openssl_server_npn_only_client(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_client_and_openssl_server_with_opts(Config,
+ [{client_preferred_next_protocols,
+ {client, [<<"spdy/2">>], <<"http/1.1">>}}], [],
+ Data,
+ fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+%%--------------------------------------------------------------------------
+erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_server_and_openssl_client_with_opts(Config,
+ [{next_protocols_advertised, [<<"spdy/2">>]}], [],
+ Data,
+ fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) ->
+ Data = "From openssl to erlang",
+ ssl_test_lib:start_erlang_server_and_openssl_client_with_opts(Config, [], ["-nextprotoneg", "spdy/2"],
+ Data,
+ fun(Server, OpensslPort) ->
+ true = port_command(OpensslPort, Data),
+ ssl_test_lib:check_result(Server, Data)
+ end).
+
+%%--------------------------------------------------------------------
+%% Internal functions -----------------------------------------------
+%%--------------------------------------------------------------------
+
+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_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),
+
+ 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", "-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),
+
+ 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, {ssl_test_lib,
+ erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
+ {options, ClientOpts}]),
+
+ Callback(Client, OpensslPort),
+
+ %% 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).
+
+start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callback) ->
+ process_flag(trap_exit, true),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ServerOpts = [{next_protocols_advertised, [<<"spdy/2">>]} | ServerOpts0],
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+
+ Exe = "openssl",
+ Args = ["s_client", "-nextprotoneg", "http/1.0,spdy/2", "-msg", "-connect",
+ ssl_test_lib:hostname_format(Hostname) ++ ":"
+ ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ Callback(Server, OpenSslPort),
+
+ ssl_test_lib:close(Server),
+
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
+
+check_openssl_npn_support(Config) ->
+ HelpText = os:cmd("openssl s_client --help"),
+ case string:str(HelpText, "nextprotoneg") of
+ 0 ->
+ {skip, "Openssl not compiled with nextprotoneg support"};
+ _ ->
+ Config
+ end.
diff --git a/lib/ssl/test/openssl_reject_SUITE.erl b/lib/ssl/test/openssl_reject_SUITE.erl
new file mode 100644
index 0000000000..deefd11823
--- /dev/null
+++ b/lib/ssl/test/openssl_reject_SUITE.erl
@@ -0,0 +1,209 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(openssl_reject_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(SLEEP, 1000).
+-define(OPENSSL_GARBAGE, "P\n").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}].
+
+groups() ->
+ [{'tlsv1.2', [], all_versions_tests()},
+ {'tlsv1.1', [], all_versions_tests()},
+ {'tlsv1', [], all_versions_tests()},
+ {'sslv3', [], all_versions_tests()}
+ ].
+
+all_versions_tests() ->
+ [
+ erlang_client_bad_openssl_server,
+ ssl2_erlang_server_openssl_client
+ ].
+
+init_per_suite(Config0) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, "Openssl not found"};
+ _ ->
+ ct:pal("Version: ~p", [os:cmd("openssl version")]),
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto),
+ ssl_test_lib:kill_openssl().
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(TestCase, Config) ->
+ ct:timetrap({seconds, 10}),
+ special_init(TestCase, Config).
+
+special_init(ssl2_erlang_server_openssl_client, Config) ->
+ case ssl_test_lib:supports_ssl_tls_version(sslv2) of
+ true ->
+ Config;
+ false ->
+ {skip, "sslv2 not supported by openssl"}
+ end;
+special_init(_, Config) ->
+ Config.
+
+end_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+erlang_client_bad_openssl_server() ->
+ [{doc,"Test what happens if openssl server sends garbage to erlang ssl client"}].
+erlang_client_bad_openssl_server(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),
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ 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],
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+
+ Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, server_sent_garbage, []}},
+ {options,
+ [{versions, [Version]} | ClientOpts]}]),
+
+ %% Send garbage
+ true = port_command(OpensslPort, ?OPENSSL_GARBAGE),
+
+ ct:sleep(?SLEEP),
+
+ Client0 ! server_sent_garbage,
+
+ ssl_test_lib:check_result(Client0, true),
+
+ ssl_test_lib:close(Client0),
+
+ %% Make sure openssl does not hang and leave zombie process
+ Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options,
+ [{versions, [Version]} | ClientOpts]}]),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close_port(OpensslPort),
+ ssl_test_lib:close(Client1),
+ process_flag(trap_exit, false).
+
+%%--------------------------------------------------------------------
+ssl2_erlang_server_openssl_client() ->
+ [{doc,"Test that ssl v2 clients are rejected"}].
+
+ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Exe = "openssl",
+ Args = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ "-ssl2", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
+ ssl_test_lib:consume_port_exit(OpenSslPort),
+ ssl_test_lib:check_server_alert(Server, unexpected_message),
+ process_flag(trap_exit, false).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+server_sent_garbage(Socket) ->
+ receive
+ server_sent_garbage ->
+ {error, closed} == ssl:send(Socket, "data")
+
+ end.
diff --git a/lib/ssl/test/openssl_renegotiate_SUITE.erl b/lib/ssl/test/openssl_renegotiate_SUITE.erl
new file mode 100644
index 0000000000..787b5208b8
--- /dev/null
+++ b/lib/ssl/test/openssl_renegotiate_SUITE.erl
@@ -0,0 +1,342 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(openssl_renegotiate_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(SLEEP, 1000).
+-define(OPENSSL_RENEGOTIATE, "R\n").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}];
+ false ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}]
+ end.
+
+groups() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{'tlsv1.2', [], all_versions_tests()},
+ {'tlsv1.1', [], all_versions_tests()},
+ {'tlsv1', [], all_versions_tests()},
+ {'sslv3', [], all_versions_tests()},
+ {'dtlsv1.2', [], all_versions_tests()},
+ {'dtlsv1', [], all_versions_tests()}
+ ];
+ false ->
+ [{'tlsv1.2', [], all_versions_tests()},
+ {'tlsv1.1', [], all_versions_tests()},
+ {'tlsv1', [], all_versions_tests()},
+ {'sslv3', [], all_versions_tests()}
+ ]
+ end.
+
+all_versions_tests() ->
+ [
+ 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
+ ].
+
+
+init_per_suite(Config0) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, "Openssl not found"};
+ _ ->
+ ct:pal("Version: ~p", [os:cmd("openssl version")]),
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto),
+ ssl_test_lib:kill_openssl().
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:check_sane_openssl_renegotaite(ssl_test_lib:init_tls_version(GroupName, Config),
+ GroupName);
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(TestCase, Config) ->
+ ct:timetrap({seconds, 10}),
+ special_init(TestCase, 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_renegotiate_after_client_data
+ ->
+ {ok, Version} = application:get_env(ssl, protocol_version),
+ ssl_test_lib:check_sane_openssl_renegotaite(Config, Version);
+special_init(_, Config) ->
+ Config.
+
+end_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+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_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()),
+ 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),
+
+ 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,
+ delayed_send, [[ErlData, OpenSslData]]}},
+ {options, [{reuse_sessions, false} | ClientOpts]}]),
+
+ true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
+ ct:sleep(?SLEEP),
+ true = port_command(OpensslPort, OpenSslData),
+
+ ssl_test_lib:check_result(Client, OpenSslData),
+
+ %% 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.
+%%--------------------------------------------------------------------
+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, [{reuse_sessions, false} |ClientOpts]}]),
+
+ true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
+ ct:sleep(?SLEEP),
+ true = port_command(OpensslPort, OpenSslData),
+
+ ssl_test_lib:check_result(Client, OpenSslData),
+
+ %% 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.
+
+%%--------------------------------------------------------------------
+erlang_client_openssl_server_nowrap_seqnum() ->
+ [{doc, "Test that erlang client will renegotiate session when",
+ "max sequence number celing is about to be reached. Although"
+ "in the testcase we use the test option renegotiate_at"
+ " 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_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ ErlData = "From erlang to openssl\n",
+ 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),
+
+ 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, {ssl_test_lib,
+ trigger_renegotiate, [[ErlData, N+2]]}},
+ {options, [{reuse_sessions, false},
+ {renegotiate_at, N} | ClientOpts]}]),
+
+ 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).
+%%--------------------------------------------------------------------
+erlang_server_openssl_client_nowrap_seqnum() ->
+ [{doc, "Test that erlang client will renegotiate session when",
+ "max sequence number celing is about to be reached. Although"
+ "in the testcase we use the test option renegotiate_at"
+ " 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_verify_opts, Config),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ N = 10,
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ trigger_renegotiate, [[Data, N+2]]}},
+ {options, [{renegotiate_at, N}, {reuse_sessions, false} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client","-connect", ssl_test_lib:hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-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).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+delayed_send(Socket, [ErlData, OpenSslData]) ->
+ ct:sleep(?SLEEP),
+ ssl:send(Socket, ErlData),
+ ssl_test_lib:active_recv(Socket, length(OpenSslData)).
+
+
+send_wait_send(Socket, [ErlData, OpenSslData]) ->
+ ssl:send(Socket, ErlData),
+ ct:sleep(?SLEEP),
+ ssl:send(Socket, ErlData),
+ ssl_test_lib:active_recv(Socket, length(OpenSslData)).
+
diff --git a/lib/ssl/test/openssl_server_cert_SUITE.erl b/lib/ssl/test/openssl_server_cert_SUITE.erl
new file mode 100644
index 0000000000..c2af864a92
--- /dev/null
+++ b/lib/ssl/test/openssl_server_cert_SUITE.erl
@@ -0,0 +1,373 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(openssl_server_cert_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, openssl_server}].
+
+groups() ->
+ [
+ {openssl_server, [], protocol_groups()},
+ {'tlsv1.3', [], tls_1_3_protocol_groups()},
+ {'tlsv1.2', [], pre_tls_1_3_protocol_groups()},
+ {'tlsv1.1', [], pre_tls_1_3_protocol_groups()},
+ {'tlsv1', [], pre_tls_1_3_protocol_groups()},
+ {'sslv3', [], ssl_protocol_groups()},
+ {'dtlsv1.2', [], pre_tls_1_3_protocol_groups()},
+ {'dtlsv1', [], pre_tls_1_3_protocol_groups()},
+ {rsa, [], all_version_tests()},
+ {ecdsa, [], all_version_tests()},
+ {dsa, [], all_version_tests()},
+ {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests()},
+ %% TODO: Create proper conf of openssl server
+ %%++ [unsupported_sign_algo_client_auth,
+ %% unsupported_sign_algo_cert_client_auth]},
+ {ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()}
+ ].
+
+protocol_groups() ->
+ [{group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+ssl_protocol_groups() ->
+ [{group, rsa},
+ {group, dsa}].
+
+pre_tls_1_3_protocol_groups() ->
+ [{group, rsa},
+ {group, ecdsa},
+ {group, dsa}].
+
+tls_1_3_protocol_groups() ->
+ [{group, rsa_1_3},
+ {group, ecdsa_1_3}].
+
+tls_1_3_tests() ->
+ [
+ hello_retry_request,
+ custom_groups,
+ hello_retry_client_auth,
+ hello_retry_client_auth_empty_cert_accepted,
+ hello_retry_client_auth_empty_cert_rejected
+ ].
+
+all_version_tests() ->
+ [
+ no_auth,
+ auth,
+ missing_root_cert_no_auth
+ %%invalid_signature_client
+ ].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+
+init_per_group(openssl_server, Config0) ->
+ Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
+ [{client_type, erlang}, {server_type, openssl} | Config];
+init_per_group(rsa = Group, Config0) ->
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ COpts = proplists:get_value(client_rsa_opts, Config),
+ SOpts = proplists:get_value(server_rsa_opts, Config),
+ %% Make sure _rsa* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(fun(dhe_rsa) ->
+ true;
+ (ecdhe_rsa) ->
+ true;
+ (_) ->
+ false
+ end, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, rsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+init_per_group(rsa_1_3 = Group, Config0) ->
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ COpts = proplists:get_value(client_rsa_opts, Config),
+ SOpts = proplists:get_value(server_rsa_opts, Config),
+ %% Make sure _rsa* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(undefined, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, rsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+init_per_group(ecdsa = Group, Config0) ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg) orelse
+ lists:member(dh, PKAlg)) of
+ true ->
+ Config = ssl_test_lib:make_ecdsa_cert(Config0),
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ %% Make sure ecdh* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(fun(ecdh_ecdsa) ->
+ true;
+ (ecdhe_ecdsa) ->
+ true;
+ (_) ->
+ false
+ end, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, ecdsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))]
+ )];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+init_per_group(ecdsa_1_3 = Group, Config0) ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg) orelse
+ lists:member(dh, PKAlg)) of
+ true ->
+ Config = ssl_test_lib:make_ecdsa_cert(Config0),
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ %% Make sure ecdh* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(undefined, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, ecdsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))]
+ )];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+init_per_group(Group, Config0) when Group == dsa ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(dss, PKAlg) andalso lists:member(dh, PKAlg) of
+ true ->
+ Config = ssl_test_lib:make_dsa_cert(Config0),
+ COpts = proplists:get_value(client_dsa_opts, Config),
+ SOpts = proplists:get_value(server_dsa_opts, Config),
+ %% Make sure dhe_dss* suite is choosen by ssl_test_lib:start_server
+ Version = proplists:get_value(version,Config),
+ Ciphers = ssl_cert_tests:test_ciphers(fun(dh_dss) ->
+ true;
+ (dhe_dss) ->
+ true;
+ (_) ->
+ false
+ end, Version),
+ case Ciphers of
+ [_|_] ->
+ [{cert_key_alg, dsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, [{ciphers, Ciphers} | COpts]},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ [] ->
+ {skip, {no_sup, Group, Version}}
+ end;
+ false ->
+ {skip, "Missing DSS crypto support"}
+ end;
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ [{version, GroupName}
+ | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, "Missing openssl support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(_TestCase, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+no_auth() ->
+ ssl_cert_tests:no_auth().
+
+no_auth(Config) ->
+ ssl_cert_tests:no_auth(Config).
+%%--------------------------------------------------------------------
+auth() ->
+ ssl_cert_tests:auth().
+auth(Config) ->
+ ssl_cert_tests:auth(Config).
+%%--------------------------------------------------------------------
+client_auth_empty_cert_accepted() ->
+ ssl_cert_tests:client_auth_empty_cert_accepted().
+client_auth_empty_cert_accepted(Config) ->
+ ssl_cert_tests:client_auth_empty_cert_accepted(Config).
+%%--------------------------------------------------------------------
+client_auth_empty_cert_rejected() ->
+ ssl_cert_tests:client_auth_empty_cert_rejected().
+client_auth_empty_cert_rejected(Config) ->
+ ssl_cert_tests:client_auth_empty_cert_rejected(Config).
+%%--------------------------------------------------------------------
+client_auth_partial_chain() ->
+ ssl_cert_tests:client_auth_partial_chain().
+client_auth_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_partial_chain(Config).
+
+%%--------------------------------------------------------------------
+client_auth_allow_partial_chain() ->
+ ssl_cert_tests:client_auth_allow_partial_chain().
+client_auth_allow_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_allow_partial_chain(Config).
+%%--------------------------------------------------------------------
+client_auth_do_not_allow_partial_chain() ->
+ ssl_cert_tests:client_auth_do_not_allow_partial_chain().
+client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_do_not_allow_partial_chain(Config).
+
+%%--------------------------------------------------------------------
+client_auth_partial_chain_fun_fail() ->
+ ssl_cert_tests:client_auth_partial_chain_fun_fail().
+client_auth_partial_chain_fun_fail(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_partial_chain_fun_fail(Config).
+
+%%--------------------------------------------------------------------
+missing_root_cert_no_auth() ->
+ ssl_cert_tests:missing_root_cert_no_auth().
+missing_root_cert_no_auth(Config) when is_list(Config) ->
+ ssl_cert_tests:missing_root_cert_no_auth(Config).
+
+%%--------------------------------------------------------------------
+invalid_signature_client() ->
+ ssl_cert_tests:invalid_signature_client().
+invalid_signature_client(Config) when is_list(Config) ->
+ ssl_cert_tests:invalid_signature_client(Config).
+%%--------------------------------------------------------------------
+invalid_signature_server() ->
+ ssl_cert_tests:invalid_signature_client().
+invalid_signature_server(Config) when is_list(Config) ->
+ ssl_cert_tests:invalid_signature_client(Config).
+
+%%--------------------------------------------------------------------
+%% TLS 1.3 Test Cases ------------------------------------------------
+%%--------------------------------------------------------------------
+hello_retry_request() ->
+ ssl_cert_tests:hello_retry_request().
+hello_retry_request(Config) ->
+ ssl_cert_tests:hello_retry_request(Config).
+%%--------------------------------------------------------------------
+custom_groups() ->
+ ssl_cert_tests:custom_groups().
+custom_groups(Config) ->
+ ssl_cert_tests:custom_groups(Config).
+unsupported_sign_algo_cert_client_auth() ->
+ ssl_cert_tests:unsupported_sign_algo_cert_client_auth().
+unsupported_sign_algo_cert_client_auth(Config) ->
+ ssl_cert_tests:unsupported_sign_algo_cert_client_auth(Config).
+unsupported_sign_algo_client_auth() ->
+ ssl_cert_tests:unsupported_sign_algo_client_auth().
+unsupported_sign_algo_client_auth(Config) ->
+ ssl_cert_tests:unsupported_sign_algo_client_auth(Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth() ->
+ ssl_cert_tests:hello_retry_client_auth().
+hello_retry_client_auth(Config) ->
+ ssl_cert_tests:hello_retry_client_auth(Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_accepted() ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_accepted().
+hello_retry_client_auth_empty_cert_accepted(Config) ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_accepted(Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_rejected() ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected().
+hello_retry_client_auth_empty_cert_rejected(Config) ->
+ ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(Config).
diff --git a/lib/ssl/test/openssl_session_SUITE.erl b/lib/ssl/test/openssl_session_SUITE.erl
new file mode 100644
index 0000000000..97d83b98c3
--- /dev/null
+++ b/lib/ssl/test/openssl_session_SUITE.erl
@@ -0,0 +1,258 @@
+%%
+%% %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%
+%%
+%%
+
+-module(openssl_session_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(SLEEP, 1000).
+-define(EXPIRE, 10).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}];
+ false ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}]
+ end.
+
+groups() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{'tlsv1.2', [], tests()},
+ {'tlsv1.1', [], tests()},
+ {'tlsv1', [], tests()},
+ {'sslv3', [], tests()},
+ {'dtlsv1.2', [], tests()},
+ {'dtlsv1', [], tests()}
+ ];
+ false ->
+ [{'tlsv1.2', [], tests()},
+ {'tlsv1.1', [], tests()},
+ {'tlsv1', [], tests()},
+ {'sslv3', [], tests()}
+ ]
+ end.
+
+tests() ->
+ [
+ reuse_session_erlang_server,
+ reuse_session_erlang_client
+ ].
+
+
+init_per_suite(Config0) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, "Openssl not found"};
+ _ ->
+ ct:pal("Version: ~p", [os:cmd("openssl version")]),
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto),
+ ssl_test_lib:kill_openssl().
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(reuse_session_erlang_client, Config) ->
+ ct:timetrap(?EXPIRE * 1000 * 5),
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, session_lifetime, ?EXPIRE),
+ ssl:start(),
+ Config;
+
+init_per_testcase(TestCase, Config) ->
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(reuse_session_erlang_client, Config) ->
+ application:unset_env(ssl, session_lifetime),
+ Config;
+end_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+reuse_session_erlang_server() ->
+ [{doc, "Test erlang server with openssl client that reconnects with the"
+ "same session id, to test reusing of sessions."}].
+reuse_session_erlang_server(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {_, 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, {ssl_test_lib, active_recv, [length(Data)]}},
+ {reconnect_times, 5},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+
+ Exe = "openssl",
+ Args = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname)
+ ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-reconnect"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, Data),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort).
+
+%%--------------------------------------------------------------------
+
+reuse_session_erlang_client() ->
+ [{doc, "Test erlang ssl client that wants to reuse sessions"}].
+reuse_session_erlang_client(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ Version = ssl_test_lib:protocol_version(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),
+
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-cert", CertFile,"-key", KeyFile, "-CAfile", CACertFile],
+
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+
+ Client0 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_sessions, save}, {verify, verify_peer}| ClientOpts]}]),
+
+ SID = receive
+ {Client0, Id0} ->
+ Id0
+ end,
+
+ ssl_test_lib:close(Client0),
+
+ Client1 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, [{reuse_session, SID} | ClientOpts]}]),
+ receive
+ {Client1, SID} ->
+ ok
+ after ?SLEEP ->
+ ct:fail(session_not_reused)
+ end,
+
+
+ ssl_test_lib:close(Client1),
+ %% Make sure session is unregistered due to expiration
+ ct:sleep(20000),
+
+ Client2 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, ClientOpts}]),
+ receive
+ {Client2, ID} ->
+ case ID of
+ SID ->
+ ct:fail(expired_session_reused);
+ _ ->
+ ok
+ end
+ end,
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close_port(OpensslPort),
+ ssl_test_lib:close(Client2).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/openssl_sni_SUITE.erl b/lib/ssl/test/openssl_sni_SUITE.erl
new file mode 100644
index 0000000000..26f08e36c0
--- /dev/null
+++ b/lib/ssl/test/openssl_sni_SUITE.erl
@@ -0,0 +1,251 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(openssl_sni_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(OPENSSL_QUIT, "Q\n").
+-define(OPENSSL_RENEGOTIATE, "R\n").
+-define(SLEEP, 1000).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ %% Note: SNI not supported in sslv3
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'}
+ %% Seems broken in openssl
+ %%{group, 'dtlsv1.2'},
+ %%{group, 'dtlsv1'}
+ ];
+ false ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'}]
+ end.
+
+groups() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{'tlsv1.2', [], sni_tests()},
+ {'tlsv1.1', [], sni_tests()},
+ {'tlsv1', [], sni_tests()}
+ %% Seems broken in openssl
+ %%{'dtlsv1.2', [], sni_tests()},
+ %%{'dtlsv1', [], sni_tests()}
+ ];
+ false ->
+ [{'tlsv1.2', [], sni_tests()},
+ {'tlsv1.1', [], sni_tests()},
+ {'tlsv1', [], sni_tests()}
+ ]
+ end.
+
+sni_tests() ->
+ [erlang_server_openssl_client_sni_match,
+ erlang_server_openssl_client_sni_match_fun,
+ erlang_server_openssl_client_sni_no_match,
+ erlang_server_openssl_client_sni_no_match_fun,
+ erlang_server_openssl_client_sni_no_header,
+ erlang_server_openssl_client_sni_no_header_fun].
+
+init_per_suite(Config0) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, "Openssl not found"};
+ _ ->
+ case check_openssl_sni_support(Config0) of
+ {skip, _} = Skip ->
+ Skip;
+ _ ->
+ ct:pal("Version: ~p", [os:cmd("openssl version")]),
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ RsaOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ [{sni_server_opts, [{sni_hosts,
+ [{"a.server", [
+ {certfile, proplists:get_value(certfile, RsaOpts)},
+ {keyfile, proplists:get_value(keyfile, RsaOpts)}
+ ]},
+ {"b.server", [
+ {certfile, proplists:get_value(certfile, RsaOpts)},
+ {keyfile, proplists:get_value(keyfile, RsaOpts)}
+ ]}
+ ]}]} | Config]
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end
+ end
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto),
+ ssl_test_lib:kill_openssl().
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(_TestCase, Config) ->
+ ct:timetrap({seconds, 10}),
+ Config.
+
+
+end_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+erlang_server_openssl_client_sni_no_header(Config) when is_list(Config) ->
+ erlang_server_openssl_client_sni_test(Config, undefined, undefined, "server Peer cert").
+
+erlang_server_openssl_client_sni_no_header_fun(Config) when is_list(Config) ->
+ erlang_server_openssl_client_sni_test_sni_fun(Config, undefined, undefined, "server Peer cert").
+
+erlang_server_openssl_client_sni_match(Config) when is_list(Config) ->
+ erlang_server_openssl_client_sni_test(Config, "a.server", "a.server", "server Peer cert").
+
+erlang_server_openssl_client_sni_match_fun(Config) when is_list(Config) ->
+ erlang_server_openssl_client_sni_test_sni_fun(Config, "a.server", "a.server", "server Peer cert").
+
+erlang_server_openssl_client_sni_no_match(Config) when is_list(Config) ->
+ erlang_server_openssl_client_sni_test(Config, "c.server", undefined, "server Peer cert").
+
+erlang_server_openssl_client_sni_no_match_fun(Config) when is_list(Config) ->
+ erlang_server_openssl_client_sni_test_sni_fun(Config, "c.server", undefined, "server Peer cert").
+
+
+erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ ct:log("Start running handshake, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p",
+ [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
+ ServerOptions = proplists:get_value(sni_server_opts, Config) ++ proplists:get_value(server_rsa_opts, Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()}, {mfa, {?MODULE, send_and_hostname, []}},
+ {options, ServerOptions}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Exe = "openssl",
+ ClientArgs = case SNIHostname of
+ undefined ->
+ openssl_client_args(Version, Hostname,Port);
+ _ ->
+ openssl_client_args(Version, Hostname, Port, SNIHostname)
+ end,
+ ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
+
+ ssl_test_lib:check_result(Server, ExpectedSNIHostname),
+ ssl_test_lib:close_port(ClientPort),
+ ssl_test_lib:close(Server),
+ ok.
+
+
+erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ ct:log("Start running handshake for sni_fun, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p",
+ [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
+ [{sni_hosts, ServerSNIConf}] = proplists:get_value(sni_server_opts, Config),
+ SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end,
+ ServerOptions = proplists:get_value(server_rsa_opts, Config) ++ [{sni_fun, SNIFun}],
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()}, {mfa, {?MODULE, send_and_hostname, []}},
+ {options, ServerOptions}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Exe = "openssl",
+ ClientArgs = case SNIHostname of
+ undefined ->
+ openssl_client_args(Version, Hostname,Port);
+ _ ->
+ openssl_client_args(Version, Hostname, Port, SNIHostname)
+ end,
+
+ ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
+
+ ssl_test_lib:check_result(Server, ExpectedSNIHostname),
+ ssl_test_lib:close_port(ClientPort),
+ ssl_test_lib:close(Server).
+
+send_and_hostname(SSLSocket) ->
+ ssl:send(SSLSocket, "OK"),
+ case ssl:connection_information(SSLSocket, [sni_hostname]) of
+ {ok, []} ->
+ undefined;
+ {ok, [{sni_hostname, Hostname}]} ->
+ Hostname
+ end.
+
+openssl_client_args(Version, Hostname, Port) ->
+ ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)].
+
+openssl_client_args(Version, Hostname, Port, ServerName) ->
+ ["s_client", "-connect", Hostname ++ ":" ++
+ integer_to_list(Port), ssl_test_lib:version_flag(Version), "-servername", ServerName].
+
+check_openssl_sni_support(Config) ->
+ HelpText = os:cmd("openssl s_client --help"),
+ case ssl_test_lib:is_sane_oppenssl_client() of
+ true ->
+ case string:str(HelpText, "-servername") of
+ 0 ->
+ {skip, "Current openssl doesn't support SNI"};
+ _ ->
+ Config
+ end;
+ false ->
+ {skip, "Current openssl doesn't support SNI or extension handling is flawed"}
+ end.
diff --git a/lib/ssl/test/openssl_tls_1_3_version_SUITE.erl b/lib/ssl/test/openssl_tls_1_3_version_SUITE.erl
new file mode 100644
index 0000000000..8a2692ec1d
--- /dev/null
+++ b/lib/ssl/test/openssl_tls_1_3_version_SUITE.erl
@@ -0,0 +1,172 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(openssl_tls_1_3_version_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ %%{group, openssl_server},
+ {group, openssl_client}
+ ].
+
+groups() ->
+ [
+ %%{openssl_server, [{group, 'tlsv1.3'}]},
+ {openssl_client, [{group, 'tlsv1.3'}]},
+ {'tlsv1.3', [], cert_groups()},
+ {rsa, [], tests()},
+ {ecdsa, [], tests()}
+ ].
+
+cert_groups() ->
+ [{group, rsa},
+ {group, ecdsa}].
+
+tests() ->
+ [tls13_client_tls12_server,
+ %%tls13_client_with_ext_tls12_server,
+ tls12_client_tls13_server].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ case ssl_test_lib:check_sane_openssl_version('tlsv1.3') of
+ true ->
+ ssl_test_lib:clean_start(),
+ Config;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+init_per_group(openssl_client, Config0) ->
+ Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
+ [{client_type, openssl}, {server_type, erlang} | Config];
+init_per_group(openssl_server, Config0) ->
+ Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
+ [{client_type, erlang}, {server_type, openssl} | Config];
+init_per_group(rsa, Config0) ->
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ COpts = proplists:get_value(client_rsa_opts, Config),
+ SOpts = proplists:get_value(server_rsa_opts, Config),
+ [{client_cert_opts, COpts}, {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts, lists:delete(client_cert_opts, Config))];
+init_per_group(ecdsa, Config0) ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(ecdsa, PKAlg) andalso
+ (lists:member(ecdh, PKAlg) orelse lists:member(dh, PKAlg)) of
+ true ->
+ Config = ssl_test_lib:make_ecdsa_cert(Config0),
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ [{client_cert_opts, COpts}, {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts, lists:delete(client_cert_opts, Config))];
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+init_per_group(GroupName, Config) ->
+ ssl_test_lib:clean_tls_version(Config),
+ case ssl_test_lib:is_tls_version(GroupName) andalso
+ ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ _ ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl:start(),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+tls13_client_tls12_server() ->
+ [{doc,"Test that a TLS 1.3 client can connect to a TLS 1.2 server."}].
+
+tls13_client_tls12_server(Config) when is_list(Config) ->
+ ClientOpts = [{versions,
+ ['tlsv1.3', 'tlsv1.2']} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{versions,
+ ['tlsv1.1', 'tlsv1.2']} | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%% tls13_client_with_ext_tls12_server() ->
+%% [{doc,"Test basic connection between TLS 1.2 server and TLS 1.3 client when "
+%% "client has TLS 1.3 specsific extensions"}].
+
+%% tls13_client_with_ext_tls12_server(Config) ->
+%% ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+%% ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+%% {ServerOpts, ClientOpts} =
+%% case proplists:get_value(client_type) of
+%% erlang ->
+%% {[{versions, ['tlsv1.2']}|ServerOpts0],
+%% [{versions, ['tlsv1.2','tlsv1.3']},
+%% {signature_algs_cert, [ecdsa_secp384r1_sha384,
+%% ecdsa_secp256r1_sha256,
+%% rsa_pss_rsae_sha256,
+%% rsa_pkcs1_sha256,
+%% {sha256,rsa},{sha256,dsa}]}|ClientOpts0]};
+%% openssl ->
+
+
+%% ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+tls12_client_tls13_server() ->
+ [{doc,"Test that a TLS 1.2 client can connect to a TLS 1.3 server."}].
+
+tls12_client_tls13_server(Config) when is_list(Config) ->
+ ClientOpts = [{versions,
+ ['tlsv1.1', 'tlsv1.2']} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{versions,
+ ['tlsv1.3', 'tlsv1.2']} | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
diff --git a/lib/ssl/test/property_test/ssl_eqc_handshake.erl b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
index 38a4b7fb11..2ceb540e15 100644
--- a/lib/ssl/test/property_test/ssl_eqc_handshake.erl
+++ b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
@@ -119,19 +119,27 @@ tls_msg(Version) ->
%%
client_hello(?'TLS_v1.3' = Version) ->
#client_hello{session_id = session_id(),
- client_version = ?'TLS_v1.2',
- cipher_suites = cipher_suites(Version),
+ client_version = ?'TLS_v1.2',
+ cipher_suites = cipher_suites(Version),
+ compression_methods = compressions(Version),
+ random = client_random(Version),
+ extensions = client_hello_extensions(Version)
+ };
+client_hello(Version) ->
+ #client_hello{session_id = session_id(),
+ client_version = Version,
+ cipher_suites = cipher_suites(Version),
compression_methods = compressions(Version),
random = client_random(Version),
extensions = client_hello_extensions(Version)
};
-client_hello(Version) ->
+client_hello(?'SSL_v3' = Version) ->
#client_hello{session_id = session_id(),
client_version = Version,
cipher_suites = cipher_suites(Version),
compression_methods = compressions(Version),
random = client_random(Version),
- extensions = client_hello_extensions(Version)
+ extensions = ssl_handshake:empty_extensions(Version, client_hello)
}.
server_hello(?'TLS_v1.3' = Version) ->
@@ -142,6 +150,14 @@ server_hello(?'TLS_v1.3' = Version) ->
compression_method = compression(Version),
extensions = server_hello_extensions(Version)
};
+server_hello(?'SSL_v3' = Version) ->
+ #server_hello{server_version = Version,
+ session_id = session_id(),
+ random = server_random(Version),
+ cipher_suite = cipher_suite(Version),
+ compression_method = compression(Version),
+ extensions = ssl_handshake:empty_extensions(Version, server_hello)
+ };
server_hello(Version) ->
#server_hello{server_version = Version,
session_id = session_id(),
@@ -291,7 +307,7 @@ pre_shared_keyextension() ->
%% | | |
%% | signature_algorithms_cert (RFC 8446) | CH, CR |
%% +--------------------------------------------------+-------------+
-extensions(?'TLS_v1.3' = Version, client_hello) ->
+extensions(?'TLS_v1.3' = Version, MsgType = client_hello) ->
?LET({
ServerName,
%% MaxFragmentLength,
@@ -306,8 +322,8 @@ extensions(?'TLS_v1.3' = Version, client_hello) ->
%% ServerCertificateType,
%% Padding,
KeyShare,
- %% PreSharedKey,
- %% PSKKeyExchangeModes,
+ PreSharedKey,
+ PSKKeyExchangeModes,
%% EarlyData,
%% Cookie,
SupportedVersions,
@@ -328,9 +344,9 @@ extensions(?'TLS_v1.3' = Version, client_hello) ->
%% oneof([client_cert_type(), undefined]),
%% oneof([server_cert_type(), undefined]),
%% oneof([padding(), undefined]),
- oneof([key_share(client_hello), undefined]),
- %% oneof([pre_shared_key(), undefined]),
- %% oneof([psk_key_exchange_modes(), undefined]),
+ oneof([key_share(MsgType), undefined]),
+ oneof([pre_shared_key(MsgType), undefined]),
+ oneof([psk_key_exchange_modes(), undefined]),
%% oneof([early_data(), undefined]),
%% oneof([cookie(), undefined]),
oneof([client_hello_versions(Version)]),
@@ -357,8 +373,8 @@ extensions(?'TLS_v1.3' = Version, client_hello) ->
%% server_cert_type => ServerCertificateType,
%% padding => Padding,
key_share => KeyShare,
- %% pre_shared_key => PreSharedKey,
- %% psk_key_exhange_modes => PSKKeyExchangeModes,
+ pre_shared_key => PreSharedKey,
+ psk_key_exchange_modes => PSKKeyExchangeModes,
%% early_data => EarlyData,
%% cookie => Cookie,
client_hello_versions => SupportedVersions,
@@ -401,15 +417,15 @@ extensions(Version, client_hello) ->
srp => SRP
%% renegotiation_info => RenegotiationInfo
}));
-extensions(?'TLS_v1.3' = Version, server_hello) ->
+extensions(?'TLS_v1.3' = Version, MsgType = server_hello) ->
?LET({
KeyShare,
- %% PreSharedKeys,
+ PreSharedKey,
SupportedVersions
},
{
- oneof([key_share(server_hello), undefined]),
- %% oneof([pre_shared_keys(), undefined]),
+ oneof([key_share(MsgType), undefined]),
+ oneof([pre_shared_key(MsgType), undefined]),
oneof([server_hello_selected_version()])
},
maps:filter(fun(_, undefined) ->
@@ -419,7 +435,7 @@ extensions(?'TLS_v1.3' = Version, server_hello) ->
end,
#{
key_share => KeyShare,
- %% pre_shared_keys => PreSharedKeys,
+ pre_shared_key => PreSharedKey,
server_hello_selected_version => SupportedVersions
}));
extensions(Version, server_hello) ->
@@ -810,3 +826,58 @@ group_list(N, Pool, Acc) ->
R = rand:uniform(length(Pool)),
G = lists:nth(R, Pool),
group_list(N - 1, Pool -- [G], [G|Acc]).
+
+
+ke_modes() ->
+ oneof([[psk_ke],[psk_dhe_ke],[psk_ke,psk_dhe_ke]]).
+
+psk_key_exchange_modes() ->
+ ?LET(KEModes, ke_modes(),
+ #psk_key_exchange_modes{
+ ke_modes = KEModes}).
+
+pre_shared_key(client_hello) ->
+ ?LET(OfferedPsks, offered_psks(),
+ #pre_shared_key_client_hello{
+ offered_psks = OfferedPsks});
+pre_shared_key(server_hello) ->
+ ?LET(SelectedIdentity, selected_identity(),
+ #pre_shared_key_server_hello{
+ selected_identity = SelectedIdentity}).
+
+selected_identity() ->
+ rand:uniform(32).
+
+offered_psks() ->
+ ?LET(Size, choose(1,5),
+ #offered_psks{
+ identities = psk_identities(Size),
+ binders = psk_binders(Size)}).
+
+psk_identities(Size) ->
+ psk_identities(Size, []).
+%%
+psk_identities(0, Acc) ->
+ Acc;
+psk_identities(N, Acc) ->
+ psk_identities(N - 1, [psk_identity()|Acc]).
+
+psk_identity() ->
+ Len = rand:uniform(32),
+ Identity = crypto:strong_rand_bytes(Len),
+ Age = crypto:strong_rand_bytes(4),
+ #psk_identity{
+ identity = Identity,
+ obfuscated_ticket_age = Age}.
+
+psk_binders(Size) ->
+ psk_binders(Size, []).
+%%
+psk_binders(0, Acc) ->
+ Acc;
+psk_binders(N, Acc) ->
+ psk_binders(N - 1, [psk_binder()|Acc]).
+
+psk_binder() ->
+ Len = rand:uniform(224) + 31,
+ crypto:strong_rand_bytes(Len).
diff --git a/lib/ssl/test/ssl_alert_SUITE.erl b/lib/ssl/test/ssl_alert_SUITE.erl
new file mode 100644
index 0000000000..cc0b636580
--- /dev/null
+++ b/lib/ssl/test/ssl_alert_SUITE.erl
@@ -0,0 +1,100 @@
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_alert_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-include_lib("ssl/src/ssl_alert.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ alerts,
+ alert_details,
+ alert_details_not_too_big
+ ].
+
+init_per_testcase(_TestCase, Config) ->
+ ct:timetrap({seconds, 5}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+alerts() ->
+ [{doc, "Test ssl_alert:alert_txt/1"}].
+alerts(Config) when is_list(Config) ->
+ Descriptions = [?CLOSE_NOTIFY, ?UNEXPECTED_MESSAGE, ?BAD_RECORD_MAC,
+ ?DECRYPTION_FAILED_RESERVED, ?RECORD_OVERFLOW, ?DECOMPRESSION_FAILURE,
+ ?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, ?USER_CANCELED,
+ ?NO_RENEGOTIATION, ?UNSUPPORTED_EXTENSION, ?CERTIFICATE_UNOBTAINABLE,
+ ?UNRECOGNISED_NAME, ?BAD_CERTIFICATE_STATUS_RESPONSE,
+ ?BAD_CERTIFICATE_HASH_VALUE, ?UNKNOWN_PSK_IDENTITY,
+ 255 %% Unsupported/unknow alert will result in a description too
+ ],
+ Alerts = [?ALERT_REC(?WARNING, ?CLOSE_NOTIFY) |
+ [?ALERT_REC(?FATAL, Desc) || Desc <- Descriptions]],
+ lists:foreach(fun(Alert) ->
+ try ssl_alert:alert_txt(Alert)
+ catch
+ C:E:T ->
+ ct:fail({unexpected, {C, E, T}})
+ end
+ end, Alerts).
+%%--------------------------------------------------------------------
+alert_details() ->
+ [{doc, "Test that ssl_alert:alert_txt/1 result contains extendend error description"}].
+alert_details(Config) when is_list(Config) ->
+ Unique = make_ref(),
+ UniqueStr = lists:flatten(io_lib:format("~w", [Unique])),
+ Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY, Unique),
+ case string:str(ssl_alert:alert_txt(Alert), UniqueStr) of
+ 0 ->
+ ct:fail(error_details_missing);
+ _ ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+alert_details_not_too_big() ->
+ [{doc, "Test that ssl_alert:alert_txt/1 limits printed depth of extended error description"}].
+alert_details_not_too_big(Config) when is_list(Config) ->
+ Reason = lists:duplicate(10, lists:duplicate(10, lists:duplicate(10, {some, data}))),
+ Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY, Reason),
+ case length(ssl_alert:alert_txt(Alert)) < 1000 of
+ true ->
+ ok;
+ false ->
+ ct:fail(ssl_alert_text_too_big)
+ end.
diff --git a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl b/lib/ssl/test/ssl_alpn_SUITE.erl
index dfc780479e..82a49e1469 100644
--- a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_alpn_SUITE.erl
@@ -19,7 +19,7 @@
%%
%%
--module(ssl_alpn_handshake_SUITE).
+-module(ssl_alpn_SUITE).
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -32,7 +32,9 @@
%%--------------------------------------------------------------------
all() ->
- [{group, 'tlsv1.2'},
+ [
+ {group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
{group, 'sslv3'},
@@ -42,12 +44,13 @@ all() ->
groups() ->
[
- {'tlsv1.2', [], alpn_tests()},
- {'tlsv1.1', [], alpn_tests()},
- {'tlsv1', [], alpn_tests()},
+ {'tlsv1.3', [], alpn_tests() -- [client_renegotiate, session_reused]},
+ {'tlsv1.2', [], alpn_tests() ++ alpn_npn_coexist()},
+ {'tlsv1.1', [], alpn_tests() ++ alpn_npn_coexist()},
+ {'tlsv1', [], alpn_tests() ++ alpn_npn_coexist()},
{'sslv3', [], alpn_not_supported()},
- {'dtlsv1.2', [], alpn_tests() -- [client_renegotiate]},
- {'dtlsv1', [], alpn_tests() -- [client_renegotiate]}
+ {'dtlsv1.2', [], alpn_tests() ++ alpn_npn_coexist()},
+ {'dtlsv1', [], alpn_tests() ++ alpn_npn_coexist()}
].
alpn_tests() ->
@@ -61,12 +64,16 @@ alpn_tests() ->
client_alpn_and_server_no_support,
client_no_support_and_server_alpn,
client_alpn_npn_and_server_alpn,
- client_alpn_npn_and_server_alpn_npn,
- client_alpn_and_server_alpn_npn,
client_renegotiate,
session_reused
].
+alpn_npn_coexist() ->
+ [
+ client_alpn_npn_and_server_alpn_npn,
+ client_alpn_and_server_alpn_npn
+ ].
+
alpn_not_supported() ->
[alpn_not_supported_client,
alpn_not_supported_server
@@ -77,8 +84,7 @@ init_per_suite(Config0) ->
try crypto:start() of
ok ->
ssl_test_lib:clean_start(),
- Config = ssl_test_lib:make_rsa_cert(Config0),
- ssl_test_lib:cert_options(Config)
+ ssl_test_lib:make_rsa_cert(Config0)
catch _:_ ->
{skip, "Crypto did not start"}
end.
diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl
new file mode 100644
index 0000000000..fefecc0b65
--- /dev/null
+++ b/lib/ssl/test/ssl_api_SUITE.erl
@@ -0,0 +1,1976 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(ssl_api_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssl/src/ssl_api.hrl").
+
+-define(SLEEP, 500).
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ [
+ {group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.3', [], ((gen_api_tests() ++ tls13_group() ++ handshake_paus_tests()) -- [dh_params, honor_server_cipher_order, honor_client_cipher_order,
+ new_options_in_handshake])
+ ++ (since_1_2() -- [conf_signature_algs])},
+ {'tlsv1.2', [], gen_api_tests() ++ since_1_2() ++ handshake_paus_tests() ++ pre_1_3()},
+ {'tlsv1.1', [], gen_api_tests() ++ handshake_paus_tests() ++ pre_1_3()},
+ {'tlsv1', [], gen_api_tests() ++ handshake_paus_tests() ++ pre_1_3() ++ beast_mitigation_test()},
+ {'sslv3', [], (gen_api_tests() -- [new_options_in_handshake]) ++ beast_mitigation_test() ++ pre_1_3()},
+ {'dtlsv1.2', [], (gen_api_tests() -- [invalid_keyfile, invalid_certfile, invalid_cacertfile,
+ invalid_options, new_options_in_handshake]) ++ handshake_paus_tests() ++ pre_1_3()},
+ {'dtlsv1', [], (gen_api_tests() -- [invalid_keyfile, invalid_certfile, invalid_cacertfile,
+ invalid_options, new_options_in_handshake]) ++ handshake_paus_tests() ++ pre_1_3()}
+ ].
+
+since_1_2() ->
+ [
+ conf_signature_algs,
+ no_common_signature_algs
+ ].
+
+pre_1_3() ->
+ [
+ default_reject_anonymous
+ ].
+gen_api_tests() ->
+ [
+ peercert,
+ peercert_with_client_cert,
+ connection_information,
+ secret_connection_info,
+ versions,
+ active_n,
+ dh_params,
+ hibernate,
+ hibernate_right_away,
+ listen_socket,
+ recv_active,
+ recv_active_once,
+ recv_active_n,
+ recv_timeout,
+ recv_close,
+ controlling_process,
+ controller_dies,
+ controlling_process_transport_accept_socket,
+ close_with_timeout,
+ close_in_error_state,
+ call_in_error_state,
+ close_transport_accept,
+ abuse_transport_accept_socket,
+ honor_server_cipher_order,
+ honor_client_cipher_order,
+ ipv6,
+ der_input,
+ new_options_in_handshake,
+ max_handshake_size,
+ invalid_certfile,
+ invalid_cacertfile,
+ invalid_keyfile,
+ options_not_proplist,
+ invalid_options
+ ].
+
+handshake_paus_tests() ->
+ [
+ handshake_continue,
+ handshake_continue_timeout,
+ hello_client_cancel,
+ hello_server_cancel
+ ].
+
+%% Only relevant for SSL 3.0 and TLS 1.1
+beast_mitigation_test() ->
+ [%% Original option
+ rizzo_disabled,
+ %% Same effect as disable
+ rizzo_zero_n,
+ %% Same as default
+ rizzo_one_n_minus_one
+ ].
+
+tls13_group() ->
+ [
+ supported_groups,
+ honor_server_cipher_order_tls13,
+ honor_client_cipher_order_tls13
+ ].
+
+
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ [{client_type, erlang},
+ {server_type, erlang} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(prf, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Version = ssl_test_lib:protocol_version(Config),
+ PRFS = [md5, sha, sha256, sha384, sha512],
+ %% All are the result of running tls_v1:prf(PrfAlgo, <<>>, <<>>, <<>>, 16)
+ %% with the specified PRF algorithm
+ ExpectedPrfResults =
+ [{md5, <<96,139,180,171,236,210,13,10,28,32,2,23,88,224,235,199>>},
+ {sha, <<95,3,183,114,33,169,197,187,231,243,19,242,220,228,70,151>>},
+ {sha256, <<166,249,145,171,43,95,158,232,6,60,17,90,183,180,0,155>>},
+ {sha384, <<153,182,217,96,186,130,105,85,65,103,123,247,146,91,47,106>>},
+ {sha512, <<145,8,98,38,243,96,42,94,163,33,53,49,241,4,127,28>>},
+ %% TLS 1.0 and 1.1 PRF:
+ {md5sha, <<63,136,3,217,205,123,200,177,251,211,17,229,132,4,173,80>>}],
+ TestPlan = prf_create_plan([Version], PRFS, ExpectedPrfResults),
+ [{prf_test_plan, TestPlan} | Config];
+init_per_testcase(_TestCase, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(internal_active_n, _Config) ->
+ application:unset_env(ssl, internal_active_n);
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+peercert() ->
+ [{doc,"Test API function peercert/1"}].
+peercert(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, ClientOpts}]),
+
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile),
+
+ ServerMsg = {error, no_peercert},
+ ClientMsg = {ok, BinCert},
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+
+peercert_with_client_cert() ->
+ [{doc,"Test API function peercert/1"}].
+peercert_with_client_cert(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, [{verify, verify_peer} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, ClientOpts}]),
+
+ ServerCertFile = proplists:get_value(certfile, ServerOpts),
+ [{'Certificate', ServerBinCert, _}]= ssl_test_lib:pem_to_der(ServerCertFile),
+ ClientCertFile = proplists:get_value(certfile, ClientOpts),
+ [{'Certificate', ClientBinCert, _}]= ssl_test_lib:pem_to_der(ClientCertFile),
+
+ ServerMsg = {ok, ClientBinCert},
+ ClientMsg = {ok, ServerBinCert},
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+connection_information() ->
+ [{doc,"Test the API function ssl:connection_information/1"}].
+connection_information(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, connection_information_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_information_result, []}},
+ {options, ClientOpts}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ 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_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, secret_connection_info_result, []}},
+ {options, [{verify, verify_peer} | ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, secret_connection_info_result, []}},
+ {options, [{verify, verify_peer} |ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, true, Client, true),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+prf() ->
+ [{doc,"Test that ssl:prf/5 uses the negotiated PRF."}].
+prf(Config) when is_list(Config) ->
+ TestPlan = proplists:get_value(prf_test_plan, Config),
+ case TestPlan of
+ [] -> ct:fail({error, empty_prf_test_plan});
+ _ -> lists:foreach(fun(Suite) ->
+ lists:foreach(
+ fun(Test) ->
+ V = proplists:get_value(tls_ver, Test),
+ C = proplists:get_value(ciphers, Test),
+ E = proplists:get_value(expected, Test),
+ P = proplists:get_value(prf, Test),
+ prf_run_test(Config, V, C, E, P)
+ end, Suite)
+ end, TestPlan)
+ end.
+
+%%--------------------------------------------------------------------
+dh_params() ->
+ [{doc,"Test to specify DH-params file in server."}].
+
+dh_params(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ DHParamFile = filename:join(DataDir, "dHParam.pem"),
+
+ {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, send_recv_result_active, []}},
+ {options, [{dhfile, DHParamFile} | 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, send_recv_result_active, []}},
+ {options,
+ [{ciphers,[{dhe_rsa,aes_256_cbc,sha}]} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+conf_signature_algs() ->
+ [{doc,"Test to set the signature_algs option on both client and server"}].
+conf_signature_algs(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false}, {signature_algs, [{sha256, rsa}]} | 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, send_recv_result, []}},
+ {options, [{active, false}, {signature_algs, [{sha256, rsa}]} | ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+%%--------------------------------------------------------------------
+no_common_signature_algs() ->
+ [{doc,"Set the signature_algs option so that there client and server does not share any hash sign algorithms"}].
+no_common_signature_algs(Config) when is_list(Config) ->
+
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, [{signature_algs, [{sha256, rsa}]}
+ | 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]}]),
+
+ ssl_test_lib:check_server_alert(Server, Client, insufficient_security).
+
+%%--------------------------------------------------------------------
+handshake_continue() ->
+ [{doc, "Test API function ssl:handshake_continue/3"}].
+handshake_continue(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ssl_test_lib:ssl_options([{reuseaddr, true},
+ {verify, verify_peer},
+ {handshake, hello} | ServerOpts
+ ],
+ Config)},
+ {continue_options, proplists:delete(reuseaddr, 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, send_recv_result_active, []}},
+ {options, ssl_test_lib:ssl_options([{handshake, hello},
+ {verify, verify_peer} | ClientOpts
+ ],
+ Config)},
+ {continue_options, proplists:delete(reuseaddr, ClientOpts)}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ 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_rsa_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},
+ {from, self()},
+ {timeout, 1},
+ {options, ssl_test_lib:ssl_options([{reuseaddr, true}, {handshake, hello},
+ {verify, verify_peer} | ServerOpts],
+ Config)},
+ {continue_options, proplists:delete(reuseaddr, ServerOpts)}
+ ]),
+
+ Port = ssl_test_lib:inet_port(Server),
+
+
+ ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options, [{verify, verify_peer} | 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"}].
+hello_client_cancel(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {options, ssl_test_lib:ssl_options([{handshake, hello},
+ {verify, verify_peer} | ServerOpts], Config)},
+ {continue_options, proplists:delete(reuseaddr, ServerOpts)}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+
+ %% That is ssl:handshake_cancel returns ok
+ {connect_failed, ok} = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options, ssl_test_lib:ssl_options([{handshake, hello},
+ {verify, verify_peer} | ClientOpts], Config)},
+ {continue_options, cancel}]),
+ 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_rsa_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},
+ {from, self()},
+ {options, ssl_test_lib:ssl_options([{handshake, hello},
+ {verify, verify_peer} | ServerOpts
+ ], Config)},
+ {continue_options, cancel}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+
+ ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options, ssl_test_lib:ssl_options([{handshake, hello},
+ {verify, verify_peer} | ClientOpts
+ ], Config)},
+ {continue_options, proplists:delete(reuseaddr, ClientOpts)}]),
+
+ ssl_test_lib:check_result(Server, ok).
+
+%%--------------------------------------------------------------------
+versions() ->
+ [{doc,"Test API function versions/0"}].
+
+versions(Config) when is_list(Config) ->
+ [_|_] = Versions = ssl:versions(),
+ ct:log("~p~n", [Versions]).
+
+%%--------------------------------------------------------------------
+%% 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_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_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.
+
+hibernate() ->
+ [{doc,"Check that an SSL connection that is started with option "
+ "{hibernate_after, 1000} indeed hibernates after 1000ms of "
+ "inactivity"}].
+
+hibernate(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {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,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{hibernate_after, 1000}|ClientOpts]}]),
+ {current_function, _} =
+ process_info(Pid, current_function),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ct:sleep(1500),
+ {current_function, {erlang, hibernate, 3}} =
+ process_info(Pid, current_function),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+
+hibernate_right_away() ->
+ [{doc,"Check that an SSL connection that is configured to hibernate "
+ "after 0 or 1 milliseconds hibernates as soon as possible and not "
+ "crashes"}].
+
+hibernate_right_away(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ StartServerOpts = [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOpts}],
+ StartClientOpts = [return_socket,
+ {node, ClientNode},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}}],
+
+ Server1 = ssl_test_lib:start_server(StartServerOpts),
+ Port1 = ssl_test_lib:inet_port(Server1),
+ {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),
+
+ ct:sleep(1000), %% Schedule out
+
+ {current_function, {erlang, hibernate, 3}} =
+ process_info(Pid1, current_function),
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1),
+
+ Server2 = ssl_test_lib:start_server(StartServerOpts),
+ Port2 = ssl_test_lib:inet_port(Server2),
+ {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),
+
+ ct:sleep(1000), %% Schedule out
+
+ {current_function, {erlang, hibernate, 3}} =
+ process_info(Pid2, current_function),
+
+ ssl_test_lib:close(Server2),
+ ssl_test_lib:close(Client2).
+
+listen_socket() ->
+ [{doc,"Check error handling and inet compliance when calling API functions with listen sockets."}].
+
+listen_socket(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ok, ListenSocket} = ssl:listen(0, ServerOpts),
+
+ %% This can be a valid thing to do as
+ %% options are inherited by the accept socket
+ ok = ssl:controlling_process(ListenSocket, self()),
+
+ {ok, _} = ssl:sockname(ListenSocket),
+
+ {error, enotconn} = ssl:send(ListenSocket, <<"data">>),
+ {error, enotconn} = ssl:recv(ListenSocket, 0),
+ {error, enotconn} = ssl:connection_information(ListenSocket),
+ {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:shutdown(ListenSocket, read_write),
+
+ ok = ssl:close(ListenSocket).
+
+%%--------------------------------------------------------------------
+recv_active() ->
+ [{doc,"Test recv on active socket"}].
+
+recv_active(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, try_recv_active, []}},
+ {options, [{active, true} | 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, []}},
+ {options, [{active, true} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+recv_active_once() ->
+ [{doc,"Test recv on active (once) socket"}].
+
+recv_active_once(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, try_recv_active_once, []}},
+ {options, [{active, once} | 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, once} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ 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_rsa_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},
+ {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).
+%%--------------------------------------------------------------------
+recv_timeout() ->
+ [{doc,"Test ssl:ssl_accept timeout"}].
+
+recv_timeout(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_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, {?MODULE, send_recv_result_timeout_server, []}},
+ {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,
+ send_recv_result_timeout_client, []}},
+ {options, [{active, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+recv_close() ->
+ [{doc,"Special case of call error handling"}].
+recv_close(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, do_recv_close, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {_Client, #sslsocket{} = SslSocket} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+ ssl:close(SslSocket),
+ ssl_test_lib:check_result(Server, ok).
+
+
+
+%%--------------------------------------------------------------------
+controlling_process() ->
+ [{doc,"Test API function controlling_process/2"}].
+
+controlling_process(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(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}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {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]),
+
+ 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).
+%%--------------------------------------------------------------------
+controller_dies() ->
+ [{doc,"Test that the socket is closed after controlling process dies"}].
+controller_dies(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ClientMsg = "Hello server",
+ ServerMsg = "Hello client",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ controller_dies_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()},
+ {mfa, {?MODULE,
+ controller_dies_result, [self(),
+ ClientMsg]}},
+ {options, ClientOpts}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]),
+ ct:sleep(?SLEEP), %% so that they are connected
+
+ process_flag(trap_exit, true),
+
+ %% Test that clients die
+ exit(Client, killed),
+ get_close(Client, ?LINE),
+
+ %% Test that clients die when process disappear
+ Server ! listen,
+ Tester = self(),
+ Connect = fun(Pid) ->
+ {ok, Socket} = ssl:connect(Hostname, Port, ClientOpts),
+ %% Make sure server finishes and verification
+ %% and is in coonection state before
+ %% killing client
+ ct:sleep(?SLEEP),
+ Pid ! {self(), connected, Socket},
+ receive die_nice -> normal end
+ end,
+ Client2 = spawn_link(fun() -> Connect(Tester) end),
+ receive {Client2, connected, _Socket} -> Client2 ! die_nice end,
+
+ get_close(Client2, ?LINE),
+
+ %% Test that clients die when the controlling process have changed
+ Server ! listen,
+
+ Client3 = spawn_link(fun() -> Connect(Tester) end),
+ Controller = spawn_link(fun() -> receive die_nice -> normal end end),
+ receive
+ {Client3, connected, Socket} ->
+ ok = ssl:controlling_process(Socket, Controller),
+ Client3 ! die_nice
+ end,
+
+ ct:log("Wating on exit ~p~n",[Client3]),
+ receive {'EXIT', Client3, normal} -> ok end,
+
+ receive %% Client3 is dead but that doesn't matter, socket should not be closed.
+ Unexpected ->
+ ct:log("Unexpected ~p~n",[Unexpected]),
+ ct:fail({line, ?LINE-1})
+ after 1000 ->
+ ok
+ end,
+ Controller ! die_nice,
+ get_close(Controller, ?LINE),
+
+ %% Test that servers die
+ Server ! listen,
+ LastClient = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ controller_dies_result, [self(),
+ ClientMsg]}},
+ {options, ClientOpts}]),
+ ct:sleep(?SLEEP), %% so that they are connected
+
+ exit(Server, killed),
+ get_close(Server, ?LINE),
+ process_flag(trap_exit, false),
+ ssl_test_lib:close(LastClient).
+%%--------------------------------------------------------------------
+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_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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).
+
+%%--------------------------------------------------------------------
+close_with_timeout() ->
+ [{doc,"Test normal (not downgrade) ssl:close/2"}].
+close_with_timeout(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, tls_close, []}},
+ {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_close, []}},
+ {options, [{active, false} |ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok).
+
+%%--------------------------------------------------------------------
+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.
+
+%%--------------------------------------------------------------------
+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.
+%%--------------------------------------------------------------------
+close_transport_accept() ->
+ [{doc,"Tests closing ssl socket when waiting on ssl:transport_accept/1"}].
+
+close_transport_accept(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config),
+
+ Port = 0,
+ Opts = [{active, false} | ServerOpts],
+ {ok, ListenSocket} = rpc:call(ServerNode, ssl, listen, [Port, Opts]),
+ spawn_link(fun() ->
+ ct:sleep(?SLEEP),
+ rpc:call(ServerNode, ssl, close, [ListenSocket])
+ end),
+ case rpc:call(ServerNode, ssl, transport_accept, [ListenSocket]) of
+ {error, closed} ->
+ ok;
+ Other ->
+ exit({?LINE, 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_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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).
+
+%%--------------------------------------------------------------------
+
+invalid_keyfile() ->
+ [{doc,"Test what happens with an invalid key file"}].
+invalid_keyfile(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ BadKeyFile = filename:join([proplists:get_value(priv_dir, Config),
+ "badkey.pem"]),
+ BadOpts = [{keyfile, BadKeyFile}| proplists:delete(keyfile, ServerOpts)],
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server =
+ ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, BadOpts}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {from, self()}, {options, ClientOpts}]),
+
+ File = proplists:get_value(keyfile,BadOpts),
+ ssl_test_lib:check_result(Server, {error,{options, {keyfile, File, {error,enoent}}}}, Client,
+ {error, closed}).
+
+%%--------------------------------------------------------------------
+honor_server_cipher_order() ->
+ [{doc,"Test API honor server cipher order."}].
+honor_server_cipher_order(Config) when is_list(Config) ->
+ 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 = [#{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}).
+
+%%--------------------------------------------------------------------
+ipv6() ->
+ [{require, ipv6_hosts},
+ {doc,"Test ipv6."}].
+ipv6(Config) when is_list(Config) ->
+ {ok, Hostname0} = inet:gethostname(),
+
+ case lists:member(list_to_atom(Hostname0), ct:get_config(ipv6_hosts)) of
+ true ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} =
+ ssl_test_lib:run_where(Config, ipv6),
+ Server = ssl_test_lib:start_server([{node, ServerNode},
+ {port, 0}, {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options,
+ [inet6, {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, {ssl_test_lib, send_recv_result, []}},
+ {options,
+ [inet6, {active, false} | ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client);
+ false ->
+ {skip, "Host does not support IPv6"}
+ end.
+
+%%--------------------------------------------------------------------
+der_input() ->
+ [{doc,"Test to input certs and key as der"}].
+
+der_input(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ DHParamFile = filename:join(DataDir, "dHParam.pem"),
+
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ [CADb | _] = element(6, State),
+
+ Size = ets:info(CADb, size),
+
+ SeverVerifyOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ServerCert, ServerKey, ServerCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
+ SeverVerifyOpts]),
+ ClientVerifyOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ {ClientCert, ClientKey, ClientCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
+ ClientVerifyOpts]),
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
+ {cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCaCerts}],
+ ClientOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
+ {cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCaCerts}],
+ {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, send_recv_result, []}},
+ {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, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ Size = ets:info(CADb, size).
+
+%%--------------------------------------------------------------------
+invalid_certfile() ->
+ [{doc,"Test what happens with an invalid cert file"}].
+
+invalid_certfile(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ BadCertFile = filename:join([proplists:get_value(priv_dir, Config),
+ "badcert.pem"]),
+ ServerBadOpts = [{certfile, BadCertFile}| proplists:delete(certfile, ServerOpts)],
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server =
+ ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerBadOpts}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {from, self()},
+ {options, ClientOpts}]),
+ File = proplists:get_value(certfile, ServerBadOpts),
+ ssl_test_lib:check_result(Server, {error,{options, {certfile, File, {error,enoent}}}},
+ Client, {error, closed}).
+
+
+%%--------------------------------------------------------------------
+invalid_cacertfile() ->
+ [{doc,"Test what happens with an invalid cacert file"}].
+
+invalid_cacertfile(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ BadCACertFile = filename:join([proplists:get_value(priv_dir, Config),
+ "badcacert.pem"]),
+ ServerBadOpts = [{cacertfile, BadCACertFile}| proplists:delete(cacertfile, ServerOpts)],
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server0 =
+ ssl_test_lib:start_server_error([{node, ServerNode},
+ {port, 0}, {from, self()},
+ {options, ServerBadOpts}]),
+
+ Port0 = ssl_test_lib:inet_port(Server0),
+
+
+ Client0 =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {from, self()},
+ {options, ClientOpts}]),
+
+ File0 = proplists:get_value(cacertfile, ServerBadOpts),
+
+ ssl_test_lib:check_result(Server0, {error, {options, {cacertfile, File0,{error,enoent}}}},
+ Client0, {error, closed}),
+
+ File = File0 ++ "do_not_exit.pem",
+ ServerBadOpts1 = [{cacertfile, File}|proplists:delete(cacertfile, ServerBadOpts)],
+
+ Server1 =
+ ssl_test_lib:start_server_error([{node, ServerNode},
+ {port, 0}, {from, self()},
+ {options, ServerBadOpts1}]),
+
+ Port1 = ssl_test_lib:inet_port(Server1),
+
+ Client1 =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port1}, {host, Hostname},
+ {from, self()},
+ {options, ClientOpts}]),
+
+
+ ssl_test_lib:check_result(Server1, {error, {options, {cacertfile, File,{error,enoent}}}},
+ Client1, {error, closed}),
+ ok.
+
+%%--------------------------------------------------------------------
+new_options_in_handshake() ->
+ [{doc,"Test that you can set ssl options in handshake/3 and not only in tcp upgrade"}].
+new_options_in_handshake(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ Version = ssl_test_lib:protocol_version(Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ [_, Cipher | _] = ssl:filter_cipher_suites(ssl:cipher_suites(all, Version),
+ [{key_exchange,
+ fun(dhe_rsa) ->
+ true;
+ (ecdhe_rsa) ->
+ true;
+ (ecdh_rsa) ->
+ true;
+ (rsa) ->
+ true;
+ (_) ->
+ false
+ end
+ }]),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {ssl_extra_opts, [{versions, [Version]},
+ {ciphers,[Cipher]}]}, %% To be set in ssl_accept/3
+ {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, [Cipher]} | ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ServerMsg = ClientMsg = {ok, {Version, Cipher}},
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%-------------------------------------------------------------------
+max_handshake_size() ->
+ [{doc,"Test that we can set max_handshake_size to max value."}].
+
+max_handshake_size(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{max_handshake_size, 8388607} |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, send_recv_result_active, []}},
+ {options, [{max_handshake_size, 8388607} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok).
+
+
+%%-------------------------------------------------------------------
+options_not_proplist() ->
+ [{doc,"Test what happens if an option is not a key value tuple"}].
+
+options_not_proplist(Config) when is_list(Config) ->
+ BadOption = {client_preferred_next_protocols,
+ client, [<<"spdy/3">>,<<"http/1.1">>], <<"http/1.1">>},
+ {option_not_a_key_value_tuple, BadOption} =
+ ssl:connect("twitter.com", 443, [binary, {active, false},
+ BadOption]).
+
+%%-------------------------------------------------------------------
+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_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) ->
+ ssl_test_lib:check_result(Server,
+ {error, {options, {sslv2, Option}}},
+ Client,
+ {error, {options, {sslv2, Option}}});
+ (Client, Server, Option) ->
+ ssl_test_lib:check_result(Server,
+ {error, {options, Option}},
+ Client,
+ {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' }],
+
+ [begin
+ Server =
+ ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, [TestOpt | ServerOpts]}]),
+ %% Will never reach a point where port is used.
+ Client =
+ ssl_test_lib:start_client_error([{node, ClientNode}, {port, 0},
+ {host, Hostname}, {from, self()},
+ {options, [TestOpt | ClientOpts]}]),
+ Check(Client, Server, TestOpt),
+ ok
+ end || TestOpt <- TestOpts],
+ ok.
+%%-------------------------------------------------------------------
+
+default_reject_anonymous()->
+ [{doc,"Test that by default anonymous cipher suites are rejected "}].
+default_reject_anonymous(Config) when is_list(Config) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ Version = ssl_test_lib:protocol_version(Config),
+ TLSVersion = ssl_test_lib:tls_version(Version),
+
+ [CipherSuite | _] = ssl_test_lib:ecdh_dh_anonymous_suites(TLSVersion),
+
+ Server = ssl_test_lib:start_server_error([{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,
+ [{ciphers,[CipherSuite]} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_server_alert(Server, Client, insufficient_security).
+
+%%-------------------------------------------------------------------
+%% Note that these test only test that the options are valid to set. As application data
+%% is a stream you can not test that the send acctually splits it up as when it arrives
+%% again at the user layer it may be concatenated. But COVER can show that the split up
+%% code has been run.
+
+rizzo_disabled() ->
+ [{doc, "Test original beast mitigation disable option for SSL 3.0 and TLS 1.0"}].
+
+rizzo_disabled(Config) ->
+ ClientOpts = [{beast_mitigation, disabled} | ssl_test_lib:ssl_options(client_rsa_opts, Config)],
+ ServerOpts = [{beast_mitigation, disabled} | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%-------------------------------------------------------------------
+rizzo_zero_n() ->
+ [{doc, "Test zero_n beast mitigation option (same affect as original disable option) for SSL 3.0 and TLS 1.0"}].
+
+rizzo_zero_n(Config) ->
+ ClientOpts = [{beast_mitigation, zero_n} | ssl_test_lib:ssl_options(client_rsa_opts, Config)],
+ ServerOpts = [{beast_mitigation, zero_n} | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%-------------------------------------------------------------------
+rizzo_one_n_minus_one () ->
+ [{doc, "Test beast_mitigation option one_n_minus_one (same affect as default) for SSL 3.0 and TLS 1.0"}].
+
+rizzo_one_n_minus_one (Config) ->
+ ClientOpts = [{beast_mitigation, one_n_minus_one } | ssl_test_lib:ssl_options(client_rsa_opts, Config)],
+ ServerOpts = [{beast_mitigation, one_n_minus_one} | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+supported_groups() ->
+ [{doc,"Test the supported_groups option in TLS 1.3."}].
+
+supported_groups(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{supported_groups, [x448, x25519]} | 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, send_recv_result_active, []}},
+ {options, [{supported_groups,[x448]} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+honor_client_cipher_order_tls13() ->
+ [{doc,"Test API honor server cipher order in TLS 1.3."}].
+honor_client_cipher_order_tls13(Config) when is_list(Config) ->
+ ClientCiphers = [#{key_exchange => any,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384},
+ #{key_exchange => any,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256}],
+ ServerCiphers = [#{key_exchange => any,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256},
+ #{key_exchange => any,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384}],
+ honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, #{key_exchange => any,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384}).
+
+%%--------------------------------------------------------------------
+honor_server_cipher_order_tls13() ->
+ [{doc,"Test API honor server cipher order in TLS 1.3."}].
+honor_server_cipher_order_tls13(Config) when is_list(Config) ->
+ ClientCiphers = [#{key_exchange => any,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384},
+ #{key_exchange => any,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256}],
+ ServerCiphers = [#{key_exchange => any,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256},
+ #{key_exchange => any,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384}],
+ honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => any,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256}).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+peercert_result(Socket) ->
+ ssl:peercert(Socket).
+
+connection_information_result(Socket) ->
+ {ok, Info = [_ | _]} = ssl:connection_information(Socket),
+ case length(Info) > 3 of
+ true ->
+ %% Atleast one ssl_option() is set
+ ct:log("Info ~p", [Info]),
+ ok;
+ false ->
+ ct:fail(no_ssl_options_returned)
+ end.
+secret_connection_info_result(Socket) ->
+ {ok, [{protocol, Protocol}]} = ssl:connection_information(Socket, [protocol]),
+ {ok, ConnInfo} = ssl:connection_information(Socket, [client_random, server_random, master_secret]),
+ check_connection_info(Protocol, ConnInfo).
+
+
+%% In TLS 1.3 the master_secret field is used to store multiple secrets from the key schedule and it is a tuple.
+%% client_random and server_random are not used in the TLS 1.3 key schedule.
+check_connection_info('tlsv1.3', [{client_random, ClientRand}, {master_secret, {master_secret, MasterSecret}}]) ->
+ is_binary(ClientRand) andalso is_binary(MasterSecret);
+check_connection_info('tlsv1.3', [{server_random, ServerRand}, {master_secret, {master_secret, MasterSecret}}]) ->
+ is_binary(ServerRand) andalso is_binary(MasterSecret);
+check_connection_info(_, [{client_random, ClientRand}, {server_random, ServerRand}, {master_secret, MasterSecret}]) ->
+ is_binary(ClientRand) andalso is_binary(ServerRand) andalso is_binary(MasterSecret);
+check_connection_info(_, _) ->
+ false.
+
+
+prf_create_plan(TlsVersions, PRFs, Results) ->
+ lists:foldl(fun(Ver, Acc) ->
+ A = prf_ciphers_and_expected(Ver, PRFs, Results),
+ [A|Acc]
+ end, [], TlsVersions).
+
+prf_ciphers_and_expected(TlsVer, PRFs, Results) ->
+ case TlsVer of
+ TlsVer when TlsVer == sslv3 orelse TlsVer == tlsv1
+ orelse TlsVer == 'tlsv1.1' orelse TlsVer == 'dtlsv1' ->
+ Ciphers = ssl:cipher_suites(),
+ {_, Expected} = lists:keyfind(md5sha, 1, Results),
+ [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected}, {prf, md5sha}]];
+ TlsVer when TlsVer == 'tlsv1.2' orelse TlsVer == 'dtlsv1.2'->
+ lists:foldl(
+ fun(PRF, Acc) ->
+ Ciphers = prf_get_ciphers(TlsVer, PRF),
+ case Ciphers of
+ [] ->
+ ct:log("No ciphers for PRF algorithm ~p. Skipping.", [PRF]),
+ Acc;
+ Ciphers ->
+ {_, Expected} = lists:keyfind(PRF, 1, Results),
+ [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected},
+ {prf, PRF}] | Acc]
+ end
+ end, [], PRFs)
+ end.
+
+prf_get_ciphers(_, PRF) ->
+ lists:filter(
+ fun(C) when tuple_size(C) == 4 andalso
+ element(4, C) == PRF ->
+ true;
+ (_) ->
+ false
+ end,
+ ssl:cipher_suites()).
+
+prf_run_test(_, TlsVer, [], _, Prf) ->
+ ct:fail({error, cipher_list_empty, TlsVer, Prf});
+prf_run_test(Config, TlsVer, Ciphers, Expected, Prf) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ BaseOpts = [{active, true}, {versions, [TlsVer]}, {ciphers, Ciphers}, {protocol, tls_or_dtls(TlsVer)}],
+ ServerOpts = BaseOpts ++ proplists:get_value(server_opts, Config),
+ ClientOpts = BaseOpts ++ proplists:get_value(client_opts, Config),
+ Server = ssl_test_lib:start_server(
+ [{node, ServerNode}, {port, 0}, {from, self()},
+ {mfa, {?MODULE, prf_verify_value, [TlsVer, Expected, Prf]}},
+ {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, prf_verify_value, [TlsVer, Expected, Prf]}},
+ {options, ClientOpts}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+prf_verify_value(Socket, TlsVer, Expected, Algo) ->
+ Ret = ssl:prf(Socket, <<>>, <<>>, [<<>>], 16),
+ case TlsVer of
+ sslv3 ->
+ case Ret of
+ {error, undefined} -> ok;
+ _ ->
+ {error, {expected, {error, undefined},
+ got, Ret, tls_ver, TlsVer, prf_algorithm, Algo}}
+ end;
+ _ ->
+ case Ret of
+ {ok, Expected} -> ok;
+ {ok, Val} -> {error, {expected, Expected, got, Val, tls_ver, TlsVer,
+ prf_algorithm, Algo}}
+ end
+ end.
+
+tls_or_dtls('dtlsv1') ->
+ dtls;
+tls_or_dtls('dtlsv1.2') ->
+ dtls;
+tls_or_dtls(_) ->
+ tls.
+
+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.
+
+try_recv_active(Socket) ->
+ ssl:send(Socket, "Hello world"),
+ {error, einval} = ssl:recv(Socket, 11),
+ ok.
+try_recv_active_once(Socket) ->
+ {error, einval} = ssl:recv(Socket, 11),
+ ok.
+
+controlling_process_result(Socket, Pid, Msg) ->
+ ok = ssl:controlling_process(Socket, Pid),
+ %% Make sure other side has evaluated controlling_process
+ %% before message is sent
+ ct:sleep(?SLEEP),
+ ssl:send(Socket, Msg),
+ no_result_msg.
+
+controller_dies_result(_Socket, _Pid, _Msg) ->
+ receive Result -> Result end.
+get_close(Pid, Where) ->
+ receive
+ {'EXIT', Pid, _Reason} ->
+ receive
+ {_, {ssl_closed, Socket}} ->
+ ct:log("Socket closed ~p~n",[Socket]);
+ Unexpected ->
+ ct:log("Unexpected ~p~n",[Unexpected]),
+ ct:fail({line, ?LINE-1})
+ after 5000 ->
+ ct:fail({timeout, {line, ?LINE, Where}})
+ end;
+ Unexpected ->
+ ct:log("Unexpected ~p~n",[Unexpected]),
+ ct:fail({line, ?LINE-1})
+ after 5000 ->
+ ct:fail({timeout, {line, ?LINE, Where}})
+ end.
+
+ssl_active_recv(N) ->
+ ssl_active_recv(N, []).
+
+ssl_active_recv(0, Acc) ->
+ Acc;
+ssl_active_recv(N, Acc) ->
+ receive
+ {ssl, _, Bytes} ->
+ ssl_active_recv(N-length(Bytes), Acc ++ Bytes)
+ end.
+
+send_recv_result_timeout_client(Socket) ->
+ {error, timeout} = ssl:recv(Socket, 11, 500),
+ {error, timeout} = ssl:recv(Socket, 11, 0),
+ ssl:send(Socket, "Hello world"),
+ receive
+ Msg ->
+ io:format("Msg ~p~n",[Msg])
+ after 500 ->
+ ok
+ end,
+ {ok, "Hello world"} = ssl:recv(Socket, 11, 500),
+ ok.
+send_recv_result_timeout_server(Socket) ->
+ ssl:send(Socket, "Hello"),
+ {ok, "Hello world"} = ssl:recv(Socket, 11),
+ ssl:send(Socket, " world"),
+ ok.
+
+do_recv_close(Socket) ->
+ {error, closed} = ssl:recv(Socket, 11),
+ receive
+ {_,{error,closed}} ->
+ error_extra_close_sent_to_user_process
+ after 500 ->
+ ok
+ end.
+
+tls_close(Socket) ->
+ ok = ssl_test_lib:send_recv_result(Socket),
+ case ssl:close(Socket, 5000) of
+ ok ->
+ ok;
+ {error, closed} ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end.
+
+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).
+
+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()).
+
+run_client_error([Port, Opts]) ->
+ ssl:connect("localhost", Port, Opts).
+
+honor_cipher_order(Config, Honor, ServerCiphers, ClientCiphers, Expected) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, connection_info_result, []}},
+ {options, [{ciphers, ServerCiphers}, {honor_cipher_order, Honor}
+ | 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, ClientCiphers}, {honor_cipher_order, Honor}
+ | ClientOpts]}]),
+
+ Version = ssl_test_lib:protocol_version(Config),
+
+ ServerMsg = ClientMsg = {ok, {Version, Expected}},
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+connection_info_result(Socket) ->
+ {ok, Info} = ssl:connection_information(Socket, [protocol, selected_cipher_suite]),
+ {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}}.
+
+der_input_opts(Opts) ->
+ Certfile = proplists:get_value(certfile, Opts),
+ CaCertsfile = proplists:get_value(cacertfile, Opts),
+ Keyfile = proplists:get_value(keyfile, Opts),
+ Dhfile = proplists:get_value(dhfile, Opts),
+ [{_, Cert, _}] = ssl_test_lib:pem_to_der(Certfile),
+ [{Asn1Type, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
+ [{_, DHParams, _}] = ssl_test_lib:pem_to_der(Dhfile),
+ CaCerts =
+ lists:map(fun(Entry) ->
+ {_, CaCert, _} = Entry,
+ CaCert
+ end, ssl_test_lib:pem_to_der(CaCertsfile)),
+ {Cert, {Asn1Type, Key}, CaCerts, DHParams}.
diff --git a/lib/ssl/test/ssl_basic_SUITE_data/dHParam.pem b/lib/ssl/test/ssl_api_SUITE_data/dHParam.pem
index feb581da30..feb581da30 100644
--- a/lib/ssl/test/ssl_basic_SUITE_data/dHParam.pem
+++ b/lib/ssl/test/ssl_api_SUITE_data/dHParam.pem
diff --git a/lib/ssl/test/ssl_app_env_SUITE.erl b/lib/ssl/test/ssl_app_env_SUITE.erl
new file mode 100644
index 0000000000..27fbcb8e47
--- /dev/null
+++ b/lib/ssl/test/ssl_app_env_SUITE.erl
@@ -0,0 +1,171 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(ssl_app_env_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssl/src/ssl_api.hrl").
+
+-define(SLEEP, 500).
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ [
+ {group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.3', [], tests()},
+ {'tlsv1.2', [], tests()},
+ {'tlsv1.1', [], tests()},
+ {'tlsv1', [], tests()},
+ {'sslv3', [], tests()},
+ {'dtlsv1.2', [], tests()},
+ {'dtlsv1', [], tests()}
+ ].
+
+tests() ->
+ [
+ internal_active_1,
+ protocol_versions,
+ empty_protocol_versions
+ ].
+
+
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ [{client_type, erlang},
+ {server_type, erlang} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(internal_active_1, Config) ->
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, internal_active_n, 1),
+ ssl:start(),
+ ct:timetrap({seconds, 5}),
+ Config;
+init_per_testcase(protocol_versions, Config) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ case atom_to_list(Version) of
+ "d" ++ _ ->
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, dtls_protocol_version, [Version]),
+ ssl:start();
+ _ ->
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, protocol_version, [Version]),
+ ssl:start()
+ end,
+ ct:timetrap({seconds, 5}),
+ Config;
+init_per_testcase(empty_protocol_versions, Config) ->
+ ssl:stop(),
+ application:load(ssl),
+ ssl_test_lib:clean_env(),
+ application:set_env(ssl, protocol_version, []),
+ application:set_env(ssl, dtls_protocol_version, []),
+ ssl:start(),
+ ct:timetrap({seconds, 5}),
+ Config;
+init_per_testcase(_TestCase, Config) ->
+ ct:timetrap({seconds, 5}),
+ Config.
+
+end_per_testcase(_, _Config) ->
+ ssl_test_lib:clean_start().
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+internal_active_1() ->
+ [{doc,"Test internal active 1 (behave as internal active once)"}].
+
+internal_active_1(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+protocol_versions() ->
+ [{doc,"Test to set a list of protocol versions in app environment."}].
+
+protocol_versions(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+empty_protocol_versions() ->
+ [{doc,"Test to set an empty list of protocol versions in app environment."}].
+
+empty_protocol_versions(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 86a0aaf67b..355cd31070 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -26,15 +26,8 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include_lib("public_key/include/public_key.hrl").
+-include_lib("ssl/src/ssl_api.hrl").
--include("ssl_api.hrl").
--include("ssl_cipher.hrl").
--include("ssl_internal.hrl").
--include("ssl_alert.hrl").
--include("ssl_internal.hrl").
--include("tls_record.hrl").
--include("tls_handshake.hrl").
-define(TIMEOUT, 20000).
-define(EXPIRE, 10).
@@ -49,243 +42,35 @@
all() ->
[
{group, basic},
- {group, basic_tls},
- {group, options},
- {group, options_tls},
- {group, session},
- {group, 'dtlsv1.2'},
- {group, 'dtlsv1'},
- {group, 'tlsv1.3'},
- {group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'sslv3'}
+ {group, options}
].
groups() ->
[{basic, [], basic_tests()},
- {basic_tls, [], basic_tests_tls()},
- {options, [], options_tests()},
- {options_tls, [], options_tests_tls()},
- {'dtlsv1.2', [], all_versions_groups()},
- {'dtlsv1', [], all_versions_groups()},
- {'tlsv1.3', [], tls13_test_group()},
- {'tlsv1.2', [], all_versions_groups() ++ tls_versions_groups() ++ [conf_signature_algs, no_common_signature_algs]},
- {'tlsv1.1', [], all_versions_groups() ++ tls_versions_groups()},
- {'tlsv1', [], all_versions_groups() ++ tls_versions_groups() ++ rizzo_tests()},
- {'sslv3', [], all_versions_groups() ++ tls_versions_groups() ++ rizzo_tests() ++ [tls_ciphersuite_vs_version]},
- {api,[], api_tests()},
- {api_tls,[], api_tests_tls()},
- {session, [], session_tests()},
- {renegotiate, [], renegotiate_tests()},
- {ciphers, [], cipher_tests()},
- {error_handling_tests, [], error_handling_tests()},
- {error_handling_tests_tls, [], error_handling_tests_tls()}
+ {options, [], options_tests()}
].
-tls_versions_groups ()->
- [
- {group, api_tls},
- {group, error_handling_tests_tls}].
-
-all_versions_groups ()->
- [{group, api},
- {group, renegotiate},
- {group, ciphers},
- {group, error_handling_tests}].
-
-
basic_tests() ->
[app,
- appup,
- alerts,
- alert_details,
- alert_details_not_too_big,
+ appup,
version_option,
connect_twice,
connect_dist,
- clear_pem_cache,
defaults,
fallback,
cipher_format,
- suite_to_str
- ].
-
-basic_tests_tls() ->
- [tls_send_close
- ].
-
-options_tests() ->
- [der_input,
- ssl_options_not_proplist,
- raw_ssl_option,
- invalid_inet_get_option,
- invalid_inet_get_option_not_list,
- invalid_inet_get_option_improper_list,
- invalid_inet_set_option,
- invalid_inet_set_option_not_list,
- invalid_inet_set_option_improper_list,
- dh_params,
- invalid_certfile,
- invalid_cacertfile,
- invalid_keyfile,
- invalid_options,
- protocol_versions,
- empty_protocol_versions,
- ipv6,
- reuseaddr,
- honor_server_cipher_order,
- honor_client_cipher_order,
- unordered_protocol_versions_server,
- unordered_protocol_versions_client,
- max_handshake_size
-].
-
-options_tests_tls() ->
- [tls_misc_ssl_options,
- tls_tcp_reuseaddr].
-
-api_tests() ->
- [secret_connection_info,
- connection_information,
- peercert,
- peercert_with_client_cert,
- versions,
+ tls_versions_option,
eccs,
- controlling_process,
- getstat,
- close_with_timeout,
- hibernate,
- hibernate_right_away,
- listen_socket,
- ssl_recv_timeout,
- server_name_indication_option,
- accept_pool,
- prf,
- socket_options,
- active_n,
- internal_active_1,
cipher_suites,
- handshake_continue,
- handshake_continue_timeout,
- hello_client_cancel,
- hello_server_cancel
- ].
-
-api_tests_tls() ->
- [tls_versions_option,
- tls_upgrade,
- tls_upgrade_with_timeout,
- tls_ssl_accept_timeout,
- tls_downgrade,
- tls_shutdown,
- tls_shutdown_write,
- tls_shutdown_both,
- tls_shutdown_error,
- peername,
- sockname,
- tls_socket_options,
- new_options_in_accept
- ].
-
-session_tests() ->
- [reuse_session,
- reuse_session_expired,
- server_does_not_want_to_reuse_session,
- no_reuses_session_server_restart_new_cert,
- no_reuses_session_server_restart_new_cert_file].
-
-renegotiate_tests() ->
- [client_renegotiate,
- server_renegotiate,
- client_secure_renegotiate,
- client_secure_renegotiate_fallback,
- client_renegotiate_reused_session,
- server_renegotiate_reused_session,
- client_no_wrap_sequence_number,
- server_no_wrap_sequence_number,
- renegotiate_dos_mitigate_active,
- renegotiate_dos_mitigate_passive,
- renegotiate_dos_mitigate_absolute].
-
-cipher_tests() ->
- [old_cipher_suites,
- cipher_suites_mix,
- default_reject_anonymous].
-
-error_handling_tests()->
- [close_transport_accept,
- recv_active,
- recv_active_once,
- 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()->
- [controller_dies,
- tls_client_closes_socket,
- tls_closed_in_active_once,
- tls_tcp_error_propagation_in_active_mode,
- tls_tcp_connect,
- tls_tcp_connect_big,
- tls_dont_crash_on_handshake_garbage
+ old_cipher_suites,
+ cipher_suites_mix
].
-rizzo_tests() ->
- [rizzo,
- no_rizzo_rc4,
- rizzo_one_n_minus_one,
- rizzo_zero_n,
- rizzo_disabled].
-
-%% For testing TLS 1.3 features and possible regressions
-tls13_test_group() ->
- [handshake_continue_tls13_client,
- tls13_enable_client_side,
- tls13_enable_server_side,
- tls_record_1_3_encode_decode,
- tls13_finished_verify_data,
- tls13_1_RTT_handshake,
- tls12_ssl_server_tls13_ssl_client,
- tls13_basic_ssl_server_openssl_client,
- tls13_basic_ssl_server_ssl_client,
- tls13_basic_openssl_server_ssl_client,
- tls13_custom_groups_ssl_server_openssl_client,
- tls13_custom_groups_ssl_server_ssl_client,
- tls13_hello_retry_request_ssl_server_openssl_client,
- tls13_hello_retry_request_ssl_server_ssl_client,
- tls13_client_auth_empty_cert_alert_ssl_server_openssl_client,
- tls13_client_auth_empty_cert_alert_ssl_server_ssl_client,
- tls13_client_auth_empty_cert_ssl_server_openssl_client,
- tls13_client_auth_empty_cert_ssl_server_ssl_client,
- tls13_client_auth_ssl_server_openssl_client,
- tls13_client_auth_ssl_server_ssl_client,
- tls13_hrr_client_auth_empty_cert_alert_ssl_server_openssl_client,
- tls13_hrr_client_auth_empty_cert_alert_ssl_server_ssl_client,
- tls13_hrr_client_auth_empty_cert_ssl_server_openssl_client,
- tls13_hrr_client_auth_empty_cert_ssl_server_ssl_client,
- tls13_hrr_client_auth_ssl_server_openssl_client,
- tls13_hrr_client_auth_ssl_server_ssl_client,
- tls13_unsupported_sign_algo_client_auth_ssl_server_openssl_client,
- tls13_unsupported_sign_algo_client_auth_ssl_server_ssl_client,
- tls13_unsupported_sign_algo_cert_client_auth_ssl_server_openssl_client,
- tls13_unsupported_sign_algo_cert_client_auth_ssl_server_ssl_client,
- tls13_connection_information,
- tls13_ssl_server_with_alpn_ssl_client,
- tls13_ssl_server_with_alpn_ssl_client_empty_alpn,
- tls13_ssl_server_with_alpn_ssl_client_bad_alpn,
- tls13_ssl_server_with_alpn_ssl_client_alpn,
- tls13_ecdsa_ssl_server_openssl_client,
- tls13_ecdsa_ssl_server_ssl_client,
- tls13_ecdsa_openssl_server_ssl_client,
- tls13_ecdsa_client_auth_ssl_server_ssl_client
- ].
+options_tests() ->
+ [
+ unordered_protocol_versions_server,
+ unordered_protocol_versions_client].
-%%--------------------------------------------------------------------
init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
@@ -308,229 +93,6 @@ end_per_suite(_Config) ->
application:stop(crypto).
%%--------------------------------------------------------------------
-
-init_per_group(GroupName, Config) when GroupName == basic_tls;
- GroupName == options_tls;
- GroupName == options;
- GroupName == basic;
- GroupName == session;
- GroupName == error_handling_tests_tls ->
- ssl_test_lib:clean_tls_version(Config);
-%% Do not automatically configure TLS version for the 'tlsv1.3' group
-init_per_group('tlsv1.3' = GroupName, Config) ->
- case ssl_test_lib:sufficient_crypto_support(GroupName) of
- true ->
- ssl:start(),
- Config;
- false ->
- {skip, "Missing crypto support"}
- end;
-init_per_group(GroupName, Config) ->
- ssl_test_lib:clean_tls_version(Config),
- case ssl_test_lib:is_tls_version(GroupName) andalso ssl_test_lib:sufficient_crypto_support(GroupName) of
- true ->
- ssl_test_lib:init_tls_version(GroupName, Config);
- _ ->
- case ssl_test_lib:sufficient_crypto_support(GroupName) of
- true ->
- ssl:start(),
- Config;
- false ->
- {skip, "Missing crypto support"}
- end
- end.
-
-end_per_group(GroupName, Config) ->
- case ssl_test_lib:is_tls_version(GroupName) of
- true ->
- ssl_test_lib:clean_tls_version(Config);
- false ->
- Config
- end.
-
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) when Case == unordered_protocol_versions_client;
- Case == unordered_protocol_versions_server->
- case proplists:get_value(supported, ssl:versions()) of
- ['tlsv1.2' | _] ->
- ct:timetrap({seconds, 5}),
- Config;
- _ ->
- {skip, "TLS 1.2 need but not supported on this platform"}
- end;
-
-init_per_testcase(protocol_versions, Config) ->
- ssl:stop(),
- application:load(ssl),
- %% For backwards compatibility sslv2 should be filtered out.
- application:set_env(ssl, protocol_version, [sslv2, sslv3, tlsv1]),
- ssl:start(),
- ct:timetrap({seconds, 5}),
- Config;
-
-init_per_testcase(reuse_session_expired, Config) ->
- ssl:stop(),
- application:load(ssl),
- ssl_test_lib:clean_env(),
- application:set_env(ssl, session_lifetime, ?EXPIRE),
- application:set_env(ssl, session_delay_cleanup_time, 500),
- ssl:start(),
- ct:timetrap({seconds, 30}),
- Config;
-
-init_per_testcase(empty_protocol_versions, Config) ->
- ssl:stop(),
- application:load(ssl),
- ssl_test_lib:clean_env(),
- application:set_env(ssl, protocol_version, []),
- ssl:start(),
- ct:timetrap({seconds, 5}),
- Config;
-
-init_per_testcase(fallback, Config) ->
- case tls_record:highest_protocol_version([]) of
- {3, N} when N > 1 ->
- ct:timetrap({seconds, 5}),
- Config;
- _ ->
- {skip, "Not relevant if highest supported version is less than 3.2"}
- end;
-
-init_per_testcase(TestCase, Config) when TestCase == client_renegotiate;
- TestCase == server_renegotiate;
- TestCase == client_secure_renegotiate;
- TestCase == client_renegotiate_reused_session;
- TestCase == server_renegotiate_reused_session;
- TestCase == client_no_wrap_sequence_number;
- TestCase == server_no_wrap_sequence_number;
- TestCase == renegotiate_dos_mitigate_active;
- TestCase == renegotiate_dos_mitigate_passive;
- TestCase == renegotiate_dos_mitigate_absolute ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, ?SEC_RENEGOTIATION_TIMEOUT + 5}),
- Config;
-
-init_per_testcase(TestCase, Config) when TestCase == versions_option;
- TestCase == tls_tcp_connect_big ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 60}),
- Config;
-
-init_per_testcase(version_option, Config) ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 10}),
- Config;
-
-init_per_testcase(reuse_session, Config) ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 10}),
- Config;
-
-init_per_testcase(rizzo, Config) ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 60}),
- Config;
-
-init_per_testcase(no_rizzo_rc4, Config) ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 60}),
- Config;
-
-init_per_testcase(rizzo_one_n_minus_one, Config) ->
- ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 60}),
- rizzo_add_mitigation_option(one_n_minus_one, Config);
-
-init_per_testcase(rizzo_zero_n, Config) ->
- ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 60}),
- rizzo_add_mitigation_option(zero_n, Config);
-
-init_per_testcase(rizzo_disabled, Config) ->
- ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 60}),
- rizzo_add_mitigation_option(disabled, Config);
-
-init_per_testcase(TestCase, Config) when TestCase == no_reuses_session_server_restart_new_cert_file;
- TestCase == no_reuses_session_server_restart_new_cert ->
- ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 15}),
- Config;
-
-init_per_testcase(prf, Config) ->
- ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 40}),
- case proplists:get_value(tc_group_path, Config) of
- [] -> Prop = [];
- [Prop] -> Prop
- end,
- case proplists:get_value(name, Prop) of
- undefined -> TlsVersions = [sslv3, tlsv1, 'tlsv1.1', 'tlsv1.2'];
- TlsVersion when is_atom(TlsVersion) ->
- TlsVersions = [TlsVersion]
- end,
- PRFS=[md5, sha, sha256, sha384, sha512],
- %All are the result of running tls_v1:prf(PrfAlgo, <<>>, <<>>, <<>>, 16)
- %with the specified PRF algorithm
- ExpectedPrfResults=
- [{md5, <<96,139,180,171,236,210,13,10,28,32,2,23,88,224,235,199>>},
- {sha, <<95,3,183,114,33,169,197,187,231,243,19,242,220,228,70,151>>},
- {sha256, <<166,249,145,171,43,95,158,232,6,60,17,90,183,180,0,155>>},
- {sha384, <<153,182,217,96,186,130,105,85,65,103,123,247,146,91,47,106>>},
- {sha512, <<145,8,98,38,243,96,42,94,163,33,53,49,241,4,127,28>>},
- %TLS 1.0 and 1.1 PRF:
- {md5sha, <<63,136,3,217,205,123,200,177,251,211,17,229,132,4,173,80>>}],
- TestPlan = prf_create_plan(TlsVersions, PRFS, ExpectedPrfResults),
- [{prf_test_plan, TestPlan} | Config];
-
-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;
-init_per_testcase(TestCase, Config) when TestCase == clear_pem_cache;
- TestCase == der_input;
- TestCase == defaults ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- %% White box test need clean start
- ssl:stop(),
- ssl:start(),
- ct:timetrap({seconds, 20}),
- Config;
-init_per_testcase(raw_ssl_option, Config) ->
- ct:timetrap({seconds, 5}),
- case os:type() of
- {unix,linux} ->
- Config;
- _ ->
- {skip, "Raw options are platform-specific"}
- end;
-
-init_per_testcase(accept_pool, Config) ->
- ct:timetrap({seconds, 5}),
- case proplists:get_value(protocol, Config) of
- dtls ->
- {skip, "Not yet supported on DTLS sockets"};
- _ ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- Config
- end;
-
-init_per_testcase(internal_active_1, Config) ->
- ssl:stop(),
- application:load(ssl),
- application:set_env(ssl, internal_active_n, 1),
- ssl:start(),
- ct:timetrap({seconds, 5}),
- Config;
-
-init_per_testcase(controller_dies, Config) ->
- ct:timetrap({seconds, 10}),
- Config;
init_per_testcase(eccs, Config) ->
case ssl:eccs() of
[] ->
@@ -545,23 +107,8 @@ init_per_testcase(_TestCase, Config) ->
ct:timetrap({seconds, 5}),
Config.
-end_per_testcase(reuse_session_expired, Config) ->
- application:unset_env(ssl, session_lifetime),
- application:unset_env(ssl, session_delay_cleanup_time),
- end_per_testcase(default_action, Config);
-
-end_per_testcase(internal_active_n, Config) ->
- application:unset_env(ssl, internal_active_n),
- end_per_testcase(default_action, Config);
-
-end_per_testcase(Case, Config) when Case == protocol_versions;
- Case == empty_protocol_versions->
- application:unset_env(ssl, protocol_versions),
- end_per_testcase(default_action, Config);
-
end_per_testcase(_TestCase, Config) ->
Config.
-
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
@@ -575,669 +122,76 @@ appup() ->
appup(Config) when is_list(Config) ->
ok = ?t:appup_test(ssl).
%%--------------------------------------------------------------------
-alerts() ->
- [{doc, "Test ssl_alert:alert_txt/1"}].
-alerts(Config) when is_list(Config) ->
- Descriptions = [?CLOSE_NOTIFY, ?UNEXPECTED_MESSAGE, ?BAD_RECORD_MAC,
- ?DECRYPTION_FAILED_RESERVED, ?RECORD_OVERFLOW, ?DECOMPRESSION_FAILURE,
- ?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, ?USER_CANCELED,
- ?NO_RENEGOTIATION, ?UNSUPPORTED_EXTENSION, ?CERTIFICATE_UNOBTAINABLE,
- ?UNRECOGNISED_NAME, ?BAD_CERTIFICATE_STATUS_RESPONSE,
- ?BAD_CERTIFICATE_HASH_VALUE, ?UNKNOWN_PSK_IDENTITY,
- 255 %% Unsupported/unknow alert will result in a description too
- ],
- Alerts = [?ALERT_REC(?WARNING, ?CLOSE_NOTIFY) |
- [?ALERT_REC(?FATAL, Desc) || Desc <- Descriptions]],
- lists:foreach(fun(Alert) ->
- try ssl_alert:alert_txt(Alert)
- catch
- C:E:T ->
- ct:fail({unexpected, {C, E, T}})
- end
- end, Alerts).
-%%--------------------------------------------------------------------
-alert_details() ->
- [{doc, "Test that ssl_alert:alert_txt/1 result contains extendend error description"}].
-alert_details(Config) when is_list(Config) ->
- Unique = make_ref(),
- UniqueStr = lists:flatten(io_lib:format("~w", [Unique])),
- Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY, Unique),
- case string:str(ssl_alert:alert_txt(Alert), UniqueStr) of
- 0 ->
- ct:fail(error_details_missing);
- _ ->
- ok
- end.
-
-%%--------------------------------------------------------------------
-alert_details_not_too_big() ->
- [{doc, "Test that ssl_alert:alert_txt/1 limits printed depth of extended error description"}].
-alert_details_not_too_big(Config) when is_list(Config) ->
- Reason = lists:duplicate(10, lists:duplicate(10, lists:duplicate(10, {some, data}))),
- Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY, Reason),
- case length(ssl_alert:alert_txt(Alert)) < 1000 of
- true ->
- ok;
- false ->
- ct:fail(ssl_alert_text_too_big)
- end.
-
-%%--------------------------------------------------------------------
-new_options_in_accept() ->
- [{doc,"Test that you can set ssl options in ssl_accept/3 and not only in tcp upgrade"}].
-new_options_in_accept(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_dsa_opts, 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, #{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]},
- {ciphers,[Cipher]} | ServerSslOpts]}, %% To be set in ssl_accept/3
- {mfa, {?MODULE, connection_info_result, []}},
- {options, proplists:delete(cacertfile, ServerOpts0)}]),
-
- 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, [{versions, [Version]},
- {ciphers,[Cipher]} | ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ServerMsg = ClientMsg = {ok, {Version, Cipher}},
+version_option() ->
+ [{doc, "Use version option and do no specify ciphers list. Bug specified incorrect ciphers"}].
+version_option(Config) when is_list(Config) ->
+ Versions = proplists:get_value(supported, ssl:versions()),
+ [version_option_test(Config, Version) || Version <- Versions].
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-handshake_continue() ->
- [{doc, "Test API function ssl:handshake_continue/3"}].
-handshake_continue(Config) when is_list(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},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ssl_test_lib:ssl_options([{reuseaddr, true}, {handshake, hello}],
- Config)},
- {continue_options, proplists:delete(reuseaddr, 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, send_recv_result_active, []}},
- {options, ssl_test_lib:ssl_options([{handshake, hello}],
- Config)},
- {continue_options, proplists:delete(reuseaddr, ClientOpts)}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-
-%%--------------------------------------------------------------------
-handshake_continue_tls13_client() ->
- [{doc, "Test API function ssl:handshake_continue/3"}].
-handshake_continue_tls13_client(Config) when is_list(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
-
- ClientOptsHello0 = ssl_test_lib:ssl_options([{handshake, hello}], Config),
- ClientOptsHello = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOptsHello0],
-
- {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, send_recv_result_active, []}},
- {options, ssl_test_lib:ssl_options([{reuseaddr, true}, {handshake, hello}],
- Config)},
- {continue_options, proplists:delete(reuseaddr, 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, send_recv_result_active, []}},
- {options, ClientOptsHello},
- {continue_options, proplists:delete(reuseaddr, ClientOpts)}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- 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"}].
-hello_client_cancel(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_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()},
- {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)},
- {continue_options, proplists:delete(reuseaddr, ServerOpts)}]),
-
- Port = ssl_test_lib:inet_port(Server),
-
- %% That is ssl:handshake_cancel returns ok
- {connect_failed, ok} = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)},
- {continue_options, cancel}]),
- 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_rsa_verify_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)},
- {continue_options, cancel}]),
-
- Port = ssl_test_lib:inet_port(Server),
-
- {connect_failed, _} = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {options, ssl_test_lib:ssl_options([{handshake, hello}], Config)},
- {continue_options, proplists:delete(reuseaddr, ClientOpts)}]),
-
- ssl_test_lib:check_result(Server, ok).
-
-%%--------------------------------------------------------------------
-prf() ->
- [{doc,"Test that ssl:prf/5 uses the negotiated PRF."}].
-prf(Config) when is_list(Config) ->
- TestPlan = proplists:get_value(prf_test_plan, Config),
- case TestPlan of
- [] -> ct:fail({error, empty_prf_test_plan});
- _ -> lists:foreach(fun(Suite) ->
- lists:foreach(
- fun(Test) ->
- V = proplists:get_value(tls_ver, Test),
- C = proplists:get_value(ciphers, Test),
- E = proplists:get_value(expected, Test),
- P = proplists:get_value(prf, Test),
- prf_run_test(Config, V, C, E, P)
- end, Suite)
- end, TestPlan)
- end.
-
-%%--------------------------------------------------------------------
-
-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_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},
- {from, self()},
- {mfa, {?MODULE, secret_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, secret_connection_info_result, []}},
- {options, ClientOpts}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, true, Client, true),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-
-%%--------------------------------------------------------------------
-
-connection_information() ->
- [{doc,"Test the API function ssl:connection_information/1"}].
-connection_information(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, connection_information_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_information_result, []}},
- {options, ClientOpts}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ServerMsg = ClientMsg = ok,
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-
-%%--------------------------------------------------------------------
-protocol_versions() ->
- [{doc,"Test to set a list of protocol versions in app environment."}].
-
-protocol_versions(Config) when is_list(Config) ->
- basic_test(Config).
-
-%%--------------------------------------------------------------------
-empty_protocol_versions() ->
- [{doc,"Test to set an empty list of protocol versions in app environment."}].
-
-empty_protocol_versions(Config) when is_list(Config) ->
- basic_test(Config).
-
-%%--------------------------------------------------------------------
-
-controlling_process() ->
- [{doc,"Test API function controlling_process/2"}].
-
-controlling_process(Config) when is_list(Config) ->
+connect_twice() ->
+ [{doc,""}].
+connect_twice(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),
- 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}]),
- Port = ssl_test_lib:inet_port(Server),
- {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]),
-
- 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).
-
-%%--------------------------------------------------------------------
-getstat() ->
- [{doc,"Test API function getstat/2"}].
-getstat(Config) when is_list(Config) ->
- ClientOpts = ?config(client_opts, Config),
- ServerOpts = ?config(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {options, [{active, false} | ServerOpts]}]),
- Port1 = ssl_test_lib:inet_port(Server1),
- Server2 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {options, [{active, false} | ServerOpts]}]),
- Port2 = ssl_test_lib:inet_port(Server2),
- {ok, ActiveC} = rpc:call(ClientNode, ssl, connect,
- [Hostname,Port1,[{active, once}|ClientOpts]]),
- {ok, PassiveC} = rpc:call(ClientNode, ssl, connect,
- [Hostname,Port2,[{active, false}|ClientOpts]]),
-
- ct:log("Testcase ~p, Client ~p Servers ~p, ~p ~n",
- [self(), self(), Server1, Server2]),
-
- %% We only check that the values are non-zero initially
- %% (due to the handshake), and that sending more changes the values.
-
- %% Passive socket.
-
- {ok, InitialStats} = ssl:getstat(PassiveC),
- ct:pal("InitialStats ~p~n", [InitialStats]),
- [true] = lists:usort([0 =/= proplists:get_value(Name, InitialStats)
- || Name <- [recv_cnt, recv_oct, recv_avg, recv_max, send_cnt, send_oct, send_avg, send_max]]),
-
- ok = ssl:send(PassiveC, "Hello world"),
- wait_for_send(PassiveC),
- {ok, SStats} = ssl:getstat(PassiveC, [send_cnt, send_oct]),
- ct:pal("SStats ~p~n", [SStats]),
- [true] = lists:usort([proplists:get_value(Name, SStats) =/= proplists:get_value(Name, InitialStats)
- || Name <- [send_cnt, send_oct]]),
-
- %% Active socket.
-
- {ok, InitialAStats} = ssl:getstat(ActiveC),
- ct:pal("InitialAStats ~p~n", [InitialAStats]),
- [true] = lists:usort([0 =/= proplists:get_value(Name, InitialAStats)
- || Name <- [recv_cnt, recv_oct, recv_avg, recv_max, send_cnt, send_oct, send_avg, send_max]]),
- _ = receive
- {ssl, ActiveC, _} ->
- ok
- after
- ?SLEEP ->
- exit(timeout)
- end,
-
- ok = ssl:send(ActiveC, "Hello world"),
- wait_for_send(ActiveC),
- {ok, ASStats} = ssl:getstat(ActiveC, [send_cnt, send_oct]),
- ct:pal("ASStats ~p~n", [ASStats]),
- [true] = lists:usort([proplists:get_value(Name, ASStats) =/= proplists:get_value(Name, InitialAStats)
- || Name <- [send_cnt, send_oct]]),
-
- ok.
-
-%%--------------------------------------------------------------------
-controller_dies() ->
- [{doc,"Test that the socket is closed after controlling process dies"}].
-controller_dies(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),
- ClientMsg = "Hello server",
- ServerMsg = "Hello client",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE,
- controller_dies_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()},
- {mfa, {?MODULE,
- controller_dies_result, [self(),
- ClientMsg]}},
- {options, ClientOpts}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]),
- ct:sleep(?SLEEP), %% so that they are connected
-
- process_flag(trap_exit, true),
-
- %% Test that clients die
- exit(Client, killed),
- get_close(Client, ?LINE),
-
- %% Test that clients die when process disappear
- Server ! listen,
- Tester = self(),
- Connect = fun(Pid) ->
- {ok, Socket} = ssl:connect(Hostname, Port, ClientOpts),
- %% Make sure server finishes and verification
- %% and is in coonection state before
- %% killing client
- ct:sleep(?SLEEP),
- Pid ! {self(), connected, Socket},
- receive die_nice -> normal end
- end,
- Client2 = spawn_link(fun() -> Connect(Tester) end),
- receive {Client2, connected, _Socket} -> Client2 ! die_nice end,
-
- get_close(Client2, ?LINE),
-
- %% Test that clients die when the controlling process have changed
- Server ! listen,
-
- Client3 = spawn_link(fun() -> Connect(Tester) end),
- Controller = spawn_link(fun() -> receive die_nice -> normal end end),
- receive
- {Client3, connected, Socket} ->
- ok = ssl:controlling_process(Socket, Controller),
- Client3 ! die_nice
- end,
-
- ct:log("Wating on exit ~p~n",[Client3]),
- receive {'EXIT', Client3, normal} -> ok end,
-
- receive %% Client3 is dead but that doesn't matter, socket should not be closed.
- Unexpected ->
- ct:log("Unexpected ~p~n",[Unexpected]),
- ct:fail({line, ?LINE-1})
- after 1000 ->
- ok
- end,
- Controller ! die_nice,
- get_close(Controller, ?LINE),
-
- %% Test that servers die
- Server ! listen,
- LastClient = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- controller_dies_result, [self(),
- ClientMsg]}},
- {options, ClientOpts}]),
- ct:sleep(?SLEEP), %% so that they are connected
-
- exit(Server, killed),
- get_close(Server, ?LINE),
- process_flag(trap_exit, false),
- ssl_test_lib:close(LastClient).
-
-%%--------------------------------------------------------------------
-tls_client_closes_socket() ->
- [{doc,"Test what happens when client closes socket before handshake is compleated"}].
-
-tls_client_closes_socket(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- TcpOpts = [binary, {reuseaddr, true}],
-
- Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {tcp_options, TcpOpts},
- {ssl_options, ServerOpts}]),
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{keepalive, true},{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, {ssl_test_lib, send_recv_result, []}},
+ {options, [{keepalive, true},{active, false}
+ | ClientOpts]}]),
+ Server ! listen,
- Connect = fun() ->
- {ok, _Socket} = rpc:call(ClientNode, gen_tcp, connect,
- [Hostname, Port, [binary]]),
- %% Make sure that ssl_accept is called before
- %% client process ends and closes socket.
- ct:sleep(?SLEEP)
- end,
-
- _Client = spawn_link(Connect),
-
- ssl_test_lib:check_result(Server, {error,closed}).
-
-%%--------------------------------------------------------------------
-tls_closed_in_active_once() ->
- [{doc, "Test that ssl_closed is delivered in active once with non-empty buffer, check ERL-420."}].
-
-tls_closed_in_active_once(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),
- TcpOpts = [binary, {reuseaddr, true}],
- Port = ssl_test_lib:inet_port(node()),
- Server = fun() ->
- {ok, Listen} = gen_tcp:listen(Port, TcpOpts),
- {ok, TcpServerSocket} = gen_tcp:accept(Listen),
- {ok, ServerSocket} = ssl:ssl_accept(TcpServerSocket, ServerOpts),
- lists:foreach(
- fun(_) ->
- ssl:send(ServerSocket, "some random message\r\n")
- end, lists:seq(1, 20)),
- %% Close TCP instead of SSL socket to trigger the bug:
- gen_tcp:close(TcpServerSocket),
- gen_tcp:close(Listen)
- end,
- spawn_link(Server),
- {ok, Socket} = ssl:connect(Hostname, Port, [{active, false} | ClientOpts]),
- Result = tls_closed_in_active_once_loop(Socket),
- ssl:close(Socket),
- case Result of
- ok -> ok;
- _ -> ct:fail(Result)
- end.
-
-tls_closed_in_active_once_loop(Socket) ->
- 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"}].
-
-connect_dist(Config) when is_list(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_kc_opts, Config),
- ClientOpts = [{ssl_imp, new},{active, false}, {packet,4}|ClientOpts0],
- ServerOpts0 = ssl_test_lib:ssl_options(server_kc_opts, Config),
- ServerOpts = [{ssl_imp, new},{active, false}, {packet,4}|ServerOpts0],
+ {Client1, #sslsocket{}} =
+ ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{keepalive, true},{active, false}
+ | ClientOpts]}]),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, connect_dist_s, []}},
- {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, connect_dist_c, []}},
- {options, ClientOpts}]),
-
ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:check_result(Server, ok, Client1, ok),
ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
-clear_pem_cache() ->
- [{doc,"Test that internal reference tabel is cleaned properly even when "
- " the PEM cache is cleared" }].
-clear_pem_cache(Config) when is_list(Config) ->
- {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- [_,{FilRefDb, _} |_] = element(6, State),
- {Server, Client} = basic_verify_test_no_close(Config),
- CountReferencedFiles = fun({_, -1}, Acc) ->
- Acc;
- ({_, N}, Acc) ->
- N + Acc
- end,
-
- 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
- ssl:clear_pem_cache(),
- _ = sys:get_status(whereis(ssl_manager)),
- {Server1, Client1} = basic_verify_test_no_close(Config),
- 4 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
- ssl_test_lib:close(Server),
ssl_test_lib:close(Client),
- ct:sleep(2000),
- _ = sys:get_status(whereis(ssl_manager)),
- 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1),
- ct:sleep(2000),
- _ = sys:get_status(whereis(ssl_manager)),
- 0 = ets:foldl(CountReferencedFiles, 0, FilRefDb).
+ ssl_test_lib:close(Client1).
+defaults(Config) when is_list(Config)->
+ Versions = ssl:versions(),
+ true = lists:member(sslv3, proplists:get_value(available, Versions)),
+ false = lists:member(sslv3, proplists:get_value(supported, Versions)),
+ true = lists:member('tlsv1', proplists:get_value(available, Versions)),
+ false = lists:member('tlsv1', proplists:get_value(supported, Versions)),
+ true = lists:member('tlsv1.1', proplists:get_value(available, Versions)),
+ false = lists:member('tlsv1.1', proplists:get_value(supported, Versions)),
+ true = lists:member('tlsv1.2', proplists:get_value(available, Versions)),
+ true = lists:member('tlsv1.2', proplists:get_value(supported, Versions)),
+ false = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites()),
+ true = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites(all)),
+ false = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites()),
+ true = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites(all)),
+ false = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites()),
+ true = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites(all)),
+ true = lists:member('dtlsv1.2', proplists:get_value(available_dtls, Versions)),
+ true = lists:member('dtlsv1', proplists:get_value(available_dtls, Versions)),
+ true = lists:member('dtlsv1.2', proplists:get_value(supported_dtls, Versions)),
+ false = lists:member('dtlsv1', proplists:get_value(supported_dtls, Versions)).
-%%--------------------------------------------------------------------
fallback() ->
[{doc, "Test TLS_FALLBACK_SCSV downgrade prevention"}].
@@ -1263,7 +217,6 @@ fallback(Config) when is_list(Config) ->
| ClientOpts]}]),
ssl_test_lib:check_server_alert(Server, Client, inappropriate_fallback).
-
%%--------------------------------------------------------------------
cipher_format() ->
[{doc, "Test that cipher conversion from maps | tuples | stings to binarys works"}].
@@ -1277,175 +230,6 @@ cipher_format(Config) when is_list(Config) ->
ssl:close(Socket2).
%%--------------------------------------------------------------------
-suite_to_str() ->
- [{doc, "Test that the suite_to_str API works"}].
-suite_to_str(Config) when is_list(Config) ->
- "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" =
- ssl:suite_to_str(#{key_exchange => null,
- cipher => null,
- mac => null,
- prf => null}),
- "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" =
- ssl:suite_to_str(#{key_exchange => ecdhe_ecdsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256}),
- "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" =
- ssl:suite_to_str(#{key_exchange => ecdh_rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256}).
-
-%%--------------------------------------------------------------------
-
-peername() ->
- [{doc,"Test API function peername/1"}].
-
-peername(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, peername_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, peername_result, []}},
- {options, [{port, 0} | ClientOpts]}]),
-
- ClientPort = ssl_test_lib:inet_port(Client),
- ServerIp = ssl_test_lib:node_to_hostip(ServerNode, server),
- ClientIp = ssl_test_lib:node_to_hostip(ClientNode, client),
- ServerMsg = {ok, {ClientIp, ClientPort}},
- ClientMsg = {ok, {ServerIp, Port}},
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-peercert() ->
- [{doc,"Test API function peercert/1"}].
-peercert(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, peercert_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, peercert_result, []}},
- {options, ClientOpts}]),
-
- CertFile = proplists:get_value(certfile, ServerOpts),
- [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile),
-
- ServerMsg = {error, no_peercert},
- ClientMsg = {ok, BinCert},
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-peercert_result(Socket) ->
- ssl:peercert(Socket).
-%%--------------------------------------------------------------------
-
-peercert_with_client_cert() ->
- [{doc,"Test API function peercert/1"}].
-peercert_with_client_cert(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_dsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_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, peercert_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, peercert_result, []}},
- {options, ClientOpts}]),
-
- ServerCertFile = proplists:get_value(certfile, ServerOpts),
- [{'Certificate', ServerBinCert, _}]= ssl_test_lib:pem_to_der(ServerCertFile),
- ClientCertFile = proplists:get_value(certfile, ClientOpts),
- [{'Certificate', ClientBinCert, _}]= ssl_test_lib:pem_to_der(ClientCertFile),
-
- ServerMsg = {ok, ClientBinCert},
- ClientMsg = {ok, ServerBinCert},
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-sockname() ->
- [{doc,"Test API function sockname/1"}].
-sockname(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, sockname_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, sockname_result, []}},
- {options, [{port, 0} | ClientOpts]}]),
-
- ClientPort = ssl_test_lib:inet_port(Client),
- ServerIp =
- case proplists:get_value(protocol, Config) of
- dtls ->
- %% DTLS sockets are not connected on the server side,
- %% so we can only get a ClientIP, ServerIP will always be 0.0.0.0
- {0,0,0,0};
- _ ->
- ssl_test_lib:node_to_hostip(ServerNode, server)
- end,
-
- ClientIp = ssl_test_lib:node_to_hostip(ClientNode, client),
- ServerMsg = {ok, {ServerIp, Port}},
- ClientMsg = {ok, {ClientIp, ClientPort}},
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-sockname_result(S) ->
- ssl:sockname(S).
-
-%%--------------------------------------------------------------------
cipher_suites() ->
[{doc,"Test API function cipher_suites/2, filter_cipher_suites/2"
@@ -1542,2750 +326,95 @@ cipher_suites_mix(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-%%--------------------------------------------------------------------
-tls_socket_options() ->
- [{doc,"Test API function getopts/2 and setopts/2"}].
+unordered_protocol_versions_server() ->
+ [{doc,"Test that the highest protocol is selected even"
+ " when it is not first in the versions list."}].
-tls_socket_options(Config) when is_list(Config) ->
+unordered_protocol_versions_server(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),
- Values = [{mode, list}, {packet, 0}, {header, 0},
- {active, true}],
- %% Shall be the reverse order of Values!
- Options = [active, header, packet, mode],
-
- NewValues = [{mode, binary}, {active, once}],
- %% Shall be the reverse order of NewValues!
- NewOptions = [active, mode],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, tls_socket_options_result,
- [Options, Values, NewOptions, NewValues]}},
- {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, tls_socket_options_result,
- [Options, Values, NewOptions, NewValues]}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
-
- {ok, Listen} = ssl:listen(0, ServerOpts),
- {ok,[{mode,list}]} = ssl:getopts(Listen, [mode]),
- ok = ssl:setopts(Listen, [{mode, binary}]),
- {ok,[{mode, binary}]} = ssl:getopts(Listen, [mode]),
- {ok,[{recbuf, _}]} = ssl:getopts(Listen, [recbuf]),
- ssl:close(Listen).
-
-tls_socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
- %% Test get/set emulated opts
- {ok, DefaultValues} = ssl:getopts(Socket, Options),
- ssl:setopts(Socket, NewValues),
- {ok, NewValues} = ssl:getopts(Socket, NewOptions),
- %% Test get/set inet opts
- {ok,[{nodelay,false}]} = ssl:getopts(Socket, [nodelay]),
- ssl:setopts(Socket, [{nodelay, true}]),
- {ok,[{nodelay, true}]} = ssl:getopts(Socket, [nodelay]),
- {ok, All} = ssl:getopts(Socket, []),
- ct:log("All opts ~p~n", [All]),
- ok.
-
-
-%%--------------------------------------------------------------------
-socket_options() ->
- [{doc,"Test API function getopts/2 and setopts/2"}].
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
-socket_options(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),
- Values = [{mode, list}, {active, true}],
- %% Shall be the reverse order of Values!
- Options = [active, mode],
-
- NewValues = [{mode, binary}, {active, once}],
- %% Shall be the reverse order of NewValues!
- NewOptions = [active, mode],
-
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, socket_options_result,
- [Options, Values, NewOptions, NewValues]}},
- {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, socket_options_result,
- [Options, Values, NewOptions, NewValues]}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
-
- {ok, Listen} = ssl:listen(0, ServerOpts),
- {ok,[{mode,list}]} = ssl:getopts(Listen, [mode]),
- ok = ssl:setopts(Listen, [{mode, binary}]),
- {ok,[{mode, binary}]} = ssl:getopts(Listen, [mode]),
- {ok,[{recbuf, _}]} = ssl:getopts(Listen, [recbuf]),
- ssl:close(Listen).
-
-
-socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
- %% Test get/set emulated opts
- {ok, DefaultValues} = ssl:getopts(Socket, Options),
- ssl:setopts(Socket, NewValues),
- {ok, NewValues} = ssl:getopts(Socket, NewOptions),
- %% Test get/set inet opts
- {ok,[{reuseaddr, _}]} = ssl:getopts(Socket, [reuseaddr]),
- {ok, All} = ssl:getopts(Socket, []),
- ct:log("All opts ~p~n", [All]),
- ok.
-
-
-%%--------------------------------------------------------------------
-invalid_inet_get_option() ->
- [{doc,"Test handling of invalid inet options in getopts"}].
-
-invalid_inet_get_option(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, get_invalid_inet_option, []}},
- {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}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-invalid_inet_get_option_not_list() ->
- [{doc,"Test handling of invalid type in getopts"}].
-
-invalid_inet_get_option_not_list(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, get_invalid_inet_option_not_list, []}},
- {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}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-
-get_invalid_inet_option_not_list(Socket) ->
- {error, {options, {socket_options, some_invalid_atom_here}}}
- = ssl:getopts(Socket, some_invalid_atom_here),
- ok.
-
-%%--------------------------------------------------------------------
-invalid_inet_get_option_improper_list() ->
- [{doc,"Test handling of invalid type in getopts"}].
-
-invalid_inet_get_option_improper_list(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, get_invalid_inet_option_improper_list, []}},
- {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}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-
-get_invalid_inet_option_improper_list(Socket) ->
- {error, {options, {socket_options, foo,_}}} = ssl:getopts(Socket, [packet | foo]),
- ok.
-
-%%--------------------------------------------------------------------
-invalid_inet_set_option() ->
- [{doc,"Test handling of invalid inet options in setopts"}].
-
-invalid_inet_set_option(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, set_invalid_inet_option, []}},
- {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}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-set_invalid_inet_option(Socket) ->
- {error, {options, {socket_options, {packet, foo}}}} = ssl:setopts(Socket, [{packet, foo}]),
- {error, {options, {socket_options, {header, foo}}}} = ssl:setopts(Socket, [{header, foo}]),
- {error, {options, {socket_options, {active, foo}}}} = ssl:setopts(Socket, [{active, foo}]),
- {error, {options, {socket_options, {mode, foo}}}} = ssl:setopts(Socket, [{mode, foo}]),
- ok.
-%%--------------------------------------------------------------------
-invalid_inet_set_option_not_list() ->
- [{doc,"Test handling of invalid type in setopts"}].
-
-invalid_inet_set_option_not_list(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, set_invalid_inet_option_not_list, []}},
- {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}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-
-set_invalid_inet_option_not_list(Socket) ->
- {error, {options, {not_a_proplist, some_invalid_atom_here}}}
- = ssl:setopts(Socket, some_invalid_atom_here),
- ok.
-
-%%--------------------------------------------------------------------
-invalid_inet_set_option_improper_list() ->
- [{doc,"Test handling of invalid tye in setopts"}].
-
-invalid_inet_set_option_improper_list(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, set_invalid_inet_option_improper_list, []}},
- {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}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-set_invalid_inet_option_improper_list(Socket) ->
- {error, {options, {not_a_proplist, [{packet, 0} | {foo, 2}]}}} =
- ssl:setopts(Socket, [{packet, 0} | {foo, 2}]),
- ok.
-
-%%--------------------------------------------------------------------
-tls_misc_ssl_options() ->
- [{doc,"Test what happens when we give valid options"}].
-
-tls_misc_ssl_options(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),
-
- %% Check that ssl options not tested elsewhere are filtered away e.i. not passed to inet.
- TestOpts = [{depth, 1},
- {key, undefined},
- {password, []},
- {reuse_session, fun(_,_,_,_) -> true end},
- {cb_info, {gen_tcp, tcp, tcp_closed, tcp_error}}],
-
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, TestOpts ++ 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, send_recv_result_active, []}},
- {options, TestOpts ++ ClientOpts}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-ssl_options_not_proplist() ->
- [{doc,"Test what happens if an option is not a key value tuple"}].
-
-ssl_options_not_proplist(Config) when is_list(Config) ->
- BadOption = {client_preferred_next_protocols,
- client, [<<"spdy/3">>,<<"http/1.1">>], <<"http/1.1">>},
- {option_not_a_key_value_tuple, BadOption} =
- ssl:connect("twitter.com", 443, [binary, {active, false},
- BadOption]).
-
-%%--------------------------------------------------------------------
-raw_ssl_option() ->
- [{doc,"Ensure that a single 'raw' option is passed to ssl:listen correctly."}].
-
-raw_ssl_option(Config) when is_list(Config) ->
- % 'raw' option values are platform-specific; these are the Linux values:
- IpProtoTcp = 6,
- % Use TCP_KEEPIDLE, because (e.g.) TCP_MAXSEG can't be read back reliably.
- TcpKeepIdle = 4,
- KeepAliveTimeSecs = 55,
- LOptions = [{raw, IpProtoTcp, TcpKeepIdle, <<KeepAliveTimeSecs:32/native>>}],
- {ok, LSocket} = ssl:listen(0, LOptions),
- % Per http://www.erlang.org/doc/man/inet.html#getopts-2, we have to specify
- % exactly which raw option we want, and the size of the buffer.
- {ok, [{raw, IpProtoTcp, TcpKeepIdle, <<KeepAliveTimeSecs:32/native>>}]} = ssl:getopts(LSocket, [{raw, IpProtoTcp, TcpKeepIdle, 4}]).
-
-
-%%--------------------------------------------------------------------
-versions() ->
- [{doc,"Test API function versions/0"}].
-
-versions(Config) when is_list(Config) ->
- [_|_] = Versions = ssl:versions(),
- ct:log("~p~n", [Versions]).
-
-
-%%--------------------------------------------------------------------
-eccs() ->
- [{doc, "Test API functions eccs/0 and eccs/1"}].
-
-eccs(Config) when is_list(Config) ->
- [_|_] = All = ssl:eccs(),
- [] = 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.
-
-%%--------------------------------------------------------------------
-send_recv() ->
- [{doc,""}].
-send_recv(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, send_recv_result, []}},
- {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, {ssl_test_lib, send_recv_result, []}},
- {options, [{active, false} | ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-tls_send_close() ->
- [{doc,""}].
-tls_send_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),
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {options, [{active, false} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- {ok, TcpS} = rpc:call(ClientNode, gen_tcp, connect,
- [Hostname,Port,[binary, {active, false}]]),
- {ok, SslS} = rpc:call(ClientNode, ssl, connect,
- [TcpS,[{active, false}|ClientOpts]]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), self(), Server]),
- ok = ssl:send(SslS, "Hello world"),
- {ok,<<"Hello world">>} = ssl:recv(SslS, 11),
- gen_tcp:close(TcpS),
- {error, _} = ssl:send(SslS, "Hello world").
-
-%%--------------------------------------------------------------------
-version_option() ->
- [{doc, "Use version option and do no specify ciphers list. Bug specified incorrect ciphers"}].
-version_option(Config) when is_list(Config) ->
- Versions = proplists:get_value(supported, ssl:versions()),
- [version_option_test(Config, Version) || Version <- Versions].
-
-%%--------------------------------------------------------------------
-close_transport_accept() ->
- [{doc,"Tests closing ssl socket when waiting on ssl:transport_accept/1"}].
-
-close_transport_accept(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- {_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config),
-
- Port = 0,
- Opts = [{active, false} | ServerOpts],
- {ok, ListenSocket} = rpc:call(ServerNode, ssl, listen, [Port, Opts]),
- spawn_link(fun() ->
- ct:sleep(?SLEEP),
- rpc:call(ServerNode, ssl, close, [ListenSocket])
- end),
- case rpc:call(ServerNode, ssl, transport_accept, [ListenSocket]) of
- {error, closed} ->
- ok;
- Other ->
- exit({?LINE, Other})
- end.
-%%--------------------------------------------------------------------
-recv_active() ->
- [{doc,"Test recv on active socket"}].
-
-recv_active(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, []}},
- {options, [{active, true} | 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, []}},
- {options, [{active, true} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-recv_active_once() ->
- [{doc,"Test recv on active (once) socket"}].
-
-recv_active_once(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, once} | ServerOpts]}]),
+ {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, try_recv_active_once, []}},
- {options, [{active, once} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- 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."}].
-
-dh_params(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- DataDir = proplists:get_value(data_dir, Config),
- DHParamFile = filename:join(DataDir, "dHParam.pem"),
-
- {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, send_recv_result_active, []}},
- {options, [{dhfile, DHParamFile} | 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, send_recv_result_active, []}},
- {options,
- [{ciphers,[{dhe_rsa,aes_256_cbc,sha}]} |
- ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-tls_upgrade() ->
- [{doc,"Test that you can upgrade an tcp connection to an ssl connection"}].
-
-tls_upgrade(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),
- TcpOpts = [binary, {reuseaddr, true}],
-
- Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE,
- upgrade_result, []}},
- {tcp_options,
- [{active, false} | TcpOpts]},
- {ssl_options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_upgrade_client([{node, ClientNode},
- {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, upgrade_result, []}},
- {tcp_options, [binary]},
- {ssl_options, ClientOpts}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-upgrade_result(Socket) ->
- ssl:setopts(Socket, [{active, true}]),
- ok = ssl:send(Socket, "Hello world"),
- %% Make sure binary is inherited from tcp socket and that we do
- %% not get the list default!
- receive
- {ssl, _, <<"H">>} ->
- receive
- {ssl, _, <<"ello world">>} ->
- ok
- end;
- {ssl, _, <<"Hello world">>} ->
- ok
- end.
-
-
-%%--------------------------------------------------------------------
-internal_active_1() ->
- [{doc,"Test internal active 1 (behave as internal active once)"}].
-
-internal_active_1(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, send_recv_result_active, []}},
- {options, [{active, true} | 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, send_recv_result_active, []}},
- {options, [{active, true} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-tls_upgrade_with_timeout() ->
- [{doc,"Test ssl_accept/3"}].
-
-tls_upgrade_with_timeout(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),
- TcpOpts = [binary, {reuseaddr, true}],
-
- Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {timeout, 5000},
- {mfa, {?MODULE,
- upgrade_result, []}},
- {tcp_options,
- [{active, false} | TcpOpts]},
- {ssl_options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_upgrade_client([{node, ClientNode},
- {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, upgrade_result, []}},
- {tcp_options, TcpOpts},
- {ssl_options, ClientOpts}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-tls_downgrade() ->
- [{doc,"Test that you can downgarde an ssl connection to an tcp connection"}].
-tls_downgrade(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, 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, [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).
-
-%%--------------------------------------------------------------------
-close_with_timeout() ->
- [{doc,"Test normal (not downgrade) ssl:close/2"}].
-close_with_timeout(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, tls_close, []}},
- {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_close, []}},
- {options, [{active, false} |ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok).
-
-
-%%--------------------------------------------------------------------
-tls_tcp_connect() ->
- [{doc,"Test what happens when a tcp tries to connect, i,e. a bad (ssl) packet is sent first"}].
-
-tls_tcp_connect(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- TcpOpts = [binary, {reuseaddr, true}, {active, false}],
-
- Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {timeout, 5000},
- {mfa, {?MODULE, dummy, []}},
- {tcp_options, TcpOpts},
- {ssl_options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]),
- ct:log("Testcase ~p connected to Server ~p ~n", [self(), Server]),
- gen_tcp:send(Socket, "<SOME GARBLED NON SSL MESSAGE>"),
-
- receive
- {tcp_closed, Socket} ->
- receive
- {Server, {error, Error}} ->
- ct:log("Error ~p", [Error])
- end
- end.
-%%--------------------------------------------------------------------
-tls_tcp_connect_big() ->
- [{doc,"Test what happens when a tcp tries to connect, i,e. a bad big (ssl) packet is sent first"}].
-
-tls_tcp_connect_big(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- TcpOpts = [binary, {reuseaddr, true}],
-
- Rand = crypto:strong_rand_bytes(?MAX_CIPHER_TEXT_LENGTH+1),
- Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {timeout, 5000},
- {mfa, {?MODULE, dummy, []}},
- {tcp_options, TcpOpts},
- {ssl_options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]),
- ct:log("Testcase ~p connected to Server ~p ~n", [self(), Server]),
-
- gen_tcp:send(Socket, <<?BYTE(0),
- ?BYTE(3), ?BYTE(1), ?UINT16(?MAX_CIPHER_TEXT_LENGTH), Rand/binary>>),
-
- receive
- {tcp_closed, Socket} ->
- receive
- {Server, {error, timeout}} ->
- ct:fail("hangs");
- {Server, {error, Error}} ->
- ct:log("Error ~p", [Error]);
- {'EXIT', Server, _} ->
- ok
- end
- end.
-
-%%--------------------------------------------------------------------
-ipv6() ->
- [{require, ipv6_hosts},
- {doc,"Test ipv6."}].
-ipv6(Config) when is_list(Config) ->
- {ok, Hostname0} = inet:gethostname(),
-
- case lists:member(list_to_atom(Hostname0), ct:get_config(ipv6_hosts)) of
- true ->
- 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, ipv6),
- Server = ssl_test_lib:start_server([{node, ServerNode},
- {port, 0}, {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {options,
- [inet6, {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, {ssl_test_lib, send_recv_result, []}},
- {options,
- [inet6, {active, false} | ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client);
- false ->
- {skip, "Host does not support IPv6"}
- end.
-
-%%--------------------------------------------------------------------
-
-invalid_keyfile() ->
- [{doc,"Test what happens with an invalid key file"}].
-invalid_keyfile(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- BadOpts = ssl_test_lib:ssl_options(server_bad_key, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server =
- ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, BadOpts}]),
-
- Port = ssl_test_lib:inet_port(Server),
-
- Client =
- ssl_test_lib:start_client_error([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {from, self()}, {options, ClientOpts}]),
+ {from, self()},
+ {mfa, {?MODULE, protocol_info_result, []}},
+ {options, ClientOpts}]),
- File = proplists:get_value(keyfile,BadOpts),
- ssl_test_lib:check_result(Server, {error,{options, {keyfile, File, {error,enoent}}}}, Client,
- {error, closed}).
+ ServerMsg = ClientMsg = {ok,'tlsv1.2'},
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
+unordered_protocol_versions_client() ->
+ [{doc,"Test that the highest protocol is selected even"
+ " when it is not first in the versions list."}].
-invalid_certfile() ->
- [{doc,"Test what happens with an invalid cert file"}].
-
-invalid_certfile(Config) when is_list(Config) ->
+unordered_protocol_versions_client(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerBadOpts = ssl_test_lib:ssl_options(server_bad_cert, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server =
- ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, ServerBadOpts}]),
-
- Port = ssl_test_lib:inet_port(Server),
-
- Client =
- ssl_test_lib:start_client_error([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {from, self()},
- {options, ClientOpts}]),
- File = proplists:get_value(certfile, ServerBadOpts),
- ssl_test_lib:check_result(Server, {error,{options, {certfile, File, {error,enoent}}}},
- Client, {error, closed}).
-
-
-%%--------------------------------------------------------------------
-invalid_cacertfile() ->
- [{doc,"Test what happens with an invalid cacert file"}].
-
-invalid_cacertfile(Config) when is_list(Config) ->
- ClientOpts = [{reuseaddr, true}|ssl_test_lib:ssl_options(client_opts, Config)],
- ServerBadOpts = [{reuseaddr, true}|ssl_test_lib:ssl_options(server_bad_ca, Config)],
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server0 =
- ssl_test_lib:start_server_error([{node, ServerNode},
- {port, 0}, {from, self()},
- {options, ServerBadOpts}]),
-
- Port0 = ssl_test_lib:inet_port(Server0),
-
-
- Client0 =
- ssl_test_lib:start_client_error([{node, ClientNode},
- {port, Port0}, {host, Hostname},
- {from, self()},
- {options, ClientOpts}]),
-
- File0 = proplists:get_value(cacertfile, ServerBadOpts),
-
- ssl_test_lib:check_result(Server0, {error, {options, {cacertfile, File0,{error,enoent}}}},
- Client0, {error, closed}),
-
- File = File0 ++ "do_not_exit.pem",
- ServerBadOpts1 = [{cacertfile, File}|proplists:delete(cacertfile, ServerBadOpts)],
-
- Server1 =
- ssl_test_lib:start_server_error([{node, ServerNode},
- {port, 0}, {from, self()},
- {options, ServerBadOpts1}]),
-
- Port1 = ssl_test_lib:inet_port(Server1),
-
- Client1 =
- ssl_test_lib:start_client_error([{node, ClientNode},
- {port, Port1}, {host, Hostname},
- {from, self()},
- {options, ClientOpts}]),
-
-
- ssl_test_lib:check_result(Server1, {error, {options, {cacertfile, File,{error,enoent}}}},
- Client1, {error, closed}),
- ok.
-
-
-
-%%--------------------------------------------------------------------
-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_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) ->
- ssl_test_lib:check_result(Server,
- {error, {options, {sslv2, Option}}},
- Client,
- {error, {options, {sslv2, Option}}});
- (Client, Server, Option) ->
- ssl_test_lib:check_result(Server,
- {error, {options, Option}},
- Client,
- {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' }],
-
- [begin
- Server =
- ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, [TestOpt | ServerOpts]}]),
- %% Will never reach a point where port is used.
- Client =
- ssl_test_lib:start_client_error([{node, ClientNode}, {port, 0},
- {host, Hostname}, {from, self()},
- {options, [TestOpt | ClientOpts]}]),
- Check(Client, Server, TestOpt),
- ok
- end || TestOpt <- TestOpts],
- ok.
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
-%%--------------------------------------------------------------------
-tls_shutdown() ->
- [{doc,"Test API function ssl:shutdown/2"}].
-tls_shutdown(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, tls_shutdown_result, [server]}},
- {options, [{exit_on_close, false},
- {active, false} | ServerOpts]}]),
+ {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, tls_shutdown_result, [client]}},
- {options,
- [{exit_on_close, false},
- {active, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-tls_shutdown_write() ->
- [{doc,"Test API function ssl:shutdown/2 with option write."}].
-tls_shutdown_write(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, tls_shutdown_write_result, [server]}},
- {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_shutdown_write_result, [client]}},
- {options, [{active, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, {error, closed}).
-
-%%--------------------------------------------------------------------
-tls_shutdown_both() ->
- [{doc,"Test API function ssl:shutdown/2 with option both."}].
-tls_shutdown_both(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, tls_shutdown_both_result, [server]}},
- {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_shutdown_both_result, [client]}},
- {options, [{active, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, {error, closed}).
-
-%%--------------------------------------------------------------------
-tls_shutdown_error() ->
- [{doc,"Test ssl:shutdown/2 error handling"}].
-tls_shutdown_error(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- Port = ssl_test_lib:inet_port(node()),
- {ok, Listen} = ssl:listen(Port, ServerOpts),
- {error, enotconn} = ssl:shutdown(Listen, read_write),
- ok = ssl:close(Listen),
- {error, closed} = ssl:shutdown(Listen, read_write).
-
-%%--------------------------------------------------------------------
-default_reject_anonymous()->
- [{doc,"Test that by default anonymous cipher suites are rejected "}].
-default_reject_anonymous(Config) when is_list(Config) ->
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- Version = ssl_test_lib:protocol_version(Config),
- TLSVersion = ssl_test_lib:tls_version(Version),
-
- [CipherSuite | _] = ssl_test_lib:ecdh_dh_anonymous_suites(TLSVersion),
-
- Server = ssl_test_lib:start_server_error([{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,
- [{ciphers,[CipherSuite]} |
- ClientOpts]}]),
-
- ssl_test_lib:check_server_alert(Server, Client, insufficient_security).
-
-%%--------------------------------------------------------------------
-reuse_session() ->
- [{doc,"Test reuse of sessions (short handshake)"}].
-reuse_session(Config) when is_list(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).
-%%--------------------------------------------------------------------
-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_rsa_verify_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, 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,
-
- %% Make sure session is unregistered due to expiration
- ct:sleep((?EXPIRE*2)),
-
- make_sure_expired(Hostname, Port0, SID),
-
- Client2 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port0}, {host, Hostname},
- {mfa, {ssl_test_lib, session_id, []}},
- {from, self()}, {options, ClientOpts}]),
- receive
- {Client2, SID} ->
- ct:fail(session_reused_when_session_expired);
- {Client2, _} ->
- ok
- end,
- process_flag(trap_exit, false),
- ssl_test_lib:close(Server0),
- ssl_test_lib:close(Client0),
- ssl_test_lib:close(Client1),
- ssl_test_lib:close(Client2).
-
-make_sure_expired(Host, Port, Id) ->
- {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- ClientCache = element(2, State),
-
- case ssl_session_cache:lookup(ClientCache, {{Host, Port}, Id}) of
- undefined ->
- ok;
- #session{is_resumable = false} ->
- ok;
- _ ->
- ct:sleep(?SLEEP),
- make_sure_expired(Host, Port, Id)
- end.
-
-%%--------------------------------------------------------------------
-server_does_not_want_to_reuse_session() ->
- [{doc,"Test reuse of sessions (short handshake)"}].
-server_does_not_want_to_reuse_session(Config) when is_list(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},
- {from, self()},
- {mfa, {ssl_test_lib, session_info_result, []}},
- {options, [{reuse_session, fun(_,_,_,_) ->
- false
- end} |
- 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),
- ssl_test_lib:close(Client0),
-
- 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} ->
- ct:fail(session_reused_when_server_does_not_want_to);
- {Client1, _Other} ->
- ok
- end,
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client1).
-
-%%--------------------------------------------------------------------
-client_renegotiate() ->
- [{doc,"Test ssl:renegotiate/1 on client."}].
-client_renegotiate(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),
-
- Data = "From erlang to erlang",
-
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {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,
- renegotiate, [Data]}},
- {options, [{reuse_sessions, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-client_secure_renegotiate() ->
- [{doc,"Test ssl:renegotiate/1 on client."}].
-client_secure_renegotiate(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),
-
- Data = "From erlang to erlang",
-
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, [{secure_renegotiate, true} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- renegotiate, [Data]}},
- {options, [{reuse_sessions, false},
- {secure_renegotiate, true}| ClientOpts]}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-client_secure_renegotiate_fallback() ->
- [{doc,"Test that we can set secure_renegotiate to false that is "
- "fallback option, we however do not have a insecure server to test against!"}].
-client_secure_renegotiate_fallback(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),
-
- Data = "From erlang to erlang",
-
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, [{secure_renegotiate, false} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
+ {mfa, {?MODULE, protocol_info_result, []}},
+ {options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- renegotiate, [Data]}},
- {options, [{reuse_sessions, false},
- {secure_renegotiate, false}| ClientOpts]}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
+ ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
+
+connect_dist() ->
+ [{doc,"Test a simple connect as is used by distribution"}].
-%%--------------------------------------------------------------------
-server_renegotiate() ->
- [{doc,"Test ssl:renegotiate/1 on server."}].
-server_renegotiate(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+connect_dist(Config) when is_list(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_kc_opts, Config),
+ ClientOpts = [{ssl_imp, new},{active, false}, {packet,4}|ClientOpts0],
+ ServerOpts0 = ssl_test_lib:ssl_options(server_kc_opts, Config),
+ ServerOpts = [{ssl_imp, new},{active, false}, {packet,4}|ServerOpts0],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Data = "From erlang to erlang",
-
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE,
- renegotiate, [Data]}},
+ {mfa, {?MODULE, connect_dist_s, []}},
{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, erlang_ssl_receive, [Data]}},
- {options, [{reuse_sessions, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-client_renegotiate_reused_session() ->
- [{doc,"Test ssl:renegotiate/1 on client when the ssl session will be reused."}].
-client_renegotiate_reused_session(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),
-
- Data = "From erlang to erlang",
-
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {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,
- renegotiate_reuse_session, [Data]}},
- {options, [{reuse_sessions, true} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-%%--------------------------------------------------------------------
-server_renegotiate_reused_session() ->
- [{doc,"Test ssl:renegotiate/1 on server when the ssl session will be reused."}].
-server_renegotiate_reused_session(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),
-
- Data = "From erlang to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE,
- renegotiate_reuse_session, [Data]}},
- {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, erlang_ssl_receive, [Data]}},
- {options, [{reuse_sessions, true} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-%%--------------------------------------------------------------------
-client_no_wrap_sequence_number() ->
- [{doc,"Test that erlang client will renegotiate session when",
- "max sequence number celing is about to be reached. Although"
- "in the testcase we use the test option renegotiate_at"
- " to lower treashold substantially."}].
-
-client_no_wrap_sequence_number(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),
-
- ErlData = "From erlang to erlang",
- N = 12,
-
- 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),
-
- Version = ssl_test_lib:protocol_version(Config, tuple),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib,
- trigger_renegotiate, [[ErlData, treashold(N, Version)]]}},
- {options, [{reuse_sessions, false},
- {renegotiate_at, N} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-server_no_wrap_sequence_number() ->
- [{doc, "Test that erlang server will renegotiate session when",
- "max sequence number celing is about to be reached. Although"
- "in the testcase we use the test option renegotiate_at"
- " to lower treashold substantially."}].
-
-server_no_wrap_sequence_number(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),
-
- Data = "From erlang to erlang",
- N = 12,
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- trigger_renegotiate, [[Data, N+2]]}},
- {options, [{renegotiate_at, N} | 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, [{reuse_sessions, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-der_input() ->
- [{doc,"Test to input certs and key as der"}].
-
-der_input(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- DHParamFile = filename:join(DataDir, "dHParam.pem"),
-
- {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- [CADb | _] = element(6, State),
-
- Size = ets:info(CADb, size),
-
- SeverVerifyOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ServerCert, ServerKey, ServerCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
- SeverVerifyOpts]),
- ClientVerifyOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- {ClientCert, ClientKey, ClientCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
- ClientVerifyOpts]),
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
- {dh, DHParams},
- {cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCaCerts}],
- ClientOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
- {dh, DHParams},
- {cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCaCerts}],
- {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, send_recv_result, []}},
- {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, {ssl_test_lib, send_recv_result, []}},
- {options, [{active, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- Size = ets:info(CADb, size).
-
-%%--------------------------------------------------------------------
-der_input_opts(Opts) ->
- Certfile = proplists:get_value(certfile, Opts),
- CaCertsfile = proplists:get_value(cacertfile, Opts),
- Keyfile = proplists:get_value(keyfile, Opts),
- Dhfile = proplists:get_value(dhfile, Opts),
- [{_, Cert, _}] = ssl_test_lib:pem_to_der(Certfile),
- [{Asn1Type, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
- [{_, DHParams, _}] = ssl_test_lib:pem_to_der(Dhfile),
- CaCerts =
- lists:map(fun(Entry) ->
- {_, CaCert, _} = Entry,
- CaCert
- end, ssl_test_lib:pem_to_der(CaCertsfile)),
- {Cert, {Asn1Type, Key}, CaCerts, DHParams}.
-
-%%--------------------------------------------------------------------
-no_reuses_session_server_restart_new_cert() ->
- [{doc,"Check that a session is not reused if the server is restarted with a new cert."}].
-no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
-
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- DsaServerOpts = ssl_test_lib:ssl_options(server_dsa_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,
-
- %% Make sure session is registered
- ct:sleep(?SLEEP),
- Monitor = erlang:monitor(process, Server),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client0),
- receive
- {'DOWN', Monitor, _, _, _} ->
- ok
- end,
-
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{reuseaddr, true} | DsaServerOpts]}]),
-
- 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} ->
- ct:fail(session_reused_when_server_has_new_cert);
- {Client1, _Other} ->
- ok
- end,
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1).
-
-%%--------------------------------------------------------------------
-no_reuses_session_server_restart_new_cert_file() ->
- [{doc,"Check that a session is not reused if a server is restarted with a new "
- "cert contained in a file with the same name as the old cert."}].
-
-no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- DsaServerOpts = ssl_test_lib:ssl_options(server_dsa_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
-
- NewServerOpts0 = new_config(PrivDir, ServerOpts),
- {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, NewServerOpts0}]),
- 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,
-
- %% Make sure session is registered and we get
- %% new file time stamp when calling new_config!
- ct:sleep(?SLEEP* 2),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client0),
-
- ssl:clear_pem_cache(),
-
- NewServerOpts1 = new_config(PrivDir, DsaServerOpts),
-
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{reuseaddr, true} | NewServerOpts1]}]),
- 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} ->
- ct:fail(session_reused_when_server_has_new_cert);
- {Client1, _Other} ->
- ok
- end,
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1).
-
-%%--------------------------------------------------------------------
-defaults(Config) when is_list(Config)->
- Versions = ssl:versions(),
- true = lists:member(sslv3, proplists:get_value(available, Versions)),
- false = lists:member(sslv3, proplists:get_value(supported, Versions)),
- true = lists:member('tlsv1', proplists:get_value(available, Versions)),
- false = lists:member('tlsv1', proplists:get_value(supported, Versions)),
- true = lists:member('tlsv1.1', proplists:get_value(available, Versions)),
- false = lists:member('tlsv1.1', proplists:get_value(supported, Versions)),
- true = lists:member('tlsv1.2', proplists:get_value(available, Versions)),
- true = lists:member('tlsv1.2', proplists:get_value(supported, Versions)),
- false = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites()),
- true = lists:member({rsa,rc4_128,sha}, ssl:cipher_suites(all)),
- false = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites()),
- true = lists:member({rsa,des_cbc,sha}, ssl:cipher_suites(all)),
- false = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites()),
- true = lists:member({dhe_rsa,des_cbc,sha}, ssl:cipher_suites(all)),
- true = lists:member('dtlsv1.2', proplists:get_value(available_dtls, Versions)),
- true = lists:member('dtlsv1', proplists:get_value(available_dtls, Versions)),
- true = lists:member('dtlsv1.2', proplists:get_value(supported_dtls, Versions)),
- false = lists:member('dtlsv1', proplists:get_value(supported_dtls, Versions)).
-
-%%--------------------------------------------------------------------
-reuseaddr() ->
- [{doc,"Test reuseaddr option"}].
-
-reuseaddr(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, no_result, []}},
- {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, {ssl_test_lib, no_result, []}},
- {options, [{active, false} | ClientOpts]}]),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
-
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {options, [{active, false} | ServerOpts]}]),
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {options, [{active, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server1, ok, Client1, ok),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1).
-
-%%--------------------------------------------------------------------
-tls_tcp_reuseaddr() ->
- [{doc, "Reference test case."}].
-tls_tcp_reuseaddr(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()},
- {transport, gen_tcp},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{active, false}, {reuseaddr, true}]}]),
- Port = ssl_test_lib:inet_port(Server),
- Client =
- ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {transport, gen_tcp},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{active, false}]}]),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
-
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
- {from, self()},
- {transport, gen_tcp},
- {mfa, {?MODULE, tcp_send_recv_result, []}},
- {options, [{active, false}, {reuseaddr, true}]}]),
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {transport, gen_tcp},
- {mfa, {?MODULE, tcp_send_recv_result, []}},
- {options, [{active, false}]}]),
-
- ssl_test_lib:check_result(Server1, ok, Client1, ok),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1).
-
-%%--------------------------------------------------------------------
-
-honor_server_cipher_order() ->
- [{doc,"Test API honor server cipher order."}].
-honor_server_cipher_order(Config) when is_list(Config) ->
- 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 = [#{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),
- 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, connection_info_result, []}},
- {options, [{ciphers, ServerCiphers}, {honor_cipher_order, Honor}
- | 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, ClientCiphers}, {honor_cipher_order, Honor}
- | ClientOpts]}]),
-
- Version = ssl_test_lib:protocol_version(Config),
-
- ServerMsg = ClientMsg = {ok, {Version, Expected}},
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-tls_ciphersuite_vs_version() ->
- [{doc,"Test a SSLv3 client cannot negotiate a TLSv* cipher suite."}].
-tls_ciphersuite_vs_version(Config) when is_list(Config) ->
-
- {_ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {active, false}]),
- ok = gen_tcp:send(Socket,
- <<22, 3,0, 49:16, % handshake, SSL 3.0, length
- 1, 45:24, % client_hello, length
- 3,0, % SSL 3.0
- 16#deadbeef:256, % 32 'random' bytes = 256 bits
- 0, % no session ID
- %% three cipher suites -- null, one with sha256 hash and one with sha hash
- 6:16, 0,255, 0,61, 0,57,
- 1, 0 % no compression
- >>),
- {ok, <<22, RecMajor:8, RecMinor:8, _RecLen:16, 2, HelloLen:24>>} = gen_tcp:recv(Socket, 9, 10000),
- {ok, <<HelloBin:HelloLen/binary>>} = gen_tcp:recv(Socket, HelloLen, 5000),
- ServerHello = tls_handshake:decode_handshake({RecMajor, RecMinor}, 2, HelloBin),
- case ServerHello of
- #server_hello{server_version = {3,0}, cipher_suite = <<0,57>>} ->
- ok;
- _ ->
- ct:fail({unexpected_server_hello, ServerHello})
- end.
-
-%%--------------------------------------------------------------------
-conf_signature_algs() ->
- [{doc,"Test to set the signature_algs option on both client and server"}].
-conf_signature_algs(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, send_recv_result, []}},
- {options, [{active, false}, {signature_algs, [{sha, rsa}]} | 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, send_recv_result, []}},
- {options, [{active, false}, {signature_algs, [{sha, rsa}]} | ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-
-%%--------------------------------------------------------------------
-no_common_signature_algs() ->
- [{doc,"Set the signature_algs option so that there client and server does not share any hash sign algorithms"}].
-no_common_signature_algs(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_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, [{signature_algs, [{sha256, rsa}]}
- | 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]}]),
-
- ssl_test_lib:check_server_alert(Server, Client, insufficient_security).
-
-%%--------------------------------------------------------------------
-
-tls_dont_crash_on_handshake_garbage() ->
- [{doc, "Ensure SSL server worker thows an alert on garbage during handshake "
- "instead of crashing and exposing state to user code"}].
-
-tls_dont_crash_on_handshake_garbage(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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- unlink(Server), monitor(process, Server),
- Port = ssl_test_lib:inet_port(Server),
-
- {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {active, false}]),
-
- % Send hello and garbage record
- ok = gen_tcp:send(Socket,
- [<<22, 3,3, 49:16, 1, 45:24, 3,3, % client_hello
- 16#deadbeef:256, % 32 'random' bytes = 256 bits
- 0, 6:16, 0,255, 0,61, 0,57, 1, 0 >>, % some hello values
-
- <<22, 3,3, 5:16, 92,64,37,228,209>> % garbage
- ]),
- % Send unexpected change_cipher_spec
- 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).
-
-drop_handshakes(Socket, Timeout) ->
- {ok, <<RecType:8, _RecMajor:8, _RecMinor:8, RecLen:16>> = Header} = gen_tcp:recv(Socket, 5, Timeout),
- {ok, <<Frag:RecLen/binary>>} = gen_tcp:recv(Socket, RecLen, Timeout),
- case RecType of
- 22 -> drop_handshakes(Socket, Timeout);
- _ -> {ok, <<Header/binary, Frag/binary>>}
- end.
-
-
-%%--------------------------------------------------------------------
-
-hibernate() ->
- [{doc,"Check that an SSL connection that is started with option "
- "{hibernate_after, 1000} indeed hibernates after 1000ms of "
- "inactivity"}].
-
-hibernate(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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=[Pid|_]}} = ssl_test_lib:start_client([return_socket,
- {node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, [{hibernate_after, 1000}|ClientOpts]}]),
- {current_function, _} =
- process_info(Pid, current_function),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ct:sleep(1500),
- {current_function, {erlang, hibernate, 3}} =
- process_info(Pid, current_function),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
-hibernate_right_away() ->
- [{doc,"Check that an SSL connection that is configured to hibernate "
- "after 0 or 1 milliseconds hibernates as soon as possible and not "
- "crashes"}].
-
-hibernate_right_away(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),
-
- StartServerOpts = [{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ServerOpts}],
- StartClientOpts = [return_socket,
- {node, ClientNode},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}}],
-
- Server1 = ssl_test_lib:start_server(StartServerOpts),
- Port1 = ssl_test_lib:inet_port(Server1),
- {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),
-
- ct:sleep(1000), %% Schedule out
-
- {current_function, {erlang, hibernate, 3}} =
- process_info(Pid1, current_function),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1),
-
- Server2 = ssl_test_lib:start_server(StartServerOpts),
- Port2 = ssl_test_lib:inet_port(Server2),
- {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),
-
- ct:sleep(1000), %% Schedule out
-
- {current_function, {erlang, hibernate, 3}} =
- process_info(Pid2, current_function),
-
- ssl_test_lib:close(Server2),
- ssl_test_lib:close(Client2).
-
-%%--------------------------------------------------------------------
-listen_socket() ->
- [{doc,"Check error handling and inet compliance when calling API functions with listen sockets."}].
-
-listen_socket(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- {ok, ListenSocket} = ssl:listen(0, ServerOpts),
-
- %% This can be a valid thing to do as
- %% options are inherited by the accept socket
- ok = ssl:controlling_process(ListenSocket, self()),
-
- {ok, _} = ssl:sockname(ListenSocket),
-
- {error, enotconn} = ssl:send(ListenSocket, <<"data">>),
- {error, enotconn} = ssl:recv(ListenSocket, 0),
- {error, enotconn} = ssl:connection_information(ListenSocket),
- {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:shutdown(ListenSocket, read_write),
-
- ok = ssl:close(ListenSocket).
-%%--------------------------------------------------------------------
-tls_ssl_accept_timeout() ->
- [{doc,"Test ssl:ssl_accept timeout"}].
-
-tls_ssl_accept_timeout(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {timeout, 5000},
- {mfa, {ssl_test_lib,
- no_result_msg, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- {ok, CSocket} = gen_tcp:connect(Hostname, Port, [binary, {active, true}]),
-
- receive
- {tcp_closed, CSocket} ->
- ssl_test_lib:check_result(Server, {error, timeout}),
- receive
- {'EXIT', Server, _} ->
- %% Make sure supervisor had time to react on process exit
- %% Could we come up with a better solution to this?
- ct:sleep(500),
- [] = supervisor:which_children(tls_connection_sup)
- end
- end.
-
-%%--------------------------------------------------------------------
-ssl_recv_timeout() ->
- [{doc,"Test ssl:ssl_accept timeout"}].
-
-ssl_recv_timeout(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([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, send_recv_result_timeout_server, []}},
- {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,
- send_recv_result_timeout_client, []}},
- {options, [{active, false} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-connect_twice() ->
- [{doc,""}].
-connect_twice(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, send_recv_result, []}},
- {options, [{keepalive, true},{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, {ssl_test_lib, send_recv_result, []}},
- {options, [{keepalive, true},{active, false}
- | ClientOpts]}]),
- Server ! listen,
-
- {Client1, #sslsocket{}} =
- ssl_test_lib:start_client([return_socket,
- {node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {options, [{keepalive, true},{active, false}
- | ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:check_result(Server, ok, Client1, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- ssl_test_lib:close(Client1).
-
-%%--------------------------------------------------------------------
-renegotiate_dos_mitigate_active() ->
- [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row",
- "immediately after each other"}].
-renegotiate_dos_mitigate_active(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([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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,
- renegotiate_immediately, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-renegotiate_dos_mitigate_passive() ->
- [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row",
- "immediately after each other"}].
-renegotiate_dos_mitigate_passive(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([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result, []}},
- {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,
- renegotiate_immediately, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-renegotiate_dos_mitigate_absolute() ->
- [{doc, "Mitigate DOS computational attack by not allowing client to initiate renegotiation"}].
-renegotiate_dos_mitigate_absolute(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([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, [{client_renegotiation, 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,
- renegotiate_rejected,
- []}},
+ {mfa, {?MODULE, connect_dist_c, []}},
{options, ClientOpts}]),
-
- ssl_test_lib:check_result(Client, ok, Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-tls_tcp_error_propagation_in_active_mode() ->
- [{doc,"Test that process recives {ssl_error, Socket, closed} when tcp error ocurres"}].
-tls_tcp_error_propagation_in_active_mode(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, 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}]),
-
- {status, _, _, StatusInfo} = sys:get_status(Pid),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- StaticEnv = element(2, State),
- Socket = element(11, StaticEnv),
- %% Fake tcp error
- Pid ! {tcp_error, Socket, etimedout},
-
- ssl_test_lib:check_result(Client, {ssl_closed, SslSocket}).
-
-%%--------------------------------------------------------------------
-recv_error_handling() ->
- [{doc,"Special case of call error handling"}].
-recv_error_handling(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, recv_close, []}},
- {options, [{active, false} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- {_Client, #sslsocket{} = SslSocket} = ssl_test_lib:start_client([return_socket,
- {node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, ClientOpts}]),
- 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),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
- 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() ->
- [{doc, "Test that there is a 1/n-1-split for non RC4 in 'TLS < 1.1' as it is
- vunrable to Rizzo/Dungon attack"}].
-
-rizzo(Config) when is_list(Config) ->
- Prop = proplists:get_value(tc_group_properties, Config),
- Version = proplists:get_value(name, Prop),
- NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(all, NVersion),
- [{key_exchange,
- fun(Alg) when Alg == ecdh_rsa; Alg == ecdhe_rsa->
- true;
- (_) ->
- false
- end},
- {cipher,
- fun(rc4_128) ->
- false;
- (chacha20_poly1305) ->
- false;
- (_) ->
- true
- end}]),
-
- run_send_recv_rizzo(Ciphers, Config, Version,
- {?MODULE, send_recv_result_active_rizzo, []}).
-%%--------------------------------------------------------------------
-no_rizzo_rc4() ->
- [{doc,"Test that there is no 1/n-1-split for RC4 as it is not vunrable to Rizzo/Dungon attack"}].
-
-no_rizzo_rc4(Config) when is_list(Config) ->
- Prop = proplists:get_value(tc_group_properties, Config),
- Version = proplists:get_value(name, Prop),
- NVersion = ssl_test_lib:protocol_version(Config, tuple),
- %% Test uses RSA certs
- Ciphers = ssl:filter_cipher_suites(ssl_test_lib:rc4_suites(NVersion),
- [{key_exchange,
- fun(Alg) when Alg == ecdh_rsa; Alg == ecdhe_rsa->
- true;
- (_) ->
- false
- end}]),
- run_send_recv_rizzo(Ciphers, Config, Version,
- {?MODULE, send_recv_result_active_no_rizzo, []}).
-
-rizzo_one_n_minus_one() ->
- [{doc,"Test that the 1/n-1-split mitigation of Rizzo/Dungon attack can be explicitly selected"}].
-
-rizzo_one_n_minus_one(Config) when is_list(Config) ->
- Prop = proplists:get_value(tc_group_properties, Config),
- Version = proplists:get_value(name, Prop),
- NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(all, NVersion),
- [{key_exchange,
- fun(Alg) when Alg == ecdh_rsa; Alg == ecdhe_rsa->
- true;
- (_) ->
- false
- end},
- {cipher,
- fun(rc4_128) ->
- false;
- %% TODO: remove this clause when chacha is fixed!
- (chacha20_poly1305) ->
- false;
- (_) ->
- true
- end}]),
- run_send_recv_rizzo(Ciphers, Config, Version,
- {?MODULE, send_recv_result_active_rizzo, []}).
-
-rizzo_zero_n() ->
- [{doc,"Test that the 0/n-split mitigation of Rizzo/Dungon attack can be explicitly selected"}].
-
-rizzo_zero_n(Config) when is_list(Config) ->
- Prop = proplists:get_value(tc_group_properties, Config),
- Version = proplists:get_value(name, Prop),
- NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, NVersion),
- [{cipher,
- fun(rc4_128) ->
- false;
- (_) ->
- true
- end}]),
- run_send_recv_rizzo(Ciphers, Config, Version,
- {?MODULE, send_recv_result_active_no_rizzo, []}).
-
-rizzo_disabled() ->
- [{doc,"Test that the mitigation of Rizzo/Dungon attack can be explicitly disabled"}].
-
-rizzo_disabled(Config) when is_list(Config) ->
- Prop = proplists:get_value(tc_group_properties, Config),
- Version = proplists:get_value(name, Prop),
- NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, NVersion),
- [{cipher,
- fun(rc4_128) ->
- false;
- (_) ->
- true
- end}]),
- run_send_recv_rizzo(Ciphers, Config, Version,
- {?MODULE, send_recv_result_active_no_rizzo, []}).
-
-%%--------------------------------------------------------------------
-new_server_wants_peer_cert() ->
- [{doc, "Test that server configured to do client certification does"
- " not reuse session without a client certificate."}].
-new_server_wants_peer_cert(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- VServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_verification_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_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, peercert_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, []}},
- {options, ClientOpts}]),
-
- Monitor = erlang:monitor(process, Server),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- receive
- {'DOWN', Monitor, _, _, _} ->
- ok
- end,
-
- Server1 = ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
- {from, self()},
- {mfa, {?MODULE, peercert_result, []}},
- {options, VServerOpts}]),
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [ClientOpts]}]),
-
- CertFile = proplists:get_value(certfile, ClientOpts),
- [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile),
-
- ServerMsg = {error, no_peercert},
- Sever1Msg = {ok, BinCert},
-
- ssl_test_lib:check_result(Server, ServerMsg, Server1, Sever1Msg),
-
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client),
- ssl_test_lib:close(Client1).
-
-%%--------------------------------------------------------------------
-session_cache_process_list() ->
- [{doc,"Test reuse of sessions (short handshake)"}].
-session_cache_process_list(Config) when is_list(Config) ->
- session_cache_process(list,Config).
-%%--------------------------------------------------------------------
-session_cache_process_mnesia() ->
- [{doc,"Test reuse of sessions (short handshake)"}].
-session_cache_process_mnesia(Config) when is_list(Config) ->
- session_cache_process(mnesia,Config).
+eccs() ->
+ [{doc, "Test API functions eccs/0 and eccs/1"}].
-%%--------------------------------------------------------------------
+eccs(Config) when is_list(Config) ->
+ [_|_] = All = ssl:eccs(),
+ [] = 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 not verified by the test
+ true = lists:sort(All) =:= lists:usort(Tls ++ Tls1 ++ Tls2),
+ ok.
tls_versions_option() ->
[{doc,"Test API versions option to connect/listen."}].
@@ -4323,2140 +452,6 @@ tls_versions_option(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-unordered_protocol_versions_server() ->
- [{doc,"Test that the highest protocol is selected even"
- " when it is not first in the versions list."}].
-
-unordered_protocol_versions_server(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, 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, protocol_info_result, []}},
- {options, ClientOpts}]),
-
- ServerMsg = ClientMsg = {ok,'tlsv1.2'},
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
-
-%%--------------------------------------------------------------------
-unordered_protocol_versions_client() ->
- [{doc,"Test that the highest protocol is selected even"
- " when it is not first in the versions list."}].
-
-unordered_protocol_versions_client(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, 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, protocol_info_result, []}},
- {options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]),
-
- ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
-
-%%--------------------------------------------------------------------
-max_handshake_size() ->
- [{doc,"Test that we can set max_handshake_size to max value."}].
-
-max_handshake_size(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, send_recv_result_active, []}},
- {options, [{max_handshake_size, 8388607} |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, send_recv_result_active, []}},
- {options, [{max_handshake_size, 8388607} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok).
-
-%%--------------------------------------------------------------------
-
-server_name_indication_option() ->
- [{doc,"Test API server_name_indication option to connect."}].
-server_name_indication_option(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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options,
- [{server_name_indication, disable} |
- ClientOpts]}
- ]),
-
- ssl_test_lib:check_result(Server, ok, Client0, ok),
- Server ! listen,
-
- Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options,
- [{server_name_indication, Hostname} | ClientOpts]
- }]),
- ssl_test_lib:check_result(Server, ok, Client1, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client0),
- ssl_test_lib:close(Client1).
-%%--------------------------------------------------------------------
-
-accept_pool() ->
- [{doc,"Test having an accept pool."}].
-accept_pool(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),
- Server0 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {accepters, 3},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server0),
- [Server1, Server2] = ssl_test_lib:accepters(2),
-
- Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ClientOpts}
- ]),
-
- Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ClientOpts}
- ]),
-
- Client2 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ClientOpts}
- ]),
-
- ssl_test_lib:check_ok([Server0, Server1, Server2, Client0, Client1, Client2]),
-
- ssl_test_lib:close(Server0),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Server2),
- ssl_test_lib:close(Client0),
- ssl_test_lib:close(Client1),
- ssl_test_lib:close(Client2).
-
-%%--------------------------------------------------------------------
-%% TLS 1.3
-%%--------------------------------------------------------------------
-
-tls13_enable_client_side() ->
- [{doc,"Test that a TLS 1.3 client can connect to a TLS 1.2 server."}].
-
-tls13_enable_client_side(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, 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, protocol_info_result, []}},
- {options, [{versions,
- ['tlsv1.2', 'tlsv1.3']} | ClientOpts]}]),
-
- ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
-
-tls13_enable_server_side() ->
- [{doc,"Test that a TLS 1.2 client can connect to a TLS 1.3 server."}].
-
-tls13_enable_server_side(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, protocol_info_result, []}},
- {options, [{versions,
- ['tlsv1.2', 'tlsv1.3']} | ServerOpts] }]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, protocol_info_result, []}},
- {options, [{versions,
- ['tlsv1.2', 'tlsv1.1']} | ClientOpts]}]),
-
- ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
-
-tls_record_1_3_encode_decode() ->
- [{doc,"Test TLS 1.3 record encode/decode functions"}].
-
-tls_record_1_3_encode_decode(_Config) ->
- ConnectionStates =
- #{current_read =>
- #{beast_mitigation => one_n_minus_one,
- cipher_state =>
- {cipher_state,
- <<14,172,111,243,199,170,242,203,126,205,34,93,122,115,226,14,
- 15,117,155,48,24,112,61,15,113,208,127,51,179,227,194,232>>,
- <<197,54,168,218,54,91,157,58,30,201,197,142,51,58,53,231,228,
- 131,57,122,170,78,82,196,30,48,23,16,95,255,185,236>>,
- undefined,undefined,undefined,16},
- client_verify_data => undefined,compression_state => undefined,
- mac_secret => undefined,secure_renegotiation => undefined,
- security_parameters =>
- {security_parameters,
- <<19,2>>,
- 0,8,2,undefined,undefined,undefined,undefined,undefined,
- sha384,undefined,undefined,
- {handshake_secret,
- <<128,229,186,211,62,127,182,20,62,166,233,23,135,64,121,
- 3,104,251,214,161,253,31,3,2,232,37,8,221,189,72,64,218,
- 121,41,112,148,254,34,68,164,228,60,161,201,132,55,56,
- 157>>},
- undefined,
- <<92,24,205,75,244,60,136,212,250,32,214,20,37,3,213,87,61,207,
- 147,61,168,145,177,118,160,153,33,53,48,108,191,174>>,
- undefined},
- sequence_number => 0,server_verify_data => undefined},
- current_write =>
- #{beast_mitigation => one_n_minus_one,
- cipher_state =>
- {cipher_state,
- <<14,172,111,243,199,170,242,203,126,205,34,93,122,115,226,14,
- 15,117,155,48,24,112,61,15,113,208,127,51,179,227,194,232>>,
- <<197,54,168,218,54,91,157,58,30,201,197,142,51,58,53,231,228,
- 131,57,122,170,78,82,196,30,48,23,16,95,255,185,236>>,
- undefined,undefined,undefined,16},
- client_verify_data => undefined,compression_state => undefined,
- mac_secret => undefined,secure_renegotiation => undefined,
- security_parameters =>
- {security_parameters,
- <<19,2>>,
- 0,8,2,undefined,undefined,undefined,undefined,undefined,
- sha384,undefined,undefined,
- {handshake_secret,
- <<128,229,186,211,62,127,182,20,62,166,233,23,135,64,121,
- 3,104,251,214,161,253,31,3,2,232,37,8,221,189,72,64,218,
- 121,41,112,148,254,34,68,164,228,60,161,201,132,55,56,
- 157>>},
- undefined,
- <<92,24,205,75,244,60,136,212,250,32,214,20,37,3,213,87,61,207,
- 147,61,168,145,177,118,160,153,33,53,48,108,191,174>>,
- undefined},
- sequence_number => 0,server_verify_data => undefined}},
-
- PlainText = [11,
- <<0,2,175>>,
- <<0,0,2,171,0,2,166,48,130,2,162,48,130,1,138,2,9,0,186,57,220,137,88,255,
- 191,235,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,18,49,16,48,14,6,3,85,
- 4,3,12,7,84,101,115,116,32,67,65,48,30,23,13,49,56,48,53,48,52,49,52,49,50,
- 51,56,90,23,13,50,56,48,50,48,52,49,52,49,50,51,56,90,48,20,49,18,48,16,6,
- 3,85,4,3,12,9,108,111,99,97,108,104,111,115,116,48,130,1,34,48,13,6,9,42,
- 134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,169,40,
- 144,176,121,63,134,97,144,126,243,183,225,157,37,131,183,225,87,243,23,88,
- 230,70,9,134,32,147,7,27,167,98,51,81,224,75,199,12,229,251,195,207,75,179,
- 181,78,128,3,255,44,58,39,43,172,142,45,186,58,51,65,187,199,154,153,245,
- 70,133,137,1,27,87,42,116,65,251,129,109,145,233,97,171,71,54,213,185,74,
- 209,166,11,218,189,119,206,86,170,60,212,213,85,189,30,50,215,23,185,53,
- 132,238,132,176,198,250,139,251,198,221,225,128,109,113,23,220,39,143,71,
- 30,59,189,51,244,61,158,214,146,180,196,103,169,189,221,136,78,129,216,148,
- 2,9,8,65,37,224,215,233,13,209,21,235,20,143,33,74,59,53,208,90,152,94,251,
- 54,114,171,39,88,230,227,158,211,135,37,182,67,205,161,59,20,138,58,253,15,
- 53,48,8,157,9,95,197,9,177,116,21,54,9,125,78,109,182,83,20,16,234,223,116,
- 41,155,123,87,77,17,120,153,246,239,124,130,105,219,166,146,242,151,66,198,
- 75,72,63,28,246,86,16,244,223,22,36,50,15,247,222,98,6,152,136,154,72,150,
- 73,127,2,3,1,0,1,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,76,
- 33,54,160,229,219,219,193,150,116,245,252,18,39,235,145,86,12,167,171,52,
- 117,166,30,83,5,216,245,177,217,247,95,1,136,94,246,212,108,248,230,111,
- 225,202,189,6,129,8,70,128,245,18,204,215,87,82,129,253,227,122,66,182,184,
- 189,30,193,169,144,218,216,109,105,110,215,144,60,104,162,178,101,164,218,
- 122,60,37,41,143,57,150,52,59,51,112,238,113,239,168,114,69,183,143,154,73,
- 61,58,80,247,172,95,251,55,28,186,28,200,206,230,118,243,92,202,189,49,76,
- 124,252,76,0,247,112,85,194,69,59,222,163,228,103,49,110,104,109,251,155,
- 138,9,37,167,49,189,48,134,52,158,185,129,24,96,153,196,251,90,206,76,239,
- 175,119,174,165,133,108,222,125,237,125,187,149,152,83,190,16,202,94,202,
- 201,40,218,22,254,63,189,41,174,97,140,203,70,18,196,118,237,175,134,79,78,
- 246,2,61,54,77,186,112,32,17,193,192,188,217,252,215,200,7,245,180,179,132,
- 183,212,229,155,15,152,206,135,56,81,88,3,123,244,149,110,182,72,109,70,62,
- 146,152,146,151,107,126,216,210,9,93,0,0>>],
-
- {[_Header|Encoded], _} = tls_record_1_3:encode_plain_text(22, PlainText, ConnectionStates),
- CipherText = #ssl_tls{type = 23, version = {3,3}, fragment = Encoded},
-
- {#ssl_tls{type = 22, version = {3,4}, fragment = DecodedText}, _} =
- tls_record_1_3:decode_cipher_text(CipherText, ConnectionStates),
-
- DecodedText = iolist_to_binary(PlainText),
- ct:log("Decoded: ~p ~n", [DecodedText]),
- ok.
-
-tls13_1_RTT_handshake() ->
- [{doc,"Test TLS 1.3 1-RTT Handshake"}].
-
-tls13_1_RTT_handshake(_Config) ->
- %% ConnectionStates with NULL cipher
- ConnStatesNull =
- #{current_write =>
- #{security_parameters =>
- #security_parameters{cipher_suite = ?TLS_NULL_WITH_NULL_NULL},
- sequence_number => 0
- }
- },
-
- %% {client} construct a ClientHello handshake message:
- %%
- %% ClientHello (196 octets): 01 00 00 c0 03 03 cb 34 ec b1 e7 81 63
- %% ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12 ec 18 a2 ef 62 83
- %% 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00 00 91 00 00 00 0b
- %% 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00
- %% 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 23
- %% 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d e5 60 e4 bd 43 d2
- %% 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a
- %% af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03
- %% 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06
- %% 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01
- %%
- %% {client} send handshake record:
- %%
- %% payload (196 octets): 01 00 00 c0 03 03 cb 34 ec b1 e7 81 63 ba
- %% 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12 ec 18 a2 ef 62 83 02
- %% 4d ec e7 00 00 06 13 01 13 03 13 02 01 00 00 91 00 00 00 0b 00
- %% 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00 12
- %% 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 23 00
- %% 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d e5 60 e4 bd 43 d2 3d
- %% 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af
- %% 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03 02
- %% 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06 02
- %% 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01
- %%
- %% complete record (201 octets): 16 03 01 00 c4 01 00 00 c0 03 03 cb
- %% 34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12
- %% ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00
- %% 00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01
- %% 00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02
- %% 01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d
- %% e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d
- %% 54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e
- %% 04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02
- %% 01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01
- ClientHello =
- hexstr2bin("01 00 00 c0 03 03 cb 34 ec b1 e7 81 63
- ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12 ec 18 a2 ef 62 83
- 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00 00 91 00 00 00 0b
- 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00
- 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 23
- 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d e5 60 e4 bd 43 d2
- 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a
- af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03
- 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06
- 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01"),
-
- ClientHelloRecord =
- %% Current implementation always sets
- %% legacy_record_version to Ox0303
- hexstr2bin("16 03 03 00 c4 01 00 00 c0 03 03 cb
- 34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12
- ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00
- 00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01
- 00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02
- 01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d
- e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d
- 54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e
- 04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02
- 01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01"),
-
- {CHEncrypted, _} =
- tls_record:encode_handshake(ClientHello, {3,4}, ConnStatesNull),
- ClientHelloRecord = iolist_to_binary(CHEncrypted),
-
- %% {server} extract secret "early":
- %%
- %% salt: 0 (all zero octets)
- %%
- %% IKM (32 octets): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- %% 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- %%
- %% secret (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c
- %% e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a
- HKDFAlgo = sha256,
- Salt = binary:copy(<<?BYTE(0)>>, 32),
- IKM = binary:copy(<<?BYTE(0)>>, 32),
- EarlySecret =
- hexstr2bin("33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c
- e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a"),
-
- {early_secret, EarlySecret} = tls_v1:key_schedule(early_secret, HKDFAlgo, {psk, Salt}),
-
- %% {client} create an ephemeral x25519 key pair:
- %%
- %% private key (32 octets): 49 af 42 ba 7f 79 94 85 2d 71 3e f2 78
- %% 4b cb ca a7 91 1d e2 6a dc 56 42 cb 63 45 40 e7 ea 50 05
- %%
- %% public key (32 octets): 99 38 1d e5 60 e4 bd 43 d2 3d 8e 43 5a 7d
- %% ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af 2c
- CPublicKey =
- hexstr2bin("99 38 1d e5 60 e4 bd 43 d2 3d 8e 43 5a 7d
- ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af 2c"),
-
- %% {server} create an ephemeral x25519 key pair:
- %%
- %% private key (32 octets): b1 58 0e ea df 6d d5 89 b8 ef 4f 2d 56
- %% 52 57 8c c8 10 e9 98 01 91 ec 8d 05 83 08 ce a2 16 a2 1e
- %%
- %% public key (32 octets): c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6
- %% 72 e1 56 d6 cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f
- SPrivateKey =
- hexstr2bin("b1 58 0e ea df 6d d5 89 b8 ef 4f 2d 56
- 52 57 8c c8 10 e9 98 01 91 ec 8d 05 83 08 ce a2 16 a2 1e"),
-
- SPublicKey =
- hexstr2bin("c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6
- 72 e1 56 d6 cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f"),
-
- %% {server} construct a ServerHello handshake message:
- %%
- %% ServerHello (90 octets): 02 00 00 56 03 03 a6 af 06 a4 12 18 60
- %% dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 34 da c1 55 77 2e
- %% d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00 1d 00 20 c9 82 88
- %% 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6 cc 25 3b 83 3d f1
- %% dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04
- ServerHello =
- hexstr2bin("02 00 00 56 03 03 a6 af 06 a4 12 18 60
- dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 34 da c1 55 77 2e
- d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00 1d 00 20 c9 82 88
- 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6 cc 25 3b 83 3d f1
- dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04"),
-
- %% {server} derive secret for handshake "tls13 derived":
- %%
- %% PRK (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c e2
- %% 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a
- %%
- %% hash (32 octets): e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24
- %% 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55
- %%
- %% info (49 octets): 00 20 0d 74 6c 73 31 33 20 64 65 72 69 76 65 64
- %% 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4
- %% 64 9b 93 4c a4 95 99 1b 78 52 b8 55
- %%
- %% expanded (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba
- %% b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba
- Hash =
- hexstr2bin("e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24
- 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55"),
-
- Hash = crypto:hash(HKDFAlgo, <<>>),
-
- Info =
- hexstr2bin("00 20 0d 74 6c 73 31 33 20 64 65 72 69 76 65 64
- 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4
- 64 9b 93 4c a4 95 99 1b 78 52 b8 55"),
-
- Info = tls_v1:create_info(<<"derived">>, Hash, ssl_cipher:hash_size(HKDFAlgo)),
-
- Expanded =
- hexstr2bin("6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba
- b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba"),
-
- Expanded = tls_v1:derive_secret(EarlySecret, <<"derived">>, <<>>, HKDFAlgo),
-
- %% {server} extract secret "handshake":
- %%
- %% salt (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba b6 97
- %% 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba
- %%
- %% IKM (32 octets): 8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d
- %% 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d
- %%
- %% secret (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b
- %% 01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
-
- %% salt = Expanded
- HandshakeIKM =
- hexstr2bin("8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d
- 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d"),
-
- HandshakeSecret =
- hexstr2bin("1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b
- 01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac"),
-
- HandshakeIKM = crypto:compute_key(ecdh, CPublicKey, SPrivateKey, x25519),
-
- {handshake_secret, HandshakeSecret} =
- tls_v1:key_schedule(handshake_secret, HKDFAlgo, HandshakeIKM,
- {early_secret, EarlySecret}),
-
- %% {server} derive secret "tls13 c hs traffic":
- %%
- %% PRK (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01
- %% 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
- %%
- %% hash (32 octets): 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed
- %% d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
- %%
- %% info (54 octets): 00 20 12 74 6c 73 31 33 20 63 20 68 73 20 74 72
- %% 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
- %% ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
- %%
- %% expanded (32 octets): b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e
- %% 2d 8f 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21
-
- %% PRK = HandshakeSecret
- CHSTHash =
- hexstr2bin("86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed
- d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8"),
-
- CHSTInfo =
- hexstr2bin("00 20 12 74 6c 73 31 33 20 63 20 68 73 20 74 72
- 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
- ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8"),
-
- CHSTrafficSecret =
- hexstr2bin(" b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e
- 2d 8f 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21"),
-
- CHSH = <<ClientHello/binary,ServerHello/binary>>,
- CHSTHash = crypto:hash(HKDFAlgo, CHSH),
- CHSTInfo = tls_v1:create_info(<<"c hs traffic">>, CHSTHash, ssl_cipher:hash_size(HKDFAlgo)),
-
- CHSTrafficSecret =
- tls_v1:client_handshake_traffic_secret(HKDFAlgo, {handshake_secret, HandshakeSecret}, CHSH),
-
- %% {server} derive secret "tls13 s hs traffic":
- %%
- %% PRK (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01
- %% 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
- %%
- %% hash (32 octets): 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed
- %% d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
- %%
- %% info (54 octets): 00 20 12 74 6c 73 31 33 20 73 20 68 73 20 74 72
- %% 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
- %% ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
- %%
- %% expanded (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d
- %% 37 b4 e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38
-
- %% PRK = HandshakeSecret
- %% hash = CHSTHash
- SHSTInfo =
- hexstr2bin("00 20 12 74 6c 73 31 33 20 73 20 68 73 20 74 72
- 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
- ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8"),
-
- SHSTrafficSecret =
- hexstr2bin("b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d
- 37 b4 e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38"),
-
- SHSTInfo = tls_v1:create_info(<<"s hs traffic">>, CHSTHash, ssl_cipher:hash_size(HKDFAlgo)),
-
- SHSTrafficSecret =
- tls_v1:server_handshake_traffic_secret(HKDFAlgo, {handshake_secret, HandshakeSecret}, CHSH),
-
-
- %% {server} derive secret for master "tls13 derived":
- %%
- %% PRK (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01
- %% 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
- %%
- %% hash (32 octets): e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24
- %% 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55
- %%
- %% info (49 octets): 00 20 0d 74 6c 73 31 33 20 64 65 72 69 76 65 64
- %% 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4
- %% 64 9b 93 4c a4 95 99 1b 78 52 b8 55
- %%
- %% expanded (32 octets): 43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25
- %% 90 b5 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4
-
- %% PRK = HandshakeSecret
- %% hash = Hash
- %% info = Info
- MasterDeriveSecret =
- hexstr2bin("43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25
- 90 b5 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4"),
-
- MasterDeriveSecret = tls_v1:derive_secret(HandshakeSecret, <<"derived">>, <<>>, HKDFAlgo),
-
- %% {server} extract secret "master":
- %%
- %% salt (32 octets): 43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25 90 b5
- %% 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4
- %%
- %% IKM (32 octets): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- %% 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- %%
- %% secret (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a
- %% 47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
-
- %% salt = MasterDeriveSecret
- %% IKM = IKM
- MasterSecret =
- hexstr2bin("18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a
- 47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19"),
-
- {master_secret, MasterSecret} =
- tls_v1:key_schedule(master_secret, HKDFAlgo, {handshake_secret, HandshakeSecret}),
-
- %% {server} send handshake record:
- %%
- %% payload (90 octets): 02 00 00 56 03 03 a6 af 06 a4 12 18 60 dc 5e
- %% 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 34 da c1 55 77 2e d3 e2
- %% 69 28 00 13 01 00 00 2e 00 33 00 24 00 1d 00 20 c9 82 88 76 11
- %% 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6 cc 25 3b 83 3d f1 dd 69
- %% b1 b0 4e 75 1f 0f 00 2b 00 02 03 04
- %%
- %% complete record (95 octets): 16 03 03 00 5a 02 00 00 56 03 03 a6
- %% af 06 a4 12 18 60 dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14
- %% 34 da c1 55 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00
- %% 1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6
- %% cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04
-
- %% payload = ServerHello
- ServerHelloRecord =
- hexstr2bin("16 03 03 00 5a 02 00 00 56 03 03 a6
- af 06 a4 12 18 60 dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14
- 34 da c1 55 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00
- 1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6
- cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04"),
-
- {SHEncrypted, _} =
- tls_record:encode_handshake(ServerHello, {3,4}, ConnStatesNull),
- ServerHelloRecord = iolist_to_binary(SHEncrypted),
-
- %% {server} derive write traffic keys for handshake data:
- %%
- %% PRK (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4
- %% e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38
- %%
- %% key info (13 octets): 00 10 09 74 6c 73 31 33 20 6b 65 79 00
- %%
- %% key expanded (16 octets): 3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e
- %% e4 03 bc
- %%
- %% iv info (12 octets): 00 0c 08 74 6c 73 31 33 20 69 76 00
- %%
- %% iv expanded (12 octets): 5d 31 3e b2 67 12 76 ee 13 00 0b 30
-
- %% PRK = SHSTrafficSecret
- WriteKeyInfo =
- hexstr2bin("00 10 09 74 6c 73 31 33 20 6b 65 79 00"),
-
- WriteKey =
- hexstr2bin("3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e e4 03 bc"),
-
- WriteIVInfo =
- hexstr2bin("00 0c 08 74 6c 73 31 33 20 69 76 00"),
-
- WriteIV =
- hexstr2bin(" 5d 31 3e b2 67 12 76 ee 13 00 0b 30"),
-
- Cipher = aes_128_gcm, %% TODO: get from ServerHello
-
- WriteKeyInfo = tls_v1:create_info(<<"key">>, <<>>, ssl_cipher:key_material(Cipher)),
- %% TODO: remove hardcoded IV size
- WriteIVInfo = tls_v1:create_info(<<"iv">>, <<>>, 12),
-
- {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, SHSTrafficSecret),
-
- %% {server} construct an EncryptedExtensions handshake message:
- %%
- %% EncryptedExtensions (40 octets): 08 00 00 24 00 22 00 0a 00 14 00
- %% 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c
- %% 00 02 40 01 00 00 00 00
- %%
- %% {server} construct a Certificate handshake message:
- %%
- %% Certificate (445 octets): 0b 00 01 b9 00 00 01 b5 00 01 b0 30 82
- %% 01 ac 30 82 01 15 a0 03 02 01 02 02 01 02 30 0d 06 09 2a 86 48
- %% 86 f7 0d 01 01 0b 05 00 30 0e 31 0c 30 0a 06 03 55 04 03 13 03
- %% 72 73 61 30 1e 17 0d 31 36 30 37 33 30 30 31 32 33 35 39 5a 17
- %% 0d 32 36 30 37 33 30 30 31 32 33 35 39 5a 30 0e 31 0c 30 0a 06
- %% 03 55 04 03 13 03 72 73 61 30 81 9f 30 0d 06 09 2a 86 48 86 f7
- %% 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 b4 bb 49 8f
- %% 82 79 30 3d 98 08 36 39 9b 36 c6 98 8c 0c 68 de 55 e1 bd b8 26
- %% d3 90 1a 24 61 ea fd 2d e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c
- %% 1a f1 9e aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 cc b0 52
- %% 4b 1b 01 8c 3e 0b 63 26 4d 44 9a 6d 38 e2 2a 5f da 43 08 46 74
- %% 80 30 53 0e f0 46 1c 8c a9 d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93
- %% ef f0 ab 9a 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 02 03
- %% 01 00 01 a3 1a 30 18 30 09 06 03 55 1d 13 04 02 30 00 30 0b 06
- %% 03 55 1d 0f 04 04 03 02 05 a0 30 0d 06 09 2a 86 48 86 f7 0d 01
- %% 01 0b 05 00 03 81 81 00 85 aa d2 a0 e5 b9 27 6b 90 8c 65 f7 3a
- %% 72 67 17 06 18 a5 4c 5f 8a 7b 33 7d 2d f7 a5 94 36 54 17 f2 ea
- %% e8 f8 a5 8c 8f 81 72 f9 31 9c f3 6b 7f d6 c5 5b 80 f2 1a 03 01
- %% 51 56 72 60 96 fd 33 5e 5e 67 f2 db f1 02 70 2e 60 8c ca e6 be
- %% c1 fc 63 a4 2a 99 be 5c 3e b7 10 7c 3c 54 e9 b9 eb 2b d5 20 3b
- %% 1c 3b 84 e0 a8 b2 f7 59 40 9b a3 ea c9 d9 1d 40 2d cc 0c c8 f8
- %% 96 12 29 ac 91 87 b4 2b 4d e1 00 00
- %%
- %% {server} construct a CertificateVerify handshake message:
- %%
- %% CertificateVerify (136 octets): 0f 00 00 84 08 04 00 80 5a 74 7c
- %% 5d 88 fa 9b d2 e5 5a b0 85 a6 10 15 b7 21 1f 82 4c d4 84 14 5a
- %% b3 ff 52 f1 fd a8 47 7b 0b 7a bc 90 db 78 e2 d3 3a 5c 14 1a 07
- %% 86 53 fa 6b ef 78 0c 5e a2 48 ee aa a7 85 c4 f3 94 ca b6 d3 0b
- %% be 8d 48 59 ee 51 1f 60 29 57 b1 54 11 ac 02 76 71 45 9e 46 44
- %% 5c 9e a5 8c 18 1e 81 8e 95 b8 c3 fb 0b f3 27 84 09 d3 be 15 2a
- %% 3d a5 04 3e 06 3d da 65 cd f5 ae a2 0d 53 df ac d4 2f 74 f3
- EncryptedExtensions =
- hexstr2bin("08 00 00 24 00 22 00 0a 00 14 00
- 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c
- 00 02 40 01 00 00 00 00"),
-
- Certificate =
- hexstr2bin("0b 00 01 b9 00 00 01 b5 00 01 b0 30 82
- 01 ac 30 82 01 15 a0 03 02 01 02 02 01 02 30 0d 06 09 2a 86 48
- 86 f7 0d 01 01 0b 05 00 30 0e 31 0c 30 0a 06 03 55 04 03 13 03
- 72 73 61 30 1e 17 0d 31 36 30 37 33 30 30 31 32 33 35 39 5a 17
- 0d 32 36 30 37 33 30 30 31 32 33 35 39 5a 30 0e 31 0c 30 0a 06
- 03 55 04 03 13 03 72 73 61 30 81 9f 30 0d 06 09 2a 86 48 86 f7
- 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 b4 bb 49 8f
- 82 79 30 3d 98 08 36 39 9b 36 c6 98 8c 0c 68 de 55 e1 bd b8 26
- d3 90 1a 24 61 ea fd 2d e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c
- 1a f1 9e aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 cc b0 52
- 4b 1b 01 8c 3e 0b 63 26 4d 44 9a 6d 38 e2 2a 5f da 43 08 46 74
- 80 30 53 0e f0 46 1c 8c a9 d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93
- ef f0 ab 9a 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 02 03
- 01 00 01 a3 1a 30 18 30 09 06 03 55 1d 13 04 02 30 00 30 0b 06
- 03 55 1d 0f 04 04 03 02 05 a0 30 0d 06 09 2a 86 48 86 f7 0d 01
- 01 0b 05 00 03 81 81 00 85 aa d2 a0 e5 b9 27 6b 90 8c 65 f7 3a
- 72 67 17 06 18 a5 4c 5f 8a 7b 33 7d 2d f7 a5 94 36 54 17 f2 ea
- e8 f8 a5 8c 8f 81 72 f9 31 9c f3 6b 7f d6 c5 5b 80 f2 1a 03 01
- 51 56 72 60 96 fd 33 5e 5e 67 f2 db f1 02 70 2e 60 8c ca e6 be
- c1 fc 63 a4 2a 99 be 5c 3e b7 10 7c 3c 54 e9 b9 eb 2b d5 20 3b
- 1c 3b 84 e0 a8 b2 f7 59 40 9b a3 ea c9 d9 1d 40 2d cc 0c c8 f8
- 96 12 29 ac 91 87 b4 2b 4d e1 00 00"),
-
- CertificateVerify =
- hexstr2bin("0f 00 00 84 08 04 00 80 5a 74 7c
- 5d 88 fa 9b d2 e5 5a b0 85 a6 10 15 b7 21 1f 82 4c d4 84 14 5a
- b3 ff 52 f1 fd a8 47 7b 0b 7a bc 90 db 78 e2 d3 3a 5c 14 1a 07
- 86 53 fa 6b ef 78 0c 5e a2 48 ee aa a7 85 c4 f3 94 ca b6 d3 0b
- be 8d 48 59 ee 51 1f 60 29 57 b1 54 11 ac 02 76 71 45 9e 46 44
- 5c 9e a5 8c 18 1e 81 8e 95 b8 c3 fb 0b f3 27 84 09 d3 be 15 2a
- 3d a5 04 3e 06 3d da 65 cd f5 ae a2 0d 53 df ac d4 2f 74 f3"),
-
- %% {server} calculate finished "tls13 finished":
- %%
- %% PRK (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4
- %% e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38
- %%
- %% hash (0 octets): (empty)
- %%
- %% info (18 octets): 00 20 0e 74 6c 73 31 33 20 66 69 6e 69 73 68 65
- %% 64 00
- %%
- %% expanded (32 octets): 00 8d 3b 66 f8 16 ea 55 9f 96 b5 37 e8 85
- %% c3 1f c0 68 bf 49 2c 65 2f 01 f2 88 a1 d8 cd c1 9f c8
- %%
- %% finished (32 octets): 9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4
- %% de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18
-
- %% PRK = SHSTrafficSecret
- FInfo =
- hexstr2bin("00 20 0e 74 6c 73 31 33 20 66 69 6e 69 73 68 65
- 64 00"),
-
- FExpanded =
- hexstr2bin("00 8d 3b 66 f8 16 ea 55 9f 96 b5 37 e8 85
- c3 1f c0 68 bf 49 2c 65 2f 01 f2 88 a1 d8 cd c1 9f c8"),
-
- FinishedVerifyData =
- hexstr2bin("9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4
- de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18"),
-
- FInfo = tls_v1:create_info(<<"finished">>, <<>>, ssl_cipher:hash_size(HKDFAlgo)),
-
- FExpanded = tls_v1:finished_key(SHSTrafficSecret, HKDFAlgo),
-
- MessageHistory0 = [CertificateVerify,
- Certificate,
- EncryptedExtensions,
- ServerHello,
- ClientHello],
-
- FinishedVerifyData = tls_v1:finished_verify_data(FExpanded, HKDFAlgo, MessageHistory0),
-
- %% {server} construct a Finished handshake message:
- %%
- %% Finished (36 octets): 14 00 00 20 9b 9b 14 1d 90 63 37 fb d2 cb
- %% dc e7 1d f4 de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07
- %% 18
- FinishedHSBin =
- hexstr2bin("14 00 00 20 9b 9b 14 1d 90 63 37 fb d2 cb
- dc e7 1d f4 de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07
- 18"),
-
- FinishedHS = #finished{verify_data = FinishedVerifyData},
-
- FinishedIOList = tls_handshake:encode_handshake(FinishedHS, {3,4}),
- FinishedHSBin = iolist_to_binary(FinishedIOList),
-
- %% {server} derive secret "tls13 c ap traffic":
- %%
- %% PRK (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47
- %% 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
- %%
- %% hash (32 octets): 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
- %% 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
- %%
- %% info (54 octets): 00 20 12 74 6c 73 31 33 20 63 20 61 70 20 74 72
- %% 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
- %% 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
- %%
- %% expanded (32 octets): 9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce
- %% 65 52 87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5
-
- %% PRK = MasterSecret
- CAPTHash =
- hexstr2bin("96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
- 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
- CAPTInfo =
- hexstr2bin("00 20 12 74 6c 73 31 33 20 63 20 61 70 20 74 72
- 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
- 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
-
- CAPTrafficSecret =
- hexstr2bin("9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce
- 65 52 87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5"),
-
- CHSF = <<ClientHello/binary,
- ServerHello/binary,
- EncryptedExtensions/binary,
- Certificate/binary,
- CertificateVerify/binary,
- FinishedHSBin/binary>>,
-
- CAPTHash = crypto:hash(HKDFAlgo, CHSF),
-
- CAPTInfo =
- tls_v1:create_info(<<"c ap traffic">>, CAPTHash, ssl_cipher:hash_size(HKDFAlgo)),
-
- CAPTrafficSecret =
- tls_v1:client_application_traffic_secret_0(HKDFAlgo, {master_secret, MasterSecret}, CHSF),
-
- %% {server} derive secret "tls13 s ap traffic":
- %%
- %% PRK (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47
- %% 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
- %%
- %% hash (32 octets): 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
- %% 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
- %%
- %% info (54 octets): 00 20 12 74 6c 73 31 33 20 73 20 61 70 20 74 72
- %% 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
- %% 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
- %%
- %% expanded (32 octets): a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9
- %% 50 32 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43
-
- %% PRK = MasterSecret
- %% hash = CAPTHash
- SAPTInfo =
- hexstr2bin(" 00 20 12 74 6c 73 31 33 20 73 20 61 70 20 74 72
- 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
- 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
-
- SAPTrafficSecret =
- hexstr2bin("a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9
- 50 32 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43"),
-
- SAPTInfo =
- tls_v1:create_info(<<"s ap traffic">>, CAPTHash, ssl_cipher:hash_size(HKDFAlgo)),
-
- SAPTrafficSecret =
- tls_v1:server_application_traffic_secret_0(HKDFAlgo, {master_secret, MasterSecret}, CHSF),
-
- %% {server} derive secret "tls13 exp master":
- %%
- %% PRK (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47
- %% 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
- %%
- %% hash (32 octets): 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
- %% 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
- %%
- %% info (52 octets): 00 20 10 74 6c 73 31 33 20 65 78 70 20 6d 61 73
- %% 74 65 72 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a 00
- %% 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
- %%
- %% expanded (32 octets): fe 22 f8 81 17 6e da 18 eb 8f 44 52 9e 67
- %% 92 c5 0c 9a 3f 89 45 2f 68 d8 ae 31 1b 43 09 d3 cf 50
-
- %% PRK = MasterSecret
- %% hash = CAPTHash
- ExporterInfo =
- hexstr2bin("00 20 10 74 6c 73 31 33 20 65 78 70 20 6d 61 73
- 74 65 72 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a 00
- 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
-
- ExporterMasterSecret =
- hexstr2bin("fe 22 f8 81 17 6e da 18 eb 8f 44 52 9e 67
- 92 c5 0c 9a 3f 89 45 2f 68 d8 ae 31 1b 43 09 d3 cf 50"),
-
- ExporterInfo =
- tls_v1:create_info(<<"exp master">>, CAPTHash, ssl_cipher:hash_size(HKDFAlgo)),
-
- ExporterMasterSecret =
- tls_v1:exporter_master_secret(HKDFAlgo, {master_secret, MasterSecret}, CHSF),
-
- %% {server} derive write traffic keys for application data:
- %%
- %% PRK (32 octets): a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9 50 32
- %% 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43
- %%
- %% key info (13 octets): 00 10 09 74 6c 73 31 33 20 6b 65 79 00
- %%
- %% key expanded (16 octets): 9f 02 28 3b 6c 9c 07 ef c2 6b b9 f2 ac
- %% 92 e3 56
- %%
- %% iv info (12 octets): 00 0c 08 74 6c 73 31 33 20 69 76 00
- %%
- %% iv expanded (12 octets): cf 78 2b 88 dd 83 54 9a ad f1 e9 84
-
- %% PRK = SAPTrafficsecret
- %% key info = WriteKeyInfo
- %% iv info = WrtieIVInfo
- SWKey =
- hexstr2bin("9f 02 28 3b 6c 9c 07 ef c2 6b b9 f2 ac 92 e3 56"),
-
- SWIV =
- hexstr2bin("cf 78 2b 88 dd 83 54 9a ad f1 e9 84"),
-
- {SWKey, SWIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, SAPTrafficSecret),
-
- %% {server} derive read traffic keys for handshake data:
- %%
- %% PRK (32 octets): b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e 2d 8f
- %% 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21
- %%
- %% key info (13 octets): 00 10 09 74 6c 73 31 33 20 6b 65 79 00
- %%
- %% key expanded (16 octets): db fa a6 93 d1 76 2c 5b 66 6a f5 d9 50
- %% 25 8d 01
- %%
- %% iv info (12 octets): 00 0c 08 74 6c 73 31 33 20 69 76 00
- %%
- %% iv expanded (12 octets): 5b d3 c7 1b 83 6e 0b 76 bb 73 26 5f
-
- %% PRK = CHSTrafficsecret
- %% key info = WriteKeyInfo
- %% iv info = WrtieIVInfo
- SRKey =
- hexstr2bin("db fa a6 93 d1 76 2c 5b 66 6a f5 d9 50 25 8d 01"),
-
- SRIV =
- hexstr2bin("5b d3 c7 1b 83 6e 0b 76 bb 73 26 5f"),
-
- {SRKey, SRIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, CHSTrafficSecret).
-
-
-tls13_finished_verify_data() ->
- [{doc,"Test TLS 1.3 Finished message handling"}].
-
-tls13_finished_verify_data(_Config) ->
- ClientHello =
- hexstr2bin("01 00 00 c6 03 03 00 01 02 03 04 05 06 07 08 09
- 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19
- 1a 1b 1c 1d 1e 1f 20 e0 e1 e2 e3 e4 e5 e6 e7 e8
- e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8
- f9 fa fb fc fd fe ff 00 06 13 01 13 02 13 03 01
- 00 00 77 00 00 00 18 00 16 00 00 13 65 78 61 6d
- 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e 65 74 00
- 0a 00 08 00 06 00 1d 00 17 00 18 00 0d 00 14 00
- 12 04 03 08 04 04 01 05 03 08 05 05 01 08 06 06
- 01 02 01 00 33 00 26 00 24 00 1d 00 20 35 80 72
- d6 36 58 80 d1 ae ea 32 9a df 91 21 38 38 51 ed
- 21 a2 8e 3b 75 e9 65 d0 d2 cd 16 62 54 00 2d 00
- 02 01 01 00 2b 00 03 02 03 04"),
-
- ServerHello =
- hexstr2bin("02 00 00 76 03 03 70 71 72 73 74 75 76 77 78 79
- 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89
- 8a 8b 8c 8d 8e 8f 20 e0 e1 e2 e3 e4 e5 e6 e7 e8
- e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8
- f9 fa fb fc fd fe ff 13 01 00 00 2e 00 33 00 24
- 00 1d 00 20 9f d7 ad 6d cf f4 29 8d d3 f9 6d 5b
- 1b 2a f9 10 a0 53 5b 14 88 d7 f8 fa bb 34 9a 98
- 28 80 b6 15 00 2b 00 02 03 04"),
-
- EncryptedExtensions =
- hexstr2bin("08 00 00 02 00 00"),
-
- Certificate =
- hexstr2bin("0b 00 03 2e 00 00 03 2a 00 03 25 30 82 03 21 30
- 82 02 09 a0 03 02 01 02 02 08 15 5a 92 ad c2 04
- 8f 90 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05
- 00 30 22 31 0b 30 09 06 03 55 04 06 13 02 55 53
- 31 13 30 11 06 03 55 04 0a 13 0a 45 78 61 6d 70
- 6c 65 20 43 41 30 1e 17 0d 31 38 31 30 30 35 30
- 31 33 38 31 37 5a 17 0d 31 39 31 30 30 35 30 31
- 33 38 31 37 5a 30 2b 31 0b 30 09 06 03 55 04 06
- 13 02 55 53 31 1c 30 1a 06 03 55 04 03 13 13 65
- 78 61 6d 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e
- 65 74 30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d
- 01 01 01 05 00 03 82 01 0f 00 30 82 01 0a 02 82
- 01 01 00 c4 80 36 06 ba e7 47 6b 08 94 04 ec a7
- b6 91 04 3f f7 92 bc 19 ee fb 7d 74 d7 a8 0d 00
- 1e 7b 4b 3a 4a e6 0f e8 c0 71 fc 73 e7 02 4c 0d
- bc f4 bd d1 1d 39 6b ba 70 46 4a 13 e9 4a f8 3d
- f3 e1 09 59 54 7b c9 55 fb 41 2d a3 76 52 11 e1
- f3 dc 77 6c aa 53 37 6e ca 3a ec be c3 aa b7 3b
- 31 d5 6c b6 52 9c 80 98 bc c9 e0 28 18 e2 0b f7
- f8 a0 3a fd 17 04 50 9e ce 79 bd 9f 39 f1 ea 69
- ec 47 97 2e 83 0f b5 ca 95 de 95 a1 e6 04 22 d5
- ee be 52 79 54 a1 e7 bf 8a 86 f6 46 6d 0d 9f 16
- 95 1a 4c f7 a0 46 92 59 5c 13 52 f2 54 9e 5a fb
- 4e bf d7 7a 37 95 01 44 e4 c0 26 87 4c 65 3e 40
- 7d 7d 23 07 44 01 f4 84 ff d0 8f 7a 1f a0 52 10
- d1 f4 f0 d5 ce 79 70 29 32 e2 ca be 70 1f df ad
- 6b 4b b7 11 01 f4 4b ad 66 6a 11 13 0f e2 ee 82
- 9e 4d 02 9d c9 1c dd 67 16 db b9 06 18 86 ed c1
- ba 94 21 02 03 01 00 01 a3 52 30 50 30 0e 06 03
- 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03
- 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03
- 02 06 08 2b 06 01 05 05 07 03 01 30 1f 06 03 55
- 1d 23 04 18 30 16 80 14 89 4f de 5b cc 69 e2 52
- cf 3e a3 00 df b1 97 b8 1d e1 c1 46 30 0d 06 09
- 2a 86 48 86 f7 0d 01 01 0b 05 00 03 82 01 01 00
- 59 16 45 a6 9a 2e 37 79 e4 f6 dd 27 1a ba 1c 0b
- fd 6c d7 55 99 b5 e7 c3 6e 53 3e ff 36 59 08 43
- 24 c9 e7 a5 04 07 9d 39 e0 d4 29 87 ff e3 eb dd
- 09 c1 cf 1d 91 44 55 87 0b 57 1d d1 9b df 1d 24
- f8 bb 9a 11 fe 80 fd 59 2b a0 39 8c de 11 e2 65
- 1e 61 8c e5 98 fa 96 e5 37 2e ef 3d 24 8a fd e1
- 74 63 eb bf ab b8 e4 d1 ab 50 2a 54 ec 00 64 e9
- 2f 78 19 66 0d 3f 27 cf 20 9e 66 7f ce 5a e2 e4
- ac 99 c7 c9 38 18 f8 b2 51 07 22 df ed 97 f3 2e
- 3e 93 49 d4 c6 6c 9e a6 39 6d 74 44 62 a0 6b 42
- c6 d5 ba 68 8e ac 3a 01 7b dd fc 8e 2c fc ad 27
- cb 69 d3 cc dc a2 80 41 44 65 d3 ae 34 8c e0 f3
- 4a b2 fb 9c 61 83 71 31 2b 19 10 41 64 1c 23 7f
- 11 a5 d6 5c 84 4f 04 04 84 99 38 71 2b 95 9e d6
- 85 bc 5c 5d d6 45 ed 19 90 94 73 40 29 26 dc b4
- 0e 34 69 a1 59 41 e8 e2 cc a8 4b b6 08 46 36 a0
- 00 00"),
-
- CertificateVerify =
- hexstr2bin("0f 00 01 04 08 04 01 00 17 fe b5 33 ca 6d 00 7d
- 00 58 25 79 68 42 4b bc 3a a6 90 9e 9d 49 55 75
- 76 a5 20 e0 4a 5e f0 5f 0e 86 d2 4f f4 3f 8e b8
- 61 ee f5 95 22 8d 70 32 aa 36 0f 71 4e 66 74 13
- 92 6e f4 f8 b5 80 3b 69 e3 55 19 e3 b2 3f 43 73
- df ac 67 87 06 6d cb 47 56 b5 45 60 e0 88 6e 9b
- 96 2c 4a d2 8d ab 26 ba d1 ab c2 59 16 b0 9a f2
- 86 53 7f 68 4f 80 8a ef ee 73 04 6c b7 df 0a 84
- fb b5 96 7a ca 13 1f 4b 1c f3 89 79 94 03 a3 0c
- 02 d2 9c bd ad b7 25 12 db 9c ec 2e 5e 1d 00 e5
- 0c af cf 6f 21 09 1e bc 4f 25 3c 5e ab 01 a6 79
- ba ea be ed b9 c9 61 8f 66 00 6b 82 44 d6 62 2a
- aa 56 88 7c cf c6 6a 0f 38 51 df a1 3a 78 cf f7
- 99 1e 03 cb 2c 3a 0e d8 7d 73 67 36 2e b7 80 5b
- 00 b2 52 4f f2 98 a4 da 48 7c ac de af 8a 23 36
- c5 63 1b 3e fa 93 5b b4 11 e7 53 ca 13 b0 15 fe
- c7 e4 a7 30 f1 36 9f 9e"),
-
- BaseKey =
- hexstr2bin("a2 06 72 65 e7 f0 65 2a 92 3d 5d 72 ab 04 67 c4
- 61 32 ee b9 68 b6 a3 2d 31 1c 80 58 68 54 88 14"),
-
- VerifyData =
- hexstr2bin("ea 6e e1 76 dc cc 4a f1 85 9e 9e 4e 93 f7 97 ea
- c9 a7 8c e4 39 30 1e 35 27 5a d4 3f 3c dd bd e3"),
-
- Messages = [CertificateVerify,
- Certificate,
- EncryptedExtensions,
- ServerHello,
- ClientHello],
-
- FinishedKey = tls_v1:finished_key(BaseKey, sha256),
- VerifyData = tls_v1:finished_verify_data(FinishedKey, sha256, Messages).
-
-
-tls12_ssl_server_tls13_ssl_client() ->
- [{doc,"Test basic connection between TLS 1.2 server and TLS 1.3 client"}].
-
-tls12_ssl_server_tls13_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2']}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {signature_algs_cert, [ecdsa_secp384r1_sha384,
- rsa_pss_rsae_sha256,
- rsa_pkcs1_sha256,
- {sha256,rsa},{sha256,dsa}]}|ClientOpts0],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_basic_ssl_server_openssl_client() ->
- [{doc,"Test TLS 1.3 basic connection between ssl server and openssl s_client"}].
-
-tls13_basic_ssl_server_openssl_client(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-tls13_basic_ssl_server_ssl_client() ->
- [{doc,"Test TLS 1.3 basic connection between ssl server and ssl client"}].
-
-tls13_basic_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_basic_openssl_server_ssl_client() ->
- [{doc,"Test TLS 1.3 basic connection between openssl server and ssl client"}].
-
-tls13_basic_openssl_server_ssl_client(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
-
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
-
- {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),
- CaCertFile = proplists:get_value(cacertfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port),
- "-tls1_3",
- "-cert", CertFile, "-CAfile", CaCertFile,
- "-key", KeyFile, "-Verify", "2"],
-
- OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ssl_test_lib:wait_for_openssl_server(Port, tls),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive, [Data]}},
- {options, 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).
-
-
-tls13_custom_groups_ssl_server_openssl_client() ->
- [{doc,"Test that ssl server can select a common group for key-exchange"}].
-
-tls13_custom_groups_ssl_server_openssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [x448, secp256r1, secp384r1]}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- ClientOpts = [{groups,"P-384:P-256:X25519"}|ClientOpts0],
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_custom_groups_ssl_server_ssl_client() ->
- [{doc,"Test that ssl server can select a common group for key-exchange"}].
-
-tls13_custom_groups_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [x448, secp256r1, secp384r1]}|ServerOpts0],
- ClientOpts1 = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- {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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- ClientOpts = [{supported_groups,[secp384r1, secp256r1, x25519]}|ClientOpts1],
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hello_retry_request_ssl_server_openssl_client() ->
- [{doc,"Test that ssl server can request a new group when the client's first key share"
- "is not supported"}].
-
-tls13_hello_retry_request_ssl_server_openssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [x448, x25519]}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- ClientOpts = [{groups,"P-256:X25519"}|ClientOpts0],
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hello_retry_request_ssl_server_ssl_client() ->
- [{doc,"Test that ssl server can request a new group when the client's first key share"
- "is not supported"}].
-
-tls13_hello_retry_request_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [x448, x25519]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [secp256r1, x25519]}|ClientOpts0],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-tls13_client_auth_empty_cert_alert_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3: Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to true."}].
-
-tls13_client_auth_empty_cert_alert_ssl_server_openssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts = proplists:delete(keyfile, ClientOpts1),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_server_alert(Server, certificate_required),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_client_auth_empty_cert_alert_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3: Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to true."}].
-
-tls13_client_auth_empty_cert_alert_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts2],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_server_alert(Server, certificate_required),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_client_auth_empty_cert_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3: Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to false."}].
-
-tls13_client_auth_empty_cert_ssl_server_openssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts = proplists:delete(keyfile, ClientOpts1),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, false}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_client_auth_empty_cert_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3: Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to false."}].
-
-tls13_client_auth_empty_cert_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, false}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts2],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_client_auth_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3: Test client authentication."}].
-
-tls13_client_auth_ssl_server_openssl_client(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_client_auth_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3: Test client authentication."}].
-
-tls13_client_auth_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- {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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- %%Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hrr_client_auth_empty_cert_alert_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to true."}].
-
-tls13_hrr_client_auth_empty_cert_alert_ssl_server_openssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
- ClientOpts = [{groups,"P-256:X25519"}|ClientOpts2],
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true},
- {supported_groups, [x448, x25519]}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_server_alert(Server, certificate_required),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hrr_client_auth_empty_cert_alert_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to true."}].
-
-tls13_hrr_client_auth_empty_cert_alert_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true},
- {supported_groups, [x448, x25519]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [secp256r1, x25519]}|ClientOpts2],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_server_alert(Server, certificate_required),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hrr_client_auth_empty_cert_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to false."}].
-
-tls13_hrr_client_auth_empty_cert_ssl_server_openssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
- ClientOpts = [{groups,"P-256:X25519"}|ClientOpts2],
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, false},
- {supported_groups, [x448, x25519]}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hrr_client_auth_empty_cert_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to false."}].
-
-tls13_hrr_client_auth_empty_cert_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- %% Delete Client Cert and Key
- ClientOpts1 = proplists:delete(certfile, ClientOpts0),
- ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, false},
- {supported_groups, [x448, x25519]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [secp256r1, x25519]}|ClientOpts2],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hrr_client_auth_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication."}].
-
-tls13_hrr_client_auth_ssl_server_openssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ClientOpts = [{groups,"P-256:X25519"}|ClientOpts0],
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true},
- {supported_groups, [x448, x25519]}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_hrr_client_auth_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication."}].
-
-tls13_hrr_client_auth_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true},
- {supported_groups, [x448, x25519]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {supported_groups, [secp256r1, x25519]}|ClientOpts0],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_unsupported_sign_algo_client_auth_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm"}].
-
-tls13_unsupported_sign_algo_client_auth_ssl_server_openssl_client(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- %% Skip rsa_pkcs1_sha256!
- {signature_algs, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
- {fail_if_no_peer_cert, true}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_server_alert(Server, insufficient_security),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_unsupported_sign_algo_client_auth_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm"}].
-
-tls13_unsupported_sign_algo_client_auth_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- %% Skip rsa_pkcs1_sha256!
- {signature_algs, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
- {fail_if_no_peer_cert, true}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_server_alert(Server, insufficient_security),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-%% Triggers a Server Alert as openssl s_client does not have a certificate with a
-%% signature algorithm supported by the server (signature_algorithms_cert extension
-%% of CertificateRequest does not contain the algorithm of the client certificate).
-%% openssl s_client sends an empty certificate.
-tls13_unsupported_sign_algo_cert_client_auth_ssl_server_openssl_client() ->
- [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm_cert"}].
-
-tls13_unsupported_sign_algo_cert_client_auth_ssl_server_openssl_client(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {log_level, debug},
- {verify, verify_peer},
- {signature_algs, [rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pss_rsae_sha256]},
- %% Skip rsa_pkcs1_sha256!
- {signature_algs_cert, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
- {fail_if_no_peer_cert, true}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_server_alert(Server, certificate_required),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-%% Triggers a Server Alert as ssl client does not have a certificate with a
-%% signature algorithm supported by the server (signature_algorithms_cert extension
-%% of CertificateRequest does not contain the algorithm of the client certificate).
-%% ssl client sends an empty certificate.
-tls13_unsupported_sign_algo_cert_client_auth_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm_cert"}].
-
-tls13_unsupported_sign_algo_cert_client_auth_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
-
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {log_level, debug},
- {verify, verify_peer},
- {signature_algs, [rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pss_rsae_sha256]},
- %% Skip rsa_pkcs1_sha256!
- {signature_algs_cert, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
- {fail_if_no_peer_cert, true}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- {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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_server_alert(Server, certificate_required),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_connection_information() ->
- [{doc,"Test the API function ssl:connection_information/1 in a TLS 1.3 connection"}].
-
-tls13_connection_information(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
- {_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, connection_information_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_ssl_server_with_alpn_ssl_client() ->
- [{doc,"Test TLS 1.3 between ssl server with ALPN configured and ssl client"}].
-
-tls13_ssl_server_with_alpn_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {alpn_preferred_protocols, [<<5,6>>, <<1>>]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_ssl_server_with_alpn_ssl_client_empty_alpn() ->
- [{doc,"Test TLS 1.3 between ssl server with ALPN configured and ssl client with empty ALPN"}].
-
-tls13_ssl_server_with_alpn_ssl_client_empty_alpn(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {alpn_preferred_protocols, [<<5,6>>, <<1>>]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {alpn_advertised_protocols, []}|ClientOpts0],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_server_alert(Server, no_application_protocol),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_ssl_server_with_alpn_ssl_client_bad_alpn() ->
- [{doc,"Test TLS 1.3 between ssl server with ALPN configured and ssl client with bad ALPN"}].
-
-tls13_ssl_server_with_alpn_ssl_client_bad_alpn(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {alpn_preferred_protocols, [<<5,6>>, <<1>>]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {alpn_advertised_protocols, [<<1,2,3,4>>]}|ClientOpts0],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_server_alert(Server, no_application_protocol),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-tls13_ssl_server_with_alpn_ssl_client_alpn() ->
- [{doc,"Test TLS 1.3 between ssl server with ALPN configured and ssl client with correct ALPN"}].
-
-tls13_ssl_server_with_alpn_ssl_client_alpn(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {alpn_preferred_protocols, [<<5,6>>, <<1>>]}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {alpn_advertised_protocols, [<<1,2,3,4>>, <<5,6>>]}|ClientOpts0],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_ecdsa_ssl_server_openssl_client() ->
- [{doc,"Test TLS 1.3 basic connection between ssl server and openssl s_client using ECDSA certificates"}].
-
-tls13_ecdsa_ssl_server_openssl_client(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_ecdsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_ecdsa_opts, Config),
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}|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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
-
- ssl_test_lib:check_result(Server, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-tls13_ecdsa_ssl_server_ssl_client() ->
- [{doc,"Test TLS 1.3 basic connection between ssl server and ssl client using ECDSA certificates"}].
-
-tls13_ecdsa_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_ecdsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_ecdsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-tls13_ecdsa_openssl_server_ssl_client() ->
- [{doc,"Test TLS 1.3 basic connection between openssl server and ssl client using ECDSA certificates"}].
-
-tls13_ecdsa_openssl_server_ssl_client(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_ecdsa_verify_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_ecdsa_opts, Config),
-
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
-
- {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),
- CaCertFile = proplists:get_value(cacertfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port),
- "-tls1_3",
- "-cert", CertFile, "-CAfile", CaCertFile,
- "-key", KeyFile, "-Verify", "2"],
-
- OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ssl_test_lib:wait_for_openssl_server(Port, tls),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive, [Data]}},
- {options, 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).
-
-
-tls13_ecdsa_client_auth_ssl_server_ssl_client() ->
- [{doc,"TLS 1.3: Test client authentication with ECDSA certificates."}].
-
-tls13_ecdsa_client_auth_ssl_server_ssl_client(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_ecdsa_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_ecdsa_opts, Config),
-
- %% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
- {verify, verify_peer},
- {fail_if_no_peer_cert, true}|ServerOpts0],
- ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- {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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- %%Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(Client).
-
-
-
-%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
send_recv_result(Socket) ->
@@ -6468,491 +463,9 @@ tcp_send_recv_result(Socket) ->
{ok,"Hello world"} = gen_tcp:recv(Socket, 11),
ok.
-basic_verify_test_no_close(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},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- {Server, Client}.
-
-basic_test(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, send_recv_result_active, []}},
- {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, send_recv_result_active, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-prf_create_plan(TlsVersions, PRFs, Results) ->
- lists:foldl(fun(Ver, Acc) ->
- A = prf_ciphers_and_expected(Ver, PRFs, Results),
- [A|Acc]
- end, [], TlsVersions).
-prf_ciphers_and_expected(TlsVer, PRFs, Results) ->
- case TlsVer of
- TlsVer when TlsVer == sslv3 orelse TlsVer == tlsv1
- orelse TlsVer == 'tlsv1.1' orelse TlsVer == 'dtlsv1' ->
- Ciphers = ssl:cipher_suites(),
- {_, Expected} = lists:keyfind(md5sha, 1, Results),
- [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected}, {prf, md5sha}]];
- TlsVer when TlsVer == 'tlsv1.2' orelse TlsVer == 'dtlsv1.2'->
- lists:foldl(
- fun(PRF, Acc) ->
- Ciphers = prf_get_ciphers(TlsVer, PRF),
- case Ciphers of
- [] ->
- ct:log("No ciphers for PRF algorithm ~p. Skipping.", [PRF]),
- Acc;
- Ciphers ->
- {_, Expected} = lists:keyfind(PRF, 1, Results),
- [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected},
- {prf, PRF}] | Acc]
- end
- end, [], PRFs)
- end.
-prf_get_ciphers(_, PRF) ->
- lists:filter(
- fun(C) when tuple_size(C) == 4 andalso
- element(4, C) == PRF ->
- true;
- (_) ->
- false
- end,
- ssl:cipher_suites()).
-prf_run_test(_, TlsVer, [], _, Prf) ->
- ct:fail({error, cipher_list_empty, TlsVer, Prf});
-prf_run_test(Config, TlsVer, Ciphers, Expected, Prf) ->
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- BaseOpts = [{active, true}, {versions, [TlsVer]}, {ciphers, Ciphers}, {protocol, tls_or_dtls(TlsVer)}],
- ServerOpts = BaseOpts ++ proplists:get_value(server_opts, Config),
- ClientOpts = BaseOpts ++ proplists:get_value(client_opts, Config),
- Server = ssl_test_lib:start_server(
- [{node, ServerNode}, {port, 0}, {from, self()},
- {mfa, {?MODULE, prf_verify_value, [TlsVer, Expected, Prf]}},
- {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, prf_verify_value, [TlsVer, Expected, Prf]}},
- {options, ClientOpts}]),
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-prf_verify_value(Socket, TlsVer, Expected, Algo) ->
- Ret = ssl:prf(Socket, <<>>, <<>>, [<<>>], 16),
- case TlsVer of
- sslv3 ->
- case Ret of
- {error, undefined} -> ok;
- _ ->
- {error, {expected, {error, undefined},
- got, Ret, tls_ver, TlsVer, prf_algorithm, Algo}}
- end;
- _ ->
- case Ret of
- {ok, Expected} -> ok;
- {ok, Val} -> {error, {expected, Expected, got, Val, tls_ver, TlsVer,
- prf_algorithm, Algo}}
- end
- end.
-
-send_recv_result_timeout_client(Socket) ->
- {error, timeout} = ssl:recv(Socket, 11, 500),
- {error, timeout} = ssl:recv(Socket, 11, 0),
- ssl:send(Socket, "Hello world"),
- receive
- Msg ->
- io:format("Msg ~p~n",[Msg])
- after 500 ->
- ok
- end,
- {ok, "Hello world"} = ssl:recv(Socket, 11, 500),
- ok.
-send_recv_result_timeout_server(Socket) ->
- ssl:send(Socket, "Hello"),
- {ok, "Hello world"} = ssl:recv(Socket, 11),
- ssl:send(Socket, " world"),
- ok.
-
-recv_close(Socket) ->
- {error, closed} = ssl:recv(Socket, 11),
- receive
- {_,{error,closed}} ->
- error_extra_close_sent_to_user_process
- after 500 ->
- ok
- end.
-
-
-send_recv_result_active_rizzo(Socket) ->
- ssl:send(Socket, "Hello world"),
- "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, _, Bytes} ->
- ssl_active_recv(N-length(Bytes), Acc ++ Bytes)
- end.
-
result_ok(_Socket) ->
ok.
-renegotiate(Socket, Data) ->
- ct:log("Renegotiating ~n", []),
- Result = ssl:renegotiate(Socket),
- ct:log("Result ~p~n", [Result]),
- ssl:send(Socket, Data),
- case Result of
- ok ->
- ok;
- Other ->
- Other
- end.
-
-renegotiate_reuse_session(Socket, Data) ->
- %% Make sure session is registered
- ct:sleep(?SLEEP),
- renegotiate(Socket, Data).
-
-renegotiate_immediately(Socket) ->
- _ = ssl_test_lib:active_recv(Socket, 11),
- ok = ssl:renegotiate(Socket),
- {error, renegotiation_rejected} = ssl:renegotiate(Socket),
- ct:sleep(?RENEGOTIATION_DISABLE_TIME + ?SLEEP),
- ok = ssl:renegotiate(Socket),
- ct:log("Renegotiated again"),
- ssl:send(Socket, "Hello world"),
- ok.
-
-renegotiate_rejected(Socket) ->
- _ = 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),
- {error, renegotiation_rejected} = ssl:renegotiate(Socket),
- ct:log("Failed to renegotiate again"),
- ssl:send(Socket, "Hello world"),
- ok.
-
-rizzo_add_mitigation_option(Value, Config) ->
- lists:foldl(fun(Opt, Acc) ->
- case proplists:get_value(Opt, Acc) of
- undefined -> Acc;
- C ->
- N = lists:keystore(beast_mitigation, 1, C,
- {beast_mitigation, Value}),
- lists:keystore(Opt, 1, Acc, {Opt, N})
- end
- end, Config,
- [client_opts, client_dsa_opts, server_opts, server_dsa_opts,
- server_ecdsa_opts, server_ecdh_rsa_opts]).
-
-new_config(PrivDir, ServerOpts0) ->
- CaCertFile = proplists:get_value(cacertfile, ServerOpts0),
- CertFile = proplists:get_value(certfile, ServerOpts0),
- KeyFile = proplists:get_value(keyfile, ServerOpts0),
- NewCaCertFile = filename:join(PrivDir, "new_ca.pem"),
- NewCertFile = filename:join(PrivDir, "new_cert.pem"),
- NewKeyFile = filename:join(PrivDir, "new_key.pem"),
- file:copy(CaCertFile, NewCaCertFile),
- file:copy(CertFile, NewCertFile),
- file:copy(KeyFile, NewKeyFile),
- ServerOpts1 = proplists:delete(cacertfile, ServerOpts0),
- ServerOpts2 = proplists:delete(certfile, ServerOpts1),
- ServerOpts = proplists:delete(keyfile, ServerOpts2),
-
- {ok, PEM} = file:read_file(NewCaCertFile),
- ct:log("CA file content: ~p~n", [public_key:pem_decode(PEM)]),
-
- [{cacertfile, NewCaCertFile}, {certfile, NewCertFile},
- {keyfile, NewKeyFile} | ServerOpts].
-
-session_cache_process(_Type,Config) when is_list(Config) ->
- reuse_session(Config).
-
-init([Type]) ->
- ets:new(ssl_test, [named_table, public, set]),
- ets:insert(ssl_test, {type, Type}),
- case Type of
- list ->
- spawn(fun() -> session_loop([]) end);
- mnesia ->
- mnesia:start(),
- {atomic,ok} = mnesia:create_table(sess_cache, []),
- sess_cache
- end.
-
-session_cb() ->
- [{type, Type}] = ets:lookup(ssl_test, type),
- Type.
-
-terminate(Cache) ->
- case session_cb() of
- list ->
- Cache ! terminate;
- mnesia ->
- catch {atomic,ok} =
- mnesia:delete_table(sess_cache)
- end.
-
-lookup(Cache, Key) ->
- case session_cb() of
- list ->
- Cache ! {self(), lookup, Key},
- receive {Cache, Res} -> Res end;
- mnesia ->
- case mnesia:transaction(fun() ->
- mnesia:read(sess_cache,
- Key, read)
- end) of
- {atomic, [{sess_cache, Key, Value}]} ->
- Value;
- _ ->
- undefined
- end
- end.
-
-update(Cache, Key, Value) ->
- case session_cb() of
- list ->
- Cache ! {update, Key, Value};
- mnesia ->
- {atomic, ok} =
- mnesia:transaction(fun() ->
- mnesia:write(sess_cache,
- {sess_cache, Key, Value}, write)
- end)
- end.
-
-delete(Cache, Key) ->
- case session_cb() of
- list ->
- Cache ! {delete, Key};
- mnesia ->
- {atomic, ok} =
- mnesia:transaction(fun() ->
- mnesia:delete(sess_cache, Key)
- end)
- end.
-
-foldl(Fun, Acc, Cache) ->
- case session_cb() of
- list ->
- Cache ! {self(),foldl,Fun,Acc},
- receive {Cache, Res} -> Res end;
- mnesia ->
- Foldl = fun() ->
- mnesia:foldl(Fun, Acc, sess_cache)
- end,
- {atomic, Res} = mnesia:transaction(Foldl),
- Res
- end.
-
-select_session(Cache, PartialKey) ->
- case session_cb() of
- list ->
- Cache ! {self(),select_session, PartialKey},
- receive
- {Cache, Res} ->
- Res
- end;
- mnesia ->
- Sel = fun() ->
- mnesia:select(Cache,
- [{{sess_cache,{PartialKey,'$1'}, '$2'},
- [],['$$']}])
- end,
- {atomic, Res} = mnesia:transaction(Sel),
- Res
- end.
-
-session_loop(Sess) ->
- receive
- terminate ->
- ok;
- {Pid, lookup, Key} ->
- case lists:keysearch(Key,1,Sess) of
- {value, {Key,Value}} ->
- Pid ! {self(), Value};
- _ ->
- Pid ! {self(), undefined}
- end,
- session_loop(Sess);
- {update, Key, Value} ->
- NewSess = [{Key,Value}| lists:keydelete(Key,1,Sess)],
- session_loop(NewSess);
- {delete, Key} ->
- session_loop(lists:keydelete(Key,1,Sess));
- {Pid,foldl,Fun,Acc} ->
- Res = lists:foldl(Fun, Acc,Sess),
- Pid ! {self(), Res},
- session_loop(Sess);
- {Pid,select_session,PKey} ->
- Sel = fun({{PKey0, Id},Session}, Acc) when PKey == PKey0 ->
- [[Id, Session]|Acc];
- (_,Acc) ->
- Acc
- end,
- Sessions = lists:foldl(Sel, [], Sess),
- Pid ! {self(), Sessions},
- session_loop(Sess)
- end.
-
-
-erlang_ssl_receive(Socket, Data) ->
- case ssl_test_lib:active_recv(Socket, length(Data)) of
- Data ->
- ok;
- Other ->
- ct:fail({{expected, Data}, {got, Other}})
- end.
-
-receive_msg(_) ->
- receive
- Msg ->
- Msg
- end.
-
-controlling_process_result(Socket, Pid, Msg) ->
- ok = ssl:controlling_process(Socket, Pid),
- %% Make sure other side has evaluated controlling_process
- %% before message is sent
- ct:sleep(?SLEEP),
- ssl:send(Socket, Msg),
- no_result_msg.
-
-
-controller_dies_result(_Socket, _Pid, _Msg) ->
- receive Result -> Result end.
-
-get_close(Pid, Where) ->
- receive
- {'EXIT', Pid, _Reason} ->
- receive
- {_, {ssl_closed, Socket}} ->
- ct:log("Socket closed ~p~n",[Socket]);
- Unexpected ->
- ct:log("Unexpected ~p~n",[Unexpected]),
- ct:fail({line, ?LINE-1})
- after 5000 ->
- ct:fail({timeout, {line, ?LINE, Where}})
- end;
- Unexpected ->
- ct:log("Unexpected ~p~n",[Unexpected]),
- ct:fail({line, ?LINE-1})
- after 5000 ->
- ct:fail({timeout, {line, ?LINE, Where}})
- end.
-
-run_send_recv_rizzo(Ciphers, Config, Version, Mfa) ->
- Result = lists:map(fun(Cipher) ->
- rizzo_test(Cipher, Config, Version, Mfa) end,
- Ciphers),
- 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.
-
-rizzo_test(Cipher, Config, Version, Mfa) ->
- {ClientOpts, ServerOpts} = client_server_opts(Cipher, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, Mfa},
- {options, [{active, true}, {ciphers, [Cipher]},
- {versions, [Version]}
- | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, Mfa},
- {options, [{active, true}, {ciphers, [Cipher]}| ClientOpts]}]),
-
- Result = ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- case Result of
- ok ->
- [];
- Error ->
- [{Cipher, Error}]
- end.
-
-client_server_opts(#{key_exchange := KeyAlgo}, Config)
- when KeyAlgo == rsa orelse
- KeyAlgo == dhe_rsa orelse
- KeyAlgo == ecdhe_rsa orelse
- KeyAlgo == rsa_psk orelse
- KeyAlgo == srp_rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_opts, Config)};
-client_server_opts(#{key_exchange := KeyAlgo}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss ->
- {ssl_test_lib:ssl_options(client_dsa_opts, Config),
- ssl_test_lib:ssl_options(server_dsa_opts, Config)};
-client_server_opts(#{key_exchange := KeyAlgo}, Config) when KeyAlgo == ecdh_ecdsa orelse KeyAlgo == ecdhe_ecdsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_ecdsa_opts, Config)};
-client_server_opts(#{key_exchange := KeyAlgo}, Config) when KeyAlgo == ecdh_rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)}.
-
-connection_information_result(Socket) ->
- {ok, Info = [_ | _]} = ssl:connection_information(Socket),
- case length(Info) > 3 of
- true ->
- %% Atleast one ssl_option() is set
- ct:log("Info ~p", [Info]),
- ok;
- false ->
- ct:fail(no_ssl_options_returned)
- end.
-
-connection_info_result(Socket) ->
- {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]),
@@ -6962,11 +475,7 @@ version_info_result(Socket) ->
{ok, [{version, Version}]} = ssl:connection_information(Socket, [version]),
{ok, Version}.
-secret_connection_info_result(Socket) ->
- {ok, [{client_random, ClientRand}, {server_random, ServerRand}, {master_secret, MasterSecret}]}
- = ssl:connection_information(Socket, [client_random, server_random, master_secret]),
- is_binary(ClientRand) andalso is_binary(ServerRand) andalso is_binary(MasterSecret).
-
+
connect_dist_s(S) ->
Msg = term_to_binary({erlang,term}),
ok = ssl:send(S, Msg).
@@ -6976,88 +485,11 @@ connect_dist_c(S) ->
{ok, Test} = ssl:recv(S, 0, 10000),
ok.
-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}]),
- gen_tcp:send(TCPSocket, "Downgraded"),
- receive
- {tcp, TCPSocket, <<"Downgraded">>} ->
- ok;
- {tcp_closed, TCPSocket} ->
- ct:fail("Peer timed out, downgrade aborted"),
- ok;
- Other ->
- {error, Other}
- end;
- {error, timeout} ->
- ct:fail("Timed out, downgrade aborted"),
- ok;
- Fail ->
- {error, Fail}
- end.
-
-tls_close(Socket) ->
- ok = ssl_test_lib:send_recv_result(Socket),
- case ssl:close(Socket, 5000) of
- ok ->
- ok;
- {error, closed} ->
- ok;
- Other ->
- ct:fail(Other)
- end.
-
- %% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast
-treashold(N, {3,0}) ->
- (N div 2) + 1;
-treashold(N, {3,1}) ->
- (N div 2) + 1;
-treashold(N, _) ->
- N + 1.
-
-get_invalid_inet_option(Socket) ->
- {error, {options, {socket_options, foo, _}}} = ssl:getopts(Socket, [foo]),
- ok.
-
-tls_shutdown_result(Socket, server) ->
- ssl:send(Socket, "Hej"),
- ok = ssl:shutdown(Socket, write),
- {ok, "Hej hopp"} = ssl:recv(Socket, 8),
- ok;
-
-tls_shutdown_result(Socket, client) ->
- ssl:send(Socket, "Hej hopp"),
- ok = ssl:shutdown(Socket, write),
- {ok, "Hej"} = ssl:recv(Socket, 3),
- ok.
-
-tls_shutdown_write_result(Socket, server) ->
- ct:sleep(?SLEEP),
- ssl:shutdown(Socket, write);
-tls_shutdown_write_result(Socket, client) ->
- ssl:recv(Socket, 0).
-
dummy(_Socket) ->
%% Should not happen as the ssl connection will not be established
%% due to fatal handshake failiure
exit(kill).
-tls_shutdown_both_result(Socket, server) ->
- ct:sleep(?SLEEP),
- ssl:shutdown(Socket, read_write);
-tls_shutdown_both_result(Socket, client) ->
- ssl:recv(Socket, 0).
-
-peername_result(S) ->
- ssl:peername(S).
-
version_option_test(Config, Version) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
@@ -7083,50 +515,3 @@ version_option_test(Config, Version) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-try_recv_active(Socket) ->
- ssl:send(Socket, "Hello world"),
- {error, einval} = ssl:recv(Socket, 11),
- ok.
-try_recv_active_once(Socket) ->
- {error, einval} = ssl:recv(Socket, 11),
- ok.
-
-
-wait_for_send(Socket) ->
- %% Make sure TLS process processed send message event
- _ = ssl:connection_information(Socket).
-
-tls_or_dtls('dtlsv1') ->
- dtls;
-tls_or_dtls('dtlsv1.2') ->
- dtls;
-tls_or_dtls(_) ->
- tls.
-
-hexstr2int(S) ->
- B = hexstr2bin(S),
- Bits = size(B) * 8,
- <<Integer:Bits/integer>> = B,
- Integer.
-
-hexstr2bin(S) when is_binary(S) ->
- hexstr2bin(S, <<>>);
-hexstr2bin(S) ->
- hexstr2bin(list_to_binary(S), <<>>).
-%%
-hexstr2bin(<<>>, Acc) ->
- Acc;
-hexstr2bin(<<C,T/binary>>, Acc) when C =:= 32; %% SPACE
- C =:= 10; %% LF
- C =:= 13 -> %% CR
- hexstr2bin(T, Acc);
-hexstr2bin(<<X,Y,T/binary>>, Acc) ->
- I = hex2int(X) * 16 + hex2int(Y),
- hexstr2bin(T, <<Acc/binary,I>>).
-
-hex2int(C) when $0 =< C, C =< $9 ->
- C - $0;
-hex2int(C) when $A =< C, C =< $F ->
- C - $A + 10;
-hex2int(C) when $a =< C, C =< $f ->
- C - $a + 10.
diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl
index 35efa2b8a3..a297539c36 100644
--- a/lib/ssl/test/ssl_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_bench_SUITE.erl
@@ -174,7 +174,12 @@ do_test(Type, TC, Loop, ParallellConnections, Server) ->
end,
{TimeInMicro, _} = timer:tc(Run),
TotalTests = ParallellConnections * Loop,
- TestPerSecond = 1000000 * TotalTests div TimeInMicro,
+ TestPerSecond = case TimeInMicro of
+ 0 ->
+ undefined;
+ _ ->
+ 1000000 * TotalTests div TimeInMicro
+ end,
io:format("TC ~p ~p ~p ~p 1/s~n", [TC, Type, ParallellConnections, TestPerSecond]),
unlink(SPid),
SPid ! quit,
diff --git a/lib/ssl/test/ssl_cert_SUITE.erl b/lib/ssl/test/ssl_cert_SUITE.erl
new file mode 100644
index 0000000000..fb1695f38a
--- /dev/null
+++ b/lib/ssl/test/ssl_cert_SUITE.erl
@@ -0,0 +1,563 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(ssl_cert_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ [
+ {group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.3', [], tls_1_3_protocol_groups()},
+ {'tlsv1.2', [], pre_tls_1_3_protocol_groups()},
+ {'tlsv1.1', [], pre_tls_1_3_protocol_groups()},
+ {'tlsv1', [], pre_tls_1_3_protocol_groups()},
+ {'sslv3', [], ssl_protocol_groups()},
+ {'dtlsv1.2', [], pre_tls_1_3_protocol_groups()},
+ {'dtlsv1', [], pre_tls_1_3_protocol_groups()},
+ {rsa, [], all_version_tests()},
+ {ecdsa, [], all_version_tests()},
+ {dsa, [], all_version_tests()},
+ {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_client_auth,
+ unsupported_sign_algo_cert_client_auth]},
+ {ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()}
+ ].
+
+ssl_protocol_groups() ->
+ [{group, rsa},
+ {group, dsa}].
+
+pre_tls_1_3_protocol_groups() ->
+ [{group, rsa},
+ {group, ecdsa},
+ {group, dsa}].
+
+tls_1_3_protocol_groups() ->
+ [{group, rsa_1_3},
+ {group, ecdsa_1_3}].
+
+tls_1_3_tests() ->
+ [
+ hello_retry_request,
+ custom_groups,
+ hello_retry_client_auth,
+ hello_retry_client_auth_empty_cert_accepted,
+ hello_retry_client_auth_empty_cert_rejected
+ ].
+
+all_version_tests() ->
+ [
+ no_auth,
+ auth,
+ client_auth_empty_cert_accepted,
+ client_auth_empty_cert_rejected,
+ client_auth_partial_chain,
+ client_auth_allow_partial_chain,
+ client_auth_do_not_allow_partial_chain,
+ client_auth_partial_chain_fun_fail,
+ missing_root_cert_no_auth,
+ missing_root_cert_auth,
+ missing_root_cert_auth_user_verify_fun_accept,
+ missing_root_cert_auth_user_verify_fun_reject,
+ verify_fun_always_run_client,
+ verify_fun_always_run_server,
+ incomplete_chain_auth
+ %%invalid_signature_client
+ ].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+
+init_per_group(Group, Config0) when Group == rsa;
+ Group == rsa_1_3 ->
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ COpts = proplists:get_value(client_rsa_opts, Config),
+ SOpts = proplists:get_value(server_rsa_opts, Config),
+ [{cert_key_alg, rsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, COpts},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+init_per_group(Group, Config0) when Group == ecdsa;
+ Group == ecdsa_1_3 ->
+
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg) orelse lists:member(dh, PKAlg)) of
+ true ->
+ Config = ssl_test_lib:make_ecdsa_cert(Config0),
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ [{cert_key_alg, ecdsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, COpts},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))]
+ )];
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+
+init_per_group(Group, Config0) when Group == dsa ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(dss, PKAlg) andalso lists:member(dh, PKAlg) of
+ true ->
+ Config = ssl_test_lib:make_dsa_cert(Config0),
+ COpts = proplists:get_value(client_dsa_opts, Config),
+ SOpts = proplists:get_value(server_dsa_opts, Config),
+ [{cert_key_alg, dsa} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, COpts},
+ {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ false ->
+ {skip, "Missing DSS crypto support"}
+ end;
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ [{client_type, erlang},
+ {server_type, erlang}, {version, GroupName}
+ | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(_TestCase, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+no_auth() ->
+ ssl_cert_tests:no_auth().
+
+no_auth(Config) ->
+ ssl_cert_tests:no_auth(Config).
+%%--------------------------------------------------------------------
+auth() ->
+ ssl_cert_tests:auth().
+auth(Config) ->
+ ssl_cert_tests:auth(Config).
+%%--------------------------------------------------------------------
+client_auth_empty_cert_accepted() ->
+ ssl_cert_tests:client_auth_empty_cert_accepted().
+client_auth_empty_cert_accepted(Config) ->
+ ssl_cert_tests:client_auth_empty_cert_accepted(Config).
+%%--------------------------------------------------------------------
+client_auth_empty_cert_rejected() ->
+ ssl_cert_tests:client_auth_empty_cert_rejected().
+client_auth_empty_cert_rejected(Config) ->
+ ssl_cert_tests:client_auth_empty_cert_rejected(Config).
+%%--------------------------------------------------------------------
+client_auth_partial_chain() ->
+ ssl_cert_tests:client_auth_partial_chain().
+client_auth_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_partial_chain(Config).
+
+%%--------------------------------------------------------------------
+client_auth_allow_partial_chain() ->
+ ssl_cert_tests:client_auth_allow_partial_chain().
+client_auth_allow_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_allow_partial_chain(Config).
+%%--------------------------------------------------------------------
+client_auth_do_not_allow_partial_chain() ->
+ ssl_cert_tests:client_auth_do_not_allow_partial_chain().
+client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_do_not_allow_partial_chain(Config).
+
+%%--------------------------------------------------------------------
+client_auth_partial_chain_fun_fail() ->
+ ssl_cert_tests:client_auth_partial_chain_fun_fail().
+client_auth_partial_chain_fun_fail(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_partial_chain_fun_fail(Config).
+
+%%--------------------------------------------------------------------
+missing_root_cert_no_auth() ->
+ ssl_cert_tests:missing_root_cert_no_auth().
+missing_root_cert_no_auth(Config) when is_list(Config) ->
+ ssl_cert_tests:missing_root_cert_no_auth(Config).
+
+%%--------------------------------------------------------------------
+missing_root_cert_auth() ->
+ [{doc,"Must have ROOT certs to be able to verify verify peer"}].
+missing_root_cert_auth(Config) when is_list(Config) ->
+ ServerOpts = proplists:delete(cacertfile, ssl_test_lib:ssl_options(server_cert_opts, Config)),
+ {ClientNode, ServerNode, _} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, [{verify, verify_peer}
+ | ServerOpts]}]),
+
+ ssl_test_lib:check_result(Server, {error, {options, {cacertfile, ""}}}),
+
+ ClientOpts = proplists:delete(cacertfile, ssl_test_lib:ssl_options(client_cert_opts, Config)),
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {options, [{verify, verify_peer}
+ | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, {error, {options, {cacertfile, ""}}}).
+
+%%--------------------------------------------------------------------
+missing_root_cert_auth_user_verify_fun_accept() ->
+ [{doc, "Test that the client succeds if the ROOT CA is unknown in verify_peer mode"
+ " with a verify_fun that accepts the unknown CA error"}].
+
+missing_root_cert_auth_user_verify_fun_accept(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ FunAndState = {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []},
+ ClientOpts = ssl_test_lib:ssl_options([{verify, verify_peer},
+ {verify_fun, FunAndState}], Config),
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+missing_root_cert_auth_user_backwardscompatibility_verify_fun_accept() ->
+ [{doc, "Test old style verify fun"}].
+
+missing_root_cert_auth_user_backwardscompatibility_verify_fun_accept(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc;
+ (Other, Acc) -> [Other | Acc]
+ end,
+ VerifyFun =
+ fun(ErrorList) ->
+ case lists:foldl(AcceptBadCa, [], ErrorList) of
+ [] -> true;
+ [_|_] -> false
+ end
+ end,
+
+ ClientOpts = ssl_test_lib:ssl_options([{verify, verify_peer},
+ {verify_fun, VerifyFun}], Config),
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+missing_root_cert_auth_user_verify_fun_reject() ->
+ [{doc, "Test that the client fails if the ROOT CA is unknown in verify_peer mode"
+ " with a verify_fun that rejects the unknown CA error"}].
+
+missing_root_cert_auth_user_verify_fun_reject(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ FunAndState = {fun(_,{bad_cert, unknown_ca} = Reason, _UserState) ->
+ {fail, Reason};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, UserState}, _) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, []},
+ ClientOpts = ssl_test_lib:ssl_options([{verify, verify_peer},
+ {verify_fun, FunAndState}], Config),
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+%%--------------------------------------------------------------------
+incomplete_chain_auth() ->
+ [{doc,"Test that we can verify an incompleat chain when we have the certs to rebuild it"}].
+incomplete_chain_auth(Config) when is_list(Config) ->
+ DefaultCertConf = ssl_test_lib:default_cert_chain_conf(),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain, DefaultCertConf},
+ {client_chain, DefaultCertConf}]),
+ [ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerOpts0),
+ ClientCas = proplists:get_value(cacerts, ClientOpts0),
+ ClientOpts = ssl_test_lib:ssl_options([{verify, verify_peer},
+ {cacerts, ServerCas ++ ClientCas} |
+ proplists:delete(cacerts, ClientOpts0)], Config),
+ ServerOpts = ssl_test_lib:ssl_options([{verify, verify_peer},
+ {cacerts, [ServerRoot]} |
+ proplists:delete(cacerts, ServerOpts0)], Config),
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_client() ->
+ [{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}].
+
+verify_fun_always_run_client(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we cannot tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [1]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}
+ | ClientOpts]}]),
+
+ ssl_test_lib:check_client_alert(Server, Client, handshake_failure).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_server() ->
+ [{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}].
+verify_fun_always_run_server(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we cannot tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [1]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState} |
+ ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_client_alert(Server, Client, handshake_failure).
+
+%%--------------------------------------------------------------------
+invalid_signature_client() ->
+ ssl_cert_tests:invalid_signature_client().
+invalid_signature_client(Config) when is_list(Config) ->
+ ssl_cert_tests:invalid_signature_client(Config).
+%%--------------------------------------------------------------------
+invalid_signature_server() ->
+ ssl_cert_tests:invalid_signature_client().
+invalid_signature_server(Config) when is_list(Config) ->
+ ssl_cert_tests:invalid_signature_client(Config).
+
+%%--------------------------------------------------------------------
+%% TLS 1.3 Test cases -----------------------------------------------
+%%--------------------------------------------------------------------
+hello_retry_request() ->
+ [{doc,"Test that ssl server can request a new group when the client's first key share"
+ "is not supported"}].
+
+hello_retry_request(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {supported_groups, [x448, x25519]}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {supported_groups, [secp256r1, x25519]}|ClientOpts0],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+custom_groups() ->
+ [{doc,"Test that ssl server can select a common group for key-exchange"}].
+
+custom_groups(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ %% Set versions
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {supported_groups, [x448, secp256r1, secp384r1]}|ServerOpts0],
+ ClientOpts1 = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
+ ClientOpts = [{supported_groups,[secp384r1, secp256r1, x25519]}|ClientOpts1],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+%% Triggers a Server Alert as ssl client does not have a certificate with a
+%% signature algorithm supported by the server (signature_algorithms_cert extension
+%% of CertificateRequest does not contain the algorithm of the client certificate).
+%% ssl client sends an empty certificate.
+unsupported_sign_algo_cert_client_auth() ->
+ [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm_cert"}].
+
+unsupported_sign_algo_cert_client_auth(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ {signature_algs, [rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pss_rsae_sha256]},
+ %% Skip rsa_pkcs1_sha256!
+ {signature_algs_cert, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
+ {fail_if_no_peer_cert, true}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required).
+
+%%--------------------------------------------------------------------
+unsupported_sign_algo_client_auth() ->
+ [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm"}].
+
+unsupported_sign_algo_client_auth(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ %% Skip rsa_pkcs1_sha256!
+ {signature_algs, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
+ {fail_if_no_peer_cert, true}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, insufficient_security).
+%%--------------------------------------------------------------------
+hello_retry_client_auth() ->
+ [{doc, "TLS 1.3 (HelloRetryRequest): Test client authentication."}].
+
+hello_retry_client_auth(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts1 = [{versions, ['tlsv1.2','tlsv1.3']},
+ {supported_groups, [x448, x25519]}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {supported_groups, [secp256r1, x25519]}|ClientOpts0],
+ ServerOpts = [{verify, verify_peer},
+ {fail_if_no_peer_cert, true} | ServerOpts1],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_accepted() ->
+ [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty "
+ "certificate and fail_if_no_peer_cert is set to true."}].
+
+hello_retry_client_auth_empty_cert_accepted(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ %% Delete Client Cert and Key
+ ClientOpts1 = proplists:delete(certfile, ClientOpts0),
+ ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
+
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ %% Set versions
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, false},
+ {supported_groups, [x448, x25519]}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {supported_groups, [secp256r1, x25519]}|ClientOpts2],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_rejected() ->
+ [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client "
+ "sends an empty certificate and fail_if_no_peer_cert is set to true."}].
+
+hello_retry_client_auth_empty_cert_rejected(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ %% Delete Client Cert and Key
+ ClientOpts1 = proplists:delete(certfile, ClientOpts0),
+ ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
+
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ %% Set versions
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, true},
+ {supported_groups, [x448, x25519]}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {supported_groups, [secp256r1, x25519]}|ClientOpts2],
+
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required).
diff --git a/lib/ssl/test/ssl_cert_tests.erl b/lib/ssl/test/ssl_cert_tests.erl
new file mode 100644
index 0000000000..c88daa2185
--- /dev/null
+++ b/lib/ssl/test/ssl_cert_tests.erl
@@ -0,0 +1,386 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(ssl_cert_tests).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+no_auth() ->
+ [{doc,"Test connection without authentication"}].
+
+no_auth(Config) ->
+ ClientOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+auth() ->
+ [{doc,"Test connection with mutual authentication"}].
+
+auth(Config) ->
+ ClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+client_auth_empty_cert_accepted() ->
+ [{doc,"Test client authentication when client sends an empty certificate and "
+ "fail_if_no_peer_cert is set to false."}].
+
+client_auth_empty_cert_accepted(Config) ->
+ ClientOpts = proplists:delete(keyfile,
+ proplists:delete(certfile,
+ ssl_test_lib:ssl_options(client_cert_opts, Config))),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts = [{verify, verify_peer},
+ {fail_if_no_peer_cert, false} | ServerOpts0],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+client_auth_empty_cert_rejected() ->
+ [{doc,"Test client authentication when client sends an empty certificate and "
+ "fail_if_no_peer_cert is set to true."}].
+
+client_auth_empty_cert_rejected(Config) ->
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
+ | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ClientOpts0 = ssl_test_lib:ssl_options([], Config),
+ %% Delete Client Cert and Key
+ ClientOpts1 = proplists:delete(certfile, ClientOpts0),
+ ClientOpts = proplists:delete(keyfile, ClientOpts1),
+
+ Version = proplists:get_value(version,Config),
+ case Version of
+ 'tlsv1.3' ->
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required);
+ _ ->
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, handshake_failure)
+ end.
+%%--------------------------------------------------------------------
+client_auth_partial_chain() ->
+ [{doc, "Client sends an incompleate chain, by default not acceptable."}].
+
+client_auth_partial_chain(Config) when is_list(Config) ->
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
+ | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ {ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts0)),
+ [{_,RootCA,_} | _] = public_key:pem_decode(ClientCAs),
+ ClientOpts = [{cacerts, [RootCA]} |
+ proplists:delete(cacertfile, ClientOpts0)],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+
+%%--------------------------------------------------------------------
+client_auth_allow_partial_chain() ->
+ [{doc, "Server trusts intermediat CA and accepts a partial chain. (partial_chain option)"}].
+
+client_auth_allow_partial_chain(Config) when is_list(Config) ->
+ ServerOpts0 = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
+ | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ {ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts)),
+ [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ClientCAs),
+
+ PartialChain = fun(CertChain) ->
+ case lists:member(IntermidiateCA, CertChain) of
+ true ->
+ {trusted_ca, IntermidiateCA};
+ false ->
+ unknown_ca
+ end
+ end,
+ ServerOpts = [{cacerts, [IntermidiateCA]},
+ {partial_chain, PartialChain} |
+ proplists:delete(cacertfile, ServerOpts0)],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+ %%--------------------------------------------------------------------
+client_auth_do_not_allow_partial_chain() ->
+ [{doc, "Server does not accept the chain sent by the client as ROOT CA is unkown, "
+ "and we do not choose to trust the intermediate CA. (partial_chain option)"}].
+
+client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
+ ServerOpts0 = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
+ | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts0)),
+ [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
+
+ PartialChain = fun(_CertChain) ->
+ unknown_ca
+ end,
+ ServerOpts = [{cacerts, [IntermidiateCA]},
+ {partial_chain, PartialChain} |
+ proplists:delete(cacertfile, ServerOpts0)],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+
+ %%--------------------------------------------------------------------
+client_auth_partial_chain_fun_fail() ->
+ [{doc, "If parial_chain fun crashes, treat it as if it returned unkown_ca"}].
+
+client_auth_partial_chain_fun_fail(Config) when is_list(Config) ->
+ ServerOpts0 = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
+ | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
+
+ {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts0)),
+ [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
+
+ PartialChain = fun(_CertChain) ->
+ true = false %% crash on purpose
+ end,
+ ServerOpts = [{cacerts, [IntermidiateCA]},
+ {partial_chain, PartialChain} |
+ proplists:delete(cacertfile, ServerOpts0)],
+
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+
+%%--------------------------------------------------------------------
+missing_root_cert_no_auth() ->
+ [{doc,"Test that the client succeds if the ROOT CA is unknown in verify_none mode"}].
+
+missing_root_cert_no_auth(Config) ->
+ ClientOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+invalid_signature_client() ->
+ [{doc,"Test server with invalid signature"}].
+
+invalid_signature_client(Config) when is_list(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+
+ KeyFile = proplists:get_value(keyfile, ClientOpts0),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
+
+ ClientCertFile = proplists:get_value(certfile, ClientOpts0),
+ NewClientCertFile = filename:join(PrivDir, "client_invalid_cert.pem"),
+ [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile),
+ ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp),
+ ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate,
+ NewClientDerCert = public_key:pkix_sign(ClientOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]),
+ ClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts0)],
+ ServerOpts = [{verify, verify_peer} | ServerOpts0],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+
+%%--------------------------------------------------------------------
+invalid_signature_server() ->
+ [{doc,"Test client with invalid signature"}].
+
+invalid_signature_server(Config) when is_list(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+
+ KeyFile = proplists:get_value(keyfile, ServerOpts0),
+ [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
+ Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
+
+ ServerCertFile = proplists:get_value(certfile, ServerOpts0),
+ NewServerCertFile = filename:join(PrivDir, "server_invalid_cert.pem"),
+ [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
+ ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp),
+ ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate,
+ NewServerDerCert = public_key:pkix_sign(ServerOTPTbsCert, Key),
+ ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]),
+ ServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts0)],
+ ClientOpts = [{verify, verify_peer} | ClientOpts0],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+
+%%--------------------------------------------------------------------
+%% TLS 1.3 Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+hello_retry_request() ->
+ [{doc,"Test that ssl server can request a new group when the client's first key share"
+ "is not supported"}].
+
+hello_retry_request(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ {ServerOpts, ClientOpts} = group_config(Config,
+ [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
+ [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]),
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+custom_groups() ->
+ [{doc,"Test that ssl server can select a common group for key-exchange"}].
+
+custom_groups(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ {ServerOpts, ClientOpts} = group_config_custom(Config,
+ [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
+ [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]),
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
+%% Triggers a Server Alert as ssl client does not have a certificate with a
+%% signature algorithm supported by the server (signature_algorithms_cert extension
+%% of CertificateRequest does not contain the algorithm of the client certificate).
+%% ssl client sends an empty certificate.
+unsupported_sign_algo_cert_client_auth() ->
+ [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm_cert"}].
+
+unsupported_sign_algo_cert_client_auth(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ {signature_algs, [rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pss_rsae_sha256]},
+ %% Skip rsa_pkcs1_sha256!
+ {signature_algs_cert, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
+ {fail_if_no_peer_cert, true}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required).
+%%--------------------------------------------------------------------
+unsupported_sign_algo_client_auth() ->
+ [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm"}].
+
+unsupported_sign_algo_client_auth(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ %% Skip rsa_pkcs1_sha256!
+ {signature_algs, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]},
+ {fail_if_no_peer_cert, true}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, insufficient_security).
+%%--------------------------------------------------------------------
+hello_retry_client_auth() ->
+ [{doc, "TLS 1.3 (HelloRetryRequest): Test client authentication."}].
+
+hello_retry_client_auth(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ {ServerOpts, ClientOpts} = group_config(Config,
+ [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, true} | ServerOpts0],
+ [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]),
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_accepted() ->
+ [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty "
+ "certificate and fail_if_no_peer_cert is set to false."}].
+
+hello_retry_client_auth_empty_cert_accepted(Config) ->
+ ClientOpts0 = proplists:delete(keyfile,
+ proplists:delete(certfile,
+ ssl_test_lib:ssl_options(client_cert_opts, Config))),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ {ServerOpts, ClientOpts} = group_config(Config,
+ [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, false} | ServerOpts0],
+ [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]),
+
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+%%--------------------------------------------------------------------
+hello_retry_client_auth_empty_cert_rejected() ->
+ [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client "
+ "sends an empty certificate and fail_if_no_peer_cert is set to true."}].
+
+hello_retry_client_auth_empty_cert_rejected(Config) ->
+ ClientOpts0 = proplists:delete(keyfile,
+ proplists:delete(certfile,
+ ssl_test_lib:ssl_options(client_cert_opts, Config))),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ {ServerOpts, ClientOpts} = group_config(Config,
+ [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, true} | ServerOpts0],
+ [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]),
+
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions -----------------------------------------------
+%%--------------------------------------------------------------------
+
+group_config_custom(Config, ServerOpts, ClientOpts) ->
+ case proplists:get_value(client_type, Config) of
+ erlang ->
+ {[{groups,"X448:P-256:P-384"} | ServerOpts],
+ [{supported_groups, [secp384r1, secp256r1, x25519]} | ClientOpts]};
+ openssl ->
+ {[{supported_groups, [x448, secp256r1, secp384r1]} | ServerOpts],
+ [{groups,"P-384:P-256:X25519"} | ClientOpts]}
+ end.
+
+group_config(Config, ServerOpts, ClientOpts) ->
+ case proplists:get_value(client_type, Config) of
+ erlang ->
+ {[{groups,"X448:X25519"} | ServerOpts],
+ [{supported_groups, [secp256r1, x25519]} | ClientOpts]};
+ openssl ->
+ {[{supported_groups, [x448, x25519]} | ServerOpts],
+ [{groups,"P-256:X25519"} | ClientOpts]}
+ end.
+
+test_ciphers(_, 'tlsv1.3' = Version) ->
+ Ciphers = ssl:cipher_suites(default, Version),
+ ct:log("Version ~p Testing ~p~n", [Version, Ciphers]),
+ OpenSSLCiphers = openssl_ciphers(),
+ ct:log("OpenSSLCiphers ~p~n", [OpenSSLCiphers]),
+ lists:filter(fun(C) ->
+ ct:log("Cipher ~p~n", [C]),
+ lists:member(ssl_cipher_format:suite_map_to_openssl_str(C), OpenSSLCiphers)
+ end, Ciphers);
+test_ciphers(Kex, Version) ->
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, Version),
+ [{key_exchange, Kex}]),
+ ct:log("Version ~p Testing ~p~n", [Version, Ciphers]),
+ OpenSSLCiphers = openssl_ciphers(),
+ ct:log("OpenSSLCiphers ~p~n", [OpenSSLCiphers]),
+ lists:filter(fun(C) ->
+ ct:log("Cipher ~p~n", [C]),
+ lists:member(ssl_cipher_format:suite_map_to_openssl_str(C), OpenSSLCiphers)
+ end, Ciphers).
+
+
+
+openssl_ciphers() ->
+ Str = os:cmd("openssl ciphers"),
+ string:split(string:strip(Str, right, $\n), ":", all).
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 4de4a35e59..f38858e0bf 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -71,37 +71,20 @@ all_protocol_groups() ->
{group, error_handling}].
tests() ->
- [verify_peer,
- verify_none,
- server_require_peer_cert_ok,
- server_require_peer_cert_fail,
- server_require_peer_cert_empty_ok,
- server_require_peer_cert_partial_chain,
- server_require_peer_cert_allow_partial_chain,
- server_require_peer_cert_do_not_allow_partial_chain,
- server_require_peer_cert_partial_chain_fun_fail,
- verify_fun_always_run_client,
- verify_fun_always_run_server,
- cert_expired,
- invalid_signature_client,
- invalid_signature_server,
+ [cert_expired,
+ %invalid_signature_client,
+ %%invalid_signature_server,
extended_key_usage_verify_both,
extended_key_usage_verify_server,
critical_extension_verify_client,
critical_extension_verify_server,
critical_extension_verify_none,
- customize_hostname_check,
- incomplete_chain,
long_chain
].
error_handling_tests()->
[client_with_cert_cipher_suites_handshake,
- server_verify_no_cacerts,
- unknown_server_ca_fail,
- unknown_server_ca_accept_verify_none,
- unknown_server_ca_accept_verify_peer,
- unknown_server_ca_accept_backwardscompatibility,
+ %%unknown_server_ca_accept_backwardscompatibility,
no_authority_key_identifier,
no_authority_key_identifier_keyEncipherment].
@@ -160,61 +143,6 @@ end_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-
-verify_peer() ->
- [{doc,"Test option verify_peer"}].
-verify_peer(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- 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}
- | 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, ReceiveFunction, []}},
- {options, [{active, Active}, {verify, verify_peer} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-verify_none() ->
- [{doc,"Test option verify_none"}].
-
-verify_none(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- 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_none}
- | 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, ReceiveFunction, []}},
- {options, [{active, Active},
- {verify, verify_none} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
server_verify_client_once() ->
[{doc,"Test server option verify_client_once"}].
@@ -253,309 +181,6 @@ server_verify_client_once(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-server_require_peer_cert_ok() ->
- [{doc,"Test server option fail_if_no_peer_cert when peer sends cert"}].
-
-server_require_peer_cert_ok(Config) when is_list(Config) ->
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- 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} | 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, ReceiveFunction, []}},
- {options, [{active, Active} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
-server_require_peer_cert_fail() ->
- [{doc,"Test server option fail_if_no_peer_cert when peer doesn't send cert"}].
-
-server_require_peer_cert_fail(Config) when is_list(Config) ->
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
- BadClientOpts = ssl_test_lib:ssl_options(empty_client_opts, Config),
- Active = proplists:get_value(active, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, [{active, Active} | ServerOpts]}]),
-
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {options, [{active, Active} | BadClientOpts]}]),
-
- Version = proplists:get_value(version,Config),
- case Version of
- 'tlsv1.3' ->
- ssl_test_lib:check_server_alert(Server, Client, certificate_required);
- _ ->
- ssl_test_lib:check_server_alert(Server, Client, handshake_failure)
- end.
-
-%%--------------------------------------------------------------------
-server_require_peer_cert_empty_ok() ->
- [{doc,"Test server option fail_if_no_peer_cert when peer sends cert"}].
-
-server_require_peer_cert_empty_ok(Config) when is_list(Config) ->
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, false}
- | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
- ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- Active = proplists:get_value(active, Config),
- ReceiveFunction = proplists:get_value(receive_function, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- ClientOpts = proplists:delete(keyfile, proplists:delete(certfile, ClientOpts0)),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{active, Active} | 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, ReceiveFunction, []}},
- {options, [{active, Active} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
-server_require_peer_cert_partial_chain() ->
- [{doc, "Client sends an incompleate chain, by default not acceptable."}].
-
-server_require_peer_cert_partial_chain(Config) when is_list(Config) ->
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- Active = proplists:get_value(active, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- {ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts)),
- [{_,RootCA,_} | _] = public_key:pem_decode(ClientCAs),
-
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{active, Active} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{active, Active},
- {cacerts, [RootCA]} |
- proplists:delete(cacertfile, ClientOpts)]}]),
- 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)"}].
-
-server_require_peer_cert_allow_partial_chain(Config) when is_list(Config) ->
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Active = proplists:get_value(active, Config),
- ReceiveFunction = proplists:get_value(receive_function, Config),
-
- {ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts)),
- [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ClientCAs),
-
- PartialChain = fun(CertChain) ->
- case lists:member(IntermidiateCA, CertChain) of
- true ->
- {trusted_ca, IntermidiateCA};
- false ->
- unknown_ca
- end
- end,
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{active, Active},
- {cacerts, [IntermidiateCA]},
- {partial_chain, PartialChain} |
- proplists:delete(cacertfile, 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, ReceiveFunction, []}},
- {options, [{active, Active} | ClientOpts]}]),
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
- %%--------------------------------------------------------------------
-server_require_peer_cert_do_not_allow_partial_chain() ->
- [{doc, "Server does not accept the chain sent by the client as ROOT CA is unkown, "
- "and we do not choose to trust the intermediate CA. (partial_chain option)"}].
-
-server_require_peer_cert_do_not_allow_partial_chain(Config) when is_list(Config) ->
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts)),
- [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
-
- PartialChain = fun(_CertChain) ->
- unknown_ca
- end,
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{cacerts, [IntermidiateCA]},
- {partial_chain, PartialChain} |
- proplists:delete(cacertfile, ServerOpts)]}]),
-
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, ClientOpts}]),
- 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"}].
-
-server_require_peer_cert_partial_chain_fun_fail(Config) when is_list(Config) ->
- ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts)),
- [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
-
- PartialChain = fun(_CertChain) ->
- true = false %% crash on purpose
- end,
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, [{cacerts, [IntermidiateCA]},
- {partial_chain, PartialChain} |
- proplists:delete(cacertfile, ServerOpts)]}]),
-
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, ClientOpts}]),
- ssl_test_lib:check_server_alert(Server, Client, unknown_ca).
-
-%%--------------------------------------------------------------------
-verify_fun_always_run_client() ->
- [{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}].
-
-verify_fun_always_run_client(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_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_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- no_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- %% If user verify fun is called correctly we fail the connection.
- %% otherwise we cannot tell this case apart form where we miss
- %% to call users verify fun
- FunAndState = {fun(_,{extension, _}, UserState) ->
- {unknown, UserState};
- (_, valid, [ChainLen]) ->
- {valid, [ChainLen + 1]};
- (_, valid_peer, [1]) ->
- {fail, "verify_fun_was_always_run"};
- (_, valid_peer, UserState) ->
- {valid, UserState}
- end, [0]},
-
- Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib,
- no_result, []}},
- {options,
- [{verify, verify_peer},
- {verify_fun, FunAndState}
- | ClientOpts]}]),
-
- ssl_test_lib:check_client_alert(Server, Client, handshake_failure).
-
-%%--------------------------------------------------------------------
-verify_fun_always_run_server() ->
- [{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}].
-verify_fun_always_run_server(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- %% If user verify fun is called correctly we fail the connection.
- %% otherwise we cannot tell this case apart form where we miss
- %% to call users verify fun
- FunAndState = {fun(_,{extension, _}, UserState) ->
- {unknown, UserState};
- (_, valid, [ChainLen]) ->
- {valid, [ChainLen + 1]};
- (_, valid_peer, [1]) ->
- {fail, "verify_fun_was_always_run"};
- (_, valid_peer, UserState) ->
- {valid, UserState}
- end, [0]},
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- no_result, []}},
- {options,
- [{verify, verify_peer},
- {verify_fun, FunAndState} |
- ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib,
- no_result, []}},
- {options, ClientOpts}]),
-
- ssl_test_lib:check_client_alert(Server, Client, handshake_failure).
-%%--------------------------------------------------------------------
-
cert_expired() ->
[{doc,"Test server with expired certificate"}].
@@ -937,235 +562,6 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-server_verify_no_cacerts() ->
- [{doc,"Test server must have cacerts if it wants to verify client"}].
-server_verify_no_cacerts(Config) when is_list(Config) ->
- ServerOpts = proplists:delete(cacertfile, ssl_test_lib:ssl_options(server_rsa_opts, Config)),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, [{verify, verify_peer}
- | ServerOpts]}]),
-
- ssl_test_lib:check_result(Server, {error, {options, {cacertfile, ""}}}).
-
-
-%%--------------------------------------------------------------------
-unknown_server_ca_fail() ->
- [{doc,"Test that the client fails if the ca is unknown in verify_peer mode"}].
-unknown_server_ca_fail(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(empty_client_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_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- no_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- FunAndState = {fun(_,{bad_cert, unknown_ca} = Reason, _) ->
- {fail, Reason};
- (_,{extension, _}, UserState) ->
- {unknown, UserState};
- (_, valid, UserState) ->
- {valid, [test_to_update_user_state | UserState]};
- (_, valid_peer, UserState) ->
- {valid, UserState}
- end, []},
-
- Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib,
- no_result, []}},
- {options,
- [{verify, verify_peer},
- {verify_fun, FunAndState}
- | ClientOpts]}]),
- ssl_test_lib:check_client_alert(Server, Client, unknown_ca).
-
-%%--------------------------------------------------------------------
-unknown_server_ca_accept_verify_none() ->
- [{doc,"Test that the client succeds if the ca is unknown in verify_none mode"}].
-unknown_server_ca_accept_verify_none(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(empty_client_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},
- {from, self()},
- {mfa, {ssl_test_lib,
- send_recv_result_active, []}},
- {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,
- send_recv_result_active, []}},
- {options,
- [{verify, verify_none}| ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-%%--------------------------------------------------------------------
-unknown_server_ca_accept_verify_peer() ->
- [{doc, "Test that the client succeds if the ca is unknown in verify_peer mode"
- " with a verify_fun that accepts the unknown ca error"}].
-unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(empty_client_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},
- {from, self()},
- {mfa, {ssl_test_lib,
- send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- FunAndState = {fun(_,{bad_cert, unknown_ca}, UserState) ->
- {valid, UserState};
- (_,{bad_cert, _} = Reason, _) ->
- {fail, Reason};
- (_,{extension, _}, UserState) ->
- {unknown, UserState};
- (_, valid, UserState) ->
- {valid, UserState};
- (_, valid_peer, UserState) ->
- {valid, UserState}
- end, []},
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib,
- send_recv_result_active, []}},
- {options,
- [{verify, verify_peer},
- {verify_fun, FunAndState}| ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-unknown_server_ca_accept_backwardscompatibility() ->
- [{doc,"Test that old style verify_funs will work"}].
-unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(empty_client_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},
- {from, self()},
- {mfa, {ssl_test_lib,
- send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc;
- (Other, Acc) -> [Other | Acc]
- end,
- VerifyFun =
- fun(ErrorList) ->
- case lists:foldl(AcceptBadCa, [], ErrorList) of
- [] -> true;
- [_|_] -> false
- end
- end,
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib,
- send_recv_result_active, []}},
- {options,
- [{verify, verify_peer},
- {verify_fun, VerifyFun}| ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
-customize_hostname_check() ->
- [{doc,"Test option customize_hostname_check."}].
-customize_hostname_check(Config) when is_list(Config) ->
- Ext = [#'Extension'{extnID = ?'id-ce-subjectAltName',
- extnValue = [{dNSName, "*.example.org"}],
- critical = false}
- ],
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
- [[],
- [],
- [{extensions, Ext}]
- ]}],
- Config, "https_hostname_convention"),
- ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
- ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, 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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- CustomFun = public_key:pkix_verify_hostname_match_fun(https),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options,
- [{server_name_indication, "other.example.org"},
- {customize_hostname_check,
- [{match_fun, CustomFun}]} | ClientOpts]
- }]),
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
-
- Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, ClientOpts}
- ]),
- 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).
long_chain() ->
[{doc,"Test option verify_peer"}].
diff --git a/lib/ssl/test/ssl_cipher_suite_SUITE.erl b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
index 51788c29e7..e598d662e9 100644
--- a/lib/ssl/test/ssl_cipher_suite_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
@@ -45,7 +45,7 @@ groups() ->
{'tlsv1.2', [], kex()},
{'tlsv1.1', [], kex()},
{'tlsv1', [], kex()},
- {'sslv3', [], kex()},
+ {'sslv3', [], ssl3_kex()},
{'dtlsv1.2', [], kex()},
{'dtlsv1', [], kex()},
{dhe_rsa, [],[dhe_rsa_3des_ede_cbc,
@@ -130,6 +130,11 @@ groups() ->
kex() ->
rsa() ++ ecdsa() ++ dss() ++ anonymous().
+
+ssl3_kex() ->
+ ssl3_rsa() ++ ssl3_dss() ++ ssl3_anonymous().
+
+
rsa() ->
[{group, dhe_rsa},
{group, ecdhe_rsa},
@@ -138,6 +143,11 @@ rsa() ->
{group, rsa_psk}
].
+ssl3_rsa() ->
+ [{group, dhe_rsa},
+ {group, rsa}
+ ].
+
ecdsa() ->
[{group, ecdhe_ecdsa}].
@@ -145,6 +155,10 @@ dss() ->
[{group, dhe_dss},
{group, srp_dss}].
+ssl3_dss() ->
+ [{group, dhe_dss}
+ ].
+
anonymous() ->
[{group, dh_anon},
{group, ecdh_anon},
@@ -154,6 +168,10 @@ anonymous() ->
{group, srp_anon}
].
+ssl3_anonymous() ->
+ [{group, dh_anon}].
+
+
init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 003e1fc448..7cfb2ac0c5 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_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.
@@ -311,9 +311,11 @@ listen_port_options(Config) when is_list(Config) ->
catch
_:Reason ->
stop_ssl_node(NH2),
+ stop_ssl_node(NH1),
ct:fail(Reason)
end,
stop_ssl_node(NH2),
+ stop_ssl_node(NH1),
success(Config).
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 1b432970b6..2750a4a9dc 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -214,7 +214,7 @@ encode_decode_srp(_Config) ->
0,3, % HostNameLength
98,97,114>>, % hostname = "bar"
EncodedExts0 = <<?UINT16(_),EncodedExts/binary>> =
- ssl_handshake:encode_hello_extensions(Exts),
+ ssl_handshake:encode_hello_extensions(Exts, {3,3}),
Exts = ssl_handshake:decode_hello_extensions(EncodedExts, {3,3}, {3,3}, client).
signature_algorithms(Config) ->
diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_SUITE.erl
index 878e983bb9..8a76a3a82b 100644
--- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_SUITE.erl
@@ -19,7 +19,7 @@
%%
%%
--module(ssl_npn_handshake_SUITE).
+-module(ssl_npn_SUITE).
%% Note: This directive should only be used in test suites.
-compile(export_all).
diff --git a/lib/ssl/test/ssl_npn_hello_SUITE.erl b/lib/ssl/test/ssl_npn_hello_SUITE.erl
index 46734ba180..7dbc0c5134 100644
--- a/lib/ssl/test/ssl_npn_hello_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_hello_SUITE.erl
@@ -24,10 +24,11 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include("ssl_cipher.hrl").
--include("ssl_internal.hrl").
--include("tls_handshake.hrl").
--include("tls_record.hrl").
+
+-include_lib("ssl/src/tls_record.hrl").
+-include_lib("ssl/src/tls_handshake.hrl").
+-include_lib("ssl/src/ssl_cipher.hrl").
+-include_lib("ssl/src/ssl_internal.hrl").
-include_lib("common_test/include/ct.hrl").
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl
index 6f11e2bbe8..3c7f6ab20f 100644
--- a/lib/ssl/test/ssl_pem_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl
@@ -34,7 +34,10 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [pem_cleanup, invalid_insert].
+ [
+ pem_cleanup,
+ clear_pem_cache,
+ invalid_insert].
groups() ->
[].
@@ -110,6 +113,37 @@ pem_cleanup(Config)when is_list(Config) ->
ssl_test_lib:close(Client),
false = Size == Size1.
+clear_pem_cache() ->
+ [{doc,"Test that internal reference tabel is cleaned properly even when "
+ " the PEM cache is cleared" }].
+clear_pem_cache(Config) when is_list(Config) ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ [_,{FilRefDb, _} |_] = element(6, State),
+ {Server, Client} = basic_verify_test_no_close(Config),
+ CountReferencedFiles = fun({_, -1}, Acc) ->
+ Acc;
+ ({_, N}, Acc) ->
+ N + Acc
+ end,
+
+ 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
+ ssl:clear_pem_cache(),
+ _ = sys:get_status(whereis(ssl_manager)),
+ {Server1, Client1} = basic_verify_test_no_close(Config),
+ 4 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ ct:sleep(2000),
+ _ = sys:get_status(whereis(ssl_manager)),
+ 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1),
+ ct:sleep(2000),
+ _ = sys:get_status(whereis(ssl_manager)),
+ 0 = ets:foldl(CountReferencedFiles, 0, FilRefDb).
+
invalid_insert() ->
[{doc, "Test that insert of invalid pem does not cause empty cache entry"}].
invalid_insert(Config)when is_list(Config) ->
@@ -163,3 +197,22 @@ later()->
Gregorian = calendar:datetime_to_gregorian_seconds(DateTime),
calendar:gregorian_seconds_to_datetime(Gregorian + (2 * ?CLEANUP_INTERVAL)).
+basic_verify_test_no_close(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {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, send_recv_result_active, []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ {Server, Client}.
diff --git a/lib/ssl/test/ssl_renegotiate_SUITE.erl b/lib/ssl/test/ssl_renegotiate_SUITE.erl
new file mode 100644
index 0000000000..ef3f9ebb52
--- /dev/null
+++ b/lib/ssl/test/ssl_renegotiate_SUITE.erl
@@ -0,0 +1,499 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_renegotiate_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-define(SLEEP, 500).
+-define(RENEGOTIATION_DISABLE_TIME, 12000).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ [{'dtlsv1.2', [], renegotiate_tests()},
+ {'dtlsv1', [], renegotiate_tests()},
+ {'tlsv1.3', [], renegotiate_tests()},
+ {'tlsv1.2', [], renegotiate_tests()},
+ {'tlsv1.1', [], renegotiate_tests()},
+ {'tlsv1', [], renegotiate_tests()},
+ {'sslv3', [], ssl3_renegotiate_tests()}
+ ].
+
+renegotiate_tests() ->
+ [client_renegotiate,
+ server_renegotiate,
+ client_secure_renegotiate,
+ client_secure_renegotiate_fallback,
+ client_renegotiate_reused_session,
+ server_renegotiate_reused_session,
+ client_no_wrap_sequence_number,
+ server_no_wrap_sequence_number,
+ renegotiate_dos_mitigate_active,
+ renegotiate_dos_mitigate_passive,
+ renegotiate_dos_mitigate_absolute].
+
+ssl3_renegotiate_tests() ->
+ [client_renegotiate,
+ server_renegotiate,
+ client_renegotiate_reused_session,
+ server_renegotiate_reused_session,
+ client_no_wrap_sequence_number,
+ server_no_wrap_sequence_number,
+ renegotiate_dos_mitigate_active,
+ renegotiate_dos_mitigate_passive,
+ renegotiate_dos_mitigate_absolute].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+init_per_group(GroupName, Config) ->
+ ssl_test_lib:clean_tls_version(Config),
+ case ssl_test_lib:is_tls_version(GroupName) andalso ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ _ ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl:start(),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+client_renegotiate() ->
+ [{doc,"Test ssl:renegotiate/1 on client."}].
+client_renegotiate(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {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,
+ renegotiate, [Data]}},
+ {options, [{reuse_sessions, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+client_secure_renegotiate() ->
+ [{doc,"Test ssl:renegotiate/1 on client."}].
+client_secure_renegotiate(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, [{secure_renegotiate, true} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ renegotiate, [Data]}},
+ {options, [{reuse_sessions, false},
+ {secure_renegotiate, true}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+client_secure_renegotiate_fallback() ->
+ [{doc,"Test that we can set secure_renegotiate to false that is "
+ "fallback option, we however do not have a insecure server to test against!"}].
+client_secure_renegotiate_fallback(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, [{secure_renegotiate, 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,
+ renegotiate, [Data]}},
+ {options, [{reuse_sessions, false},
+ {secure_renegotiate, false}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+server_renegotiate() ->
+ [{doc,"Test ssl:renegotiate/1 on server."}].
+server_renegotiate(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ renegotiate, [Data]}},
+ {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, erlang_ssl_receive, [Data]}},
+ {options, [{reuse_sessions, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+client_renegotiate_reused_session() ->
+ [{doc,"Test ssl:renegotiate/1 on client when the ssl session will be reused."}].
+client_renegotiate_reused_session(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {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,
+ renegotiate_reuse_session, [Data]}},
+ {options, [{reuse_sessions, true} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+server_renegotiate_reused_session() ->
+ [{doc,"Test ssl:renegotiate/1 on server when the ssl session will be reused."}].
+server_renegotiate_reused_session(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ renegotiate_reuse_session, [Data]}},
+ {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, erlang_ssl_receive, [Data]}},
+ {options, [{reuse_sessions, true} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+client_no_wrap_sequence_number() ->
+ [{doc,"Test that erlang client will renegotiate session when",
+ "max sequence number celing is about to be reached. Although"
+ "in the testcase we use the test option renegotiate_at"
+ " to lower treashold substantially."}].
+
+client_no_wrap_sequence_number(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ ErlData = "From erlang to erlang",
+ N = 12,
+
+ 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),
+
+ Version = ssl_test_lib:protocol_version(Config, tuple),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ trigger_renegotiate, [[ErlData, treashold(N, Version)]]}},
+ {options, [{reuse_sessions, false},
+ {renegotiate_at, N} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+server_no_wrap_sequence_number() ->
+ [{doc, "Test that erlang server will renegotiate session when",
+ "max sequence number celing is about to be reached. Although"
+ "in the testcase we use the test option renegotiate_at"
+ " to lower treashold substantially."}].
+
+server_no_wrap_sequence_number(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From erlang to erlang",
+ N = 12,
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ trigger_renegotiate, [[Data, N+2]]}},
+ {options, [{renegotiate_at, N} | 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, [{reuse_sessions, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+renegotiate_dos_mitigate_active() ->
+ [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row",
+ "immediately after each other"}].
+renegotiate_dos_mitigate_active(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {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,
+ renegotiate_immediately, []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+renegotiate_dos_mitigate_passive() ->
+ [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row",
+ "immediately after each other"}].
+renegotiate_dos_mitigate_passive(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {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,
+ renegotiate_immediately, []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+renegotiate_dos_mitigate_absolute() ->
+ [{doc, "Mitigate DOS computational attack by not allowing client to initiate renegotiation"}].
+renegotiate_dos_mitigate_absolute(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{client_renegotiation, 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,
+ renegotiate_rejected,
+ []}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Client, ok, Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+renegotiate(Socket, Data) ->
+ ct:log("Renegotiating ~n", []),
+ Result = ssl:renegotiate(Socket),
+ ct:log("Result ~p~n", [Result]),
+ ssl:send(Socket, Data),
+ case Result of
+ ok ->
+ ok;
+ Other ->
+ Other
+ end.
+
+renegotiate_reuse_session(Socket, Data) ->
+ %% Make sure session is registered
+ ct:sleep(?SLEEP),
+ renegotiate(Socket, Data).
+
+renegotiate_immediately(Socket) ->
+ _ = ssl_test_lib:active_recv(Socket, 11),
+ ok = ssl:renegotiate(Socket),
+ {error, renegotiation_rejected} = ssl:renegotiate(Socket),
+ ct:sleep(?RENEGOTIATION_DISABLE_TIME + ?SLEEP),
+ ok = ssl:renegotiate(Socket),
+ ct:log("Renegotiated again"),
+ ssl:send(Socket, "Hello world"),
+ ok.
+
+renegotiate_rejected(Socket) ->
+ _ = 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),
+ {error, renegotiation_rejected} = ssl:renegotiate(Socket),
+ ct:log("Failed to renegotiate again"),
+ ssl:send(Socket, "Hello world"),
+ ok.
+
+%% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast
+treashold(N, {3,0}) ->
+ (N div 2) + 1;
+treashold(N, {3,1}) ->
+ (N div 2) + 1;
+treashold(N, _) ->
+ N + 1.
+
+erlang_ssl_receive(Socket, Data) ->
+ case ssl_test_lib:active_recv(Socket, length(Data)) of
+ Data ->
+ ok;
+ Other ->
+ ct:fail({{expected, Data}, {got, Other}})
+ end.
diff --git a/lib/ssl/test/ssl_session_SUITE.erl b/lib/ssl/test/ssl_session_SUITE.erl
new file mode 100644
index 0000000000..aa79698a72
--- /dev/null
+++ b/lib/ssl/test/ssl_session_SUITE.erl
@@ -0,0 +1,377 @@
+%%
+%% %CopyrightBegin%
+%%
+%% 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.
+%% 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(ssl_session_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("tls_handshake.hrl").
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-define(SLEEP, 500).
+-define(EXPIRE, 10).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ [{'dtlsv1.2', [], session_tests()},
+ {'dtlsv1', [], session_tests()},
+ {'tlsv1.3', [], session_tests()},
+ {'tlsv1.2', [], session_tests()},
+ {'tlsv1.1', [], session_tests()},
+ {'tlsv1', [], session_tests()},
+ {'sslv3', [], session_tests()}
+ ].
+
+session_tests() ->
+ [reuse_session,
+ reuse_session_expired,
+ server_does_not_want_to_reuse_session,
+ no_reuses_session_server_restart_new_cert,
+ no_reuses_session_server_restart_new_cert_file].
+
+
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ ssl_test_lib:make_dsa_cert(Config)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+init_per_group(GroupName, Config) ->
+ ssl_test_lib:clean_tls_version(Config),
+ case ssl_test_lib:is_tls_version(GroupName) andalso ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ _ ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl:start(),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(reuse_session_expired, Config) ->
+ ssl:stop(),
+ application:load(ssl),
+ ssl_test_lib:clean_env(),
+ application:set_env(ssl, session_lifetime, ?EXPIRE),
+ application:set_env(ssl, session_delay_cleanup_time, 500),
+ ssl:start(),
+ ct:timetrap({seconds, 30}),
+ Config;
+init_per_testcase(_, Config) ->
+ ct:timetrap({seconds, 15}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+reuse_session() ->
+ [{doc,"Test reuse of sessions (short handshake)"}].
+reuse_session(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+
+ 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_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, 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,
+
+ %% Make sure session is unregistered due to expiration
+ ct:sleep((?EXPIRE*2)),
+
+ make_sure_expired(Hostname, Port0, SID),
+
+ Client2 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_id, []}},
+ {from, self()}, {options, ClientOpts}]),
+ receive
+ {Client2, SID} ->
+ ct:fail(session_reused_when_session_expired);
+ {Client2, _} ->
+ ok
+ end,
+ process_flag(trap_exit, false),
+ ssl_test_lib:close(Server0),
+ ssl_test_lib:close(Client0),
+ ssl_test_lib:close(Client1),
+ ssl_test_lib:close(Client2).
+
+make_sure_expired(Host, Port, Id) ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ ClientCache = element(2, State),
+
+ case ssl_session_cache:lookup(ClientCache, {{Host, Port}, Id}) of
+ undefined ->
+ ok;
+ #session{is_resumable = false} ->
+ ok;
+ _ ->
+ ct:sleep(?SLEEP),
+ make_sure_expired(Host, Port, Id)
+ end.
+
+%%--------------------------------------------------------------------
+server_does_not_want_to_reuse_session() ->
+ [{doc,"Test reuse of sessions (short handshake)"}].
+server_does_not_want_to_reuse_session(Config) when is_list(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},
+ {from, self()},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {options, [{reuse_session, fun(_,_,_,_) ->
+ false
+ end} |
+ 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} ->
+ ct:fail(session_reused_when_server_does_not_want_to);
+ {Client1, _Other} ->
+ ok
+ end,
+ ssl_test_lib:close(Client0),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client1).
+
+no_reuses_session_server_restart_new_cert() ->
+ [{doc,"Check that a session is not reused if the server is restarted with a new cert."}].
+no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
+
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ DsaServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_opts, Config),
+ DsaClientOpts = ssl_test_lib:ssl_options(client_dsa_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,
+
+ %% Make sure session is registered
+ ct:sleep(?SLEEP),
+ Monitor = erlang:monitor(process, Server),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client0),
+ receive
+ {'DOWN', Monitor, _, _, _} ->
+ ok
+ end,
+
+ Server1 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, [{reuseaddr, true} | DsaServerOpts]}]),
+
+ Client1 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {from, self()}, {options, DsaClientOpts}]),
+ receive
+ {Client1, SessionInfo} ->
+ ct:fail(session_reused_when_server_has_new_cert);
+ {Client1, _Other} ->
+ ok
+ end,
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1).
+
+%%--------------------------------------------------------------------
+no_reuses_session_server_restart_new_cert_file() ->
+ [{doc,"Check that a session is not reused if a server is restarted with a new "
+ "cert contained in a file with the same name as the old cert."}].
+
+no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ DsaServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_opts, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+
+ NewServerOpts0 = ssl_test_lib:new_config(PrivDir, ServerOpts),
+ {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, NewServerOpts0}]),
+ 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,
+
+ %% Make sure session is registered and we get
+ %% new file time stamp when calling new_config!
+ ct:sleep(?SLEEP* 2),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client0),
+
+ ssl:clear_pem_cache(),
+
+ NewServerOpts1 = ssl_test_lib:new_config(PrivDir, DsaServerOpts),
+
+ Server1 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, [{reuseaddr, true} | NewServerOpts1]}]),
+ 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} ->
+ ct:fail(session_reused_when_server_has_new_cert);
+ {Client1, _Other} ->
+ ok
+ end,
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1).
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_sni_SUITE.erl b/lib/ssl/test/ssl_sni_SUITE.erl
index 7629d75100..e68ea2c99d 100644
--- a/lib/ssl/test/ssl_sni_SUITE.erl
+++ b/lib/ssl/test/ssl_sni_SUITE.erl
@@ -36,7 +36,6 @@ all() ->
[{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
- {group, 'sslv3'},
{group, 'dtlsv1.2'},
{group, 'dtlsv1'}
].
@@ -46,7 +45,6 @@ groups() ->
{'tlsv1.2', [], sni_tests()},
{'tlsv1.1', [], sni_tests()},
{'tlsv1', [], sni_tests()},
- {'sslv3', [], sni_tests()},
{'dtlsv1.2', [], sni_tests()},
{'dtlsv1', [], sni_tests()}
].
@@ -61,7 +59,8 @@ sni_tests() ->
dns_name,
ip_fallback,
no_ip_fallback,
- dns_name_reuse].
+ dns_name_reuse,
+ customize_hostname_check].
init_per_suite(Config0) ->
catch crypto:stop(),
@@ -88,12 +87,10 @@ end_per_suite(_) ->
ssl:stop(),
application:stop(crypto).
-init_per_testcase(TestCase, Config) when TestCase == ip_fallback;
- TestCase == no_ip_fallback;
- TestCase == dns_name_reuse ->
+init_per_testcase(customize_hostname_check, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
- ct:timetrap({seconds, 20}),
+ ssl_test_lib:clean_start(),
+ ct:timetrap({seconds, 5}),
Config;
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
@@ -236,7 +233,60 @@ dns_name_reuse(Config) ->
{mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, [{verify, verify_peer} | ClientConf]}]),
- ssl_test_lib:check_client_alert(Client1, handshake_failure).
+ ssl_test_lib:check_client_alert(Client1, handshake_failure),
+ ssl_test_lib:close(Client0).
+
+
+customize_hostname_check() ->
+ [{doc,"Test option customize_hostname_check."}].
+customize_hostname_check(Config) when is_list(Config) ->
+ Ext = [#'Extension'{extnID = ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, "*.example.org"}],
+ critical = false}
+ ],
+ #{server_config := ServerOpts0,
+ client_config := ClientOpts0} = ssl_test_lib:make_cert_chains_pem(rsa, [{server_chain,
+ [[],
+ [],
+ [{extensions, Ext}]
+ ]}],
+ Config, "https_hostname_convention"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ CustomFun = public_key:pkix_verify_hostname_match_fun(https),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options,
+ [{verify, verify_peer},
+ {server_name_indication, "other.example.org"},
+ {customize_hostname_check,
+ [{match_fun, CustomFun}]} | ClientOpts]
+ }]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+
+ Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, [{verify, verify_peer},
+ {server_name_indication, "other.example.org"} | ClientOpts]}
+ ]),
+ ssl_test_lib:check_client_alert(Server, Client1, handshake_failure).
%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
diff --git a/lib/ssl/test/ssl_socket_SUITE.erl b/lib/ssl/test/ssl_socket_SUITE.erl
new file mode 100644
index 0000000000..d648f2f9e1
--- /dev/null
+++ b/lib/ssl/test/ssl_socket_SUITE.erl
@@ -0,0 +1,437 @@
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_socket_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-define(SLEEP, 500).
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, tls},
+ {group, dtls}
+ ].
+
+groups() ->
+ [
+ {tls,[], socket_tests() ++ raw_inet_opt()},
+ {dtls,[], socket_tests()}
+ ].
+
+socket_tests() ->
+ [
+ getstat,
+ socket_options,
+ invalid_inet_get_option,
+ invalid_inet_get_option_not_list,
+ invalid_inet_get_option_improper_list,
+ invalid_inet_set_option,
+ invalid_inet_set_option_not_list,
+ invalid_inet_set_option_improper_list
+ ].
+
+raw_inet_opt() ->
+ [
+ raw_inet_option
+ ].
+
+
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+
+init_per_group(dtls, Config) ->
+ [{protocol_opts, [{protocol, dtls}]} | proplists:delete(protocol_opts, Config)];
+init_per_group(tls, Config) ->
+ [{protocol_opts, [{protocol, tls}]} | proplists:delete(protocol_opts, Config)];
+init_per_group(_GroupName, Config) ->
+ [{client_type, erlang},
+ {server_type, erlang} | Config].
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_testcase(raw_inet_option, Config) ->
+ ct:timetrap({seconds, 5}),
+ case os:type() of
+ {unix,linux} ->
+ Config;
+ _ ->
+ {skip, "Raw options are platform-specific"}
+ end;
+init_per_testcase(_TestCase, Config) ->
+ ct:timetrap({seconds, 5}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+getstat() ->
+ [{doc,"Test API function getstat/2"}].
+
+getstat(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_rsa_opts, Config),
+ ServerOpts = ?config(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server1 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port1 = ssl_test_lib:inet_port(Server1),
+ Server2 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port2 = ssl_test_lib:inet_port(Server2),
+ {ok, ActiveC} = rpc:call(ClientNode, ssl, connect,
+ [Hostname,Port1,[{active, once}|ClientOpts]]),
+ {ok, PassiveC} = rpc:call(ClientNode, ssl, connect,
+ [Hostname,Port2,[{active, false}|ClientOpts]]),
+
+ ct:log("Testcase ~p, Client ~p Servers ~p, ~p ~n",
+ [self(), self(), Server1, Server2]),
+
+ %% We only check that the values are non-zero initially
+ %% (due to the handshake), and that sending more changes the values.
+
+ %% Passive socket.
+
+ {ok, InitialStats} = ssl:getstat(PassiveC),
+ ct:pal("InitialStats ~p~n", [InitialStats]),
+ [true] = lists:usort([0 =/= proplists:get_value(Name, InitialStats)
+ || Name <- [recv_cnt, recv_oct, recv_avg, recv_max, send_cnt, send_oct, send_avg, send_max]]),
+
+ ok = ssl:send(PassiveC, "Hello world"),
+ wait_for_send(PassiveC),
+ {ok, SStats} = ssl:getstat(PassiveC, [send_cnt, send_oct]),
+ ct:pal("SStats ~p~n", [SStats]),
+ [true] = lists:usort([proplists:get_value(Name, SStats) =/= proplists:get_value(Name, InitialStats)
+ || Name <- [send_cnt, send_oct]]),
+
+ %% Active socket.
+
+ {ok, InitialAStats} = ssl:getstat(ActiveC),
+ ct:pal("InitialAStats ~p~n", [InitialAStats]),
+ [true] = lists:usort([0 =/= proplists:get_value(Name, InitialAStats)
+ || Name <- [recv_cnt, recv_oct, recv_avg, recv_max, send_cnt, send_oct, send_avg, send_max]]),
+
+ _ = receive
+ {ssl, ActiveC, _} ->
+ ok
+ after
+ ?SLEEP ->
+ exit(timeout)
+ end,
+
+ ok = ssl:send(ActiveC, "Hello world"),
+ wait_for_send(ActiveC),
+ {ok, ASStats} = ssl:getstat(ActiveC, [send_cnt, send_oct]),
+ ct:pal("ASStats ~p~n", [ASStats]),
+ [true] = lists:usort([proplists:get_value(Name, ASStats) =/= proplists:get_value(Name, InitialAStats)
+ || Name <- [send_cnt, send_oct]]),
+
+ ok.
+%%--------------------------------------------------------------------
+socket_options() ->
+ [{doc,"Test API function getopts/2 and setopts/2"}].
+
+socket_options(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Values = [{mode, list}, {active, true}],
+ %% Shall be the reverse order of Values!
+ Options = [active, mode],
+
+ NewValues = [{mode, binary}, {active, once}],
+ %% Shall be the reverse order of NewValues!
+ NewOptions = [active, mode],
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, socket_options_result,
+ [Options, Values, NewOptions, NewValues]}},
+ {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, socket_options_result,
+ [Options, Values, NewOptions, NewValues]}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+
+ {ok, Listen} = ssl:listen(0, ServerOpts),
+ {ok,[{mode,list}]} = ssl:getopts(Listen, [mode]),
+ ok = ssl:setopts(Listen, [{mode, binary}]),
+ {ok,[{mode, binary}]} = ssl:getopts(Listen, [mode]),
+ {ok,[{recbuf, _}]} = ssl:getopts(Listen, [recbuf]),
+ ssl:close(Listen).
+
+%%--------------------------------------------------------------------
+raw_inet_option() ->
+ [{doc,"Ensure that a single 'raw' option is passed to ssl:listen correctly."}].
+
+raw_inet_option(Config) when is_list(Config) ->
+ % 'raw' option values are platform-specific; these are the Linux values:
+ IpProtoTcp = 6,
+ % Use TCP_KEEPIDLE, because (e.g.) TCP_MAXSEG can't be read back reliably.
+ TcpKeepIdle = 4,
+ KeepAliveTimeSecs = 55,
+ LOptions = [{raw, IpProtoTcp, TcpKeepIdle, <<KeepAliveTimeSecs:32/native>>}],
+ {ok, LSocket} = ssl:listen(0, LOptions),
+ % Per http://www.erlang.org/doc/man/inet.html#getopts-2, we have to specify
+ % exactly which raw option we want, and the size of the buffer.
+ {ok, [{raw, IpProtoTcp, TcpKeepIdle, <<KeepAliveTimeSecs:32/native>>}]} =
+ ssl:getopts(LSocket, [{raw, IpProtoTcp, TcpKeepIdle, 4}]).
+
+%%--------------------------------------------------------------------
+
+invalid_inet_get_option() ->
+ [{doc,"Test handling of invalid inet options in getopts"}].
+
+invalid_inet_get_option(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option, []}},
+ {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}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option_not_list() ->
+ [{doc,"Test handling of invalid type in getopts"}].
+
+invalid_inet_get_option_not_list(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option_not_list, []}},
+ {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}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option_improper_list() ->
+ [{doc,"Test handling of invalid type in getopts"}].
+
+invalid_inet_get_option_improper_list(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option_improper_list, []}},
+ {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}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+invalid_inet_set_option() ->
+ [{doc,"Test handling of invalid inet options in setopts"}].
+
+invalid_inet_set_option(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option, []}},
+ {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}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+invalid_inet_set_option_not_list() ->
+ [{doc,"Test handling of invalid type in setopts"}].
+
+invalid_inet_set_option_not_list(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option_not_list, []}},
+ {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}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+invalid_inet_set_option_improper_list() ->
+ [{doc,"Test handling of invalid tye in setopts"}].
+
+invalid_inet_set_option_improper_list(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option_improper_list, []}},
+ {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}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
+ %% Test get/set emulated opts
+ {ok, DefaultValues} = ssl:getopts(Socket, Options),
+ ssl:setopts(Socket, NewValues),
+ {ok, NewValues} = ssl:getopts(Socket, NewOptions),
+ %% Test get/set inet opts
+ {ok,[{reuseaddr, _}]} = ssl:getopts(Socket, [reuseaddr]),
+ {ok, All} = ssl:getopts(Socket, []),
+ ct:log("All opts ~p~n", [All]),
+ ok.
+
+get_invalid_inet_option(Socket) ->
+ {error, {options, {socket_options, foo, _}}} = ssl:getopts(Socket, [foo]),
+ ok.
+
+get_invalid_inet_option_not_list(Socket) ->
+ {error, {options, {socket_options, some_invalid_atom_here}}}
+ = ssl:getopts(Socket, some_invalid_atom_here),
+ ok.
+
+get_invalid_inet_option_improper_list(Socket) ->
+ {error, {options, {socket_options, foo,_}}} = ssl:getopts(Socket, [packet | foo]),
+ ok.
+
+set_invalid_inet_option(Socket) ->
+ {error, {options, {socket_options, {packet, foo}}}} = ssl:setopts(Socket, [{packet, foo}]),
+ {error, {options, {socket_options, {header, foo}}}} = ssl:setopts(Socket, [{header, foo}]),
+ {error, {options, {socket_options, {active, foo}}}} = ssl:setopts(Socket, [{active, foo}]),
+ {error, {options, {socket_options, {mode, foo}}}} = ssl:setopts(Socket, [{mode, foo}]),
+ ok.
+
+set_invalid_inet_option_not_list(Socket) ->
+ {error, {options, {not_a_proplist, some_invalid_atom_here}}}
+ = ssl:setopts(Socket, some_invalid_atom_here),
+ ok.
+
+set_invalid_inet_option_improper_list(Socket) ->
+ {error, {options, {not_a_proplist, [{packet, 0} | {foo, 2}]}}} =
+ ssl:setopts(Socket, [{packet, 0} | {foo, 2}]),
+ ok.
+
+wait_for_send(Socket) ->
+ %% Make sure TLS process processed send message event
+ _ = ssl:connection_information(Socket).
+
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index c791f438d0..5dd5fc45af 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -218,6 +218,55 @@ start_server_transport_control(Args) ->
Result
end.
+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_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),
+
+ 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 = case OpensslServerOpts of
+ [] ->
+ ["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,
+
+ 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,
+ active_recv, [length(Data)]}},
+ {options, ClientOpts}]),
+
+ Callback(Client, OpensslPort),
+
+ %% 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).
+
transport_accept_abuse(Opts) ->
Port = proplists:get_value(port, Opts),
@@ -233,6 +282,34 @@ transport_accept_abuse(Opts) ->
_ = ssl:handshake(AcceptSocket, infinity),
Pid ! {self(), ok}.
+start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenSSLClientOpts, Data, Callback) ->
+ process_flag(trap_exit, true),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ServerOpts = ErlangServerOpts ++ ServerOpts0,
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, active_recv, [length(Data)]}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+
+ Exe = "openssl",
+ Args = ["s_client"] ++ OpenSSLClientOpts ++ ["-msg", "-connect",
+ hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version)],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ Callback(Server, OpenSslPort),
+
+ ssl_test_lib:close(Server),
+
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
transport_switch_control(Opts) ->
Port = proplists:get_value(port, Opts),
@@ -571,8 +648,7 @@ cert_options(Config) ->
"badcert.pem"]),
BadKeyFile = filename:join([proplists:get_value(priv_dir, Config),
"badkey.pem"]),
- PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
-
+
[{client_opts, [{cacertfile, ClientCaCertFile},
{certfile, ClientCertFile},
{keyfile, ClientKeyFile}]},
@@ -586,30 +662,6 @@ cert_options(Config) ->
{ssl_imp, new}]},
{server_opts, [{ssl_imp, new},{reuseaddr, true}, {cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {client_psk, [{ssl_imp, new},
- {psk_identity, "Test-User"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
- {server_psk, [{ssl_imp, new},{reuseaddr, true},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
- {server_psk_hint, [{ssl_imp, new},{reuseaddr, true},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {psk_identity, "HINT"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
- {server_psk_anon, [{ssl_imp, new},{reuseaddr, true},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
- {server_psk_anon_hint, [{ssl_imp, new},{reuseaddr, true},
- {psk_identity, "HINT"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
- {client_srp, [{ssl_imp, new},
- {srp_identity, {"Test-User", "secret"}}]},
- {server_srp, [{ssl_imp, new},{reuseaddr, true},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {user_lookup_fun, {fun user_lookup/3, undefined}},
- {ciphers, srp_suites()}]},
- {server_srp_anon, [{ssl_imp, new},{reuseaddr, true},
- {user_lookup_fun, {fun user_lookup/3, undefined}},
- {ciphers, srp_anon_suites()}]},
{server_verification_opts, [{ssl_imp, new},{reuseaddr, true},
{cacertfile, ClientCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
@@ -650,15 +702,32 @@ make_dsa_cert(Config) ->
[{server_dsa_opts, ServerConf},
{server_dsa_verify_opts, [{verify, verify_peer} | ServerConf]},
- {client_dsa_opts, ClientConf},
- {server_srp_dsa, [{user_lookup_fun, {fun user_lookup/3, undefined}},
- {ciphers, srp_dss_suites()} | ServerConf]},
- {client_srp_dsa, [{srp_identity, {"Test-User", "secret"}}
- | ClientConf]}
+ {client_dsa_opts, ClientConf}
| Config];
false ->
Config
end.
+
+
+make_cert_chains_der(Alg, UserConf) ->
+ 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(Alg, Alg, ClientChain, ServerChain),
+ public_key:pkix_test_data(CertChainConf).
+
+make_cert_chains_pem(Alg, UserConf, Config, Suffix) ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(Alg, Alg, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(Alg) ++ Suffix]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(Alg) ++ Suffix]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ Conf = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ CConf = proplists:get_value(client_config, Conf),
+ SConf = proplists:get_value(server_config, Conf),
+ #{server_config => SConf,
+ client_config => CConf}.
+
make_rsa_cert_chains(UserConf, Config, Suffix) ->
ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
@@ -1156,6 +1225,52 @@ basic_test(COpts, SOpts, Config) ->
gen_check_result(Server, SType, Client, CType),
stop(Server, Client).
+basic_alert(ClientOpts, ServerOpts, Config, Alert) ->
+ SType = proplists:get_value(server_type, Config),
+ CType = proplists:get_value(client_type, Config),
+ run_basic_alert(SType, CType, ClientOpts, ServerOpts, Config, Alert).
+
+run_basic_alert(erlang, erlang, ClientOpts, ServerOpts, Config, Alert) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ServerOpts}]),
+
+ Port = inet_port(Server),
+
+ Client = start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ check_server_alert(Server, Client, Alert);
+run_basic_alert(openssl = SType, erlang, ClientOpts, ServerOpts, Config, Alert) ->
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ {_Server, Port} = start_server(SType, ClientOpts, ServerOpts, Config),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+ Client = start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ check_client_alert(Client, Alert);
+run_basic_alert(erlang, openssl = CType, ClientOpts, ServerOpts, Config, Alert) ->
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = start_server_error([{node, ServerNode}, {port, 0},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ServerOpts}]),
+ Port = inet_port(Server),
+ start_client(CType, Port, ClientOpts, Config),
+
+ check_server_alert(Server, Alert).
+
+
ecc_test(Expect, COpts, SOpts, CECCOpts, SECCOpts, Config) ->
{Server, Port} = start_server_ecc(erlang, SOpts, Expect, SECCOpts, Config),
Client = start_client_ecc(erlang, Port, COpts, Expect, CECCOpts, Config),
@@ -1197,15 +1312,22 @@ start_basic_client(openssl, Version, Port, ClientOpts) ->
OpenSslPort.
start_client(openssl, Port, ClientOpts, Config) ->
- Cert = proplists:get_value(certfile, ClientOpts),
- Key = proplists:get_value(keyfile, ClientOpts),
- CA = proplists:get_value(cacertfile, ClientOpts),
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- 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"],
+ Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
+ Groups0 = proplists:get_value(groups, ClientOpts),
+ CertArgs = openssl_cert_options(ClientOpts, client),
+ Exe = "openssl",
+ Args0 = case Groups0 of
+ undefined ->
+ ["s_client", "-verify", "2", "-port", integer_to_list(Port), cipher_flag(Version),
+ ciphers(Ciphers, Version),
+ ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"];
+ Group ->
+ ["s_client", "-verify", "2", "-port", integer_to_list(Port), cipher_flag(Version),
+ ciphers(Ciphers, Version), "-groups", Group,
+ ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"]
+ end,
Args = maybe_force_ipv4(Args0),
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
@@ -1257,24 +1379,54 @@ start_server(openssl, ClientOpts, ServerOpts, Config) ->
Port = inet_port(node()),
Version = protocol_version(Config),
Exe = "openssl",
- CertArgs = openssl_cert_options(ServerOpts),
- [Cipher|_] = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
- Args = ["s_server", "-accept", integer_to_list(Port), "-cipher",
- ssl_cipher_format:suite_map_to_openssl_str(Cipher),
- ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"],
+ CertArgs = openssl_cert_options(ServerOpts, server),
+ Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
+ Groups0 = proplists:get_value(groups, ServerOpts),
+ Args = case Groups0 of
+ undefined ->
+ ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version),
+ ciphers(Ciphers, Version),
+ ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"];
+ Group ->
+ ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version),
+ ciphers(Ciphers, Version), "-groups", Group,
+ ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"]
+ end,
OpenSslPort = portable_open_port(Exe, Args),
true = port_command(OpenSslPort, "Hello world"),
{OpenSslPort, Port};
start_server(erlang, _, ServerOpts, Config) ->
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
KeyEx = proplists:get_value(check_keyex, Config, false),
+ Versions = protocol_versions(Config),
Server = start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib,
check_key_exchange_send_active,
[KeyEx]}},
- {options, [{verify, verify_peer} | ServerOpts]}]),
+ {options, [{verify, verify_peer}, {versions, Versions} | ServerOpts]}]),
{Server, inet_port(Server)}.
+
+cipher_flag('tlsv1.3') ->
+ "-ciphersuites";
+cipher_flag(_) ->
+ "-cipher".
+
+ciphers(Ciphers, Version) ->
+ Strs = [ssl_cipher_format:suite_map_to_openssl_str(Cipher) || Cipher <- Ciphers],
+ ciphers_concat(Version, Strs, "").
+
+ciphers_concat(_, [], [":" | Acc]) ->
+ lists:append(lists:reverse(Acc));
+ciphers_concat('tlsv1.3' = Version, [Head| Tail], Acc) ->
+ case Head of
+ "TLS" ++ _ ->
+ ciphers_concat(Version, Tail, [":", Head | Acc]);
+ _ ->
+ ciphers_concat(Version, Tail, Acc)
+ end;
+ciphers_concat(Version, [Head| Tail], Acc) ->
+ ciphers_concat(Version, Tail, [":", Head | Acc]).
start_server_with_raw_key(erlang, ServerOpts, Config) ->
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
@@ -1329,23 +1481,31 @@ stop(Client, Server) ->
close(Client).
-openssl_cert_options(ServerOpts) ->
- Cert = proplists:get_value(certfile, ServerOpts, undefined),
- Key = proplists:get_value(keyfile, ServerOpts, undefined),
- CA = proplists:get_value(cacertfile, ServerOpts, undefined),
+openssl_cert_options(Opts, Role) ->
+ Cert = proplists:get_value(certfile, Opts, undefined),
+ Key = proplists:get_value(keyfile, Opts, undefined),
+ CA = proplists:get_value(cacertfile, Opts, undefined),
case CA of
undefined ->
case cert_option("-cert", Cert) ++ cert_option("-key", Key) of
- [] ->
+ [] when Role == server ->
["-nocert"];
Other ->
Other
end;
_ ->
cert_option("-cert", Cert) ++ cert_option("-CAfile", CA) ++
- cert_option("-key", Key) ++ ["-verify", "2"]
+ cert_option("-key", Key) ++ openssl_verify(Opts) ++ ["2"]
end.
+openssl_verify(Opts) ->
+ case proplists:get_value(fail_if_no_peer_cert, Opts, undefined) of
+ true ->
+ ["-Verify"];
+ _ ->
+ ["-verify"]
+ end.
+
cert_option(_, undefined) ->
[];
cert_option(Opt, Value) ->
@@ -2005,12 +2165,68 @@ check_sane_openssl_version(Version) ->
false;
{'tlsv1.1', "OpenSSL 0" ++ _} ->
false;
+ {'tlsv1', "OpenSSL 0" ++ _} ->
+ false;
{_, _} ->
true
end;
false ->
false
end.
+check_sane_openssl_renegotaite(Config, Version) when Version == 'tlsv1.1';
+ Version == 'tlsv1.2' ->
+ case os:cmd("openssl version") of
+ "OpenSSL 1.0.1c" ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
+ "OpenSSL 1.0.1b" ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
+ "OpenSSL 1.0.1a" ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
+ "OpenSSL 1.0.1 " ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
+ _ ->
+ check_sane_openssl_renegotaite(Config)
+ end;
+check_sane_openssl_renegotaite(Config, 'sslv3') ->
+ case os:cmd("openssl version") of
+ "OpenSSL 1" ++ _ ->
+ {skip, "Known renegotiation bug with sslv3 in OpenSSL"};
+ _ ->
+ check_sane_openssl_renegotaite(Config)
+ end;
+check_sane_openssl_renegotaite(Config, _) ->
+ check_sane_openssl_renegotaite(Config).
+
+check_sane_openssl_renegotaite(Config) ->
+ case os:cmd("openssl version") of
+ "OpenSSL 1.0.0" ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
+ "OpenSSL 0.9.8" ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
+ "OpenSSL 0.9.7" ++ _ ->
+ {skip, "Known renegotiation bug in OpenSSL"};
+ _ ->
+ Config
+ end.
+
+workaround_openssl_s_clinent() ->
+ %% http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=683159
+ %% https://bugs.archlinux.org/task/33919
+ %% Bug seems to manifests it self if TLS version is not
+ %% explicitly specified
+ case os:cmd("openssl version") of
+ "OpenSSL 1.0.1c" ++ _ ->
+ ["-no_tls1_2"];
+ "OpenSSL 1.0.1d" ++ _ ->
+ ["-no_tls1_2"];
+ "OpenSSL 1.0.1e" ++ _ ->
+ ["-no_tls1_2"];
+ "OpenSSL 1.0.1f" ++ _ ->
+ ["-no_tls1_2"];
+ _ ->
+ []
+ end.
+
enough_openssl_crl_support("OpenSSL 0." ++ _) -> false;
enough_openssl_crl_support(_) -> true.
@@ -2060,8 +2276,8 @@ filter_suites(Ciphers0, AtomVersion) ->
++ ssl_cipher:anonymous_suites(Version)
++ ssl_cipher:psk_suites(Version)
++ ssl_cipher:psk_suites_anon(Version)
- ++ ssl_cipher:srp_suites()
- ++ ssl_cipher:srp_suites_anon()
+ ++ ssl_cipher:srp_suites(Version)
+ ++ ssl_cipher:srp_suites_anon(Version)
++ ssl_cipher:rc4_suites(Version),
Supported1 = ssl_cipher:filter_suites(Supported0),
Supported2 = [ssl_cipher_format:suite_bin_to_map(S) || S <- Supported1],
@@ -2178,6 +2394,14 @@ protocol_version(Config, atom) ->
tls_record:protocol_version(protocol_version(Config, tuple))
end.
+protocol_versions(Config) ->
+ Version = protocol_version(Config),
+ case Version of
+ 'tlsv1.3' -> %% TLS-1.3 servers shall also support 1.2
+ ['tlsv1.3', 'tlsv1.2'];
+ _ ->
+ [Version]
+ end.
protocol_options(Config, Options) ->
Protocol = proplists:get_value(protocol, Config, tls),
{Protocol, Opts} = lists:keyfind(Protocol, 1, Options),
@@ -2504,3 +2728,70 @@ kill_openssl() ->
{win32, _} ->
os:cmd("cmd.exe /C \"taskkill /IM openssl.exe /F\"")
end.
+
+hostname_format(Hostname) ->
+ case lists:member($., Hostname) of
+ true ->
+ Hostname;
+ false ->
+ "localhost"
+ end.
+
+erlang_ssl_receive_and_assert_negotiated_protocol(Socket, Protocol, Data) ->
+ case ssl:negotiated_protocol(Socket) of
+ {ok, Protocol} ->
+ active_recv(Socket, length(Data));
+ Result ->
+ {error, {{expected, Protocol}, {got, Result}}}
+ end.
+
+check_openssl_npn_support(Config) ->
+ HelpText = os:cmd("openssl s_client --help"),
+ case string:str(HelpText, "nextprotoneg") of
+ 0 ->
+ {skip, "Openssl not compiled with nextprotoneg support"};
+ _ ->
+ Config
+ end.
+
+new_config(PrivDir, ServerOpts0) ->
+ CaCertFile = proplists:get_value(cacertfile, ServerOpts0),
+ CertFile = proplists:get_value(certfile, ServerOpts0),
+ KeyFile = proplists:get_value(keyfile, ServerOpts0),
+ NewCaCertFile = filename:join(PrivDir, "new_ca.pem"),
+ NewCertFile = filename:join(PrivDir, "new_cert.pem"),
+ NewKeyFile = filename:join(PrivDir, "new_key.pem"),
+ file:copy(CaCertFile, NewCaCertFile),
+ file:copy(CertFile, NewCertFile),
+ file:copy(KeyFile, NewKeyFile),
+ ServerOpts1 = proplists:delete(cacertfile, ServerOpts0),
+ ServerOpts2 = proplists:delete(certfile, ServerOpts1),
+ ServerOpts = proplists:delete(keyfile, ServerOpts2),
+
+ {ok, PEM} = file:read_file(NewCaCertFile),
+ ct:log("CA file content: ~p~n", [public_key:pem_decode(PEM)]),
+
+ [{cacertfile, NewCaCertFile}, {certfile, NewCertFile},
+ {keyfile, NewKeyFile} | ServerOpts].
+
+sane_openssl_alpn_npn_renegotiate() ->
+ case os:cmd("openssl version") of
+ "LibreSSL 2.9.1" ++ _ ->
+ false;
+ "LibreSSL 2.6.4" ++ _ ->
+ false;
+ "OpenSSL 1.1.1a-freebsd" ++ _ ->
+ false;
+ _ ->
+ true
+ end.
+
+openssl_sane_dtls_alpn() ->
+ case os:cmd("openssl version") of
+ "OpenSSL 1.1.0g" ++ _ ->
+ false;
+ "OpenSSL 1.1.1a" ++ _ ->
+ false;
+ _->
+ openssl_sane_dtls()
+ end.
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
deleted file mode 100644
index 31d9af5298..0000000000
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ /dev/null
@@ -1,2021 +0,0 @@
-%%
-%% %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%
-%%
-%%
-
--module(ssl_to_openssl_SUITE).
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(SLEEP, 1000).
--define(OPENSSL_RENEGOTIATE, "R\n").
--define(OPENSSL_QUIT, "Q\n").
--define(OPENSSL_GARBAGE, "P\n").
--define(EXPIRE, 10).
-
-%%--------------------------------------------------------------------
-%% Common Test interface functions -----------------------------------
-%%--------------------------------------------------------------------
-
-all() ->
- case ssl_test_lib:openssl_sane_dtls() of
- true ->
- [{group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'sslv3'},
- {group, 'dtlsv1.2'},
- {group, 'dtlsv1'}];
- false ->
- [{group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'sslv3'}]
- end.
-
-groups() ->
- case ssl_test_lib:openssl_sane_dtls() of
- true ->
- [{'tlsv1.2', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'tlsv1.1', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'tlsv1', [], all_versions_tests()++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'sslv3', [], all_versions_tests()},
- {'dtlsv1.2', [], dtls_all_versions_tests()},
- {'dtlsv1', [], dtls_all_versions_tests()}
- ];
- false ->
- [{'tlsv1.2', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'tlsv1.1', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'tlsv1', [], all_versions_tests()++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'sslv3', [], all_versions_tests()}
- ]
- end.
-
-all_versions_tests() ->
- [
- erlang_client_openssl_server,
- erlang_server_openssl_client,
- erlang_client_openssl_server_dsa_cert,
- erlang_server_openssl_client_dsa_cert,
- erlang_client_openssl_server_anon,
- erlang_server_openssl_client_anon,
- 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,
- erlang_client_openssl_server_client_cert,
- erlang_server_openssl_client_client_cert,
- ciphers_rsa_signed_certs,
- ciphers_dsa_signed_certs,
- erlang_client_bad_openssl_server,
- expired_session,
- ssl2_erlang_server_openssl_client
- ].
-
-dtls_all_versions_tests() ->
- case ssl_test_lib:openssl_sane_client_cert() of
- true ->
- [erlang_server_openssl_client_client_cert,
- erlang_client_openssl_server_no_server_ca_cert,
- erlang_client_openssl_server_client_cert
- | dtls_all_versions_tests_2()];
- false ->
- dtls_all_versions_tests_2()
- end.
-
-dtls_all_versions_tests_2() ->
- [erlang_client_openssl_server,
- erlang_server_openssl_client,
- erlang_client_openssl_server_dsa_cert,
- erlang_server_openssl_client_dsa_cert,
- erlang_client_openssl_server_anon,
- erlang_server_openssl_client_anon,
- erlang_server_openssl_client_anon_with_cert,
- erlang_server_openssl_client_reuse_session,
- erlang_client_openssl_server_renegotiate,
- erlang_client_openssl_server_nowrap_seqnum,
- erlang_server_openssl_client_nowrap_seqnum,
- ciphers_rsa_signed_certs,
- ciphers_dsa_signed_certs
- %%expired_session
- ].
-
-alpn_tests() ->
- [erlang_client_alpn_openssl_server_alpn,
- erlang_server_alpn_openssl_client_alpn,
- erlang_client_alpn_openssl_server,
- erlang_client_openssl_server_alpn,
- erlang_server_alpn_openssl_client,
- erlang_server_openssl_client_alpn,
- erlang_client_alpn_openssl_server_alpn_renegotiate,
- erlang_server_alpn_openssl_client_alpn_renegotiate,
- erlang_client_alpn_npn_openssl_server_alpn_npn,
- erlang_server_alpn_npn_openssl_client_alpn_npn].
-
-npn_tests() ->
- [erlang_client_openssl_server_npn,
- erlang_server_openssl_client_npn,
- erlang_server_openssl_client_npn_renegotiate,
- erlang_client_openssl_server_npn_renegotiate,
- erlang_server_openssl_client_npn_only_client,
- erlang_server_openssl_client_npn_only_server,
- erlang_client_openssl_server_npn_only_client,
- erlang_client_openssl_server_npn_only_server].
-
-sni_server_tests() ->
- [erlang_server_openssl_client_sni_match,
- erlang_server_openssl_client_sni_match_fun,
- erlang_server_openssl_client_sni_no_match,
- erlang_server_openssl_client_sni_no_match_fun,
- erlang_server_openssl_client_sni_no_header,
- erlang_server_openssl_client_sni_no_header_fun].
-
-
-init_per_suite(Config0) ->
- case os:find_executable("openssl") of
- false ->
- {skip, "Openssl not found"};
- _ ->
- ct:pal("Version: ~p", [os:cmd("openssl version")]),
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- Config =
- case ssl_test_lib:openssl_dsa_support() of
- true ->
- Config1 = ssl_test_lib:make_rsa_cert(Config0),
- ssl_test_lib:make_dsa_cert(Config1);
- false ->
- ssl_test_lib:make_rsa_cert(Config0)
- end,
- ssl_test_lib:cipher_restriction(Config)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end
- end.
-
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
-
-init_per_group(GroupName, Config) ->
- case ssl_test_lib:is_tls_version(GroupName) of
- true ->
- case ssl_test_lib:supports_ssl_tls_version(GroupName) of
- true ->
- case ssl_test_lib:check_sane_openssl_version(GroupName) of
- true ->
- ssl_test_lib:init_tls_version(GroupName, Config);
- false ->
- {skip, openssl_does_not_support_version}
- end;
- false ->
- {skip, openssl_does_not_support_version}
- end;
- _ ->
- ssl:start(),
- Config
- end.
-
-end_per_group(GroupName, Config) ->
- case ssl_test_lib:is_tls_version(GroupName) of
- true ->
- ssl_test_lib:clean_tls_version(Config);
- false ->
- Config
- end.
-
-init_per_testcase(expired_session, Config) ->
- ct:timetrap(?EXPIRE * 1000 * 5),
- ssl:stop(),
- application:load(ssl),
- application:set_env(ssl, session_lifetime, ?EXPIRE),
- ssl:start(),
- Config;
-
-init_per_testcase(TestCase, Config) when
- TestCase == ciphers_dsa_signed_certs;
- TestCase == erlang_client_openssl_server_dsa_cert;
- TestCase == erlang_server_openssl_client_dsa_cert;
- TestCase == erlang_client_openssl_server_dsa_cert;
- TestCase == erlang_server_openssl_client_dsa_cert ->
- case ssl_test_lib:openssl_dsa_support() andalso ssl_test_lib:is_sane_oppenssl_client() of
- true ->
- special_init(TestCase, Config);
- false ->
- {skip, "DSA not supported by OpenSSL"}
- end;
-init_per_testcase(TestCase, Config) ->
- ct:timetrap({seconds, 35}),
- special_init(TestCase, Config).
-
-special_init(TestCase, Config) when
- TestCase == ciphers_rsa_signed_certs;
- TestCase == ciphers_dsa_signed_certs->
- ct:timetrap({seconds, 90}),
- 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_renegotiate_after_client_data
- ->
- {ok, Version} = application:get_env(ssl, protocol_version),
- check_sane_openssl_renegotaite(Config, Version);
-
-special_init(ssl2_erlang_server_openssl_client, Config) ->
- case ssl_test_lib:supports_ssl_tls_version(sslv2) of
- true ->
- Config;
- false ->
- {skip, "sslv2 not supported by openssl"}
- end;
-
-special_init(TestCase, Config)
- when TestCase == erlang_client_alpn_openssl_server_alpn;
- TestCase == erlang_server_alpn_openssl_client_alpn;
- TestCase == erlang_client_alpn_openssl_server;
- TestCase == erlang_client_openssl_server_alpn;
- TestCase == erlang_server_alpn_openssl_client;
- TestCase == erlang_server_openssl_client_alpn ->
- check_openssl_alpn_support(Config);
-
-special_init(TestCase, Config)
- when TestCase == erlang_client_alpn_openssl_server_alpn_renegotiate;
- TestCase == erlang_server_alpn_openssl_client_alpn_renegotiate ->
- {ok, Version} = application:get_env(ssl, protocol_version),
- case check_sane_openssl_renegotaite(Config, Version) of
- {skip, _} = Skip ->
- Skip;
- _ ->
- check_openssl_alpn_support(Config)
- end;
-
-special_init(TestCase, Config)
- when TestCase == erlang_client_alpn_npn_openssl_server_alpn_npn;
- TestCase == erlang_server_alpn_npn_openssl_client_alpn_npn ->
- case check_openssl_alpn_support(Config) of
- {skip, _} = Skip ->
- Skip;
- _ ->
- check_openssl_npn_support(Config)
- end;
-
-special_init(TestCase, Config)
- when TestCase == erlang_client_openssl_server_npn;
- TestCase == erlang_server_openssl_client_npn;
- TestCase == erlang_server_openssl_client_npn_only_server;
- TestCase == erlang_server_openssl_client_npn_only_client;
- TestCase == erlang_client_openssl_server_npn_only_client;
- TestCase == erlang_client_openssl_server_npn_only_server ->
- check_openssl_npn_support(Config);
-
-special_init(TestCase, Config)
- when TestCase == erlang_server_openssl_client_npn_renegotiate;
- TestCase == erlang_client_openssl_server_npn_renegotiate ->
- {ok, Version} = application:get_env(ssl, protocol_version),
- case check_sane_openssl_renegotaite(Config, Version) of
- {skip, _} = Skip ->
- Skip;
- _ ->
- check_openssl_npn_support(Config)
- end;
-
-special_init(TestCase, Config0)
- when TestCase == erlang_server_openssl_client_sni_match;
- TestCase == erlang_server_openssl_client_sni_no_match;
- TestCase == erlang_server_openssl_client_sni_no_header;
- TestCase == erlang_server_openssl_client_sni_match_fun;
- TestCase == erlang_server_openssl_client_sni_no_match_fun;
- TestCase == erlang_server_openssl_client_sni_no_header_fun ->
- RsaOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config0),
- Config = [{sni_server_opts, [{sni_hosts,
- [{"a.server", [
- {certfile, proplists:get_value(certfile, RsaOpts)},
- {keyfile, proplists:get_value(keyfile, RsaOpts)}
- ]},
- {"b.server", [
- {certfile, proplists:get_value(certfile, RsaOpts)},
- {keyfile, proplists:get_value(keyfile, RsaOpts)}
- ]}
- ]}]} | Config0],
- check_openssl_sni_support(Config);
-special_init(TestCase, Config)
- when TestCase == erlang_server_openssl_client;
- TestCase == erlang_server_openssl_client_client_cert;
- TestCase == erlang_server_openssl_client_reuse_session ->
- case ssl_test_lib:is_sane_oppenssl_client() of
- true ->
- Config;
- false ->
- {skip, "Broken OpenSSL client"}
- end;
-special_init(_, Config) ->
- Config.
-
-end_per_testcase(reuse_session_expired, Config) ->
- application:unset_env(ssl, session_lifetime),
- Config;
-end_per_testcase(_, Config) ->
- Config.
-
-%%--------------------------------------------------------------------
-%% Test Cases --------------------------------------------------------
-%%--------------------------------------------------------------------
-
-erlang_client_openssl_server() ->
- [{doc,"Test erlang client with openssl server"}].
-erlang_client_openssl_server(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),
-
- {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],
-
- 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, 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).
-
-%%--------------------------------------------------------------------
-erlang_server_openssl_client() ->
- [{doc,"Test erlang server with openssl client"}].
-erlang_server_openssl_client(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
- {_, 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, 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)],
-
- 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).
-
-erlang_client_openssl_server_dsa_cert() ->
- [{doc,"Test erlang server with openssl client"}].
-erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ClientOpts = ssl_test_lib:ssl_options(client_dsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_opts, Config),
-
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- 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", "-accept", integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cert", CertFile, "-CAfile", CaCertFile,
- "-key", KeyFile, "-Verify", "2", "-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, 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.
-%%--------------------------------------------------------------------
-erlang_server_openssl_client_dsa_cert() ->
- [{doc,"Test erlang server with openssl client"}].
-erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ClientOpts = ssl_test_lib:ssl_options(client_dsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_opts, Config),
-
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
- CaCertFile = proplists:get_value(cacertfile, ClientOpts),
- CertFile = proplists:get_value(certfile, ClientOpts),
- KeyFile = proplists:get_value(keyfile, ClientOpts),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, 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),
- "-cert", CertFile,
- "-CAfile", CaCertFile,
- "-key", KeyFile, "-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).
-
- %%--------------------------------------------------------------------
-erlang_client_openssl_server_anon() ->
- [{doc,"Test erlang client with openssl server, anonymous"}].
-erlang_client_openssl_server_anon(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- %% OpenSSL expects a certificate and key, even if the cipher spec
- %% is restructed to aNULL, so we use 'server_rsa_opts' here
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_anon_opts, Config),
- VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
- Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
-
- 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)
- 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),
-
- 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)
- end.
-
-%%--------------------------------------------------------------------
-erlang_server_openssl_client_anon_with_cert() ->
- [{doc,"Test erlang server with openssl client, anonymous (with cert)"}].
-erlang_server_openssl_client_anon_with_cert(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
- Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
-
- 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)
- end.
-
- %%--------------------------------------------------------------------
-erlang_server_openssl_client_reuse_session() ->
- [{doc, "Test erlang server with openssl client that reconnects with the"
- "same session id, to test reusing of sessions."}].
-erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
- {_, 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]}},
- {reconnect_times, 5},
- {options, 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),
- "-reconnect"],
-
- 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),
- ok.
-
-%%--------------------------------------------------------------------
-
-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_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()),
- 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),
-
- 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,
- delayed_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.
-%%--------------------------------------------------------------------
-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.
-
-%%--------------------------------------------------------------------
-
-erlang_client_openssl_server_nowrap_seqnum() ->
- [{doc, "Test that erlang client will renegotiate session when",
- "max sequence number celing is about to be reached. Although"
- "in the testcase we use the test option renegotiate_at"
- " 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_verify_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
-
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- ErlData = "From erlang to openssl\n",
- 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),
-
- 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, {ssl_test_lib,
- trigger_renegotiate, [[ErlData, N+2]]}},
- {options, [{reuse_sessions, false},
- {renegotiate_at, N} | ClientOpts]}]),
-
- 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).
-%%--------------------------------------------------------------------
-erlang_server_openssl_client_nowrap_seqnum() ->
- [{doc, "Test that erlang client will renegotiate session when",
- "max sequence number celing is about to be reached. Although"
- "in the testcase we use the test option renegotiate_at"
- " 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_verify_opts, Config),
-
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- N = 10,
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- trigger_renegotiate, [[Data, N+2]]}},
- {options, [{renegotiate_at, N}, {reuse_sessions, false} | 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),
- "-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).
-
-%%--------------------------------------------------------------------
-
-erlang_client_openssl_server_no_server_ca_cert() ->
- [{doc, "Test erlang client when openssl server sends a cert chain not"
- "including the ca cert. Explicitly test this even if it is"
- "implicitly tested eleswhere."}].
-erlang_client_openssl_server_no_server_ca_cert(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),
-
- {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, "-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, 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).
-
-%%--------------------------------------------------------------------
-erlang_client_openssl_server_client_cert() ->
- [{doc,"Test erlang client with openssl server when client sends cert"}].
-erlang_client_openssl_server_client_cert(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),
-
- Data = "From openssl to erlang",
-
- 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),
- "-cert", CertFile, "-CAfile", CaCertFile,
- "-key", KeyFile, "-Verify", "2"],
-
- 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, 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).
-
-%%--------------------------------------------------------------------
-erlang_server_openssl_client_client_cert() ->
- [{doc,"Test erlang server with openssl client when client sends cert"}].
-erlang_server_openssl_client_client_cert(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),
-
- {_, 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,
- [{verify , verify_peer}
- | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- CaCertFile = proplists:get_value(cacertfile, ClientOpts),
- CertFile = proplists:get_value(certfile, ClientOpts),
- KeyFile = proplists:get_value(keyfile, ClientOpts),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_client", "-cert", CertFile,
- "-CAfile", CaCertFile,
- "-key", KeyFile,"-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version)],
- 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_port(OpenSslPort),
- ssl_test_lib:close(Server),
- process_flag(trap_exit, false).
-
-%%--------------------------------------------------------------------
-erlang_server_erlang_client_client_cert() ->
- [{doc,"Test erlang server with erlang client when client sends cert"}].
-erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
- ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
- Version = ssl_test_lib:protocol_version(Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From erlang to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive,
- %% Due to 1/n-1 splitting countermeasure Rizzo/Duong-Beast
- [Data]}},
- {options,
- [{verify , verify_peer}
- | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- %% Due to 1/n-1 splitting countermeasure Rizzo/Duong-Beast
- {mfa, {ssl, send, [Data]}},
- {options,
- [{versions, [Version]} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- process_flag(trap_exit, false).
-
-%%--------------------------------------------------------------------
-
-ciphers_rsa_signed_certs() ->
- [{doc,"Test cipher suites that uses rsa certs"}].
-ciphers_rsa_signed_certs(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:rsa_suites(openssl),
- run_suites(Ciphers, Version, Config, rsa).
-%%--------------------------------------------------------------------
-
-ciphers_dsa_signed_certs() ->
- [{doc,"Test cipher suites that uses dsa certs"}].
-ciphers_dsa_signed_certs(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Ciphers = ssl_test_lib:dsa_suites(NVersion),
- run_suites(Ciphers, Version, Config, dsa).
-
-%%--------------------------------------------------------------------
-erlang_client_bad_openssl_server() ->
- [{doc,"Test what happens if openssl server sends garbage to erlang ssl client"}].
-erlang_client_bad_openssl_server(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),
-
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- 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],
- OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
-
- Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, server_sent_garbage, []}},
- {options,
- [{versions, [Version]} | ClientOpts]}]),
-
- %% Send garbage
- true = port_command(OpensslPort, ?OPENSSL_GARBAGE),
-
- ct:sleep(?SLEEP),
-
- Client0 ! server_sent_garbage,
-
- ssl_test_lib:check_result(Client0, true),
-
- ssl_test_lib:close(Client0),
-
- %% Make sure openssl does not hang and leave zombie process
- Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options,
- [{versions, [Version]} | ClientOpts]}]),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close_port(OpensslPort),
- ssl_test_lib:close(Client1),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-
-expired_session() ->
- [{doc, "Test our ssl client handling of expired sessions. Will make"
- "better code coverage of the ssl_manager module"}].
-expired_session(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- Port = ssl_test_lib:inet_port(node()),
- CertFile = proplists:get_value(certfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port),
- "-cert", CertFile,"-key", KeyFile],
-
- OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ssl_test_lib:wait_for_openssl_server(Port, tls),
-
- Client0 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- ssl_test_lib:close(Client0),
-
- %% Make sure session is registered
- ct:sleep(?SLEEP),
-
- Client1 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- ssl_test_lib:close(Client1),
- %% Make sure session is unregistered due to expiration
- ct:sleep((?EXPIRE+1) * 1000),
-
- Client2 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close_port(OpensslPort),
- ssl_test_lib:close(Client2),
- process_flag(trap_exit, false).
-
-%%--------------------------------------------------------------------
-ssl2_erlang_server_openssl_client() ->
- [{doc,"Test that ssl v2 clients are rejected"}].
-
-ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Exe = "openssl",
- Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- "-ssl2", "-msg"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
- ssl_test_lib:consume_port_exit(OpenSslPort),
- ssl_test_lib:check_server_alert(Server, unexpected_message),
- process_flag(trap_exit, false).
-
-%%--------------------------------------------------------------------
-
-erlang_client_alpn_openssl_server_alpn(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------
-
-erlang_server_alpn_openssl_client_alpn(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------------
-
-erlang_client_alpn_openssl_server(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_with_opts(Config,
- [{alpn_advertised_protocols, [<<"spdy/2">>]}],
- [],
- Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------------
-
-erlang_client_openssl_server_alpn(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_with_opts(Config,
- [],
- ["-alpn", "spdy/2"],
- Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------------
-
-erlang_server_alpn_openssl_client(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_with_opts(Config,
- [{alpn_preferred_protocols, [<<"spdy/2">>]}],
- [],
- Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------------
-
-erlang_server_openssl_client_alpn(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_with_opts(Config,
- [],
- ["-alpn", "spdy/2"],
- Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------
-
-erlang_client_alpn_openssl_server_alpn_renegotiate(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
- ct:sleep(?SLEEP),
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------
-
-erlang_server_alpn_openssl_client_alpn_renegotiate(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
- ct:sleep(?SLEEP),
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------
-
-erlang_client_alpn_npn_openssl_server_alpn_npn(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------
-
-erlang_server_alpn_npn_openssl_client_alpn_npn(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------
-erlang_client_openssl_server_npn() ->
- [{doc,"Test erlang client with openssl server doing npn negotiation"}].
-
-erlang_client_openssl_server_npn(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------
-erlang_client_openssl_server_npn_renegotiate() ->
- [{doc,"Test erlang client with openssl server doing npn negotiation and renegotiate"}].
-
-erlang_client_openssl_server_npn_renegotiate(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, fun(Client, OpensslPort) ->
- true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
- ct:sleep(?SLEEP),
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Client, ok)
- end),
- ok.
-%%--------------------------------------------------------------------------
-erlang_server_openssl_client_npn() ->
- [{doc,"Test erlang server with openssl client and npn negotiation"}].
-
-erlang_server_openssl_client_npn(Config) when is_list(Config) ->
-
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------------
-erlang_server_openssl_client_npn_renegotiate() ->
- [{doc,"Test erlang server with openssl client and npn negotiation with renegotiation"}].
-
-erlang_server_openssl_client_npn_renegotiate(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, ?OPENSSL_RENEGOTIATE),
- ct:sleep(?SLEEP),
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-%%--------------------------------------------------------------------------
-erlang_client_openssl_server_npn_only_server(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_with_opts(Config, [],
- ["-nextprotoneg", "spdy/2"], Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------------
-
-erlang_client_openssl_server_npn_only_client(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_client_and_openssl_server_with_opts(Config,
- [{client_preferred_next_protocols,
- {client, [<<"spdy/2">>], <<"http/1.1">>}}], [],
- Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-%%--------------------------------------------------------------------------
-erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_with_opts(Config, [{next_protocols_advertised, [<<"spdy/2">>]}], [],
- Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-
-erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) ->
- Data = "From openssl to erlang",
- start_erlang_server_and_openssl_client_with_opts(Config, [], ["-nextprotoneg", "spdy/2"],
- Data, fun(Server, OpensslPort) ->
- true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Server, ok)
- end),
- ok.
-%--------------------------------------------------------------------------
-erlang_server_openssl_client_sni_no_header(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test(Config, undefined, undefined, "server Peer cert").
-
-erlang_server_openssl_client_sni_no_header_fun(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test_sni_fun(Config, undefined, undefined, "server Peer cert").
-
-erlang_server_openssl_client_sni_match(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test(Config, "a.server", "a.server", "server Peer cert").
-
-erlang_server_openssl_client_sni_match_fun(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test_sni_fun(Config, "a.server", "a.server", "server Peer cert").
-
-erlang_server_openssl_client_sni_no_match(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test(Config, "c.server", undefined, "server Peer cert").
-
-erlang_server_openssl_client_sni_no_match_fun(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test_sni_fun(Config, "c.server", undefined, "server Peer cert").
-
-
-%%--------------------------------------------------------------------
-%% Internal functions ------------------------------------------------
-%%--------------------------------------------------------------------
-run_suites(Ciphers, Version, Config, Type) ->
- {ClientOpts, ServerOpts} =
- case Type of
- rsa ->
- {ssl_test_lib:ssl_options(client_rsa_opts, Config),
- ssl_test_lib:ssl_options(server_rsa_opts, Config)};
- dsa ->
- {ssl_test_lib:ssl_options(client_dsa_opts, Config),
- ssl_test_lib:ssl_options(server_dsa_verify_opts, Config)}
- end,
-
- Result = lists:map(fun(Cipher) ->
- cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
- Ciphers),
- 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.
-
-client_read_check([], _Data) ->
- ok;
-client_read_check([Hd | T], Data) ->
- case binary:match(Data, list_to_binary(Hd)) of
- nomatch ->
- nomatch;
- _ ->
- client_read_check(T, Data)
- end.
-client_check_result(Port, DataExpected, DataReceived) ->
- receive
- {Port, {data, TheData}} ->
- Data = list_to_binary(TheData),
- NewData = <<DataReceived/binary, Data/binary>>,
- ct:log("New Data: ~p", [NewData]),
- case client_read_check(DataExpected, NewData) of
- ok ->
- ok;
- _ ->
- client_check_result(Port, DataExpected, NewData)
- end
- after 20000 ->
- ct:fail({"Time out on openSSL Client", {expected, DataExpected},
- {got, DataReceived}})
- end.
-client_check_result(Port, DataExpected) ->
- client_check_result(Port, DataExpected, <<"">>).
-
-send_and_hostname(SSLSocket) ->
- ssl:send(SSLSocket, "OK"),
- case ssl:connection_information(SSLSocket, [sni_hostname]) of
- {ok, []} ->
- undefined;
- {ok, [{sni_hostname, Hostname}]} ->
- Hostname
- end.
-
-erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
- Version = ssl_test_lib:protocol_version(Config),
- ct:log("Start running handshake, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
- ServerOptions = proplists:get_value(sni_server_opts, Config) ++ proplists:get_value(server_rsa_opts, Config),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()}, {mfa, {?MODULE, send_and_hostname, []}},
- {options, ServerOptions}]),
- Port = ssl_test_lib:inet_port(Server),
- Exe = "openssl",
- ClientArgs = case SNIHostname of
- undefined ->
- openssl_client_args(Version, Hostname,Port);
- _ ->
- openssl_client_args(Version, Hostname, Port, SNIHostname)
- end,
- ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
-
- ssl_test_lib:check_result(Server, ExpectedSNIHostname),
- ssl_test_lib:close_port(ClientPort),
- ssl_test_lib:close(Server),
- ok.
-
-
-erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
- Version = ssl_test_lib:protocol_version(Config),
- ct:log("Start running handshake for sni_fun, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
- [{sni_hosts, ServerSNIConf}] = proplists:get_value(sni_server_opts, Config),
- SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end,
- ServerOptions = proplists:get_value(server_rsa_opts, Config) ++ [{sni_fun, SNIFun}],
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()}, {mfa, {?MODULE, send_and_hostname, []}},
- {options, ServerOptions}]),
- Port = ssl_test_lib:inet_port(Server),
- Exe = "openssl",
- ClientArgs = case SNIHostname of
- undefined ->
- openssl_client_args(Version, Hostname,Port);
- _ ->
- openssl_client_args(Version, Hostname, Port, SNIHostname)
- end,
-
- ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
-
- ssl_test_lib:check_result(Server, ExpectedSNIHostname),
- ssl_test_lib:close_port(ClientPort),
- ssl_test_lib:close(Server).
-
-
-cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
- process_flag(trap_exit, true),
- ct:log("Testing CipherSuite ~p~n", [CipherSuite]),
- {ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Port = ssl_test_lib:inet_port(node()),
- CertFile = proplists:get_value(certfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
-
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-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)),
-
- ConnectionInfo = {ok, {Version, CipherSuite}},
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}},
- {options,
- [{ciphers,[CipherSuite]} |
- ClientOpts]}]),
-
- true = port_command(OpenSslPort, "Hello\n"),
-
- receive
- {Port, {data, _}} when is_port(Port) ->
- ok
- after 500 ->
- ct:log("Time out on openssl port, check that"
- " the messages Hello and world are received"
- " during close of port" , []),
- ok
- end,
-
- true = port_command(OpenSslPort, " world\n"),
-
- Result = ssl_test_lib:wait_for_result(Client, ok),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close_port(OpenSslPort),
- ssl_test_lib:close(Client),
-
- Return = case Result of
- ok ->
- [];
- Error ->
- [{CipherSuite, Error}]
- end,
- process_flag(trap_exit, false),
- Return.
-
-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_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),
-
- 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 = case OpensslServerOpts of
- [] ->
- ["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,
-
- 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, ClientOpts}]),
-
- Callback(Client, OpensslPort),
-
- %% 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).
-
-start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callback) ->
- process_flag(trap_exit, true),
- 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),
-
- 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)),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
- {options, ClientOpts}]),
-
- Callback(Client, OpensslPort),
-
- %% 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).
-
-start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, Callback) ->
- process_flag(trap_exit, true),
- ServerOpts0 = proplists:get_value(server_rsa_opts, Config),
- ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]} | ServerOpts0],
-
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
-
- Exe = "openssl",
- Args = ["s_client", "-alpn", "http/1.0,spdy/2", "-msg", "-port",
- integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-host", "localhost"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- Callback(Server, OpenSslPort),
-
- ssl_test_lib:close(Server),
-
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
-
-start_erlang_client_and_openssl_server_for_alpn_npn_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),
- ClientOpts = [{alpn_advertised_protocols, [<<"spdy/2">>]},
- {client_preferred_next_protocols, {client, [<<"spdy/3">>, <<"http/1.1">>]}} | ClientOpts0],
-
- {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", "-msg", "-alpn", "http/1.1,spdy/2", "-nextprotoneg",
- "spdy/3", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-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)),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE,
- erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
- {options, ClientOpts}]),
-
- Callback(Client, OpensslPort),
-
- %% 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).
-
-start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Callback) ->
- process_flag(trap_exit, true),
- ServerOpts0 = proplists:get_value(server_rsa_opts, Config),
- ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]},
- {next_protocols_advertised, [<<"spdy/3">>, <<"http/1.1">>]} | ServerOpts0],
-
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_client", "-alpn", "http/1.1,spdy/2", "-nextprotoneg", "spdy/3",
- "-msg", "-port", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-host", "localhost"],
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- Callback(Server, OpenSslPort),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
-
-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_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),
-
- 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", "-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),
-
- 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_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
- {options, ClientOpts}]),
-
- Callback(Client, OpensslPort),
-
- %% 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).
-
-start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callback) ->
- process_flag(trap_exit, true),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- ServerOpts = [{next_protocols_advertised, [<<"spdy/2">>]}, ServerOpts0],
-
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive_and_assert_negotiated_protocol, [<<"spdy/2">>, Data]}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
-
- Exe = "openssl",
- Args = ["s_client", "-nextprotoneg", "http/1.0,spdy/2", "-msg", "-connect",
- hostname_format(Hostname) ++ ":"
- ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- Callback(Server, OpenSslPort),
-
- ssl_test_lib:close(Server),
-
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
-
-
-start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenSSLClientOpts, Data, Callback) ->
- process_flag(trap_exit, true),
- ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- ServerOpts = ErlangServerOpts ++ ServerOpts0,
-
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
-
- Exe = "openssl",
- Args = ["s_client"] ++ OpenSSLClientOpts ++ ["-msg", "-connect",
- hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version)],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- Callback(Server, OpenSslPort),
-
- ssl_test_lib:close(Server),
-
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
-
-
-erlang_ssl_receive_and_assert_negotiated_protocol(Socket, Protocol, Data) ->
- {ok, Protocol} = ssl:negotiated_protocol(Socket),
- erlang_ssl_receive(Socket, Data),
- {ok, Protocol} = ssl:negotiated_protocol(Socket),
- ok.
-
-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
- ssl:send(Socket, "Got it"),
- ok;
- {ssl, Socket, Byte} when length(Byte) == 1 ->
- erlang_ssl_receive(Socket, tl(Data));
- {Port, {data,Debug}} when is_port(Port) ->
- io:format("openssl ~s~n",[Debug]),
- erlang_ssl_receive(Socket,Data);
- Other ->
- ct:fail({unexpected_message, Other})
- end.
-
-connection_info(Socket, Version) ->
- case ssl:connection_information(Socket, [version]) of
- {ok, [{version, Version}] = Info} ->
- ct:log("Connection info: ~p~n", [Info]),
- ok;
- {ok, [{version, OtherVersion}]} ->
- {wrong_version, OtherVersion}
- end.
-
-connection_info_result(Socket) ->
- ssl:connection_information(Socket).
-
-
-delayed_send(Socket, [ErlData, OpenSslData]) ->
- ct:sleep(?SLEEP),
- ssl:send(Socket, ErlData),
- erlang_ssl_receive(Socket, OpenSslData).
-
-server_sent_garbage(Socket) ->
- receive
- server_sent_garbage ->
- {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"),
- case ssl_test_lib:is_sane_oppenssl_client() of
- true ->
- case string:str(HelpText, "-servername") of
- 0 ->
- {skip, "Current openssl doesn't support SNI"};
- _ ->
- Config
- end;
- false ->
- {skip, "Current openssl doesn't support SNI or extension handling is flawed"}
- end.
-
-
-check_openssl_npn_support(Config) ->
- HelpText = os:cmd("openssl s_client --help"),
- case string:str(HelpText, "nextprotoneg") of
- 0 ->
- {skip, "Openssl not compiled with nextprotoneg support"};
- _ ->
- Config
- end.
-
-check_openssl_alpn_support(Config) ->
- HelpText = os:cmd("openssl s_client --help"),
- case string:str(HelpText, "alpn") of
- 0 ->
- {skip, "Openssl not compiled with alpn support"};
- _ ->
- Config
- end.
-
-check_sane_openssl_renegotaite(Config, Version) when Version == 'tlsv1.1';
- Version == 'tlsv1.2' ->
- case os:cmd("openssl version") of
- "OpenSSL 1.0.1c" ++ _ ->
- {skip, "Known renegotiation bug in OpenSSL"};
- "OpenSSL 1.0.1b" ++ _ ->
- {skip, "Known renegotiation bug in OpenSSL"};
- "OpenSSL 1.0.1a" ++ _ ->
- {skip, "Known renegotiation bug in OpenSSL"};
- "OpenSSL 1.0.1 " ++ _ ->
- {skip, "Known renegotiation bug in OpenSSL"};
- _ ->
- check_sane_openssl_renegotaite(Config)
- end;
-check_sane_openssl_renegotaite(Config, _) ->
- check_sane_openssl_renegotaite(Config).
-
-check_sane_openssl_renegotaite(Config) ->
- case os:cmd("openssl version") of
- "OpenSSL 1.0.0" ++ _ ->
- {skip, "Known renegotiation bug in OpenSSL"};
- "OpenSSL 0.9.8" ++ _ ->
- {skip, "Known renegotiation bug in OpenSSL"};
- "OpenSSL 0.9.7" ++ _ ->
- {skip, "Known renegotiation bug in OpenSSL"};
- _ ->
- Config
- end.
-
-workaround_openssl_s_clinent() ->
- %% http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=683159
- %% https://bugs.archlinux.org/task/33919
- %% Bug seems to manifests it self if TLS version is not
- %% explicitly specified
- case os:cmd("openssl version") of
- "OpenSSL 1.0.1c" ++ _ ->
- ["-no_tls1_2"];
- "OpenSSL 1.0.1d" ++ _ ->
- ["-no_tls1_2"];
- "OpenSSL 1.0.1e" ++ _ ->
- ["-no_tls1_2"];
- "OpenSSL 1.0.1f" ++ _ ->
- ["-no_tls1_2"];
- _ ->
- []
- end.
-
-openssl_client_args(Version, Hostname, Port) ->
- ["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port), ssl_test_lib:version_flag(Version)].
-
-openssl_client_args(Version, Hostname, Port, ServerName) ->
- ["s_client", "-connect", Hostname ++ ":" ++
- integer_to_list(Port), ssl_test_lib:version_flag(Version), "-servername", ServerName].
-
-
-hostname_format(Hostname) ->
- case lists:member($., Hostname) of
- true ->
- Hostname;
- false ->
- "localhost"
- end.
-
-
-openssl_has_common_ciphers(Ciphers) ->
- OCiphers = ssl_test_lib:common_ciphers(openssl),
- has_common_ciphers(Ciphers, OCiphers).
-
-has_common_ciphers([], _) ->
- 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/test/tls_1_3_record_SUITE.erl b/lib/ssl/test/tls_1_3_record_SUITE.erl
new file mode 100644
index 0000000000..5df8853b1b
--- /dev/null
+++ b/lib/ssl/test/tls_1_3_record_SUITE.erl
@@ -0,0 +1,973 @@
+%%
+%% %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%
+%%
+
+-module(tls_1_3_record_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssl/src/tls_record.hrl").
+-include_lib("ssl/src/tls_handshake.hrl").
+-include_lib("ssl/src/ssl_cipher.hrl").
+-include_lib("ssl/src/ssl_internal.hrl").
+
+all() ->
+ [encode_decode,
+ finished_verify_data,
+ '1_RTT_handshake'].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try (ok == crypto:start()) andalso ssl_test_lib:sufficient_crypto_support('tlsv1.3') of
+ true ->
+ ssl_test_lib:clean_start(),
+ Config;
+ false ->
+ {skip, "Not enough crypto support for TLS-1.3"}
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+encode_decode() ->
+ [{doc,"Test TLS 1.3 record encode/decode functions"}].
+
+encode_decode(_Config) ->
+ ConnectionStates =
+ #{current_read =>
+ #{beast_mitigation => one_n_minus_one,
+ cipher_state =>
+ {cipher_state,
+ <<14,172,111,243,199,170,242,203,126,205,34,93,122,115,226,14,
+ 15,117,155,48,24,112,61,15,113,208,127,51,179,227,194,232>>,
+ <<197,54,168,218,54,91,157,58,30,201,197,142,51,58,53,231,228,
+ 131,57,122,170,78,82,196,30,48,23,16,95,255,185,236>>,
+ undefined,undefined,undefined,16},
+ client_verify_data => undefined,compression_state => undefined,
+ mac_secret => undefined,secure_renegotiation => undefined,
+ security_parameters =>
+ {security_parameters,
+ <<19,2>>,
+ 0,8,2,undefined,undefined,undefined,undefined,undefined,
+ sha384,undefined,undefined,
+ {handshake_secret,
+ <<128,229,186,211,62,127,182,20,62,166,233,23,135,64,121,
+ 3,104,251,214,161,253,31,3,2,232,37,8,221,189,72,64,218,
+ 121,41,112,148,254,34,68,164,228,60,161,201,132,55,56,
+ 157>>},
+ undefined,
+ <<92,24,205,75,244,60,136,212,250,32,214,20,37,3,213,87,61,207,
+ 147,61,168,145,177,118,160,153,33,53,48,108,191,174>>,
+ undefined},
+ sequence_number => 0,server_verify_data => undefined},
+ current_write =>
+ #{beast_mitigation => one_n_minus_one,
+ cipher_state =>
+ {cipher_state,
+ <<14,172,111,243,199,170,242,203,126,205,34,93,122,115,226,14,
+ 15,117,155,48,24,112,61,15,113,208,127,51,179,227,194,232>>,
+ <<197,54,168,218,54,91,157,58,30,201,197,142,51,58,53,231,228,
+ 131,57,122,170,78,82,196,30,48,23,16,95,255,185,236>>,
+ undefined,undefined,undefined,16},
+ client_verify_data => undefined,compression_state => undefined,
+ mac_secret => undefined,secure_renegotiation => undefined,
+ security_parameters =>
+ {security_parameters,
+ <<19,2>>,
+ 0,8,2,undefined,undefined,undefined,undefined,undefined,
+ sha384,undefined,undefined,
+ {handshake_secret,
+ <<128,229,186,211,62,127,182,20,62,166,233,23,135,64,121,
+ 3,104,251,214,161,253,31,3,2,232,37,8,221,189,72,64,218,
+ 121,41,112,148,254,34,68,164,228,60,161,201,132,55,56,
+ 157>>},
+ undefined,
+ <<92,24,205,75,244,60,136,212,250,32,214,20,37,3,213,87,61,207,
+ 147,61,168,145,177,118,160,153,33,53,48,108,191,174>>,
+ undefined},
+ sequence_number => 0,server_verify_data => undefined}},
+
+ PlainText = [11,
+ <<0,2,175>>,
+ <<0,0,2,171,0,2,166,48,130,2,162,48,130,1,138,2,9,0,186,57,220,137,88,255,
+ 191,235,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,48,18,49,16,48,14,6,3,85,
+ 4,3,12,7,84,101,115,116,32,67,65,48,30,23,13,49,56,48,53,48,52,49,52,49,50,
+ 51,56,90,23,13,50,56,48,50,48,52,49,52,49,50,51,56,90,48,20,49,18,48,16,6,
+ 3,85,4,3,12,9,108,111,99,97,108,104,111,115,116,48,130,1,34,48,13,6,9,42,
+ 134,72,134,247,13,1,1,1,5,0,3,130,1,15,0,48,130,1,10,2,130,1,1,0,169,40,
+ 144,176,121,63,134,97,144,126,243,183,225,157,37,131,183,225,87,243,23,88,
+ 230,70,9,134,32,147,7,27,167,98,51,81,224,75,199,12,229,251,195,207,75,179,
+ 181,78,128,3,255,44,58,39,43,172,142,45,186,58,51,65,187,199,154,153,245,
+ 70,133,137,1,27,87,42,116,65,251,129,109,145,233,97,171,71,54,213,185,74,
+ 209,166,11,218,189,119,206,86,170,60,212,213,85,189,30,50,215,23,185,53,
+ 132,238,132,176,198,250,139,251,198,221,225,128,109,113,23,220,39,143,71,
+ 30,59,189,51,244,61,158,214,146,180,196,103,169,189,221,136,78,129,216,148,
+ 2,9,8,65,37,224,215,233,13,209,21,235,20,143,33,74,59,53,208,90,152,94,251,
+ 54,114,171,39,88,230,227,158,211,135,37,182,67,205,161,59,20,138,58,253,15,
+ 53,48,8,157,9,95,197,9,177,116,21,54,9,125,78,109,182,83,20,16,234,223,116,
+ 41,155,123,87,77,17,120,153,246,239,124,130,105,219,166,146,242,151,66,198,
+ 75,72,63,28,246,86,16,244,223,22,36,50,15,247,222,98,6,152,136,154,72,150,
+ 73,127,2,3,1,0,1,48,13,6,9,42,134,72,134,247,13,1,1,11,5,0,3,130,1,1,0,76,
+ 33,54,160,229,219,219,193,150,116,245,252,18,39,235,145,86,12,167,171,52,
+ 117,166,30,83,5,216,245,177,217,247,95,1,136,94,246,212,108,248,230,111,
+ 225,202,189,6,129,8,70,128,245,18,204,215,87,82,129,253,227,122,66,182,184,
+ 189,30,193,169,144,218,216,109,105,110,215,144,60,104,162,178,101,164,218,
+ 122,60,37,41,143,57,150,52,59,51,112,238,113,239,168,114,69,183,143,154,73,
+ 61,58,80,247,172,95,251,55,28,186,28,200,206,230,118,243,92,202,189,49,76,
+ 124,252,76,0,247,112,85,194,69,59,222,163,228,103,49,110,104,109,251,155,
+ 138,9,37,167,49,189,48,134,52,158,185,129,24,96,153,196,251,90,206,76,239,
+ 175,119,174,165,133,108,222,125,237,125,187,149,152,83,190,16,202,94,202,
+ 201,40,218,22,254,63,189,41,174,97,140,203,70,18,196,118,237,175,134,79,78,
+ 246,2,61,54,77,186,112,32,17,193,192,188,217,252,215,200,7,245,180,179,132,
+ 183,212,229,155,15,152,206,135,56,81,88,3,123,244,149,110,182,72,109,70,62,
+ 146,152,146,151,107,126,216,210,9,93,0,0>>],
+
+ {[_Header|Encoded], _} = tls_record_1_3:encode_plain_text(22, PlainText, ConnectionStates),
+ CipherText = #ssl_tls{type = 23, version = {3,3}, fragment = Encoded},
+
+ {#ssl_tls{type = 22, version = {3,4}, fragment = DecodedText}, _} =
+ tls_record_1_3:decode_cipher_text(CipherText, ConnectionStates),
+
+ DecodedText = iolist_to_binary(PlainText),
+ ct:log("Decoded: ~p ~n", [DecodedText]),
+ ok.
+%%--------------------------------------------------------------------
+'1_RTT_handshake'() ->
+ [{doc,"Test TLS 1.3 1-RTT Handshake"}].
+
+'1_RTT_handshake'(_Config) ->
+ %% ConnectionStates with NULL cipher
+ ConnStatesNull =
+ #{current_write =>
+ #{security_parameters =>
+ #security_parameters{cipher_suite = ?TLS_NULL_WITH_NULL_NULL},
+ sequence_number => 0
+ }
+ },
+
+ %% {client} construct a ClientHello handshake message:
+ %%
+ %% ClientHello (196 octets): 01 00 00 c0 03 03 cb 34 ec b1 e7 81 63
+ %% ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12 ec 18 a2 ef 62 83
+ %% 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00 00 91 00 00 00 0b
+ %% 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00
+ %% 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 23
+ %% 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d e5 60 e4 bd 43 d2
+ %% 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a
+ %% af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03
+ %% 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06
+ %% 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01
+ %%
+ %% {client} send handshake record:
+ %%
+ %% payload (196 octets): 01 00 00 c0 03 03 cb 34 ec b1 e7 81 63 ba
+ %% 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12 ec 18 a2 ef 62 83 02
+ %% 4d ec e7 00 00 06 13 01 13 03 13 02 01 00 00 91 00 00 00 0b 00
+ %% 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00 12
+ %% 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 23 00
+ %% 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d e5 60 e4 bd 43 d2 3d
+ %% 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af
+ %% 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03 02
+ %% 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06 02
+ %% 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01
+ %%
+ %% complete record (201 octets): 16 03 01 00 c4 01 00 00 c0 03 03 cb
+ %% 34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12
+ %% ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00
+ %% 00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01
+ %% 00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02
+ %% 01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d
+ %% e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d
+ %% 54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e
+ %% 04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02
+ %% 01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01
+ ClientHello =
+ hexstr2bin("01 00 00 c0 03 03 cb 34 ec b1 e7 81 63
+ ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12 ec 18 a2 ef 62 83
+ 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00 00 91 00 00 00 0b
+ 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00
+ 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 23
+ 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d e5 60 e4 bd 43 d2
+ 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a
+ af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03
+ 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06
+ 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01"),
+
+ ClientHelloRecord =
+ %% Current implementation always sets
+ %% legacy_record_version to Ox0303
+ hexstr2bin("16 03 03 00 c4 01 00 00 c0 03 03 cb
+ 34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12
+ ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00
+ 00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01
+ 00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02
+ 01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d
+ e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d
+ 54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e
+ 04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02
+ 01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01"),
+
+ {CHEncrypted, _} =
+ tls_record:encode_handshake(ClientHello, {3,4}, ConnStatesNull),
+ ClientHelloRecord = iolist_to_binary(CHEncrypted),
+
+ %% {server} extract secret "early":
+ %%
+ %% salt: 0 (all zero octets)
+ %%
+ %% IKM (32 octets): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ %% 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ %%
+ %% secret (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c
+ %% e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a
+ HKDFAlgo = sha256,
+ Salt = binary:copy(<<?BYTE(0)>>, 32),
+ IKM = binary:copy(<<?BYTE(0)>>, 32),
+ EarlySecret =
+ hexstr2bin("33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c
+ e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a"),
+
+ {early_secret, EarlySecret} = tls_v1:key_schedule(early_secret, HKDFAlgo, {psk, Salt}),
+
+ %% {client} create an ephemeral x25519 key pair:
+ %%
+ %% private key (32 octets): 49 af 42 ba 7f 79 94 85 2d 71 3e f2 78
+ %% 4b cb ca a7 91 1d e2 6a dc 56 42 cb 63 45 40 e7 ea 50 05
+ %%
+ %% public key (32 octets): 99 38 1d e5 60 e4 bd 43 d2 3d 8e 43 5a 7d
+ %% ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af 2c
+ CPublicKey =
+ hexstr2bin("99 38 1d e5 60 e4 bd 43 d2 3d 8e 43 5a 7d
+ ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af 2c"),
+
+ %% {server} create an ephemeral x25519 key pair:
+ %%
+ %% private key (32 octets): b1 58 0e ea df 6d d5 89 b8 ef 4f 2d 56
+ %% 52 57 8c c8 10 e9 98 01 91 ec 8d 05 83 08 ce a2 16 a2 1e
+ %%
+ %% public key (32 octets): c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6
+ %% 72 e1 56 d6 cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f
+ SPrivateKey =
+ hexstr2bin("b1 58 0e ea df 6d d5 89 b8 ef 4f 2d 56
+ 52 57 8c c8 10 e9 98 01 91 ec 8d 05 83 08 ce a2 16 a2 1e"),
+
+ SPublicKey =
+ hexstr2bin("c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6
+ 72 e1 56 d6 cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f"),
+
+ %% {server} construct a ServerHello handshake message:
+ %%
+ %% ServerHello (90 octets): 02 00 00 56 03 03 a6 af 06 a4 12 18 60
+ %% dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 34 da c1 55 77 2e
+ %% d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00 1d 00 20 c9 82 88
+ %% 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6 cc 25 3b 83 3d f1
+ %% dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04
+ ServerHello =
+ hexstr2bin("02 00 00 56 03 03 a6 af 06 a4 12 18 60
+ dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 34 da c1 55 77 2e
+ d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00 1d 00 20 c9 82 88
+ 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6 cc 25 3b 83 3d f1
+ dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04"),
+
+ %% {server} derive secret for handshake "tls13 derived":
+ %%
+ %% PRK (32 octets): 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c e2
+ %% 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a
+ %%
+ %% hash (32 octets): e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24
+ %% 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55
+ %%
+ %% info (49 octets): 00 20 0d 74 6c 73 31 33 20 64 65 72 69 76 65 64
+ %% 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4
+ %% 64 9b 93 4c a4 95 99 1b 78 52 b8 55
+ %%
+ %% expanded (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba
+ %% b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba
+ Hash =
+ hexstr2bin("e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24
+ 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55"),
+
+ Hash = crypto:hash(HKDFAlgo, <<>>),
+
+ Info =
+ hexstr2bin("00 20 0d 74 6c 73 31 33 20 64 65 72 69 76 65 64
+ 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4
+ 64 9b 93 4c a4 95 99 1b 78 52 b8 55"),
+
+ Info = tls_v1:create_info(<<"derived">>, Hash, ssl_cipher:hash_size(HKDFAlgo)),
+
+ Expanded =
+ hexstr2bin("6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba
+ b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba"),
+
+ Expanded = tls_v1:derive_secret(EarlySecret, <<"derived">>, <<>>, HKDFAlgo),
+
+ %% {server} extract secret "handshake":
+ %%
+ %% salt (32 octets): 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba b6 97
+ %% 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba
+ %%
+ %% IKM (32 octets): 8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d
+ %% 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d
+ %%
+ %% secret (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b
+ %% 01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
+
+ %% salt = Expanded
+ HandshakeIKM =
+ hexstr2bin("8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d
+ 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d"),
+
+ HandshakeSecret =
+ hexstr2bin("1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b
+ 01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac"),
+
+ HandshakeIKM = crypto:compute_key(ecdh, CPublicKey, SPrivateKey, x25519),
+
+ {handshake_secret, HandshakeSecret} =
+ tls_v1:key_schedule(handshake_secret, HKDFAlgo, HandshakeIKM,
+ {early_secret, EarlySecret}),
+
+ %% {server} derive secret "tls13 c hs traffic":
+ %%
+ %% PRK (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01
+ %% 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
+ %%
+ %% hash (32 octets): 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed
+ %% d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
+ %%
+ %% info (54 octets): 00 20 12 74 6c 73 31 33 20 63 20 68 73 20 74 72
+ %% 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
+ %% ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
+ %%
+ %% expanded (32 octets): b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e
+ %% 2d 8f 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21
+
+ %% PRK = HandshakeSecret
+ CHSTHash =
+ hexstr2bin("86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed
+ d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8"),
+
+ CHSTInfo =
+ hexstr2bin("00 20 12 74 6c 73 31 33 20 63 20 68 73 20 74 72
+ 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
+ ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8"),
+
+ CHSTrafficSecret =
+ hexstr2bin(" b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e
+ 2d 8f 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21"),
+
+ CHSH = <<ClientHello/binary,ServerHello/binary>>,
+ CHSTHash = crypto:hash(HKDFAlgo, CHSH),
+ CHSTInfo = tls_v1:create_info(<<"c hs traffic">>, CHSTHash, ssl_cipher:hash_size(HKDFAlgo)),
+
+ CHSTrafficSecret =
+ tls_v1:client_handshake_traffic_secret(HKDFAlgo, {handshake_secret, HandshakeSecret}, CHSH),
+
+ %% {server} derive secret "tls13 s hs traffic":
+ %%
+ %% PRK (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01
+ %% 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
+ %%
+ %% hash (32 octets): 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed
+ %% d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
+ %%
+ %% info (54 octets): 00 20 12 74 6c 73 31 33 20 73 20 68 73 20 74 72
+ %% 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
+ %% ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8
+ %%
+ %% expanded (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d
+ %% 37 b4 e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38
+
+ %% PRK = HandshakeSecret
+ %% hash = CHSTHash
+ SHSTInfo =
+ hexstr2bin("00 20 12 74 6c 73 31 33 20 73 20 68 73 20 74 72
+ 61 66 66 69 63 20 86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58
+ ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8"),
+
+ SHSTrafficSecret =
+ hexstr2bin("b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d
+ 37 b4 e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38"),
+
+ SHSTInfo = tls_v1:create_info(<<"s hs traffic">>, CHSTHash, ssl_cipher:hash_size(HKDFAlgo)),
+
+ SHSTrafficSecret =
+ tls_v1:server_handshake_traffic_secret(HKDFAlgo, {handshake_secret, HandshakeSecret}, CHSH),
+
+
+ %% {server} derive secret for master "tls13 derived":
+ %%
+ %% PRK (32 octets): 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01
+ %% 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
+ %%
+ %% hash (32 octets): e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24
+ %% 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55
+ %%
+ %% info (49 octets): 00 20 0d 74 6c 73 31 33 20 64 65 72 69 76 65 64
+ %% 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4
+ %% 64 9b 93 4c a4 95 99 1b 78 52 b8 55
+ %%
+ %% expanded (32 octets): 43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25
+ %% 90 b5 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4
+
+ %% PRK = HandshakeSecret
+ %% hash = Hash
+ %% info = Info
+ MasterDeriveSecret =
+ hexstr2bin("43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25
+ 90 b5 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4"),
+
+ MasterDeriveSecret = tls_v1:derive_secret(HandshakeSecret, <<"derived">>, <<>>, HKDFAlgo),
+
+ %% {server} extract secret "master":
+ %%
+ %% salt (32 octets): 43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25 90 b5
+ %% 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4
+ %%
+ %% IKM (32 octets): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ %% 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ %%
+ %% secret (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a
+ %% 47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
+
+ %% salt = MasterDeriveSecret
+ %% IKM = IKM
+ MasterSecret =
+ hexstr2bin("18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a
+ 47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19"),
+
+ {master_secret, MasterSecret} =
+ tls_v1:key_schedule(master_secret, HKDFAlgo, {handshake_secret, HandshakeSecret}),
+
+ %% {server} send handshake record:
+ %%
+ %% payload (90 octets): 02 00 00 56 03 03 a6 af 06 a4 12 18 60 dc 5e
+ %% 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 34 da c1 55 77 2e d3 e2
+ %% 69 28 00 13 01 00 00 2e 00 33 00 24 00 1d 00 20 c9 82 88 76 11
+ %% 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6 cc 25 3b 83 3d f1 dd 69
+ %% b1 b0 4e 75 1f 0f 00 2b 00 02 03 04
+ %%
+ %% complete record (95 octets): 16 03 03 00 5a 02 00 00 56 03 03 a6
+ %% af 06 a4 12 18 60 dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14
+ %% 34 da c1 55 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00
+ %% 1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6
+ %% cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04
+
+ %% payload = ServerHello
+ ServerHelloRecord =
+ hexstr2bin("16 03 03 00 5a 02 00 00 56 03 03 a6
+ af 06 a4 12 18 60 dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14
+ 34 da c1 55 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00
+ 1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6
+ cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04"),
+
+ {SHEncrypted, _} =
+ tls_record:encode_handshake(ServerHello, {3,4}, ConnStatesNull),
+ ServerHelloRecord = iolist_to_binary(SHEncrypted),
+
+ %% {server} derive write traffic keys for handshake data:
+ %%
+ %% PRK (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4
+ %% e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38
+ %%
+ %% key info (13 octets): 00 10 09 74 6c 73 31 33 20 6b 65 79 00
+ %%
+ %% key expanded (16 octets): 3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e
+ %% e4 03 bc
+ %%
+ %% iv info (12 octets): 00 0c 08 74 6c 73 31 33 20 69 76 00
+ %%
+ %% iv expanded (12 octets): 5d 31 3e b2 67 12 76 ee 13 00 0b 30
+
+ %% PRK = SHSTrafficSecret
+ WriteKeyInfo =
+ hexstr2bin("00 10 09 74 6c 73 31 33 20 6b 65 79 00"),
+
+ WriteKey =
+ hexstr2bin("3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e e4 03 bc"),
+
+ WriteIVInfo =
+ hexstr2bin("00 0c 08 74 6c 73 31 33 20 69 76 00"),
+
+ WriteIV =
+ hexstr2bin(" 5d 31 3e b2 67 12 76 ee 13 00 0b 30"),
+
+ Cipher = aes_128_gcm, %% TODO: get from ServerHello
+
+ WriteKeyInfo = tls_v1:create_info(<<"key">>, <<>>, ssl_cipher:key_material(Cipher)),
+ %% TODO: remove hardcoded IV size
+ WriteIVInfo = tls_v1:create_info(<<"iv">>, <<>>, 12),
+
+ {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, SHSTrafficSecret),
+
+ %% {server} construct an EncryptedExtensions handshake message:
+ %%
+ %% EncryptedExtensions (40 octets): 08 00 00 24 00 22 00 0a 00 14 00
+ %% 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c
+ %% 00 02 40 01 00 00 00 00
+ %%
+ %% {server} construct a Certificate handshake message:
+ %%
+ %% Certificate (445 octets): 0b 00 01 b9 00 00 01 b5 00 01 b0 30 82
+ %% 01 ac 30 82 01 15 a0 03 02 01 02 02 01 02 30 0d 06 09 2a 86 48
+ %% 86 f7 0d 01 01 0b 05 00 30 0e 31 0c 30 0a 06 03 55 04 03 13 03
+ %% 72 73 61 30 1e 17 0d 31 36 30 37 33 30 30 31 32 33 35 39 5a 17
+ %% 0d 32 36 30 37 33 30 30 31 32 33 35 39 5a 30 0e 31 0c 30 0a 06
+ %% 03 55 04 03 13 03 72 73 61 30 81 9f 30 0d 06 09 2a 86 48 86 f7
+ %% 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 b4 bb 49 8f
+ %% 82 79 30 3d 98 08 36 39 9b 36 c6 98 8c 0c 68 de 55 e1 bd b8 26
+ %% d3 90 1a 24 61 ea fd 2d e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c
+ %% 1a f1 9e aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 cc b0 52
+ %% 4b 1b 01 8c 3e 0b 63 26 4d 44 9a 6d 38 e2 2a 5f da 43 08 46 74
+ %% 80 30 53 0e f0 46 1c 8c a9 d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93
+ %% ef f0 ab 9a 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 02 03
+ %% 01 00 01 a3 1a 30 18 30 09 06 03 55 1d 13 04 02 30 00 30 0b 06
+ %% 03 55 1d 0f 04 04 03 02 05 a0 30 0d 06 09 2a 86 48 86 f7 0d 01
+ %% 01 0b 05 00 03 81 81 00 85 aa d2 a0 e5 b9 27 6b 90 8c 65 f7 3a
+ %% 72 67 17 06 18 a5 4c 5f 8a 7b 33 7d 2d f7 a5 94 36 54 17 f2 ea
+ %% e8 f8 a5 8c 8f 81 72 f9 31 9c f3 6b 7f d6 c5 5b 80 f2 1a 03 01
+ %% 51 56 72 60 96 fd 33 5e 5e 67 f2 db f1 02 70 2e 60 8c ca e6 be
+ %% c1 fc 63 a4 2a 99 be 5c 3e b7 10 7c 3c 54 e9 b9 eb 2b d5 20 3b
+ %% 1c 3b 84 e0 a8 b2 f7 59 40 9b a3 ea c9 d9 1d 40 2d cc 0c c8 f8
+ %% 96 12 29 ac 91 87 b4 2b 4d e1 00 00
+ %%
+ %% {server} construct a CertificateVerify handshake message:
+ %%
+ %% CertificateVerify (136 octets): 0f 00 00 84 08 04 00 80 5a 74 7c
+ %% 5d 88 fa 9b d2 e5 5a b0 85 a6 10 15 b7 21 1f 82 4c d4 84 14 5a
+ %% b3 ff 52 f1 fd a8 47 7b 0b 7a bc 90 db 78 e2 d3 3a 5c 14 1a 07
+ %% 86 53 fa 6b ef 78 0c 5e a2 48 ee aa a7 85 c4 f3 94 ca b6 d3 0b
+ %% be 8d 48 59 ee 51 1f 60 29 57 b1 54 11 ac 02 76 71 45 9e 46 44
+ %% 5c 9e a5 8c 18 1e 81 8e 95 b8 c3 fb 0b f3 27 84 09 d3 be 15 2a
+ %% 3d a5 04 3e 06 3d da 65 cd f5 ae a2 0d 53 df ac d4 2f 74 f3
+ EncryptedExtensions =
+ hexstr2bin("08 00 00 24 00 22 00 0a 00 14 00
+ 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c
+ 00 02 40 01 00 00 00 00"),
+
+ Certificate =
+ hexstr2bin("0b 00 01 b9 00 00 01 b5 00 01 b0 30 82
+ 01 ac 30 82 01 15 a0 03 02 01 02 02 01 02 30 0d 06 09 2a 86 48
+ 86 f7 0d 01 01 0b 05 00 30 0e 31 0c 30 0a 06 03 55 04 03 13 03
+ 72 73 61 30 1e 17 0d 31 36 30 37 33 30 30 31 32 33 35 39 5a 17
+ 0d 32 36 30 37 33 30 30 31 32 33 35 39 5a 30 0e 31 0c 30 0a 06
+ 03 55 04 03 13 03 72 73 61 30 81 9f 30 0d 06 09 2a 86 48 86 f7
+ 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 b4 bb 49 8f
+ 82 79 30 3d 98 08 36 39 9b 36 c6 98 8c 0c 68 de 55 e1 bd b8 26
+ d3 90 1a 24 61 ea fd 2d e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c
+ 1a f1 9e aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 cc b0 52
+ 4b 1b 01 8c 3e 0b 63 26 4d 44 9a 6d 38 e2 2a 5f da 43 08 46 74
+ 80 30 53 0e f0 46 1c 8c a9 d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93
+ ef f0 ab 9a 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 02 03
+ 01 00 01 a3 1a 30 18 30 09 06 03 55 1d 13 04 02 30 00 30 0b 06
+ 03 55 1d 0f 04 04 03 02 05 a0 30 0d 06 09 2a 86 48 86 f7 0d 01
+ 01 0b 05 00 03 81 81 00 85 aa d2 a0 e5 b9 27 6b 90 8c 65 f7 3a
+ 72 67 17 06 18 a5 4c 5f 8a 7b 33 7d 2d f7 a5 94 36 54 17 f2 ea
+ e8 f8 a5 8c 8f 81 72 f9 31 9c f3 6b 7f d6 c5 5b 80 f2 1a 03 01
+ 51 56 72 60 96 fd 33 5e 5e 67 f2 db f1 02 70 2e 60 8c ca e6 be
+ c1 fc 63 a4 2a 99 be 5c 3e b7 10 7c 3c 54 e9 b9 eb 2b d5 20 3b
+ 1c 3b 84 e0 a8 b2 f7 59 40 9b a3 ea c9 d9 1d 40 2d cc 0c c8 f8
+ 96 12 29 ac 91 87 b4 2b 4d e1 00 00"),
+
+ CertificateVerify =
+ hexstr2bin("0f 00 00 84 08 04 00 80 5a 74 7c
+ 5d 88 fa 9b d2 e5 5a b0 85 a6 10 15 b7 21 1f 82 4c d4 84 14 5a
+ b3 ff 52 f1 fd a8 47 7b 0b 7a bc 90 db 78 e2 d3 3a 5c 14 1a 07
+ 86 53 fa 6b ef 78 0c 5e a2 48 ee aa a7 85 c4 f3 94 ca b6 d3 0b
+ be 8d 48 59 ee 51 1f 60 29 57 b1 54 11 ac 02 76 71 45 9e 46 44
+ 5c 9e a5 8c 18 1e 81 8e 95 b8 c3 fb 0b f3 27 84 09 d3 be 15 2a
+ 3d a5 04 3e 06 3d da 65 cd f5 ae a2 0d 53 df ac d4 2f 74 f3"),
+
+ %% {server} calculate finished "tls13 finished":
+ %%
+ %% PRK (32 octets): b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4
+ %% e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38
+ %%
+ %% hash (0 octets): (empty)
+ %%
+ %% info (18 octets): 00 20 0e 74 6c 73 31 33 20 66 69 6e 69 73 68 65
+ %% 64 00
+ %%
+ %% expanded (32 octets): 00 8d 3b 66 f8 16 ea 55 9f 96 b5 37 e8 85
+ %% c3 1f c0 68 bf 49 2c 65 2f 01 f2 88 a1 d8 cd c1 9f c8
+ %%
+ %% finished (32 octets): 9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4
+ %% de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18
+
+ %% PRK = SHSTrafficSecret
+ FInfo =
+ hexstr2bin("00 20 0e 74 6c 73 31 33 20 66 69 6e 69 73 68 65
+ 64 00"),
+
+ FExpanded =
+ hexstr2bin("00 8d 3b 66 f8 16 ea 55 9f 96 b5 37 e8 85
+ c3 1f c0 68 bf 49 2c 65 2f 01 f2 88 a1 d8 cd c1 9f c8"),
+
+ FinishedVerifyData =
+ hexstr2bin("9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4
+ de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18"),
+
+ FInfo = tls_v1:create_info(<<"finished">>, <<>>, ssl_cipher:hash_size(HKDFAlgo)),
+
+ FExpanded = tls_v1:finished_key(SHSTrafficSecret, HKDFAlgo),
+
+ MessageHistory0 = [CertificateVerify,
+ Certificate,
+ EncryptedExtensions,
+ ServerHello,
+ ClientHello],
+
+ FinishedVerifyData = tls_v1:finished_verify_data(FExpanded, HKDFAlgo, MessageHistory0),
+
+ %% {server} construct a Finished handshake message:
+ %%
+ %% Finished (36 octets): 14 00 00 20 9b 9b 14 1d 90 63 37 fb d2 cb
+ %% dc e7 1d f4 de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07
+ %% 18
+ FinishedHSBin =
+ hexstr2bin("14 00 00 20 9b 9b 14 1d 90 63 37 fb d2 cb
+ dc e7 1d f4 de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07
+ 18"),
+
+ FinishedHS = #finished{verify_data = FinishedVerifyData},
+
+ FinishedIOList = tls_handshake:encode_handshake(FinishedHS, {3,4}),
+ FinishedHSBin = iolist_to_binary(FinishedIOList),
+
+ %% {server} derive secret "tls13 c ap traffic":
+ %%
+ %% PRK (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47
+ %% 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
+ %%
+ %% hash (32 octets): 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
+ %% 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
+ %%
+ %% info (54 octets): 00 20 12 74 6c 73 31 33 20 63 20 61 70 20 74 72
+ %% 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
+ %% 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
+ %%
+ %% expanded (32 octets): 9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce
+ %% 65 52 87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5
+
+ %% PRK = MasterSecret
+ CAPTHash =
+ hexstr2bin("96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
+ 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
+ CAPTInfo =
+ hexstr2bin("00 20 12 74 6c 73 31 33 20 63 20 61 70 20 74 72
+ 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
+ 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
+
+ CAPTrafficSecret =
+ hexstr2bin("9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce
+ 65 52 87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5"),
+
+ CHSF = <<ClientHello/binary,
+ ServerHello/binary,
+ EncryptedExtensions/binary,
+ Certificate/binary,
+ CertificateVerify/binary,
+ FinishedHSBin/binary>>,
+
+ CAPTHash = crypto:hash(HKDFAlgo, CHSF),
+
+ CAPTInfo =
+ tls_v1:create_info(<<"c ap traffic">>, CAPTHash, ssl_cipher:hash_size(HKDFAlgo)),
+
+ CAPTrafficSecret =
+ tls_v1:client_application_traffic_secret_0(HKDFAlgo, {master_secret, MasterSecret}, CHSF),
+
+ %% {server} derive secret "tls13 s ap traffic":
+ %%
+ %% PRK (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47
+ %% 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
+ %%
+ %% hash (32 octets): 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
+ %% 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
+ %%
+ %% info (54 octets): 00 20 12 74 6c 73 31 33 20 73 20 61 70 20 74 72
+ %% 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
+ %% 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
+ %%
+ %% expanded (32 octets): a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9
+ %% 50 32 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43
+
+ %% PRK = MasterSecret
+ %% hash = CAPTHash
+ SAPTInfo =
+ hexstr2bin(" 00 20 12 74 6c 73 31 33 20 73 20 61 70 20 74 72
+ 61 66 66 69 63 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b
+ 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
+
+ SAPTrafficSecret =
+ hexstr2bin("a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9
+ 50 32 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43"),
+
+ SAPTInfo =
+ tls_v1:create_info(<<"s ap traffic">>, CAPTHash, ssl_cipher:hash_size(HKDFAlgo)),
+
+ SAPTrafficSecret =
+ tls_v1:server_application_traffic_secret_0(HKDFAlgo, {master_secret, MasterSecret}, CHSF),
+
+ %% {server} derive secret "tls13 exp master":
+ %%
+ %% PRK (32 octets): 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47
+ %% 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
+ %%
+ %% hash (32 octets): 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a
+ %% 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
+ %%
+ %% info (52 octets): 00 20 10 74 6c 73 31 33 20 65 78 70 20 6d 61 73
+ %% 74 65 72 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a 00
+ %% 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13
+ %%
+ %% expanded (32 octets): fe 22 f8 81 17 6e da 18 eb 8f 44 52 9e 67
+ %% 92 c5 0c 9a 3f 89 45 2f 68 d8 ae 31 1b 43 09 d3 cf 50
+
+ %% PRK = MasterSecret
+ %% hash = CAPTHash
+ ExporterInfo =
+ hexstr2bin("00 20 10 74 6c 73 31 33 20 65 78 70 20 6d 61 73
+ 74 65 72 20 96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a 00
+ 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13"),
+
+ ExporterMasterSecret =
+ hexstr2bin("fe 22 f8 81 17 6e da 18 eb 8f 44 52 9e 67
+ 92 c5 0c 9a 3f 89 45 2f 68 d8 ae 31 1b 43 09 d3 cf 50"),
+
+ ExporterInfo =
+ tls_v1:create_info(<<"exp master">>, CAPTHash, ssl_cipher:hash_size(HKDFAlgo)),
+
+ ExporterMasterSecret =
+ tls_v1:exporter_master_secret(HKDFAlgo, {master_secret, MasterSecret}, CHSF),
+
+ %% {server} derive write traffic keys for application data:
+ %%
+ %% PRK (32 octets): a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9 50 32
+ %% 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43
+ %%
+ %% key info (13 octets): 00 10 09 74 6c 73 31 33 20 6b 65 79 00
+ %%
+ %% key expanded (16 octets): 9f 02 28 3b 6c 9c 07 ef c2 6b b9 f2 ac
+ %% 92 e3 56
+ %%
+ %% iv info (12 octets): 00 0c 08 74 6c 73 31 33 20 69 76 00
+ %%
+ %% iv expanded (12 octets): cf 78 2b 88 dd 83 54 9a ad f1 e9 84
+
+ %% PRK = SAPTrafficsecret
+ %% key info = WriteKeyInfo
+ %% iv info = WrtieIVInfo
+ SWKey =
+ hexstr2bin("9f 02 28 3b 6c 9c 07 ef c2 6b b9 f2 ac 92 e3 56"),
+
+ SWIV =
+ hexstr2bin("cf 78 2b 88 dd 83 54 9a ad f1 e9 84"),
+
+ {SWKey, SWIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, SAPTrafficSecret),
+
+ %% {server} derive read traffic keys for handshake data:
+ %%
+ %% PRK (32 octets): b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e 2d 8f
+ %% 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21
+ %%
+ %% key info (13 octets): 00 10 09 74 6c 73 31 33 20 6b 65 79 00
+ %%
+ %% key expanded (16 octets): db fa a6 93 d1 76 2c 5b 66 6a f5 d9 50
+ %% 25 8d 01
+ %%
+ %% iv info (12 octets): 00 0c 08 74 6c 73 31 33 20 69 76 00
+ %%
+ %% iv expanded (12 octets): 5b d3 c7 1b 83 6e 0b 76 bb 73 26 5f
+
+ %% PRK = CHSTrafficsecret
+ %% key info = WriteKeyInfo
+ %% iv info = WrtieIVInfo
+ SRKey =
+ hexstr2bin("db fa a6 93 d1 76 2c 5b 66 6a f5 d9 50 25 8d 01"),
+
+ SRIV =
+ hexstr2bin("5b d3 c7 1b 83 6e 0b 76 bb 73 26 5f"),
+
+ {SRKey, SRIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, CHSTrafficSecret).
+
+%%--------------------------------------------------------------------
+finished_verify_data() ->
+ [{doc,"Test TLS 1.3 Finished message handling"}].
+
+finished_verify_data(_Config) ->
+ ClientHello =
+ hexstr2bin("01 00 00 c6 03 03 00 01 02 03 04 05 06 07 08 09
+ 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19
+ 1a 1b 1c 1d 1e 1f 20 e0 e1 e2 e3 e4 e5 e6 e7 e8
+ e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8
+ f9 fa fb fc fd fe ff 00 06 13 01 13 02 13 03 01
+ 00 00 77 00 00 00 18 00 16 00 00 13 65 78 61 6d
+ 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e 65 74 00
+ 0a 00 08 00 06 00 1d 00 17 00 18 00 0d 00 14 00
+ 12 04 03 08 04 04 01 05 03 08 05 05 01 08 06 06
+ 01 02 01 00 33 00 26 00 24 00 1d 00 20 35 80 72
+ d6 36 58 80 d1 ae ea 32 9a df 91 21 38 38 51 ed
+ 21 a2 8e 3b 75 e9 65 d0 d2 cd 16 62 54 00 2d 00
+ 02 01 01 00 2b 00 03 02 03 04"),
+
+ ServerHello =
+ hexstr2bin("02 00 00 76 03 03 70 71 72 73 74 75 76 77 78 79
+ 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89
+ 8a 8b 8c 8d 8e 8f 20 e0 e1 e2 e3 e4 e5 e6 e7 e8
+ e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8
+ f9 fa fb fc fd fe ff 13 01 00 00 2e 00 33 00 24
+ 00 1d 00 20 9f d7 ad 6d cf f4 29 8d d3 f9 6d 5b
+ 1b 2a f9 10 a0 53 5b 14 88 d7 f8 fa bb 34 9a 98
+ 28 80 b6 15 00 2b 00 02 03 04"),
+
+ EncryptedExtensions =
+ hexstr2bin("08 00 00 02 00 00"),
+
+ Certificate =
+ hexstr2bin("0b 00 03 2e 00 00 03 2a 00 03 25 30 82 03 21 30
+ 82 02 09 a0 03 02 01 02 02 08 15 5a 92 ad c2 04
+ 8f 90 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05
+ 00 30 22 31 0b 30 09 06 03 55 04 06 13 02 55 53
+ 31 13 30 11 06 03 55 04 0a 13 0a 45 78 61 6d 70
+ 6c 65 20 43 41 30 1e 17 0d 31 38 31 30 30 35 30
+ 31 33 38 31 37 5a 17 0d 31 39 31 30 30 35 30 31
+ 33 38 31 37 5a 30 2b 31 0b 30 09 06 03 55 04 06
+ 13 02 55 53 31 1c 30 1a 06 03 55 04 03 13 13 65
+ 78 61 6d 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e
+ 65 74 30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d
+ 01 01 01 05 00 03 82 01 0f 00 30 82 01 0a 02 82
+ 01 01 00 c4 80 36 06 ba e7 47 6b 08 94 04 ec a7
+ b6 91 04 3f f7 92 bc 19 ee fb 7d 74 d7 a8 0d 00
+ 1e 7b 4b 3a 4a e6 0f e8 c0 71 fc 73 e7 02 4c 0d
+ bc f4 bd d1 1d 39 6b ba 70 46 4a 13 e9 4a f8 3d
+ f3 e1 09 59 54 7b c9 55 fb 41 2d a3 76 52 11 e1
+ f3 dc 77 6c aa 53 37 6e ca 3a ec be c3 aa b7 3b
+ 31 d5 6c b6 52 9c 80 98 bc c9 e0 28 18 e2 0b f7
+ f8 a0 3a fd 17 04 50 9e ce 79 bd 9f 39 f1 ea 69
+ ec 47 97 2e 83 0f b5 ca 95 de 95 a1 e6 04 22 d5
+ ee be 52 79 54 a1 e7 bf 8a 86 f6 46 6d 0d 9f 16
+ 95 1a 4c f7 a0 46 92 59 5c 13 52 f2 54 9e 5a fb
+ 4e bf d7 7a 37 95 01 44 e4 c0 26 87 4c 65 3e 40
+ 7d 7d 23 07 44 01 f4 84 ff d0 8f 7a 1f a0 52 10
+ d1 f4 f0 d5 ce 79 70 29 32 e2 ca be 70 1f df ad
+ 6b 4b b7 11 01 f4 4b ad 66 6a 11 13 0f e2 ee 82
+ 9e 4d 02 9d c9 1c dd 67 16 db b9 06 18 86 ed c1
+ ba 94 21 02 03 01 00 01 a3 52 30 50 30 0e 06 03
+ 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03
+ 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03
+ 02 06 08 2b 06 01 05 05 07 03 01 30 1f 06 03 55
+ 1d 23 04 18 30 16 80 14 89 4f de 5b cc 69 e2 52
+ cf 3e a3 00 df b1 97 b8 1d e1 c1 46 30 0d 06 09
+ 2a 86 48 86 f7 0d 01 01 0b 05 00 03 82 01 01 00
+ 59 16 45 a6 9a 2e 37 79 e4 f6 dd 27 1a ba 1c 0b
+ fd 6c d7 55 99 b5 e7 c3 6e 53 3e ff 36 59 08 43
+ 24 c9 e7 a5 04 07 9d 39 e0 d4 29 87 ff e3 eb dd
+ 09 c1 cf 1d 91 44 55 87 0b 57 1d d1 9b df 1d 24
+ f8 bb 9a 11 fe 80 fd 59 2b a0 39 8c de 11 e2 65
+ 1e 61 8c e5 98 fa 96 e5 37 2e ef 3d 24 8a fd e1
+ 74 63 eb bf ab b8 e4 d1 ab 50 2a 54 ec 00 64 e9
+ 2f 78 19 66 0d 3f 27 cf 20 9e 66 7f ce 5a e2 e4
+ ac 99 c7 c9 38 18 f8 b2 51 07 22 df ed 97 f3 2e
+ 3e 93 49 d4 c6 6c 9e a6 39 6d 74 44 62 a0 6b 42
+ c6 d5 ba 68 8e ac 3a 01 7b dd fc 8e 2c fc ad 27
+ cb 69 d3 cc dc a2 80 41 44 65 d3 ae 34 8c e0 f3
+ 4a b2 fb 9c 61 83 71 31 2b 19 10 41 64 1c 23 7f
+ 11 a5 d6 5c 84 4f 04 04 84 99 38 71 2b 95 9e d6
+ 85 bc 5c 5d d6 45 ed 19 90 94 73 40 29 26 dc b4
+ 0e 34 69 a1 59 41 e8 e2 cc a8 4b b6 08 46 36 a0
+ 00 00"),
+
+ CertificateVerify =
+ hexstr2bin("0f 00 01 04 08 04 01 00 17 fe b5 33 ca 6d 00 7d
+ 00 58 25 79 68 42 4b bc 3a a6 90 9e 9d 49 55 75
+ 76 a5 20 e0 4a 5e f0 5f 0e 86 d2 4f f4 3f 8e b8
+ 61 ee f5 95 22 8d 70 32 aa 36 0f 71 4e 66 74 13
+ 92 6e f4 f8 b5 80 3b 69 e3 55 19 e3 b2 3f 43 73
+ df ac 67 87 06 6d cb 47 56 b5 45 60 e0 88 6e 9b
+ 96 2c 4a d2 8d ab 26 ba d1 ab c2 59 16 b0 9a f2
+ 86 53 7f 68 4f 80 8a ef ee 73 04 6c b7 df 0a 84
+ fb b5 96 7a ca 13 1f 4b 1c f3 89 79 94 03 a3 0c
+ 02 d2 9c bd ad b7 25 12 db 9c ec 2e 5e 1d 00 e5
+ 0c af cf 6f 21 09 1e bc 4f 25 3c 5e ab 01 a6 79
+ ba ea be ed b9 c9 61 8f 66 00 6b 82 44 d6 62 2a
+ aa 56 88 7c cf c6 6a 0f 38 51 df a1 3a 78 cf f7
+ 99 1e 03 cb 2c 3a 0e d8 7d 73 67 36 2e b7 80 5b
+ 00 b2 52 4f f2 98 a4 da 48 7c ac de af 8a 23 36
+ c5 63 1b 3e fa 93 5b b4 11 e7 53 ca 13 b0 15 fe
+ c7 e4 a7 30 f1 36 9f 9e"),
+
+ BaseKey =
+ hexstr2bin("a2 06 72 65 e7 f0 65 2a 92 3d 5d 72 ab 04 67 c4
+ 61 32 ee b9 68 b6 a3 2d 31 1c 80 58 68 54 88 14"),
+
+ VerifyData =
+ hexstr2bin("ea 6e e1 76 dc cc 4a f1 85 9e 9e 4e 93 f7 97 ea
+ c9 a7 8c e4 39 30 1e 35 27 5a d4 3f 3c dd bd e3"),
+
+ Messages = [CertificateVerify,
+ Certificate,
+ EncryptedExtensions,
+ ServerHello,
+ ClientHello],
+
+ FinishedKey = tls_v1:finished_key(BaseKey, sha256),
+ VerifyData = tls_v1:finished_verify_data(FinishedKey, sha256, Messages).
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+hexstr2int(S) ->
+ B = hexstr2bin(S),
+ Bits = size(B) * 8,
+ <<Integer:Bits/integer>> = B,
+ Integer.
+
+hexstr2bin(S) when is_binary(S) ->
+ hexstr2bin(S, <<>>);
+hexstr2bin(S) ->
+ hexstr2bin(list_to_binary(S), <<>>).
+%%
+hexstr2bin(<<>>, Acc) ->
+ Acc;
+hexstr2bin(<<C,T/binary>>, Acc) when C =:= 32; %% SPACE
+ C =:= 10; %% LF
+ C =:= 13 -> %% CR
+ hexstr2bin(T, Acc);
+hexstr2bin(<<X,Y,T/binary>>, Acc) ->
+ I = hex2int(X) * 16 + hex2int(Y),
+ hexstr2bin(T, <<Acc/binary,I>>).
+
+hex2int(C) when $0 =< C, C =< $9 ->
+ C - $0;
+hex2int(C) when $A =< C, C =< $F ->
+ C - $A + 10;
+hex2int(C) when $a =< C, C =< $f ->
+ C - $a + 10.
diff --git a/lib/ssl/test/tls_1_3_version_SUITE.erl b/lib/ssl/test/tls_1_3_version_SUITE.erl
new file mode 100644
index 0000000000..f0b224d4e5
--- /dev/null
+++ b/lib/ssl/test/tls_1_3_version_SUITE.erl
@@ -0,0 +1,153 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(tls_1_3_version_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ {group, 'tlsv1.3'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.3', [], cert_groups()},
+ {rsa, [], tests()},
+ {ecdsa, [], tests()}
+ ].
+
+cert_groups() ->
+ [{group, rsa},
+ {group, ecdsa}].
+
+tests() ->
+ [tls13_client_tls12_server,
+ tls13_client_with_ext_tls12_server,
+ tls12_client_tls13_server].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ [{client_type, erlang}, {server_type, erlang} |
+ Config]
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+init_per_group(rsa, Config0) ->
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ COpts = proplists:get_value(client_rsa_opts, Config),
+ SOpts = proplists:get_value(server_rsa_opts, Config),
+ [{client_cert_opts, COpts}, {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts, lists:delete(client_cert_opts, Config))];
+init_per_group(ecdsa, Config0) ->
+ PKAlg = crypto:supports(public_keys),
+ case lists:member(ecdsa, PKAlg) andalso
+ (lists:member(ecdh, PKAlg) orelse lists:member(dh, PKAlg)) of
+ true ->
+ Config = ssl_test_lib:make_ecdsa_cert(Config0),
+ COpts = proplists:get_value(client_ecdsa_opts, Config),
+ SOpts = proplists:get_value(server_ecdsa_opts, Config),
+ [{client_cert_opts, COpts}, {server_cert_opts, SOpts} |
+ lists:delete(server_cert_opts, lists:delete(client_cert_opts, Config))];
+ false ->
+ {skip, "Missing EC crypto support"}
+ end;
+init_per_group(GroupName, Config) ->
+ ssl_test_lib:clean_tls_version(Config),
+ case ssl_test_lib:is_tls_version(GroupName) andalso
+ ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ _ ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl:start(),
+ Config;
+ false ->
+ {skip, "Missing crypto support"}
+ end
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+tls13_client_tls12_server() ->
+ [{doc,"Test that a TLS 1.3 client can connect to a TLS 1.2 server."}].
+
+tls13_client_tls12_server(Config) when is_list(Config) ->
+ ClientOpts = [{versions,
+ ['tlsv1.3', 'tlsv1.2']} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{versions,
+ ['tlsv1.1', 'tlsv1.2']} | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+tls13_client_with_ext_tls12_server() ->
+ [{doc,"Test basic connection between TLS 1.2 server and TLS 1.3 client when "
+ "client has TLS 1.3 specsific extensions"}].
+
+tls13_client_with_ext_tls12_server(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ ServerOpts = [{versions, ['tlsv1.2']}|ServerOpts0],
+ ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
+ {signature_algs_cert, [ecdsa_secp384r1_sha384,
+ ecdsa_secp256r1_sha256,
+ rsa_pss_rsae_sha256,
+ rsa_pkcs1_sha256,
+ {sha256,rsa},{sha256,dsa}]}|ClientOpts0],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+tls12_client_tls13_server() ->
+ [{doc,"Test that a TLS 1.2 client can connect to a TLS 1.3 server."}].
+
+tls12_client_tls13_server(Config) when is_list(Config) ->
+ ClientOpts = [{versions,
+ ['tlsv1.1', 'tlsv1.2']} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{versions,
+ ['tlsv1.3', 'tlsv1.2']} | ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
diff --git a/lib/ssl/test/tls_api_SUITE.erl b/lib/ssl/test/tls_api_SUITE.erl
new file mode 100644
index 0000000000..5a74ec1892
--- /dev/null
+++ b/lib/ssl/test/tls_api_SUITE.erl
@@ -0,0 +1,880 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(tls_api_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssl/src/ssl_record.hrl").
+-include_lib("ssl/src/ssl_internal.hrl").
+-include_lib("ssl/src/ssl_api.hrl").
+-include_lib("ssl/src/tls_handshake.hrl").
+
+-define(SLEEP, 500).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ [
+ {group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.3', [], api_tests() -- [sockname]},
+ {'tlsv1.2', [], api_tests()},
+ {'tlsv1.1', [], api_tests()},
+ {'tlsv1', [], api_tests()},
+ {'sslv3', [], api_tests() ++ [ssl3_cipher_suite_limitation]}
+ ].
+
+api_tests() ->
+ [
+ tls_upgrade,
+ tls_upgrade_with_timeout,
+ tls_downgrade,
+ tls_shutdown,
+ tls_shutdown_write,
+ tls_shutdown_both,
+ tls_shutdown_error,
+ tls_client_closes_socket,
+ tls_closed_in_active_once,
+ tls_tcp_msg,
+ tls_tcp_msg_big,
+ tls_dont_crash_on_handshake_garbage,
+ tls_tcp_error_propagation_in_active_mode,
+ peername,
+ sockname,
+ tls_server_handshake_timeout,
+ transport_close,
+ emulated_options,
+ accept_pool,
+ reuseaddr
+ ].
+
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config0)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:unload(ssl),
+ application:stop(crypto).
+
+
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ false ->
+ {skip, "Missing crypto support"}
+ end;
+ _ ->
+ ssl:start(),
+ Config
+ end.
+
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
+init_per_testcase(_TestCase, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+tls_upgrade() ->
+ [{doc,"Test that you can upgrade an tcp connection to an ssl connection"}].
+
+tls_upgrade(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+
+ Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ upgrade_result, []}},
+ {tcp_options,
+ [{active, false} | TcpOpts]},
+ {ssl_options, [{verify, verify_peer} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_upgrade_client([{node, ClientNode},
+ {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, upgrade_result, []}},
+ {tcp_options, [binary]},
+ {ssl_options, [{verify, verify_peer},
+ {server_name_indication, Hostname} | ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+tls_upgrade_with_timeout() ->
+ [{doc,"Test ssl_accept/3"}].
+
+tls_upgrade_with_timeout(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+
+ Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {timeout, 5000},
+ {mfa, {?MODULE,
+ upgrade_result, []}},
+ {tcp_options,
+ [{active, false} | TcpOpts]},
+ {ssl_options, [{verify, verify_peer} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_upgrade_client([{node, ClientNode},
+ {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, upgrade_result, []}},
+ {tcp_options, TcpOpts},
+ {ssl_options, [{verify, verify_peer},
+ {server_name_indication, Hostname} | ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+tls_downgrade() ->
+ [{doc,"Test that you can downgarde an ssl connection to an tcp connection"}].
+tls_downgrade(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, tls_downgrade_result, [self()]}},
+ {options, [{active, false}, {verify, verify_peer} | 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, [self()]}},
+ {options, [{active, false}, {verify, verify_peer} | 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).
+
+
+%%--------------------------------------------------------------------
+tls_shutdown() ->
+ [{doc,"Test API function ssl:shutdown/2"}].
+tls_shutdown(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, tls_shutdown_result, [server]}},
+ {options, [{exit_on_close, false},
+ {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_shutdown_result, [client]}},
+ {options,
+ [{exit_on_close, false},
+ {active, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+tls_shutdown_write() ->
+ [{doc,"Test API function ssl:shutdown/2 with option write."}].
+tls_shutdown_write(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, tls_shutdown_write_result, [server]}},
+ {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_shutdown_write_result, [client]}},
+ {options, [{active, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, {error, closed}).
+
+%%--------------------------------------------------------------------
+tls_shutdown_both() ->
+ [{doc,"Test API function ssl:shutdown/2 with option both."}].
+tls_shutdown_both(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, tls_shutdown_both_result, [server]}},
+ {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_shutdown_both_result, [client]}},
+ {options, [{active, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, {error, closed}).
+
+%%--------------------------------------------------------------------
+tls_shutdown_error() ->
+ [{doc,"Test ssl:shutdown/2 error handling"}].
+tls_shutdown_error(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ Port = ssl_test_lib:inet_port(node()),
+ {ok, Listen} = ssl:listen(Port, ServerOpts),
+ {error, enotconn} = ssl:shutdown(Listen, read_write),
+ ok = ssl:close(Listen),
+ {error, closed} = ssl:shutdown(Listen, read_write).
+%%--------------------------------------------------------------------
+tls_client_closes_socket() ->
+ [{doc,"Test what happens when client closes socket before handshake is compleated"}].
+
+tls_client_closes_socket(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+
+ Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {tcp_options, TcpOpts},
+ {ssl_options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Connect = fun() ->
+ {ok, _Socket} = rpc:call(ClientNode, gen_tcp, connect,
+ [Hostname, Port, [binary]]),
+ %% Make sure that ssl_accept is called before
+ %% client process ends and closes socket.
+ ct:sleep(?SLEEP)
+ end,
+
+ _Client = spawn_link(Connect),
+
+ ssl_test_lib:check_result(Server, {error,closed}).
+
+%%--------------------------------------------------------------------
+tls_closed_in_active_once() ->
+ [{doc, "Test that ssl_closed is delivered in active once with non-empty buffer, check ERL-420."}].
+
+tls_closed_in_active_once(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {_ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+ Port = ssl_test_lib:inet_port(node()),
+ Server = fun() ->
+ {ok, Listen} = gen_tcp:listen(Port, TcpOpts),
+ {ok, TcpServerSocket} = gen_tcp:accept(Listen),
+ {ok, ServerSocket} = ssl:handshake(TcpServerSocket, ServerOpts),
+ lists:foreach(
+ fun(_) ->
+ ssl:send(ServerSocket, "some random message\r\n")
+ end, lists:seq(1, 20)),
+ %% Close TCP instead of SSL socket to trigger the bug:
+ gen_tcp:close(TcpServerSocket),
+ gen_tcp:close(Listen)
+ end,
+ spawn_link(Server),
+ {ok, Socket} = ssl:connect(Hostname, Port, [{active, false} | ClientOpts]),
+ Result = tls_closed_in_active_once_loop(Socket),
+ ssl:close(Socket),
+ case Result of
+ ok -> ok;
+ _ -> ct:fail(Result)
+ end.
+%%--------------------------------------------------------------------
+tls_tcp_msg() ->
+ [{doc,"Test what happens when a tcp tries to connect, i,e. a bad (ssl) packet is sent first"}].
+
+tls_tcp_msg(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}, {active, false}],
+
+ Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {timeout, 5000},
+ {mfa, {?MODULE, dummy, []}},
+ {tcp_options, TcpOpts},
+ {ssl_options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]),
+ ct:log("Testcase ~p connected to Server ~p ~n", [self(), Server]),
+ gen_tcp:send(Socket, "<SOME GARBLED NON SSL MESSAGE>"),
+
+ receive
+ {tcp_closed, Socket} ->
+ receive
+ {Server, {error, Error}} ->
+ ct:log("Error ~p", [Error])
+ end
+ end.
+%%--------------------------------------------------------------------
+tls_tcp_msg_big() ->
+ [{doc,"Test what happens when a tcp tries to connect, i,e. a bad big (ssl) packet is sent first"}].
+
+tls_tcp_msg_big(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+
+ Rand = crypto:strong_rand_bytes(?MAX_CIPHER_TEXT_LENGTH+1),
+ Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {timeout, 5000},
+ {mfa, {?MODULE, dummy, []}},
+ {tcp_options, TcpOpts},
+ {ssl_options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]),
+ ct:log("Testcase ~p connected to Server ~p ~n", [self(), Server]),
+
+ gen_tcp:send(Socket, <<?BYTE(0),
+ ?BYTE(3), ?BYTE(1), ?UINT16(?MAX_CIPHER_TEXT_LENGTH), Rand/binary>>),
+
+ receive
+ {tcp_closed, Socket} ->
+ receive
+ {Server, {error, timeout}} ->
+ ct:fail("hangs");
+ {Server, {error, Error}} ->
+ ct:log("Error ~p", [Error]);
+ {'EXIT', Server, _} ->
+ ok
+ end
+ end.
+
+%%--------------------------------------------------------------------
+tls_dont_crash_on_handshake_garbage() ->
+ [{doc, "Ensure SSL server worker thows an alert on garbage during handshake "
+ "instead of crashing and exposing state to user code"}].
+
+tls_dont_crash_on_handshake_garbage(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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ unlink(Server), monitor(process, Server),
+ Port = ssl_test_lib:inet_port(Server),
+
+ {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {active, false}]),
+
+ % Send hello and garbage record
+ ok = gen_tcp:send(Socket,
+ [<<22, 3,3, 49:16, 1, 45:24, 3,3, % client_hello
+ 16#deadbeef:256, % 32 'random' bytes = 256 bits
+ 0, 6:16, 0,255, 0,61, 0,57, 1, 0 >>, % some hello values
+
+ <<22, 3,3, 5:16, 92,64,37,228,209>> % garbage
+ ]),
+ % Send unexpected change_cipher_spec
+ 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).
+
+%%--------------------------------------------------------------------
+tls_tcp_error_propagation_in_active_mode() ->
+ [{doc,"Test that process recives {ssl_error, Socket, closed} when tcp error ocurres"}].
+tls_tcp_error_propagation_in_active_mode(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {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}]),
+
+ {status, _, _, StatusInfo} = sys:get_status(Pid),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ StaticEnv = element(2, State),
+ Socket = element(11, StaticEnv),
+ %% Fake tcp error
+ Pid ! {tcp_error, Socket, etimedout},
+
+ ssl_test_lib:check_result(Client, {ssl_closed, SslSocket}).
+
+%%--------------------------------------------------------------------
+peername() ->
+ [{doc,"Test API function peername/1"}].
+
+peername(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, peername_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, peername_result, []}},
+ {options, [{port, 0} | ClientOpts]}]),
+
+ ClientPort = ssl_test_lib:inet_port(Client),
+ ServerIp = ssl_test_lib:node_to_hostip(ServerNode, server),
+ ClientIp = ssl_test_lib:node_to_hostip(ClientNode, client),
+ ServerMsg = {ok, {ClientIp, ClientPort}},
+ ClientMsg = {ok, {ServerIp, Port}},
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+sockname() ->
+ [{doc,"Test API function sockname/1"}].
+sockname(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {?MODULE, sockname_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, sockname_result, []}},
+ {options, [{port, 0} | ClientOpts]}]),
+
+ ClientPort = ssl_test_lib:inet_port(Client),
+ ServerIp = ssl_test_lib:node_to_hostip(ServerNode, server),
+ ClientIp = ssl_test_lib:node_to_hostip(ClientNode, client),
+ ServerMsg = {ok, {ServerIp, Port}},
+ ClientMsg = {ok, {ClientIp, ClientPort}},
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+tls_server_handshake_timeout() ->
+ [{doc,"Test server handshake timeout"}].
+
+tls_server_handshake_timeout(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {timeout, 5000},
+ {mfa, {ssl_test_lib,
+ no_result_msg, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {ok, CSocket} = gen_tcp:connect(Hostname, Port, [binary, {active, true}]),
+
+ receive
+ {tcp_closed, CSocket} ->
+ ssl_test_lib:check_result(Server, {error, timeout}),
+ receive
+ {'EXIT', Server, _} ->
+ %% Make sure supervisor had time to react on process exit
+ %% Could we come up with a better solution to this?
+ ct:sleep(500),
+ [] = supervisor:which_children(tls_connection_sup)
+ end
+ end.
+transport_close() ->
+ [{doc, "Test what happens if socket is closed on TCP level after a while of normal operation"}].
+transport_close(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {ok, TcpS} = rpc:call(ClientNode, gen_tcp, connect,
+ [Hostname,Port,[binary, {active, false}]]),
+ {ok, SslS} = rpc:call(ClientNode, ssl, connect,
+ [TcpS,[{active, false}|ClientOpts]]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), self(), Server]),
+ ok = ssl:send(SslS, "Hello world"),
+ {ok,<<"Hello world">>} = ssl:recv(SslS, 11),
+ gen_tcp:close(TcpS),
+ {error, _} = ssl:send(SslS, "Hello world").
+
+%%--------------------------------------------------------------------
+ssl3_cipher_suite_limitation() ->
+ [{doc,"Test a SSLv3 client cannot negotiate a TLSv* cipher suite."}].
+ssl3_cipher_suite_limitation(Config) when is_list(Config) ->
+
+ {_ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {active, false}]),
+ ok = gen_tcp:send(Socket,
+ <<22, 3,0, 49:16, % handshake, SSL 3.0, length
+ 1, 45:24, % client_hello, length
+ 3,0, % SSL 3.0
+ 16#deadbeef:256, % 32 'random' bytes = 256 bits
+ 0, % no session ID
+ %% three cipher suites -- null, one with sha256 hash and one with sha hash
+ 6:16, 0,255, 0,61, 0,57,
+ 1, 0 % no compression
+ >>),
+ {ok, <<22, RecMajor:8, RecMinor:8, _RecLen:16, 2, HelloLen:24>>} = gen_tcp:recv(Socket, 9, 10000),
+ {ok, <<HelloBin:HelloLen/binary>>} = gen_tcp:recv(Socket, HelloLen, 5000),
+ ServerHello = tls_handshake:decode_handshake({RecMajor, RecMinor}, 2, HelloBin),
+ case ServerHello of
+ #server_hello{server_version = {3,0}, cipher_suite = <<0,57>>} ->
+ ok;
+ _ ->
+ ct:fail({unexpected_server_hello, ServerHello})
+ end.
+%%--------------------------------------------------------------------
+emulated_options() ->
+ [{doc,"Test API function getopts/2 and setopts/2"}].
+
+emulated_options(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Values = [{mode, list}, {packet, 0}, {header, 0},
+ {active, true}],
+ %% Shall be the reverse order of Values!
+ Options = [active, header, packet, mode],
+
+ NewValues = [{mode, binary}, {active, once}],
+ %% Shall be the reverse order of NewValues!
+ NewOptions = [active, mode],
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, tls_socket_options_result,
+ [Options, Values, NewOptions, NewValues]}},
+ {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, tls_socket_options_result,
+ [Options, Values, NewOptions, NewValues]}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+
+ {ok, Listen} = ssl:listen(0, ServerOpts),
+ {ok,[{mode,list}]} = ssl:getopts(Listen, [mode]),
+ ok = ssl:setopts(Listen, [{mode, binary}]),
+ {ok,[{mode, binary}]} = ssl:getopts(Listen, [mode]),
+ {ok,[{recbuf, _}]} = ssl:getopts(Listen, [recbuf]),
+ ssl:close(Listen).
+accept_pool() ->
+ [{doc,"Test having an accept pool."}].
+accept_pool(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server0 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {accepters, 3},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server0),
+ [Server1, Server2] = ssl_test_lib:accepters(2),
+
+ Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ClientOpts}
+ ]),
+
+ Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ClientOpts}
+ ]),
+
+ Client2 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ClientOpts}
+ ]),
+
+ ssl_test_lib:check_ok([Server0, Server1, Server2, Client0, Client1, Client2]),
+
+ ssl_test_lib:close(Server0),
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Server2),
+ ssl_test_lib:close(Client0),
+ ssl_test_lib:close(Client1),
+ ssl_test_lib:close(Client2).
+
+%%--------------------------------------------------------------------
+reuseaddr() ->
+ [{doc,"Test reuseaddr option"}].
+
+reuseaddr(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_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},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, [{active, false}, {reuseaddr, true}| 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, [{active, false} | ClientOpts]}]),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+
+ Server1 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false}, {reuseaddr, true} | ServerOpts]}]),
+ Client1 =
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server1, ok, Client1, ok),
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1).
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+upgrade_result(Socket) ->
+ ssl:setopts(Socket, [{active, true}]),
+ ok = ssl:send(Socket, "Hello world"),
+ %% Make sure binary is inherited from tcp socket and that we do
+ %% not get the list default!
+ receive
+ {ssl, _, <<"H">>} ->
+ receive
+ {ssl, _, <<"ello world">>} ->
+ ok
+ end;
+ {ssl, _, <<"Hello world">>} ->
+ ok
+ end.
+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}]),
+ gen_tcp:send(TCPSocket, "Downgraded"),
+ receive
+ {tcp, TCPSocket, <<"Downgraded">>} ->
+ ok;
+ {tcp_closed, TCPSocket} ->
+ ct:fail("Peer timed out, downgrade aborted"),
+ ok;
+ Other ->
+ {error, Other}
+ end;
+ {error, timeout} ->
+ ct:fail("Timed out, downgrade aborted"),
+ ok;
+ Fail ->
+ {error, Fail}
+ end.
+
+tls_shutdown_result(Socket, server) ->
+ ssl:send(Socket, "Hej"),
+ ok = ssl:shutdown(Socket, write),
+ {ok, "Hej hopp"} = ssl:recv(Socket, 8),
+ ok;
+
+tls_shutdown_result(Socket, client) ->
+ ssl:send(Socket, "Hej hopp"),
+ ok = ssl:shutdown(Socket, write),
+ {ok, "Hej"} = ssl:recv(Socket, 3),
+ ok.
+
+tls_shutdown_write_result(Socket, server) ->
+ ct:sleep(?SLEEP),
+ ssl:shutdown(Socket, write);
+tls_shutdown_write_result(Socket, client) ->
+ ssl:recv(Socket, 0).
+
+tls_shutdown_both_result(Socket, server) ->
+ ct:sleep(?SLEEP),
+ ssl:shutdown(Socket, read_write);
+tls_shutdown_both_result(Socket, client) ->
+ ssl:recv(Socket, 0).
+
+tls_closed_in_active_once_loop(Socket) ->
+ 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.
+
+drop_handshakes(Socket, Timeout) ->
+ {ok, <<RecType:8, _RecMajor:8, _RecMinor:8, RecLen:16>> = Header} = gen_tcp:recv(Socket, 5, Timeout),
+ {ok, <<Frag:RecLen/binary>>} = gen_tcp:recv(Socket, RecLen, Timeout),
+ case RecType of
+ 22 -> drop_handshakes(Socket, Timeout);
+ _ -> {ok, <<Header/binary, Frag/binary>>}
+ end.
+
+receive_msg(_) ->
+ receive
+ Msg ->
+ Msg
+ end.
+
+sockname_result(S) ->
+ ssl:sockname(S).
+
+peername_result(S) ->
+ ssl:peername(S).
+
+tls_socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
+ %% Test get/set emulated opts
+ {ok, DefaultValues} = ssl:getopts(Socket, Options),
+ ssl:setopts(Socket, NewValues),
+ {ok, NewValues} = ssl:getopts(Socket, NewOptions),
+ %% Test get/set inet opts
+ {ok,[{nodelay,false}]} = ssl:getopts(Socket, [nodelay]),
+ ssl:setopts(Socket, [{nodelay, true}]),
+ {ok,[{nodelay, true}]} = ssl:getopts(Socket, [nodelay]),
+ {ok, All} = ssl:getopts(Socket, []),
+ ct:log("All opts ~p~n", [All]),
+ ok.
+
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 9b2033ec4a..be8ab3b98e 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -716,22 +716,22 @@ referenced(Config) when is_list(Config) ->
badarg = ?MASK_ERROR(binary:referenced_byte_size(apa)),
badarg = ?MASK_ERROR(binary:referenced_byte_size({})),
badarg = ?MASK_ERROR(binary:referenced_byte_size(1)),
- A = <<1,2,3>>,
- B = binary:copy(A,1000),
- 3 = binary:referenced_byte_size(A),
- 3000 = binary:referenced_byte_size(B),
- <<_:8,C:2/binary>> = A,
- 3 = binary:referenced_byte_size(C),
- 2 = binary:referenced_byte_size(binary:copy(C)),
- <<_:7,D:2/binary,_:1>> = A,
- 2 = binary:referenced_byte_size(binary:copy(D)),
- 3 = binary:referenced_byte_size(D),
- <<_:8,E:2/binary,_/binary>> = B,
- 3000 = binary:referenced_byte_size(E),
- 2 = binary:referenced_byte_size(binary:copy(E)),
- <<_:7,F:2/binary,_:1,_/binary>> = B,
- 2 = binary:referenced_byte_size(binary:copy(F)),
- 3000 = binary:referenced_byte_size(F),
+ A = <<0:(1024 * 8)>>,
+ B = binary:copy(A, 1000),
+ 1024 = binary:referenced_byte_size(A),
+ 1024000 = binary:referenced_byte_size(B),
+ <<_:8,C:1023/binary>> = A,
+ 1024 = binary:referenced_byte_size(C),
+ 1023 = binary:referenced_byte_size(binary:copy(C)),
+ <<_:7,D:1023/binary,_:1>> = A,
+ 1023 = binary:referenced_byte_size(binary:copy(D)),
+ 1024 = binary:referenced_byte_size(D),
+ <<_:8,E:128/binary,_/binary>> = B,
+ 1024000 = binary:referenced_byte_size(E),
+ 128 = binary:referenced_byte_size(binary:copy(E)),
+ <<_:7,F:128/binary,_:1,_/binary>> = B,
+ 128 = binary:referenced_byte_size(binary:copy(F)),
+ 1024000 = binary:referenced_byte_size(F),
ok.
diff --git a/scripts/build-otp b/scripts/build-otp
index abf8d5d67f..55023ba7d8 100755
--- a/scripts/build-otp
+++ b/scripts/build-otp
@@ -44,6 +44,8 @@ fi
do_and_log "Autoconfing" ./otp_build autoconf
do_and_log "Configuring" ./otp_build configure
+echo Configure result:
+tail -n 20 $log
do_and_log "Building OTP" ./otp_build boot -a
if [ "$1" = "release" ]; then